squiggle/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/helpers.ts

220 lines
4.5 KiB
TypeScript
Raw Normal View History

2022-06-26 08:14:51 +00:00
import { LocationRange } from "peggy";
export const toFunction = {
"-": "subtract",
"->": "pipe",
"!=": "unequal",
".-": "dotSubtract",
".*": "dotMultiply",
"./": "dotDivide",
".^": "dotPow",
".+": "dotAdd",
"*": "multiply",
"/": "divide",
"&&": "and",
"^": "pow", // or xor
"+": "add",
"<": "smaller",
"<=": "smallerEq",
"==": "equal",
">": "larger",
">=": "largerEq",
"||": "or",
to: "credibleIntervalToDistribution",
};
export const unaryToFunction = {
"-": "unaryMinus",
"!": "not",
".-": "unaryDotMinus",
};
export const postOperatorToFunction = {
".": "$_atIndex_$",
"()": "$$_applyAll_$$",
"[]": "$_atIndex_$",
};
type NodeBlock = {
type: "Block";
statements: AnyPeggyNode[];
};
type NodeExpression = {
type: "Expression";
nodes: AnyPeggyNode[];
};
type NodeFloat = {
type: "Float";
value: number;
};
type NodeInteger = {
type: "Integer";
value: number;
};
type NodeIdentifier = {
type: "Identifier";
value: string;
location: LocationRange;
};
type NodeCallIdentifier = {
type: "CallIdentifier";
value: string;
};
type NodeLetStatement = {
type: "LetStatement";
variable: NodeIdentifier;
value: AnyPeggyNode;
};
type NodeLambda = {
type: "Lambda";
args: AnyPeggyNode[];
body: AnyPeggyNode;
};
type NodeTernary = {
type: "Ternary";
condition: AnyPeggyNode;
trueExpression: AnyPeggyNode;
falseExpression: AnyPeggyNode;
};
type NodeKeyValue = {
type: "KeyValue";
key: AnyPeggyNode;
value: AnyPeggyNode;
};
type NodeString = {
type: "String";
value: string;
location?: LocationRange;
2022-06-26 08:14:51 +00:00
};
type NodeBoolean = {
type: "Boolean";
value: boolean;
};
export type AnyPeggyNode =
| NodeBlock
| NodeExpression
| NodeFloat
| NodeInteger
| NodeIdentifier
| NodeCallIdentifier
| NodeLetStatement
| NodeLambda
| NodeTernary
| NodeKeyValue
| NodeString
| NodeBoolean;
export function makeFunctionCall(fn: string, args: AnyPeggyNode[]) {
if (fn === "$$_applyAll_$$") {
// Any list of values is applied from left to right anyway.
// Like in Haskell and Lisp.
// So we remove the redundant $$_applyAll_$$.
if (args[0].type === "Identifier") {
args[0] = {
...args[0],
type: "CallIdentifier",
};
}
return nodeExpression(args);
} else {
return nodeExpression([nodeCallIndentifier(fn), ...args]);
}
}
export function apply(fn: string, arg: AnyPeggyNode) {
return makeFunctionCall(fn, [arg]);
}
export function constructArray(elems: AnyPeggyNode[]) {
2022-09-06 18:14:24 +00:00
return makeFunctionCall("$_constructArray_$", elems);
2022-06-26 08:14:51 +00:00
}
export function constructRecord(elems: AnyPeggyNode[]) {
return apply("$_constructRecord_$", nodeExpression(elems));
}
export function nodeBlock(statements: AnyPeggyNode[]): NodeBlock {
return { type: "Block", statements };
}
export function nodeBoolean(value: boolean): NodeBoolean {
return { type: "Boolean", value };
}
export function nodeCallIndentifier(value: string): NodeCallIdentifier {
return { type: "CallIdentifier", value };
}
export function nodeExpression(args: AnyPeggyNode[]): NodeExpression {
return { type: "Expression", nodes: args };
}
export function nodeFloat(value: number): NodeFloat {
return { type: "Float", value };
}
export function nodeIdentifier(
value: string,
location: LocationRange
): NodeIdentifier {
return { type: "Identifier", value, location };
}
export function nodeInteger(value: number): NodeInteger {
return { type: "Integer", value };
}
export function nodeKeyValue(
key: AnyPeggyNode,
value: AnyPeggyNode
): NodeKeyValue {
if (key.type === "Identifier") {
key = {
...key,
type: "String",
};
}
return { type: "KeyValue", key, value };
}
export function nodeLambda(
args: AnyPeggyNode[],
body: AnyPeggyNode
): NodeLambda {
return { type: "Lambda", args, body };
}
export function nodeLetStatement(
variable: NodeIdentifier,
value: AnyPeggyNode
): NodeLetStatement {
return { type: "LetStatement", variable, value };
}
export function nodeModuleIdentifier(value: string) {
return { type: "ModuleIdentifier", value };
}
export function nodeString(value: string): NodeString {
return { type: "String", value };
}
export function nodeTernary(
condition: AnyPeggyNode,
trueExpression: AnyPeggyNode,
falseExpression: AnyPeggyNode
): NodeTernary {
return {
type: "Ternary",
condition,
trueExpression,
falseExpression,
};
}
export function nodeTypeIdentifier(typeValue: string) {
return { type: "TypeIdentifier", value: typeValue };
}
export function nodeVoid() {
return { type: "Void" };
}