Merge pull request #666 from quantified-uncertainty/reducer-modules
Reducer modules
This commit is contained in:
commit
2ced133889
19
packages/squiggle-lang/__tests__/Reducer/Reducer_Helpers.res
Normal file
19
packages/squiggle-lang/__tests__/Reducer/Reducer_Helpers.res
Normal file
|
@ -0,0 +1,19 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
module Bindings = Reducer_Category_Bindings
|
||||
|
||||
let removeDefaults = (ev: ExpressionT.expressionValue): ExpressionT.expressionValue =>
|
||||
switch ev {
|
||||
| EvRecord(extbindings) => {
|
||||
let bindings: Bindings.t = Bindings.fromRecord(extbindings)
|
||||
let keys = Js.Dict.keys(Reducer.defaultExternalBindings)
|
||||
Belt.Map.String.keep(bindings, (key, _value) => {
|
||||
let removeThis = Js.Array2.includes(keys, key)
|
||||
!removeThis
|
||||
})->Bindings.toExpressionValue
|
||||
}
|
||||
| value => value
|
||||
}
|
||||
|
||||
let rRemoveDefaults = r => Belt.Result.map(r, ev => removeDefaults(ev))
|
|
@ -235,6 +235,9 @@ describe("Peggy parse", () => {
|
|||
testParse("1M", "{(::fromUnit_M 1)}")
|
||||
testParse("1m+2cm", "{(::add (::fromUnit_m 1) (::fromUnit_cm 2))}")
|
||||
})
|
||||
describe("Module", () => {
|
||||
testParse("Math.pi", "{(::$_atIndex_$ @Math 'pi')}")
|
||||
})
|
||||
})
|
||||
|
||||
describe("parsing new line", () => {
|
||||
|
|
|
@ -23,8 +23,13 @@ let expectToExpressionToBe = (expr, answer, ~v="_", ()) => {
|
|||
let a2 =
|
||||
rExpr
|
||||
->Result.flatMap(expr =>
|
||||
Expression.reduceExpression(expr, Belt.Map.String.empty, ExpressionValue.defaultEnvironment)
|
||||
Expression.reduceExpression(
|
||||
expr,
|
||||
ReducerInterface_DefaultExternalBindings.defaultInternalBindings,
|
||||
ExpressionValue.defaultEnvironment,
|
||||
)
|
||||
)
|
||||
->Reducer_Helpers.rRemoveDefaults
|
||||
->ExpressionValue.toStringResultOkless
|
||||
(a1, a2)->expect->toEqual((answer, v))
|
||||
}
|
||||
|
|
|
@ -181,4 +181,8 @@ describe("Peggy to Expression", () => {
|
|||
(),
|
||||
)
|
||||
})
|
||||
|
||||
describe("module", () => {
|
||||
testToExpression("Math.pi", "{(:$_atIndex_$ :Math 'pi')}", ~v="3.141592653589793", ())
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
module Bindings = Reducer_Category_Bindings
|
||||
|
||||
open Jest
|
||||
open Expect
|
||||
|
@ -17,7 +18,11 @@ let expectParseToBe = (expr: string, answer: string) =>
|
|||
Reducer.parse(expr)->ExpressionT.toStringResult->expect->toBe(answer)
|
||||
|
||||
let expectEvalToBe = (expr: string, answer: string) =>
|
||||
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
||||
Reducer.evaluate(expr)
|
||||
->Reducer_Helpers.rRemoveDefaults
|
||||
->ExpressionValue.toStringResult
|
||||
->expect
|
||||
->toBe(answer)
|
||||
|
||||
let expectEvalError = (expr: string) =>
|
||||
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toMatch("Error\(")
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
open Jest
|
||||
open Reducer_TestHelpers
|
||||
|
||||
describe("Math Library", () => {
|
||||
testEvalToBe("Math.e", "Ok(2.718281828459045)")
|
||||
testEvalToBe("Math.pi", "Ok(3.141592653589793)")
|
||||
})
|
|
@ -187,5 +187,16 @@ function createTsExport(
|
|||
return tag("lambdaDeclaration", x.value);
|
||||
case "EvTypeIdentifier":
|
||||
return tag("typeIdentifier", x.value);
|
||||
case "EvModule":
|
||||
let moduleResult: tagged<
|
||||
"module",
|
||||
{ [key: string]: squiggleExpression }
|
||||
> = tag(
|
||||
"module",
|
||||
_.mapValues(x.value, (x: unknown) =>
|
||||
convertRawToTypescript(x as rescriptExport, environment)
|
||||
)
|
||||
);
|
||||
return moduleResult;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,10 @@ export type rescriptExport =
|
|||
| {
|
||||
TAG: 13; // EvTypeIdentifier
|
||||
_0: string;
|
||||
}
|
||||
| {
|
||||
TAG: 14; // EvModule
|
||||
_0: { [key: string]: rescriptExport };
|
||||
};
|
||||
|
||||
type rescriptDist =
|
||||
|
@ -125,7 +129,8 @@ export type squiggleExpression =
|
|||
| tagged<"timeDuration", number>
|
||||
| tagged<"lambdaDeclaration", lambdaDeclaration>
|
||||
| tagged<"record", { [key: string]: squiggleExpression }>
|
||||
| tagged<"typeIdentifier", string>;
|
||||
| tagged<"typeIdentifier", string>
|
||||
| tagged<"module", { [key: string]: squiggleExpression }>;
|
||||
|
||||
export { lambdaValue };
|
||||
|
||||
|
@ -177,6 +182,11 @@ export function convertRawToTypescript(
|
|||
});
|
||||
case 13: // EvSymbol
|
||||
return tag("typeIdentifier", result._0);
|
||||
case 14: // EvModule
|
||||
return tag(
|
||||
"module",
|
||||
_.mapValues(result._0, (x) => convertRawToTypescript(x, environment))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,4 +24,4 @@ let foreignFunctionInterface = (
|
|||
|
||||
let defaultEnvironment = ExpressionValue.defaultEnvironment
|
||||
|
||||
let defaultExternalBindings = ExpressionValue.defaultExternalBindings
|
||||
let defaultExternalBindings = ReducerInterface_DefaultExternalBindings.defaultExternalBindings
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
include Reducer_Category_Module // Bindings inherit from Module
|
||||
|
||||
open ReducerInterface_ExpressionValue
|
||||
|
||||
let emptyBindings = emptyModule
|
||||
|
||||
let toExpressionValue = (container: t): expressionValue => EvRecord(toRecord(container))
|
||||
let fromExpressionValue = (aValue: expressionValue): t =>
|
||||
switch aValue {
|
||||
| EvRecord(r) => fromRecord(r)
|
||||
| _ => emptyBindings
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
open ReducerInterface_ExpressionValue
|
||||
let expressionValueToString = toString
|
||||
|
||||
type t = ExpressionT.bindings
|
||||
|
||||
let typeAliasesKey = "_typeAliases_"
|
||||
let typeReferencesKey = "_typeReferences_"
|
||||
|
||||
let emptyModule: t = Belt.Map.String.empty
|
||||
|
||||
let cloneRecord = (r: record): record => r->Js.Dict.entries->Js.Dict.fromArray
|
||||
let fromRecord = (r: record): t => Js.Dict.entries(r)->Belt.Map.String.fromArray
|
||||
let toRecord = (container: t): record => Belt.Map.String.toArray(container)->Js.Dict.fromArray
|
||||
|
||||
let toExpressionValue = (container: t): expressionValue => EvModule(toRecord(container))
|
||||
let fromExpressionValue = (aValue: expressionValue): t =>
|
||||
switch aValue {
|
||||
| EvModule(r) => fromRecord(r)
|
||||
| _ => emptyModule
|
||||
}
|
||||
|
||||
let toString = (container: t): string => container->toRecord->EvRecord->expressionValueToString
|
||||
|
||||
// -- Module definition
|
||||
let define = (container: t, identifier: string, ev: expressionValue): t =>
|
||||
Belt.Map.String.set(container, identifier, ev) // TODO build lambda for polymorphic functions here
|
||||
|
||||
let defineNumber = (container: t, identifier: string, value: float): t =>
|
||||
container->define(identifier, EvNumber(value))
|
||||
|
||||
let defineModule = (container: t, identifier: string, value: t): t =>
|
||||
container->define(identifier, toExpressionValue(value))
|
|
@ -256,6 +256,7 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
|
||||
switch call {
|
||||
| ("$_atIndex_$", [EvArray(aValueArray), EvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
||||
| ("$_atIndex_$", [EvModule(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||
| ("$_atIndex_$", [EvRecord(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||
| ("$_constructArray_$", [EvArray(aValueArray)]) => EvArray(aValueArray)->Ok
|
||||
| ("$_constructRecord_$", [EvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||
|
|
|
@ -123,7 +123,7 @@ let evaluateUsingOptions = (
|
|||
|
||||
let anExternalBindings = switch externalBindings {
|
||||
| Some(bindings) => bindings
|
||||
| None => ReducerInterface_ExpressionValue.defaultExternalBindings
|
||||
| None => ReducerInterface_DefaultExternalBindings.defaultExternalBindings
|
||||
}
|
||||
|
||||
let bindings = anExternalBindings->Bindings.fromExternalBindings
|
||||
|
|
|
@ -2,77 +2,25 @@ module ErrorValue = Reducer_ErrorValue
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module Result = Belt.Result
|
||||
module Bindings = Reducer_Category_Bindings
|
||||
|
||||
type errorValue = Reducer_ErrorValue.errorValue
|
||||
type expression = ExpressionT.expression
|
||||
type expressionValue = ExpressionValue.expressionValue
|
||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
||||
|
||||
let defaultBindings: ExpressionT.bindings = Belt.Map.String.empty
|
||||
let emptyBindings = Reducer_Category_Bindings.emptyBindings
|
||||
|
||||
let typeAliasesKey = "_typeAliases_"
|
||||
let typeReferencesKey = "_typeReferences_"
|
||||
let typeAliasesKey = Bindings.typeAliasesKey
|
||||
let typeReferencesKey = Bindings.typeReferencesKey
|
||||
|
||||
let toExternalBindings = (bindings: ExpressionT.bindings): externalBindings => {
|
||||
let keys = Belt.Map.String.keysToArray(bindings)
|
||||
keys->Belt.Array.reduce(Js.Dict.empty(), (acc, key) => {
|
||||
let value = bindings->Belt.Map.String.getExn(key)
|
||||
Js.Dict.set(acc, key, value)
|
||||
acc
|
||||
})
|
||||
}
|
||||
let toExternalBindings = (bindings: ExpressionT.bindings): externalBindings =>
|
||||
Bindings.toRecord(bindings)
|
||||
|
||||
let fromExternalBindings_ = (externalBindings: externalBindings): ExpressionT.bindings => {
|
||||
let keys = Js.Dict.keys(externalBindings)
|
||||
keys->Belt.Array.reduce(defaultBindings, (acc, key) => {
|
||||
let value = Js.Dict.unsafeGet(externalBindings, key)
|
||||
acc->Belt.Map.String.set(key, value)
|
||||
})
|
||||
}
|
||||
let fromExternalBindings = (externalBindings: externalBindings): ExpressionT.bindings =>
|
||||
Bindings.fromRecord(externalBindings)
|
||||
|
||||
let fromExternalBindings = (externalBindings: externalBindings): ExpressionT.bindings => {
|
||||
// TODO: This code will be removed in the future when maps are used instead of records. Please don't mind this function for now.
|
||||
|
||||
let internalBindings0 = fromExternalBindings_(externalBindings)
|
||||
|
||||
let oExistingTypeAliases = Belt.Map.String.get(internalBindings0, typeAliasesKey)
|
||||
let internalBindings1 = Belt.Option.mapWithDefault(
|
||||
oExistingTypeAliases,
|
||||
internalBindings0,
|
||||
existingTypeAliases => {
|
||||
let newTypeAliases = switch existingTypeAliases {
|
||||
| EvRecord(actualTypeAliases) =>
|
||||
actualTypeAliases->fromExternalBindings_->toExternalBindings->ExpressionValue.EvRecord
|
||||
| _ => existingTypeAliases
|
||||
}
|
||||
Belt.Map.String.set(internalBindings0, typeAliasesKey, newTypeAliases)
|
||||
},
|
||||
)
|
||||
|
||||
let oExistingTypeReferences = Belt.Map.String.get(internalBindings1, typeReferencesKey)
|
||||
let internalBindings2 = Belt.Option.mapWithDefault(
|
||||
oExistingTypeReferences,
|
||||
internalBindings1,
|
||||
existingTypeReferences => {
|
||||
let newTypeReferences = switch existingTypeReferences {
|
||||
| EvRecord(actualTypeReferences) =>
|
||||
actualTypeReferences->fromExternalBindings_->toExternalBindings->ExpressionValue.EvRecord
|
||||
| _ => existingTypeReferences
|
||||
}
|
||||
Belt.Map.String.set(internalBindings0, typeReferencesKey, newTypeReferences)
|
||||
},
|
||||
)
|
||||
|
||||
internalBindings2
|
||||
}
|
||||
|
||||
let fromValue = (aValue: expressionValue) =>
|
||||
switch aValue {
|
||||
| EvRecord(externalBindings) => fromExternalBindings(externalBindings)
|
||||
| _ => defaultBindings
|
||||
}
|
||||
|
||||
let externalFromArray = anArray => Js.Dict.fromArray(anArray)
|
||||
let fromValue = (aValue: expressionValue) => Bindings.fromExpressionValue(aValue)
|
||||
|
||||
let isMacroName = (fName: string): bool => fName->Js.String2.startsWith("$$")
|
||||
|
||||
|
|
|
@ -65,5 +65,7 @@ let eBindExpression = (bindingExpr: expression, expression: expression): express
|
|||
let eBindExpressionDefault = (expression: expression): expression =>
|
||||
eFunction("$$_bindExpression_$$", list{expression})
|
||||
|
||||
let eIdentifier = (name: string): expression => name->BExpressionValue.EvSymbol->BExpressionT.EValue
|
||||
|
||||
let eTypeIdentifier = (name: string): expression =>
|
||||
name->BExpressionValue.EvTypeIdentifier->BExpressionT.EValue
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
return {type: 'KeyValue', key: key, value: value}}
|
||||
function nodeLambda(args, body) {return {type: 'Lambda', args: args, body: body}}
|
||||
function nodeLetStatment(variable, value) {return {type: 'LetStatement', variable: variable, value: value}}
|
||||
function nodeModuleIdentifier(value) {return {type: 'ModuleIdentifier', value: value}}
|
||||
function nodeString(value) {return {type: 'String', value: value}}
|
||||
function nodeTernary(condition, trueExpression, falseExpression) {return {type: 'Ternary', condition: condition, trueExpression: trueExpression, falseExpression: falseExpression}}
|
||||
|
||||
|
@ -256,11 +257,11 @@ basicLiteral
|
|||
|
||||
dollarIdentifierWithModule 'identifier'
|
||||
= head:moduleIdentifier
|
||||
tail:('.' _nl @moduleIdentifier)* '.' _nl
|
||||
final:dollarIdentifier
|
||||
tail:('.' _nl @$moduleIdentifier)* '.' _nl
|
||||
final:$dollarIdentifier
|
||||
{ tail.push(final);
|
||||
return tail.reduce(function(result, element) {
|
||||
return makeFunctionCall(postOperatorToFunction['[]'], [result, element])
|
||||
return makeFunctionCall(postOperatorToFunction['[]'], [result, nodeString(element)])
|
||||
}, head)}
|
||||
|
||||
identifier 'identifier'
|
||||
|
@ -273,7 +274,7 @@ dollarIdentifier '$identifier'
|
|||
= ([\$_a-z]+[\$_a-z0-9]i*) {return nodeIdentifier(text())}
|
||||
|
||||
moduleIdentifier 'identifier'
|
||||
= ([A-Z]+[_a-z0-9]i*) {return nodeIdentifier(text())}
|
||||
= ([A-Z]+[_a-z0-9]i*) {return nodeModuleIdentifier(text())}
|
||||
|
||||
|
||||
string 'string'
|
||||
|
|
|
@ -22,6 +22,7 @@ type nodeInteger = {...node, "value": int}
|
|||
type nodeKeyValue = {...node, "key": node, "value": node}
|
||||
type nodeLambda = {...node, "args": array<nodeIdentifier>, "body": nodeBlock}
|
||||
type nodeLetStatement = {...node, "variable": nodeIdentifier, "value": node}
|
||||
type nodeModuleIdentifier = {...node, "value": string}
|
||||
type nodeString = {...node, "value": string}
|
||||
type nodeTernary = {...node, "condition": node, "trueExpression": node, "falseExpression": node}
|
||||
type nodeTypeIdentifier = {...node, "value": string}
|
||||
|
@ -37,6 +38,7 @@ type peggyNode =
|
|||
| PgNodeKeyValue(nodeKeyValue)
|
||||
| PgNodeLambda(nodeLambda)
|
||||
| PgNodeLetStatement(nodeLetStatement)
|
||||
| PgNodeModuleIdentifier(nodeModuleIdentifier)
|
||||
| PgNodeString(nodeString)
|
||||
| PgNodeTernary(nodeTernary)
|
||||
| PgNodeTypeIdentifier(nodeTypeIdentifier)
|
||||
|
@ -51,6 +53,7 @@ external castNodeInteger: node => nodeInteger = "%identity"
|
|||
external castNodeKeyValue: node => nodeKeyValue = "%identity"
|
||||
external castNodeLambda: node => nodeLambda = "%identity"
|
||||
external castNodeLetStatement: node => nodeLetStatement = "%identity"
|
||||
external castNodeModuleIdentifier: node => nodeModuleIdentifier = "%identity"
|
||||
external castNodeString: node => nodeString = "%identity"
|
||||
external castNodeTernary: node => nodeTernary = "%identity"
|
||||
external castNodeTypeIdentifier: node => nodeTypeIdentifier = "%identity"
|
||||
|
@ -68,6 +71,7 @@ let castNodeType = (node: node) =>
|
|||
| "KeyValue" => node->castNodeKeyValue->PgNodeKeyValue
|
||||
| "Lambda" => node->castNodeLambda->PgNodeLambda
|
||||
| "LetStatement" => node->castNodeLetStatement->PgNodeLetStatement
|
||||
| "ModuleIdentifier" => node->castNodeModuleIdentifier->PgNodeModuleIdentifier
|
||||
| "String" => node->castNodeString->PgNodeString
|
||||
| "Ternary" => node->castNodeTernary->PgNodeTernary
|
||||
| "TypeIdentifier" => node->castNodeTypeIdentifier->PgNodeTypeIdentifier
|
||||
|
@ -94,6 +98,7 @@ let rec pgToString = (peggyNode: peggyNode): string => {
|
|||
"{|" ++ node["args"]->argsToString ++ "| " ++ pgToString(PgNodeBlock(node["body"])) ++ "}"
|
||||
| PgNodeLetStatement(node) =>
|
||||
pgToString(PgNodeIdentifier(node["variable"])) ++ " = " ++ toString(node["value"])
|
||||
| PgNodeModuleIdentifier(node) => `@${node["value"]}`
|
||||
| PgNodeString(node) => `'${node["value"]->Js.String.make}'`
|
||||
| PgNodeTernary(node) =>
|
||||
"(::$$_ternary_$$ " ++
|
||||
|
|
|
@ -34,6 +34,8 @@ let rec fromNode = (node: Parse.node): expression => {
|
|||
nodeLetStatement["variable"]["value"],
|
||||
fromNode(nodeLetStatement["value"]),
|
||||
)
|
||||
| PgNodeModuleIdentifier(nodeModuleIdentifier) =>
|
||||
ExpressionBuilder.eIdentifier(nodeModuleIdentifier["value"])
|
||||
| PgNodeString(nodeString) => ExpressionBuilder.eString(nodeString["value"])
|
||||
| PgNodeTernary(nodeTernary) =>
|
||||
ExpressionBuilder.eFunction(
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
module Bindings = Reducer_Category_Bindings
|
||||
|
||||
let defaultInternalBindings = Bindings.emptyBindings->SquiggleLibrary_Math.makeBindings
|
||||
|
||||
@genType
|
||||
let defaultExternalBindings = defaultInternalBindings->Bindings.toRecord
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
module Extra_Array = Reducer_Extra_Array
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
|
||||
@genType.opaque
|
||||
type internalCode = Object
|
||||
|
||||
|
@ -24,6 +23,7 @@ type rec expressionValue =
|
|||
| EvTimeDuration(float)
|
||||
| EvDeclaration(lambdaDeclaration)
|
||||
| EvTypeIdentifier(string)
|
||||
| EvModule(record)
|
||||
and record = Js.Dict.t<expressionValue>
|
||||
and externalBindings = record
|
||||
and lambdaValue = {
|
||||
|
@ -33,9 +33,6 @@ and lambdaValue = {
|
|||
}
|
||||
and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
||||
|
||||
@genType
|
||||
let defaultExternalBindings: externalBindings = Js.Dict.empty()
|
||||
|
||||
type functionCall = (string, array<expressionValue>)
|
||||
|
||||
let rec toString = aValue =>
|
||||
|
@ -60,6 +57,7 @@ let rec toString = aValue =>
|
|||
| EvTimeDuration(t) => DateTime.Duration.toString(t)
|
||||
| EvDeclaration(d) => Declaration.toString(d, r => toString(EvLambda(r)))
|
||||
| EvTypeIdentifier(id) => `#${id}`
|
||||
| EvModule(m) => `@${m->toStringRecord}`
|
||||
}
|
||||
and toStringRecord = aRecord => {
|
||||
let pairs =
|
||||
|
@ -86,6 +84,7 @@ let toStringWithType = aValue =>
|
|||
| EvTimeDuration(_) => `Date::${toString(aValue)}`
|
||||
| EvDeclaration(_) => `Declaration::${toString(aValue)}`
|
||||
| EvTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}`
|
||||
| EvModule(_) => `Module::${toString(aValue)}`
|
||||
}
|
||||
|
||||
let argsToString = (args: array<expressionValue>): string => {
|
||||
|
@ -133,6 +132,7 @@ type expressionValueType =
|
|||
| EvtTimeDuration
|
||||
| EvtDeclaration
|
||||
| EvtTypeIdentifier
|
||||
| EvtModule
|
||||
|
||||
type functionCallSignature = CallSignature(string, array<expressionValueType>)
|
||||
type functionDefinitionSignature =
|
||||
|
@ -154,6 +154,7 @@ let valueToValueType = value =>
|
|||
| EvTimeDuration(_) => EvtTimeDuration
|
||||
| EvDeclaration(_) => EvtDeclaration
|
||||
| EvTypeIdentifier(_) => EvtTypeIdentifier
|
||||
| EvModule(_) => EvtModule
|
||||
}
|
||||
|
||||
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
||||
|
@ -177,6 +178,7 @@ let valueTypeToString = (valueType: expressionValueType): string =>
|
|||
| EvtTimeDuration => `Duration`
|
||||
| EvtDeclaration => `Declaration`
|
||||
| EvtTypeIdentifier => `TypeIdentifier`
|
||||
| EvtModule => `Module`
|
||||
}
|
||||
|
||||
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
module Bindings = Reducer_Category_Bindings
|
||||
module Module = Reducer_Category_Module
|
||||
|
||||
let m =
|
||||
Module.emptyModule->Module.defineNumber("pi", Js.Math._PI)->Module.defineNumber("e", Js.Math._E)
|
||||
|
||||
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
||||
previousBindings->Bindings.defineModule("Math", m)
|
Loading…
Reference in New Issue
Block a user