Merge branch 'develop' into observable-refactor
This commit is contained in:
commit
f836afce7a
|
@ -244,7 +244,28 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
case "module": {
|
case "module": {
|
||||||
return (
|
return (
|
||||||
<VariableBox heading="Module" showTypes={showTypes}>
|
<VariableBox heading="Module" showTypes={showTypes}>
|
||||||
<span className="text-slate-600 font-semibold">Internal Module</span>
|
<div className="space-y-3">
|
||||||
|
{Object.entries(expression.value)
|
||||||
|
.filter(([key, r]) => key !== "Math")
|
||||||
|
.map(([key, r]) => (
|
||||||
|
<div key={key} className="flex space-x-2">
|
||||||
|
<div className="flex-none">
|
||||||
|
<header className="text-slate-500 font-mono">{key}:</header>
|
||||||
|
</div>
|
||||||
|
<div className="px-2 grow bg-gray-50 border border-gray-100 rounded-sm">
|
||||||
|
<SquiggleItem
|
||||||
|
expression={r}
|
||||||
|
width={width !== undefined ? width - 20 : width}
|
||||||
|
height={height / 3}
|
||||||
|
showTypes={showTypes}
|
||||||
|
distributionPlotSettings={distributionPlotSettings}
|
||||||
|
chartSettings={chartSettings}
|
||||||
|
environment={environment}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
1
packages/squiggle-lang/.gitignore
vendored
1
packages/squiggle-lang/.gitignore
vendored
|
@ -22,3 +22,4 @@ _coverage
|
||||||
coverage
|
coverage
|
||||||
.nyc_output/
|
.nyc_output/
|
||||||
src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.js
|
src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.js
|
||||||
|
src/rescript/Reducer/Reducer_Peggy/helpers.js
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
open Jest
|
||||||
|
open Expect
|
||||||
|
|
||||||
|
test("todo", () => expect("1")->toBe("1"))
|
|
@ -19,23 +19,23 @@ describe("bindStatement", () => {
|
||||||
testMacro(
|
testMacro(
|
||||||
[],
|
[],
|
||||||
eBindStatement(eBindings([]), exampleStatementY),
|
eBindStatement(eBindings([]), exampleStatementY),
|
||||||
"Ok((:$_setBindings_$ {} :y 1) context: {})",
|
"Ok((:$_setBindings_$ @{} :y 1) context: @{})",
|
||||||
)
|
)
|
||||||
// Then it answers the bindings for the next statement when reduced
|
// Then it answers the bindings for the next statement when reduced
|
||||||
testMacroEval([], eBindStatement(eBindings([]), exampleStatementY), "Ok({y: 1})")
|
testMacroEval([], eBindStatement(eBindings([]), exampleStatementY), "Ok(@{y: 1})")
|
||||||
// Now let's feed a binding to see what happens
|
// Now let's feed a binding to see what happens
|
||||||
testMacro(
|
testMacro(
|
||||||
[],
|
[],
|
||||||
eBindStatement(eBindings([("x", EvNumber(2.))]), exampleStatementX),
|
eBindStatement(eBindings([("x", IEvNumber(2.))]), exampleStatementX),
|
||||||
"Ok((:$_setBindings_$ {x: 2} :y 2) context: {x: 2})",
|
"Ok((:$_setBindings_$ @{x: 2} :y 2) context: @{x: 2})",
|
||||||
)
|
)
|
||||||
// An expression does not return a binding, thus error
|
// An expression does not return a binding, thus error
|
||||||
testMacro([], eBindStatement(eBindings([]), exampleExpression), "Assignment expected")
|
testMacro([], eBindStatement(eBindings([]), exampleExpression), "Assignment expected")
|
||||||
// When bindings from previous statement are missing the context is injected. This must be the first statement of a block
|
// When bindings from previous statement are missing the context is injected. This must be the first statement of a block
|
||||||
testMacro(
|
testMacro(
|
||||||
[("z", EvNumber(99.))],
|
[("z", IEvNumber(99.))],
|
||||||
eBindStatementDefault(exampleStatementY),
|
eBindStatementDefault(exampleStatementY),
|
||||||
"Ok((:$_setBindings_$ {z: 99} :y 1) context: {z: 99})",
|
"Ok((:$_setBindings_$ @{z: 99} :y 1) context: @{z: 99})",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -43,26 +43,26 @@ describe("bindExpression", () => {
|
||||||
// x is simply bound in the expression
|
// x is simply bound in the expression
|
||||||
testMacro(
|
testMacro(
|
||||||
[],
|
[],
|
||||||
eBindExpression(eBindings([("x", EvNumber(2.))]), eSymbol("x")),
|
eBindExpression(eBindings([("x", IEvNumber(2.))]), eSymbol("x")),
|
||||||
"Ok(2 context: {x: 2})",
|
"Ok(2 context: @{x: 2})",
|
||||||
)
|
)
|
||||||
// When an let statement is the end expression then bindings are returned
|
// When an let statement is the end expression then bindings are returned
|
||||||
testMacro(
|
testMacro(
|
||||||
[],
|
[],
|
||||||
eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY),
|
eBindExpression(eBindings([("x", IEvNumber(2.))]), exampleStatementY),
|
||||||
"Ok((:$_exportBindings_$ (:$_setBindings_$ {x: 2} :y 1)) context: {x: 2})",
|
"Ok((:$_exportBindings_$ (:$_setBindings_$ @{x: 2} :y 1)) context: @{x: 2})",
|
||||||
)
|
)
|
||||||
// Now let's reduce that expression
|
// Now let's reduce that expression
|
||||||
testMacroEval(
|
testMacroEval(
|
||||||
[],
|
[],
|
||||||
eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY),
|
eBindExpression(eBindings([("x", IEvNumber(2.))]), exampleStatementY),
|
||||||
"Ok({x: 2,y: 1})",
|
"Ok(@{x: 2,y: 1})",
|
||||||
)
|
)
|
||||||
// When bindings are missing the context is injected. This must be the first and last statement of a block
|
// When bindings are missing the context is injected. This must be the first and last statement of a block
|
||||||
testMacroEval(
|
testMacroEval(
|
||||||
[("z", EvNumber(99.))],
|
[("z", IEvNumber(99.))],
|
||||||
eBindExpressionDefault(exampleStatementY),
|
eBindExpressionDefault(exampleStatementY),
|
||||||
"Ok({y: 1,z: 99})",
|
"Ok(@{y: 1,z: 99})",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ describe("block", () => {
|
||||||
testMacroEval([], eBlock(list{exampleExpression}), "Ok(1)")
|
testMacroEval([], eBlock(list{exampleExpression}), "Ok(1)")
|
||||||
// Block with a single statement
|
// Block with a single statement
|
||||||
testMacro([], eBlock(list{exampleStatementY}), "Ok((:$$_bindExpression_$$ (:$_let_$ :y 1)))")
|
testMacro([], eBlock(list{exampleStatementY}), "Ok((:$$_bindExpression_$$ (:$_let_$ :y 1)))")
|
||||||
testMacroEval([], eBlock(list{exampleStatementY}), "Ok({y: 1})")
|
testMacroEval([], eBlock(list{exampleStatementY}), "Ok(@{y: 1})")
|
||||||
// Block with a statement and an expression
|
// Block with a statement and an expression
|
||||||
testMacro(
|
testMacro(
|
||||||
[],
|
[],
|
||||||
|
@ -86,7 +86,7 @@ describe("block", () => {
|
||||||
eBlock(list{exampleStatementY, exampleStatementZ}),
|
eBlock(list{exampleStatementY, exampleStatementZ}),
|
||||||
"Ok((:$$_bindExpression_$$ (:$$_bindStatement_$$ (:$_let_$ :y 1)) (:$_let_$ :z :y)))",
|
"Ok((:$$_bindExpression_$$ (:$$_bindStatement_$$ (:$_let_$ :y 1)) (:$_let_$ :z :y)))",
|
||||||
)
|
)
|
||||||
testMacroEval([], eBlock(list{exampleStatementY, exampleStatementZ}), "Ok({y: 1,z: 1})")
|
testMacroEval([], eBlock(list{exampleStatementY, exampleStatementZ}), "Ok(@{y: 1,z: 1})")
|
||||||
// Block inside a block
|
// Block inside a block
|
||||||
testMacro([], eBlock(list{eBlock(list{exampleExpression})}), "Ok((:$$_bindExpression_$$ {1}))")
|
testMacro([], eBlock(list{eBlock(list{exampleExpression})}), "Ok((:$$_bindExpression_$$ {1}))")
|
||||||
testMacroEval([], eBlock(list{eBlock(list{exampleExpression})}), "Ok(1)")
|
testMacroEval([], eBlock(list{eBlock(list{exampleExpression})}), "Ok(1)")
|
||||||
|
@ -99,7 +99,7 @@ describe("block", () => {
|
||||||
testMacroEval(
|
testMacroEval(
|
||||||
[],
|
[],
|
||||||
eBlock(list{eLetStatement("z", eBlock(list{eBlock(list{exampleExpressionY})}))}),
|
eBlock(list{eLetStatement("z", eBlock(list{eBlock(list{exampleExpressionY})}))}),
|
||||||
"Ok({z: :y})",
|
"Ok(@{z: :y})",
|
||||||
)
|
)
|
||||||
// Empty block
|
// Empty block
|
||||||
testMacro([], eBlock(list{}), "Ok(:undefined block)") //TODO: should be an error
|
testMacro([], eBlock(list{}), "Ok(:undefined block)") //TODO: should be an error
|
||||||
|
@ -115,7 +115,7 @@ describe("block", () => {
|
||||||
"Ok((:$$_bindExpression_$$ {(:$_let_$ :y (:add :x 1)); :y}))",
|
"Ok((:$$_bindExpression_$$ {(:$_let_$ :y (:add :x 1)); :y}))",
|
||||||
)
|
)
|
||||||
testMacroEval(
|
testMacroEval(
|
||||||
[("x", EvNumber(1.))],
|
[("x", IEvNumber(1.))],
|
||||||
eBlock(list{
|
eBlock(list{
|
||||||
eBlock(list{
|
eBlock(list{
|
||||||
eLetStatement("y", eFunction("add", list{eSymbol("x"), eNumber(1.)})),
|
eLetStatement("y", eFunction("add", list{eSymbol("x"), eNumber(1.)})),
|
||||||
|
@ -135,12 +135,12 @@ describe("lambda", () => {
|
||||||
testMacro([], callLambdaExpression, "Ok(((:$$_lambda_$$ [y] :y) 1))")
|
testMacro([], callLambdaExpression, "Ok(((:$$_lambda_$$ [y] :y) 1))")
|
||||||
testMacroEval([], callLambdaExpression, "Ok(1)")
|
testMacroEval([], callLambdaExpression, "Ok(1)")
|
||||||
// Parameters shadow the outer scope
|
// Parameters shadow the outer scope
|
||||||
testMacroEval([("y", EvNumber(666.))], callLambdaExpression, "Ok(1)")
|
testMacroEval([("y", IEvNumber(666.))], callLambdaExpression, "Ok(1)")
|
||||||
// When not shadowed by the parameters, the outer scope variables are available
|
// When not shadowed by the parameters, the outer scope variables are available
|
||||||
let lambdaExpression = eFunction(
|
let lambdaExpression = eFunction(
|
||||||
"$$_lambda_$$",
|
"$$_lambda_$$",
|
||||||
list{eArrayString(["z"]), eFunction("add", list{eSymbol("y"), eSymbol("z")})},
|
list{eArrayString(["z"]), eFunction("add", list{eSymbol("y"), eSymbol("z")})},
|
||||||
)
|
)
|
||||||
let callLambdaExpression = eList(list{lambdaExpression, eNumber(1.)})
|
let callLambdaExpression = eList(list{lambdaExpression, eNumber(1.)})
|
||||||
testMacroEval([("y", EvNumber(666.))], callLambdaExpression, "Ok(667)")
|
testMacroEval([("y", IEvNumber(666.))], callLambdaExpression, "Ok(667)")
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module ExpressionValue = ReducerInterface.ExternalExpressionValue
|
||||||
|
|
||||||
open Jest
|
open Jest
|
||||||
open Expect
|
open Expect
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
module ExpressionT = Reducer_Expression_T
|
// Reducer_Helpers
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
|
||||||
module ErrorValue = Reducer_ErrorValue
|
module ErrorValue = Reducer_ErrorValue
|
||||||
module Bindings = Reducer_Category_Bindings
|
module ExternalExpressionValue = ReducerInterface.ExternalExpressionValue
|
||||||
|
module InternalExpressionValue = ReducerInterface.InternalExpressionValue
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
|
|
||||||
let removeDefaults = (ev: ExpressionT.expressionValue): ExpressionT.expressionValue =>
|
let removeDefaultsInternal = (iev: InternalExpressionValue.t) => {
|
||||||
switch ev {
|
switch iev {
|
||||||
| EvRecord(extbindings) => {
|
| InternalExpressionValue.IEvModule(nameSpace) =>
|
||||||
let bindings: Bindings.t = Bindings.fromRecord(extbindings)
|
Module.removeOther(
|
||||||
let keys = Js.Dict.keys(Reducer.defaultExternalBindings)
|
nameSpace,
|
||||||
Belt.Map.String.keep(bindings, (key, _value) => {
|
ReducerInterface.StdLib.internalStdLib,
|
||||||
let removeThis = Js.Array2.includes(keys, key)
|
)->InternalExpressionValue.IEvModule
|
||||||
!removeThis
|
|
||||||
})->Bindings.toExpressionValue
|
|
||||||
}
|
|
||||||
| value => value
|
| value => value
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let rRemoveDefaults = r => Belt.Result.map(r, ev => removeDefaults(ev))
|
let removeDefaultsExternal = (ev: ExternalExpressionValue.t): ExternalExpressionValue.t =>
|
||||||
|
ev->InternalExpressionValue.toInternal->removeDefaultsInternal->InternalExpressionValue.toExternal
|
||||||
|
|
||||||
|
let rRemoveDefaultsInternal = r => Belt.Result.map(r, removeDefaultsInternal)
|
||||||
|
let rRemoveDefaultsExternal = r => Belt.Result.map(r, removeDefaultsExternal)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
open ReducerInterface.ExpressionValue
|
|
||||||
module MathJs = Reducer_MathJs
|
module MathJs = Reducer_MathJs
|
||||||
module ErrorValue = Reducer.ErrorValue
|
module ErrorValue = Reducer.ErrorValue
|
||||||
|
|
||||||
|
@ -6,14 +5,14 @@ open Jest
|
||||||
open ExpectJs
|
open ExpectJs
|
||||||
|
|
||||||
describe("eval", () => {
|
describe("eval", () => {
|
||||||
test("Number", () => expect(MathJs.Eval.eval("1"))->toEqual(Ok(EvNumber(1.))))
|
test("Number", () => expect(MathJs.Eval.eval("1"))->toEqual(Ok(IEvNumber(1.))))
|
||||||
test("Number expr", () => expect(MathJs.Eval.eval("1-1"))->toEqual(Ok(EvNumber(0.))))
|
test("Number expr", () => expect(MathJs.Eval.eval("1-1"))->toEqual(Ok(IEvNumber(0.))))
|
||||||
test("String", () => expect(MathJs.Eval.eval("'hello'"))->toEqual(Ok(EvString("hello"))))
|
test("String", () => expect(MathJs.Eval.eval("'hello'"))->toEqual(Ok(IEvString("hello"))))
|
||||||
test("String expr", () =>
|
test("String expr", () =>
|
||||||
expect(MathJs.Eval.eval("concat('hello ','world')"))->toEqual(Ok(EvString("hello world")))
|
expect(MathJs.Eval.eval("concat('hello ','world')"))->toEqual(Ok(IEvString("hello world")))
|
||||||
)
|
)
|
||||||
test("Boolean", () => expect(MathJs.Eval.eval("true"))->toEqual(Ok(EvBool(true))))
|
test("Boolean", () => expect(MathJs.Eval.eval("true"))->toEqual(Ok(IEvBool(true))))
|
||||||
test("Boolean expr", () => expect(MathJs.Eval.eval("2>1"))->toEqual(Ok(EvBool(true))))
|
test("Boolean expr", () => expect(MathJs.Eval.eval("2>1"))->toEqual(Ok(IEvBool(true))))
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("errors", () => {
|
describe("errors", () => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Expression = Reducer_Expression
|
module Expression = Reducer_Expression
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
module ExpressionValue = ReducerInterface.InternalExpressionValue
|
||||||
module Parse = Reducer_Peggy_Parse
|
module Parse = Reducer_Peggy_Parse
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
module ToExpression = Reducer_Peggy_ToExpression
|
module ToExpression = Reducer_Peggy_ToExpression
|
||||||
|
@ -29,7 +29,7 @@ let expectToExpressionToBe = (expr, answer, ~v="_", ()) => {
|
||||||
ExpressionValue.defaultEnvironment,
|
ExpressionValue.defaultEnvironment,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
->Reducer_Helpers.rRemoveDefaults
|
->Reducer_Helpers.rRemoveDefaultsInternal
|
||||||
->ExpressionValue.toStringResultOkless
|
->ExpressionValue.toStringResultOkless
|
||||||
(a1, a2)->expect->toEqual((answer, v))
|
(a1, a2)->expect->toEqual((answer, v))
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,11 @@ describe("Peggy to Expression", () => {
|
||||||
|
|
||||||
describe("multi-line", () => {
|
describe("multi-line", () => {
|
||||||
testToExpression("x=1; 2", "{(:$_let_$ :x {1}); 2}", ~v="2", ())
|
testToExpression("x=1; 2", "{(:$_let_$ :x {1}); 2}", ~v="2", ())
|
||||||
testToExpression("x=1; y=2", "{(:$_let_$ :x {1}); (:$_let_$ :y {2})}", ~v="{x: 1,y: 2}", ())
|
testToExpression("x=1; y=2", "{(:$_let_$ :x {1}); (:$_let_$ :y {2})}", ~v="@{x: 1,y: 2}", ())
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("variables", () => {
|
describe("variables", () => {
|
||||||
testToExpression("x = 1", "{(:$_let_$ :x {1})}", ~v="{x: 1}", ())
|
testToExpression("x = 1", "{(:$_let_$ :x {1})}", ~v="@{x: 1}", ())
|
||||||
testToExpression("x", "{:x}", ~v=":x", ()) //TODO: value should return error
|
testToExpression("x", "{:x}", ~v=":x", ()) //TODO: value should return error
|
||||||
testToExpression("x = 1; x", "{(:$_let_$ :x {1}); :x}", ~v="1", ())
|
testToExpression("x = 1; x", "{(:$_let_$ :x {1}); :x}", ~v="1", ())
|
||||||
})
|
})
|
||||||
|
@ -35,7 +35,7 @@ describe("Peggy to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"identity(x) = x",
|
"identity(x) = x",
|
||||||
"{(:$_let_$ :identity (:$$_lambda_$$ [x] {:x}))}",
|
"{(:$_let_$ :identity (:$$_lambda_$$ [x] {:x}))}",
|
||||||
~v="{identity: lambda(x=>internal code)}",
|
~v="@{identity: lambda(x=>internal code)}",
|
||||||
(),
|
(),
|
||||||
) // Function definitions become lambda assignments
|
) // Function definitions become lambda assignments
|
||||||
testToExpression("identity(x)", "{(:identity :x)}", ()) // Note value returns error properly
|
testToExpression("identity(x)", "{(:identity :x)}", ()) // Note value returns error properly
|
||||||
|
@ -155,7 +155,7 @@ describe("Peggy to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"y=99; x={y=1; y}",
|
"y=99; x={y=1; y}",
|
||||||
"{(:$_let_$ :y {99}); (:$_let_$ :x {(:$_let_$ :y {1}); :y})}",
|
"{(:$_let_$ :y {99}); (:$_let_$ :x {(:$_let_$ :y {1}); :y})}",
|
||||||
~v="{x: 1,y: 99}",
|
~v="@{x: 1,y: 99}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -165,19 +165,19 @@ describe("Peggy to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"f={|x| x}",
|
"f={|x| x}",
|
||||||
"{(:$_let_$ :f {(:$$_lambda_$$ [x] {:x})})}",
|
"{(:$_let_$ :f {(:$$_lambda_$$ [x] {:x})})}",
|
||||||
~v="{f: lambda(x=>internal code)}",
|
~v="@{f: lambda(x=>internal code)}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"f(x)=x",
|
"f(x)=x",
|
||||||
"{(:$_let_$ :f (:$$_lambda_$$ [x] {:x}))}",
|
"{(:$_let_$ :f (:$$_lambda_$$ [x] {:x}))}",
|
||||||
~v="{f: lambda(x=>internal code)}",
|
~v="@{f: lambda(x=>internal code)}",
|
||||||
(),
|
(),
|
||||||
) // Function definitions are lambda assignments
|
) // Function definitions are lambda assignments
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"f(x)=x ? 1 : 0",
|
"f(x)=x ? 1 : 0",
|
||||||
"{(:$_let_$ :f (:$$_lambda_$$ [x] {(:$$_ternary_$$ :x 1 0)}))}",
|
"{(:$_let_$ :f (:$$_lambda_$$ [x] {(:$$_ternary_$$ :x 1 0)}))}",
|
||||||
~v="{f: lambda(x=>internal code)}",
|
~v="@{f: lambda(x=>internal code)}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,7 +6,7 @@ describe("Peggy Types to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"p: number",
|
"p: number",
|
||||||
"{(:$_typeOf_$ :p #number)}",
|
"{(:$_typeOf_$ :p #number)}",
|
||||||
~v="{_typeReferences_: {p: #number}}",
|
~v="@{_typeReferences_: {p: #number}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -14,7 +14,7 @@ describe("Peggy Types to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"type index=number",
|
"type index=number",
|
||||||
"{(:$_typeAlias_$ #index #number)}",
|
"{(:$_typeAlias_$ #index #number)}",
|
||||||
~v="{_typeAliases_: {index: #number}}",
|
~v="@{_typeAliases_: {index: #number}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -22,7 +22,7 @@ describe("Peggy Types to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number|string|distribution",
|
"answer: number|string|distribution",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ (#number #string #distribution))))}",
|
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ (#number #string #distribution))))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeOr',typeOr: [#number,#string,#distribution]}}}",
|
~v="@{_typeReferences_: {answer: {typeOr: [#number,#string,#distribution],typeTag: 'typeOr'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -30,13 +30,13 @@ describe("Peggy Types to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"f: number=>number=>number",
|
"f: number=>number=>number",
|
||||||
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#number #number #number))))}",
|
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#number #number #number))))}",
|
||||||
~v="{_typeReferences_: {f: {typeTag: 'typeFunction',inputs: [#number,#number],output: #number}}}",
|
~v="@{_typeReferences_: {f: {inputs: [#number,#number],output: #number,typeTag: 'typeFunction'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"f: number=>number",
|
"f: number=>number",
|
||||||
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#number #number))))}",
|
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#number #number))))}",
|
||||||
~v="{_typeReferences_: {f: {typeTag: 'typeFunction',inputs: [#number],output: #number}}}",
|
~v="@{_typeReferences_: {f: {inputs: [#number],output: #number,typeTag: 'typeFunction'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -44,37 +44,37 @@ describe("Peggy Types to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number<-min(1)<-max(100)|string",
|
"answer: number<-min(1)<-max(100)|string",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ ((:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 100) #string))))}",
|
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ ((:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 100) #string))))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeOr',typeOr: [{typeTag: 'typeIdentifier',typeIdentifier: #number,min: 1,max: 100},#string]}}}",
|
~v="@{_typeReferences_: {answer: {typeOr: [{max: 100,min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'},#string],typeTag: 'typeOr'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number<-memberOf([1,3,5])",
|
"answer: number<-memberOf([1,3,5])",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeModifier_memberOf_$ #number (:$_constructArray_$ (1 3 5))))}",
|
"{(:$_typeOf_$ :answer (:$_typeModifier_memberOf_$ #number (:$_constructArray_$ (1 3 5))))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,memberOf: [1,3,5]}}}",
|
~v="@{_typeReferences_: {answer: {memberOf: [1,3,5],typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number<-min(1)",
|
"answer: number<-min(1)",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ #number 1))}",
|
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ #number 1))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,min: 1}}}",
|
~v="@{_typeReferences_: {answer: {min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number<-max(10)",
|
"answer: number<-max(10)",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ #number 10))}",
|
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ #number 10))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,max: 10}}}",
|
~v="@{_typeReferences_: {answer: {max: 10,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number<-min(1)<-max(10)",
|
"answer: number<-min(1)<-max(10)",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 10))}",
|
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 10))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,min: 1,max: 10}}}",
|
~v="@{_typeReferences_: {answer: {max: 10,min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number<-max(10)<-min(1)",
|
"answer: number<-max(10)<-min(1)",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ (:$_typeModifier_max_$ #number 10) 1))}",
|
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ (:$_typeModifier_max_$ #number 10) 1))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,max: 10,min: 1}}}",
|
~v="@{_typeReferences_: {answer: {max: 10,min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -82,7 +82,7 @@ describe("Peggy Types to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"answer: number | string $ opaque",
|
"answer: number | string $ opaque",
|
||||||
"{(:$_typeOf_$ :answer (:$_typeModifier_opaque_$ (:$_typeOr_$ (:$_constructArray_$ (#number #string)))))}",
|
"{(:$_typeOf_$ :answer (:$_typeModifier_opaque_$ (:$_typeOr_$ (:$_constructArray_$ (#number #string)))))}",
|
||||||
~v="{_typeReferences_: {answer: {typeTag: 'typeOr',typeOr: [#number,#string],opaque: true}}}",
|
~v="@{_typeReferences_: {answer: {opaque: true,typeOr: [#number,#string],typeTag: 'typeOr'}}}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -90,7 +90,7 @@ describe("Peggy Types to Expression", () => {
|
||||||
testToExpression(
|
testToExpression(
|
||||||
"odds1 = [1,3,5]; odds2 = [7, 9]; type odds = number<-memberOf(concat(odds1, odds2))",
|
"odds1 = [1,3,5]; odds2 = [7, 9]; type odds = number<-memberOf(concat(odds1, odds2))",
|
||||||
"{(:$_let_$ :odds1 {(:$_constructArray_$ (1 3 5))}); (:$_let_$ :odds2 {(:$_constructArray_$ (7 9))}); (:$_typeAlias_$ #odds (:$_typeModifier_memberOf_$ #number (:concat :odds1 :odds2)))}",
|
"{(:$_let_$ :odds1 {(:$_constructArray_$ (1 3 5))}); (:$_let_$ :odds2 {(:$_constructArray_$ (7 9))}); (:$_typeAlias_$ #odds (:$_typeModifier_memberOf_$ #number (:concat :odds1 :odds2)))}",
|
||||||
~v="{_typeAliases_: {odds: {typeTag: 'typeIdentifier',typeIdentifier: #number,memberOf: [1,3,5,7,9]}},odds1: [1,3,5],odds2: [7,9]}",
|
~v="@{_typeAliases_: {odds: {memberOf: [1,3,5,7,9],typeIdentifier: #number,typeTag: 'typeIdentifier'}},odds1: [1,3,5],odds2: [7,9]}",
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module ExternalExpressionValue = ReducerInterface.ExternalExpressionValue
|
||||||
module ErrorValue = Reducer_ErrorValue
|
module ErrorValue = Reducer_ErrorValue
|
||||||
module Bindings = Reducer_Category_Bindings
|
|
||||||
|
|
||||||
open Jest
|
open Jest
|
||||||
open Expect
|
open Expect
|
||||||
|
@ -9,7 +8,7 @@ open Expect
|
||||||
let unwrapRecord = rValue =>
|
let unwrapRecord = rValue =>
|
||||||
rValue->Belt.Result.flatMap(value =>
|
rValue->Belt.Result.flatMap(value =>
|
||||||
switch value {
|
switch value {
|
||||||
| ExpressionValue.EvRecord(aRecord) => Ok(aRecord)
|
| ExternalExpressionValue.EvRecord(aRecord) => Ok(aRecord)
|
||||||
| _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error
|
| _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -19,18 +18,18 @@ let expectParseToBe = (expr: string, answer: string) =>
|
||||||
|
|
||||||
let expectEvalToBe = (expr: string, answer: string) =>
|
let expectEvalToBe = (expr: string, answer: string) =>
|
||||||
Reducer.evaluate(expr)
|
Reducer.evaluate(expr)
|
||||||
->Reducer_Helpers.rRemoveDefaults
|
->Reducer_Helpers.rRemoveDefaultsExternal
|
||||||
->ExpressionValue.toStringResult
|
->ExternalExpressionValue.toStringResult
|
||||||
->expect
|
->expect
|
||||||
->toBe(answer)
|
->toBe(answer)
|
||||||
|
|
||||||
let expectEvalError = (expr: string) =>
|
let expectEvalError = (expr: string) =>
|
||||||
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toMatch("Error\(")
|
Reducer.evaluate(expr)->ExternalExpressionValue.toStringResult->expect->toMatch("Error\(")
|
||||||
|
|
||||||
let expectEvalBindingsToBe = (expr: string, bindings: Reducer.externalBindings, answer: string) =>
|
let expectEvalBindingsToBe = (expr: string, bindings: Reducer.externalBindings, answer: string) =>
|
||||||
Reducer.evaluateUsingOptions(expr, ~externalBindings=Some(bindings), ~environment=None)
|
Reducer.evaluateUsingOptions(expr, ~externalBindings=Some(bindings), ~environment=None)
|
||||||
->Reducer_Helpers.rRemoveDefaults
|
->Reducer_Helpers.rRemoveDefaultsExternal
|
||||||
->ExpressionValue.toStringResult
|
->ExternalExpressionValue.toStringResult
|
||||||
->expect
|
->expect
|
||||||
->toBe(answer)
|
->toBe(answer)
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,27 @@
|
||||||
open Jest
|
open Jest
|
||||||
open Expect
|
open Expect
|
||||||
|
|
||||||
module Bindings = Reducer_Expression_Bindings
|
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module Expression = Reducer_Expression
|
module Expression = Reducer_Expression
|
||||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
// module ExpressionValue = ReducerInterface.ExpressionValue
|
||||||
|
module InternalExpressionValue = ReducerInterface.InternalExpressionValue
|
||||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||||
module Macro = Reducer_Expression_Macro
|
module Macro = Reducer_Expression_Macro
|
||||||
module T = Reducer_Expression_T
|
module T = Reducer_Expression_T
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
|
|
||||||
let testMacro_ = (
|
let testMacro_ = (
|
||||||
tester,
|
tester,
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedCode: string,
|
expectedCode: string,
|
||||||
) => {
|
) => {
|
||||||
let bindings = Belt.Map.String.fromArray(bindArray)
|
let bindings = Module.fromArray(bindArray)
|
||||||
tester(expr->T.toString, () =>
|
tester(expr->T.toString, () =>
|
||||||
expr
|
expr
|
||||||
->Macro.expandMacroCall(
|
->Macro.expandMacroCall(
|
||||||
bindings,
|
bindings,
|
||||||
ExpressionValue.defaultEnvironment,
|
InternalExpressionValue.defaultEnvironment,
|
||||||
Expression.reduceExpression,
|
Expression.reduceExpression,
|
||||||
)
|
)
|
||||||
->ExpressionWithContext.toStringResult
|
->ExpressionWithContext.toStringResult
|
||||||
|
@ -30,39 +32,43 @@ let testMacro_ = (
|
||||||
|
|
||||||
let testMacroEval_ = (
|
let testMacroEval_ = (
|
||||||
tester,
|
tester,
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedValue: string,
|
expectedValue: string,
|
||||||
) => {
|
) => {
|
||||||
let bindings = Belt.Map.String.fromArray(bindArray)
|
let bindings = Module.fromArray(bindArray)
|
||||||
tester(expr->T.toString, () =>
|
tester(expr->T.toString, () =>
|
||||||
expr
|
expr
|
||||||
->Macro.doMacroCall(bindings, ExpressionValue.defaultEnvironment, Expression.reduceExpression)
|
->Macro.doMacroCall(
|
||||||
->ExpressionValue.toStringResult
|
bindings,
|
||||||
|
InternalExpressionValue.defaultEnvironment,
|
||||||
|
Expression.reduceExpression,
|
||||||
|
)
|
||||||
|
->InternalExpressionValue.toStringResult
|
||||||
->expect
|
->expect
|
||||||
->toEqual(expectedValue)
|
->toEqual(expectedValue)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let testMacro = (
|
let testMacro = (
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedExpr: string,
|
expectedExpr: string,
|
||||||
) => testMacro_(test, bindArray, expr, expectedExpr)
|
) => testMacro_(test, bindArray, expr, expectedExpr)
|
||||||
let testMacroEval = (
|
let testMacroEval = (
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedValue: string,
|
expectedValue: string,
|
||||||
) => testMacroEval_(test, bindArray, expr, expectedValue)
|
) => testMacroEval_(test, bindArray, expr, expectedValue)
|
||||||
|
|
||||||
module MySkip = {
|
module MySkip = {
|
||||||
let testMacro = (
|
let testMacro = (
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedExpr: string,
|
expectedExpr: string,
|
||||||
) => testMacro_(Skip.test, bindArray, expr, expectedExpr)
|
) => testMacro_(Skip.test, bindArray, expr, expectedExpr)
|
||||||
let testMacroEval = (
|
let testMacroEval = (
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedValue: string,
|
expectedValue: string,
|
||||||
) => testMacroEval_(Skip.test, bindArray, expr, expectedValue)
|
) => testMacroEval_(Skip.test, bindArray, expr, expectedValue)
|
||||||
|
@ -70,12 +76,12 @@ module MySkip = {
|
||||||
|
|
||||||
module MyOnly = {
|
module MyOnly = {
|
||||||
let testMacro = (
|
let testMacro = (
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedExpr: string,
|
expectedExpr: string,
|
||||||
) => testMacro_(Only.test, bindArray, expr, expectedExpr)
|
) => testMacro_(Only.test, bindArray, expr, expectedExpr)
|
||||||
let testMacroEval = (
|
let testMacroEval = (
|
||||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
bindArray: array<(string, InternalExpressionValue.t)>,
|
||||||
expr: T.expression,
|
expr: T.expression,
|
||||||
expectedValue: string,
|
expectedValue: string,
|
||||||
) => testMacroEval_(Only.test, bindArray, expr, expectedValue)
|
) => testMacroEval_(Only.test, bindArray, expr, expectedValue)
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
// TODO: Reimplement with usual parse
|
|
||||||
open Jest
|
open Jest
|
||||||
open Reducer_TestHelpers
|
open Reducer_TestHelpers
|
||||||
|
|
||||||
describe("Eval with Bindings", () => {
|
describe("Eval with Bindings", () => {
|
||||||
testEvalBindingsToBe("x", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(1)")
|
testEvalBindingsToBe("x", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(1)")
|
||||||
testEvalBindingsToBe("x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(2)")
|
testEvalBindingsToBe("x+1", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||||
testParseToBe("y = x+1; y", "Ok({(:$_let_$ :y {(:add :x 1)}); :y})")
|
testParseToBe("y = x+1; y", "Ok({(:$_let_$ :y {(:add :x 1)}); :y})")
|
||||||
testEvalBindingsToBe("y = x+1; y", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(2)")
|
testEvalBindingsToBe("y = x+1; y", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||||
testEvalBindingsToBe("y = x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok({x: 1,y: 2})")
|
testEvalBindingsToBe(
|
||||||
|
"y = x+1",
|
||||||
|
list{("x", ExternalExpressionValue.EvNumber(1.))},
|
||||||
|
"Ok(@{x: 1,y: 2})",
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -39,15 +39,15 @@ describe("symbol not defined", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("call and bindings", () => {
|
describe("call and bindings", () => {
|
||||||
testEvalToBe("f(x)=x+1", "Ok({f: lambda(x=>internal code)})")
|
testEvalToBe("f(x)=x+1", "Ok(@{f: lambda(x=>internal code)})")
|
||||||
testEvalToBe("f(x)=x+1; f(1)", "Ok(2)")
|
testEvalToBe("f(x)=x+1; f(1)", "Ok(2)")
|
||||||
testEvalToBe("f=1;y=2", "Ok({f: 1,y: 2})")
|
testEvalToBe("f=1;y=2", "Ok(@{f: 1,y: 2})")
|
||||||
testEvalToBe("f(x)=x+1; y=f(1)", "Ok({f: lambda(x=>internal code),y: 2})")
|
testEvalToBe("f(x)=x+1; y=f(1)", "Ok(@{f: lambda(x=>internal code),y: 2})")
|
||||||
testEvalToBe("f(x)=x+1; y=f(1); f(1)", "Ok(2)")
|
testEvalToBe("f(x)=x+1; y=f(1); f(1)", "Ok(2)")
|
||||||
testEvalToBe("f(x)=x+1; y=f(1); z=f(1)", "Ok({f: lambda(x=>internal code),y: 2,z: 2})")
|
testEvalToBe("f(x)=x+1; y=f(1); z=f(1)", "Ok(@{f: lambda(x=>internal code),y: 2,z: 2})")
|
||||||
testEvalToBe(
|
testEvalToBe(
|
||||||
"f(x)=x+1; g(x)=f(x)+1",
|
"f(x)=x+1; g(x)=f(x)+1",
|
||||||
"Ok({f: lambda(x=>internal code),g: lambda(x=>internal code)})",
|
"Ok(@{f: lambda(x=>internal code),g: lambda(x=>internal code)})",
|
||||||
)
|
)
|
||||||
testParseToBe(
|
testParseToBe(
|
||||||
"f=99; g(x)=f; g(2)",
|
"f=99; g(x)=f; g(2)",
|
||||||
|
@ -57,7 +57,7 @@ describe("call and bindings", () => {
|
||||||
testEvalToBe("f(x)=x; g(x)=f(x); g(2)", "Ok(2)")
|
testEvalToBe("f(x)=x; g(x)=f(x); g(2)", "Ok(2)")
|
||||||
testEvalToBe(
|
testEvalToBe(
|
||||||
"f(x)=x+1; g(x)=f(x)+1; y=g(2)",
|
"f(x)=x+1; g(x)=f(x)+1; y=g(2)",
|
||||||
"Ok({f: lambda(x=>internal code),g: lambda(x=>internal code),y: 4})",
|
"Ok(@{f: lambda(x=>internal code),g: lambda(x=>internal code),y: 4})",
|
||||||
)
|
)
|
||||||
testEvalToBe("f(x)=x+1; g(x)=f(x)+1; g(2)", "Ok(4)")
|
testEvalToBe("f(x)=x+1; g(x)=f(x)+1; g(2)", "Ok(4)")
|
||||||
})
|
})
|
||||||
|
@ -65,7 +65,7 @@ describe("call and bindings", () => {
|
||||||
describe("function tricks", () => {
|
describe("function tricks", () => {
|
||||||
testEvalError("f(x)=f(y)=2; f(2)") //Error because chain assignment is not allowed
|
testEvalError("f(x)=f(y)=2; f(2)") //Error because chain assignment is not allowed
|
||||||
testEvalToBe("y=2;g(x)=y+1;g(2)", "Ok(3)")
|
testEvalToBe("y=2;g(x)=y+1;g(2)", "Ok(3)")
|
||||||
testEvalToBe("y=2;g(x)=inspect(y)+1", "Ok({g: lambda(x=>internal code),y: 2})")
|
testEvalToBe("y=2;g(x)=inspect(y)+1", "Ok(@{g: lambda(x=>internal code),y: 2})")
|
||||||
MySkip.testEvalToBe("f(x) = x(x); f(f)", "????") // TODO: Infinite loop. Any solution? Catching proper exception or timeout?
|
MySkip.testEvalToBe("f(x) = x(x); f(f)", "????") // TODO: Infinite loop. Any solution? Catching proper exception or timeout?
|
||||||
MySkip.testEvalToBe("f(x, x)=x+x; f(1,2)", "????") // TODO: Duplicate parameters
|
MySkip.testEvalToBe("f(x, x)=x+x; f(1,2)", "????") // TODO: Duplicate parameters
|
||||||
testEvalToBe("myadd(x,y)=x+y; z=myadd; z", "Ok(lambda(x,y=>internal code))")
|
testEvalToBe("myadd(x,y)=x+y; z=myadd; z", "Ok(lambda(x,y=>internal code))")
|
||||||
|
@ -75,7 +75,7 @@ describe("function tricks", () => {
|
||||||
describe("lambda in structures", () => {
|
describe("lambda in structures", () => {
|
||||||
testEvalToBe(
|
testEvalToBe(
|
||||||
"myadd(x,y)=x+y; z=[myadd]",
|
"myadd(x,y)=x+y; z=[myadd]",
|
||||||
"Ok({myadd: lambda(x,y=>internal code),z: [lambda(x,y=>internal code)]})",
|
"Ok(@{myadd: lambda(x,y=>internal code),z: [lambda(x,y=>internal code)]})",
|
||||||
)
|
)
|
||||||
testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0]", "Ok(lambda(x,y=>internal code))")
|
testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0]", "Ok(lambda(x,y=>internal code))")
|
||||||
testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0](3,2)", "Ok(5)")
|
testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0](3,2)", "Ok(5)")
|
||||||
|
|
|
@ -39,7 +39,7 @@ describe("eval", () => {
|
||||||
testEvalToBe("x=1; y=x+1; y+1", "Ok(3)")
|
testEvalToBe("x=1; y=x+1; y+1", "Ok(3)")
|
||||||
testEvalError("1; x=1")
|
testEvalError("1; x=1")
|
||||||
testEvalError("1; 1")
|
testEvalError("1; 1")
|
||||||
testEvalToBe("x=1; x=1", "Ok({x: 1})")
|
testEvalToBe("x=1; x=1", "Ok(@{x: 1})")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
open ReducerInterface.ExpressionValue
|
open ReducerInterface.ExternalExpressionValue
|
||||||
open Jest
|
open Jest
|
||||||
open Expect
|
open Expect
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"peggy": "peggy --cache",
|
"peggy": "peggy --cache",
|
||||||
|
"rescript": "rescript",
|
||||||
"build": "yarn build:peggy && yarn build:rescript && yarn build:typescript",
|
"build": "yarn build:peggy && yarn build:rescript && yarn build:typescript",
|
||||||
"build:peggy": "find . -type f -name *.peggy -exec yarn peggy {} \\;",
|
"build:peggy:helpers": "tsc --module commonjs --outDir src/rescript/Reducer/Reducer_Peggy/ src/rescript/Reducer/Reducer_Peggy/helpers.ts",
|
||||||
|
"build:peggy": "yarn build:peggy:helpers && find . -type f -name *.peggy -exec yarn peggy {} \\;",
|
||||||
"build:rescript": "rescript build -with-deps",
|
"build:rescript": "rescript build -with-deps",
|
||||||
"build:typescript": "tsc",
|
"build:typescript": "tsc",
|
||||||
"bundle": "webpack",
|
"bundle": "webpack",
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
evaluatePartialUsingExternalBindings,
|
evaluatePartialUsingExternalBindings,
|
||||||
evaluateUsingOptions,
|
evaluateUsingOptions,
|
||||||
foreignFunctionInterface,
|
foreignFunctionInterface,
|
||||||
parse as parseRescript,
|
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
export {
|
export {
|
||||||
makeSampleSetDist,
|
makeSampleSetDist,
|
||||||
|
@ -32,12 +31,14 @@ import {
|
||||||
convertRawToTypescript,
|
convertRawToTypescript,
|
||||||
lambdaValue,
|
lambdaValue,
|
||||||
} from "./rescript_interop";
|
} from "./rescript_interop";
|
||||||
import { Ok, result, resultMap, tag, tagged } from "./types";
|
import { result, resultMap, tag, tagged } from "./types";
|
||||||
import { Distribution, shape } from "./distribution";
|
import { Distribution, shape } from "./distribution";
|
||||||
|
|
||||||
export { Distribution, resultMap, defaultEnvironment };
|
export { Distribution, resultMap, defaultEnvironment };
|
||||||
export type { result, shape, environment, lambdaValue, squiggleExpression };
|
export type { result, shape, environment, lambdaValue, squiggleExpression };
|
||||||
|
|
||||||
|
export { parse } from "./parse";
|
||||||
|
|
||||||
export let defaultSamplingInputs: environment = {
|
export let defaultSamplingInputs: environment = {
|
||||||
sampleCount: 10000,
|
sampleCount: 10000,
|
||||||
xyPointLength: 10000,
|
xyPointLength: 10000,
|
||||||
|
@ -59,23 +60,6 @@ export function run(
|
||||||
return resultMap(res, (x) => createTsExport(x, e));
|
return resultMap(res, (x) => createTsExport(x, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parse(
|
|
||||||
squiggleString: string
|
|
||||||
): result<null, Extract<errorValue, { tag: "RESyntaxError" }>> {
|
|
||||||
const maybeExpression = parseRescript(squiggleString);
|
|
||||||
if (maybeExpression.tag === "Ok") {
|
|
||||||
return Ok(null); // TODO - return AST
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
typeof maybeExpression.value !== "object" ||
|
|
||||||
maybeExpression.value.tag !== "RESyntaxError"
|
|
||||||
) {
|
|
||||||
throw new Error("Expected syntax error");
|
|
||||||
}
|
|
||||||
return { tag: "Error", value: maybeExpression.value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run Partial. A partial is a block of code that doesn't return a value
|
// Run Partial. A partial is a block of code that doesn't return a value
|
||||||
export function runPartial(
|
export function runPartial(
|
||||||
squiggleString: string,
|
squiggleString: string,
|
||||||
|
@ -147,30 +131,13 @@ function createTsExport(
|
||||||
// case
|
// case
|
||||||
return tag(
|
return tag(
|
||||||
"array",
|
"array",
|
||||||
x.value.map((arrayItem): squiggleExpression => {
|
x.value.map(
|
||||||
switch (arrayItem.tag) {
|
(arrayItem): squiggleExpression =>
|
||||||
case "EvRecord":
|
convertRawToTypescript(
|
||||||
return tag(
|
arrayItem as unknown as rescriptExport,
|
||||||
"record",
|
environment
|
||||||
_.mapValues(arrayItem.value, (recordValue: unknown) =>
|
)
|
||||||
convertRawToTypescript(
|
)
|
||||||
recordValue as rescriptExport,
|
|
||||||
environment
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
case "EvArray":
|
|
||||||
let y = arrayItem.value as unknown as rescriptExport[];
|
|
||||||
return tag(
|
|
||||||
"array",
|
|
||||||
y.map((childArrayItem) =>
|
|
||||||
convertRawToTypescript(childArrayItem, environment)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return createTsExport(arrayItem, environment);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
case "EvArrayString":
|
case "EvArrayString":
|
||||||
return tag("arraystring", x.value);
|
return tag("arraystring", x.value);
|
||||||
|
|
23
packages/squiggle-lang/src/js/parse.ts
Normal file
23
packages/squiggle-lang/src/js/parse.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import {
|
||||||
|
errorValue,
|
||||||
|
parse as parseRescript,
|
||||||
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
|
import { result } from "./types";
|
||||||
|
import { AnyPeggyNode } from "../rescript/Reducer/Reducer_Peggy/helpers";
|
||||||
|
|
||||||
|
export function parse(
|
||||||
|
squiggleString: string
|
||||||
|
): result<AnyPeggyNode, Extract<errorValue, { tag: "RESyntaxError" }>> {
|
||||||
|
const maybeExpression = parseRescript(squiggleString);
|
||||||
|
if (maybeExpression.tag === "Ok") {
|
||||||
|
return { tag: "Ok", value: maybeExpression.value as AnyPeggyNode };
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
typeof maybeExpression.value !== "object" ||
|
||||||
|
maybeExpression.value.tag !== "RESyntaxError"
|
||||||
|
) {
|
||||||
|
throw new Error("Expected syntax error");
|
||||||
|
}
|
||||||
|
return { tag: "Error", value: maybeExpression.value };
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
@@warning("-27") //TODO: Remove and fix the warning
|
||||||
open Distributions
|
open Distributions
|
||||||
|
|
||||||
type t = PointSetTypes.discreteShape
|
type t = PointSetTypes.discreteShape
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@@warning("-27") //TODO: Remove and fix the warning
|
||||||
|
@@warning("-32") //TODO: Remove and fix the warning
|
||||||
open Distributions
|
open Distributions
|
||||||
|
|
||||||
type t = PointSetTypes.mixedShape
|
type t = PointSetTypes.mixedShape
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type internalExpressionValue = ReducerInterface_InternalExpressionValue.t
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function Registry "Type". A type, without any other information.
|
Function Registry "Type". A type, without any other information.
|
||||||
|
@ -28,7 +28,7 @@ type rec frValue =
|
||||||
| FRValueArray(array<frValue>)
|
| FRValueArray(array<frValue>)
|
||||||
| FRValueDistOrNumber(frValueDistOrNumber)
|
| FRValueDistOrNumber(frValueDistOrNumber)
|
||||||
| FRValueRecord(frValueRecord)
|
| FRValueRecord(frValueRecord)
|
||||||
| FRValueLambda(ReducerInterface_ExpressionValue.lambdaValue)
|
| FRValueLambda(ReducerInterface_InternalExpressionValue.lambdaValue)
|
||||||
| FRValueString(string)
|
| FRValueString(string)
|
||||||
| FRValueVariant(string)
|
| FRValueVariant(string)
|
||||||
| FRValueAny(frValue)
|
| FRValueAny(frValue)
|
||||||
|
@ -41,7 +41,7 @@ and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.g
|
||||||
type fnDefinition = {
|
type fnDefinition = {
|
||||||
name: string,
|
name: string,
|
||||||
inputs: array<frType>,
|
inputs: array<frType>,
|
||||||
run: (array<frValue>, DistributionOperation.env) => result<expressionValue, string>,
|
run: (array<frValue>, DistributionOperation.env) => result<internalExpressionValue, string>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type function = {
|
type function = {
|
||||||
|
@ -73,47 +73,47 @@ module FRType = {
|
||||||
| FRTypeAny => `any`
|
| FRTypeAny => `any`
|
||||||
}
|
}
|
||||||
|
|
||||||
let rec toFrValue = (r: expressionValue): option<frValue> =>
|
let rec toFrValue = (r: internalExpressionValue): option<frValue> =>
|
||||||
switch r {
|
switch r {
|
||||||
| EvNumber(f) => Some(FRValueNumber(f))
|
| IEvNumber(f) => Some(FRValueNumber(f))
|
||||||
| EvString(f) => Some(FRValueString(f))
|
| IEvString(f) => Some(FRValueString(f))
|
||||||
| EvDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
| IEvDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||||
| EvLambda(f) => Some(FRValueLambda(f))
|
| IEvLambda(f) => Some(FRValueLambda(f))
|
||||||
| EvArray(elements) =>
|
| IEvArray(elements) =>
|
||||||
elements->E.A2.fmap(toFrValue)->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueArray(r))
|
elements->E.A2.fmap(toFrValue)->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueArray(r))
|
||||||
| EvRecord(record) =>
|
| IEvRecord(map) =>
|
||||||
Js.Dict.entries(record)
|
Belt.Map.String.toArray(map)
|
||||||
->E.A2.fmap(((key, item)) => item->toFrValue->E.O2.fmap(o => (key, o)))
|
->E.A2.fmap(((key, item)) => item->toFrValue->E.O2.fmap(o => (key, o)))
|
||||||
->E.A.O.openIfAllSome
|
->E.A.O.openIfAllSome
|
||||||
->E.O2.fmap(r => FRValueRecord(r))
|
->E.O2.fmap(r => FRValueRecord(r))
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
let rec matchWithExpressionValue = (t: t, r: expressionValue): option<frValue> =>
|
let rec matchWithExpressionValue = (t: t, r: internalExpressionValue): option<frValue> =>
|
||||||
switch (t, r) {
|
switch (t, r) {
|
||||||
| (FRTypeAny, f) => toFrValue(f)
|
| (FRTypeAny, f) => toFrValue(f)
|
||||||
| (FRTypeString, EvString(f)) => Some(FRValueString(f))
|
| (FRTypeString, IEvString(f)) => Some(FRValueString(f))
|
||||||
| (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f))
|
| (FRTypeNumber, IEvNumber(f)) => Some(FRValueNumber(f))
|
||||||
| (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f)))
|
| (FRTypeDistOrNumber, IEvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f)))
|
||||||
| (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) =>
|
| (FRTypeDistOrNumber, IEvDistribution(Symbolic(#Float(f)))) =>
|
||||||
Some(FRValueDistOrNumber(FRValueNumber(f)))
|
Some(FRValueDistOrNumber(FRValueNumber(f)))
|
||||||
| (FRTypeDistOrNumber, EvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
| (FRTypeDistOrNumber, IEvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||||
| (FRTypeNumeric, EvNumber(f)) => Some(FRValueNumber(f))
|
| (FRTypeNumeric, IEvNumber(f)) => Some(FRValueNumber(f))
|
||||||
| (FRTypeNumeric, EvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
|
| (FRTypeNumeric, IEvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
|
||||||
| (FRTypeLambda, EvLambda(f)) => Some(FRValueLambda(f))
|
| (FRTypeLambda, IEvLambda(f)) => Some(FRValueLambda(f))
|
||||||
| (FRTypeArray(intendedType), EvArray(elements)) => {
|
| (FRTypeArray(intendedType), IEvArray(elements)) => {
|
||||||
let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType))
|
let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType))
|
||||||
E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r))
|
E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r))
|
||||||
}
|
}
|
||||||
| (FRTypeDict(r), EvRecord(record)) =>
|
| (FRTypeDict(r), IEvRecord(map)) =>
|
||||||
record
|
map
|
||||||
->Js.Dict.entries
|
->Belt.Map.String.toArray
|
||||||
->E.A2.fmap(((key, item)) => matchWithExpressionValue(r, item)->E.O2.fmap(o => (key, o)))
|
->E.A2.fmap(((key, item)) => matchWithExpressionValue(r, item)->E.O2.fmap(o => (key, o)))
|
||||||
->E.A.O.openIfAllSome
|
->E.A.O.openIfAllSome
|
||||||
->E.O2.fmap(r => FRValueDict(Js.Dict.fromArray(r)))
|
->E.O2.fmap(r => FRValueDict(Js.Dict.fromArray(r)))
|
||||||
| (FRTypeRecord(recordParams), EvRecord(record)) => {
|
| (FRTypeRecord(recordParams), IEvRecord(map)) => {
|
||||||
let getAndMatch = (name, input) =>
|
let getAndMatch = (name, input) =>
|
||||||
E.Dict.get(record, name)->E.O.bind(matchWithExpressionValue(input))
|
Belt.Map.String.get(map, name)->E.O.bind(matchWithExpressionValue(input))
|
||||||
//All names in the type must be present. If any are missing, the corresponding
|
//All names in the type must be present. If any are missing, the corresponding
|
||||||
//value will be None, and this function would return None.
|
//value will be None, and this function would return None.
|
||||||
let namesAndValues: array<option<(Js.Dict.key, frValue)>> =
|
let namesAndValues: array<option<(Js.Dict.key, frValue)>> =
|
||||||
|
@ -125,35 +125,38 @@ module FRType = {
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
let rec matchReverse = (e: frValue): expressionValue =>
|
let rec matchReverse = (e: frValue): internalExpressionValue =>
|
||||||
switch e {
|
switch e {
|
||||||
| FRValueNumber(f) => EvNumber(f)
|
| FRValueNumber(f) => IEvNumber(f)
|
||||||
| FRValueDistOrNumber(FRValueNumber(n)) => EvNumber(n)
|
| FRValueDistOrNumber(FRValueNumber(n)) => IEvNumber(n)
|
||||||
| FRValueDistOrNumber(FRValueDist(n)) => EvDistribution(n)
|
| FRValueDistOrNumber(FRValueDist(n)) => IEvDistribution(n)
|
||||||
| FRValueDist(dist) => EvDistribution(dist)
|
| FRValueDist(dist) => IEvDistribution(dist)
|
||||||
| FRValueArray(elements) => EvArray(elements->E.A2.fmap(matchReverse))
|
| FRValueArray(elements) => IEvArray(elements->E.A2.fmap(matchReverse))
|
||||||
| FRValueRecord(frValueRecord) => {
|
| FRValueRecord(frValueRecord) => {
|
||||||
let record =
|
let map =
|
||||||
frValueRecord->E.A2.fmap(((name, value)) => (name, matchReverse(value)))->E.Dict.fromArray
|
frValueRecord
|
||||||
EvRecord(record)
|
->E.A2.fmap(((name, value)) => (name, matchReverse(value)))
|
||||||
|
->Belt.Map.String.fromArray
|
||||||
|
IEvRecord(map)
|
||||||
}
|
}
|
||||||
| FRValueDict(frValueRecord) => {
|
| FRValueDict(frValueRecord) => {
|
||||||
let record =
|
let map =
|
||||||
frValueRecord
|
frValueRecord
|
||||||
->Js.Dict.entries
|
->Js.Dict.entries
|
||||||
->E.A2.fmap(((name, value)) => (name, matchReverse(value)))
|
->E.A2.fmap(((name, value)) => (name, matchReverse(value)))
|
||||||
->E.Dict.fromArray
|
->Belt.Map.String.fromArray
|
||||||
EvRecord(record)
|
IEvRecord(map)
|
||||||
}
|
}
|
||||||
| FRValueLambda(l) => EvLambda(l)
|
| FRValueLambda(l) => IEvLambda(l)
|
||||||
| FRValueString(string) => EvString(string)
|
| FRValueString(string) => IEvString(string)
|
||||||
| FRValueVariant(string) => EvString(string)
|
| FRValueVariant(string) => IEvString(string)
|
||||||
| FRValueAny(f) => matchReverse(f)
|
| FRValueAny(f) => matchReverse(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
let matchWithExpressionValueArray = (inputs: array<t>, args: array<expressionValue>): option<
|
let matchWithExpressionValueArray = (
|
||||||
array<frValue>,
|
inputs: array<t>,
|
||||||
> => {
|
args: array<internalExpressionValue>,
|
||||||
|
): option<array<frValue>> => {
|
||||||
let isSameLength = E.A.length(inputs) == E.A.length(args)
|
let isSameLength = E.A.length(inputs) == E.A.length(args)
|
||||||
if !isSameLength {
|
if !isSameLength {
|
||||||
None
|
None
|
||||||
|
@ -204,14 +207,14 @@ module Matcher = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module FnDefinition = {
|
module FnDefinition = {
|
||||||
let matchAssumingSameName = (f: fnDefinition, args: array<expressionValue>) => {
|
let matchAssumingSameName = (f: fnDefinition, args: array<internalExpressionValue>) => {
|
||||||
switch FRType.matchWithExpressionValueArray(f.inputs, args) {
|
switch FRType.matchWithExpressionValueArray(f.inputs, args) {
|
||||||
| Some(_) => MatchSimple.FullMatch
|
| Some(_) => MatchSimple.FullMatch
|
||||||
| None => MatchSimple.SameNameDifferentArguments
|
| None => MatchSimple.SameNameDifferentArguments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let match = (f: fnDefinition, fnName: string, args: array<expressionValue>) => {
|
let match = (f: fnDefinition, fnName: string, args: array<internalExpressionValue>) => {
|
||||||
if f.name !== fnName {
|
if f.name !== fnName {
|
||||||
MatchSimple.DifferentName
|
MatchSimple.DifferentName
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,7 +227,7 @@ module Matcher = {
|
||||||
type definitionId = int
|
type definitionId = int
|
||||||
type match = Match.t<array<definitionId>, definitionId>
|
type match = Match.t<array<definitionId>, definitionId>
|
||||||
|
|
||||||
let match = (f: function, fnName: string, args: array<expressionValue>): match => {
|
let match = (f: function, fnName: string, args: array<internalExpressionValue>): match => {
|
||||||
let matchedDefinition = () =>
|
let matchedDefinition = () =>
|
||||||
E.A.getIndexBy(f.definitions, r =>
|
E.A.getIndexBy(f.definitions, r =>
|
||||||
MatchSimple.isFullMatch(FnDefinition.match(r, fnName, args))
|
MatchSimple.isFullMatch(FnDefinition.match(r, fnName, args))
|
||||||
|
@ -258,7 +261,7 @@ module Matcher = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module Registry = {
|
module Registry = {
|
||||||
let _findExactMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
let _findExactMatches = (r: registry, fnName: string, args: array<internalExpressionValue>) => {
|
||||||
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
||||||
let fullMatch = functionMatchPairs->E.A.getBy(((_, match)) => Match.isFullMatch(match))
|
let fullMatch = functionMatchPairs->E.A.getBy(((_, match)) => Match.isFullMatch(match))
|
||||||
fullMatch->E.O.bind(((fn, match)) =>
|
fullMatch->E.O.bind(((fn, match)) =>
|
||||||
|
@ -269,7 +272,7 @@ module Matcher = {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let _findNameMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
let _findNameMatches = (r: registry, fnName: string, args: array<internalExpressionValue>) => {
|
||||||
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
||||||
let getNameMatches =
|
let getNameMatches =
|
||||||
functionMatchPairs
|
functionMatchPairs
|
||||||
|
@ -288,7 +291,7 @@ module Matcher = {
|
||||||
E.A.toNoneIfEmpty(matches)
|
E.A.toNoneIfEmpty(matches)
|
||||||
}
|
}
|
||||||
|
|
||||||
let findMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
let findMatches = (r: registry, fnName: string, args: array<internalExpressionValue>) => {
|
||||||
switch _findExactMatches(r, fnName, args) {
|
switch _findExactMatches(r, fnName, args) {
|
||||||
| Some(r) => Match.FullMatch(r)
|
| Some(r) => Match.FullMatch(r)
|
||||||
| None =>
|
| None =>
|
||||||
|
@ -316,7 +319,7 @@ module FnDefinition = {
|
||||||
t.name ++ `(${inputs})`
|
t.name ++ `(${inputs})`
|
||||||
}
|
}
|
||||||
|
|
||||||
let run = (t: t, args: array<expressionValue>, env: DistributionOperation.env) => {
|
let run = (t: t, args: array<internalExpressionValue>, env: DistributionOperation.env) => {
|
||||||
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
|
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
|
||||||
switch argValues {
|
switch argValues {
|
||||||
| Some(values) => t.run(values, env)
|
| Some(values) => t.run(values, env)
|
||||||
|
@ -370,7 +373,7 @@ module Registry = {
|
||||||
let matchAndRun = (
|
let matchAndRun = (
|
||||||
~registry: registry,
|
~registry: registry,
|
||||||
~fnName: string,
|
~fnName: string,
|
||||||
~args: array<expressionValue>,
|
~args: array<internalExpressionValue>,
|
||||||
~env: DistributionOperation.env,
|
~env: DistributionOperation.env,
|
||||||
) => {
|
) => {
|
||||||
let matchToDef = m => Matcher.Registry.matchToDef(registry, m)
|
let matchToDef = m => Matcher.Registry.matchToDef(registry, m)
|
||||||
|
|
|
@ -4,11 +4,11 @@ let impossibleError = "Wrong inputs / Logically impossible"
|
||||||
|
|
||||||
module Wrappers = {
|
module Wrappers = {
|
||||||
let symbolic = r => DistributionTypes.Symbolic(r)
|
let symbolic = r => DistributionTypes.Symbolic(r)
|
||||||
let evDistribution = r => ReducerInterface_ExpressionValue.EvDistribution(r)
|
let evDistribution = r => ReducerInterface_InternalExpressionValue.IEvDistribution(r)
|
||||||
let evNumber = r => ReducerInterface_ExpressionValue.EvNumber(r)
|
let evNumber = r => ReducerInterface_InternalExpressionValue.IEvNumber(r)
|
||||||
let evArray = r => ReducerInterface_ExpressionValue.EvArray(r)
|
let evArray = r => ReducerInterface_InternalExpressionValue.IEvArray(r)
|
||||||
let evRecord = r => ReducerInterface_ExpressionValue.EvRecord(r)
|
let evRecord = r => ReducerInterface_InternalExpressionValue.IEvRecord(r)
|
||||||
let evString = r => ReducerInterface_ExpressionValue.EvString(r)
|
let evString = r => ReducerInterface_InternalExpressionValue.IEvString(r)
|
||||||
let symbolicEvDistribution = r => r->DistributionTypes.Symbolic->evDistribution
|
let symbolicEvDistribution = r => r->DistributionTypes.Symbolic->evDistribution
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ module Declaration = {
|
||||||
("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))),
|
("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))),
|
||||||
])
|
])
|
||||||
|
|
||||||
let fromExpressionValue = (e: frValue): result<expressionValue, string> => {
|
let fromExpressionValue = (e: frValue): result<internalExpressionValue, string> => {
|
||||||
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e]) {
|
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e]) {
|
||||||
| Ok([FRValueLambda(lambda), FRValueArray(inputs)]) => {
|
| Ok([FRValueLambda(lambda), FRValueArray(inputs)]) => {
|
||||||
open FunctionRegistry_Helpers.Prepare
|
open FunctionRegistry_Helpers.Prepare
|
||||||
|
@ -20,7 +20,7 @@ module Declaration = {
|
||||||
inputs
|
inputs
|
||||||
->E.A2.fmap(getMinMax)
|
->E.A2.fmap(getMinMax)
|
||||||
->E.A.R.firstErrorOrOpen
|
->E.A.R.firstErrorOrOpen
|
||||||
->E.R2.fmap(args => ReducerInterface_ExpressionValue.EvDeclaration(
|
->E.R2.fmap(args => ReducerInterface_InternalExpressionValue.IEvDeclaration(
|
||||||
Declaration.make(lambda, args),
|
Declaration.make(lambda, args),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,9 @@ let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => {
|
||||||
let expressionValue =
|
let expressionValue =
|
||||||
xyCoords
|
xyCoords
|
||||||
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
|
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
|
||||||
->E.R2.fmap(r => ReducerInterface_ExpressionValue.EvDistribution(PointSet(makeDist(r))))
|
->E.R2.fmap(r => ReducerInterface_InternalExpressionValue.IEvDistribution(
|
||||||
|
PointSet(makeDist(r)),
|
||||||
|
))
|
||||||
expressionValue
|
expressionValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +371,7 @@ to(5,10)
|
||||||
E.Dict.concat(d1, d2) |> Js.Dict.map((. r) =>
|
E.Dict.concat(d1, d2) |> Js.Dict.map((. r) =>
|
||||||
FunctionRegistry_Core.FRType.matchReverse(r)
|
FunctionRegistry_Core.FRType.matchReverse(r)
|
||||||
)
|
)
|
||||||
newDict->Wrappers.evRecord->Ok
|
newDict->Js.Dict.entries->Belt.Map.String.fromArray->Wrappers.evRecord->Ok
|
||||||
}
|
}
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
}
|
}
|
||||||
|
@ -390,6 +392,7 @@ to(5,10)
|
||||||
->Prepare.ToTypedArray.dicts
|
->Prepare.ToTypedArray.dicts
|
||||||
->E.R2.fmap(E.Dict.concatMany)
|
->E.R2.fmap(E.Dict.concatMany)
|
||||||
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r)))
|
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r)))
|
||||||
|
->E.R2.fmap(r => r->Js.Dict.entries->Belt.Map.String.fromArray)
|
||||||
->E.R2.fmap(Wrappers.evRecord)
|
->E.R2.fmap(Wrappers.evRecord)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -462,7 +465,7 @@ to(5,10)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
->E.A.R.firstErrorOrOpen
|
->E.A.R.firstErrorOrOpen
|
||||||
->E.R2.fmap(Js.Dict.fromArray)
|
->E.R2.fmap(Belt.Map.String.fromArray)
|
||||||
->E.R2.fmap(Wrappers.evRecord)
|
->E.R2.fmap(Wrappers.evRecord)
|
||||||
inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.arrayOfArrays)
|
inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.arrayOfArrays)
|
||||||
|> E.R2.bind(convertInternalItems)
|
|> E.R2.bind(convertInternalItems)
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
module ErrorValue = Reducer_ErrorValue
|
module ErrorValue = Reducer_ErrorValue
|
||||||
module Expression = Reducer_Expression
|
module Expression = Reducer_Expression
|
||||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
module ExternalExpressionValue = ReducerInterface_ExternalExpressionValue
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module Lambda = Reducer_Expression_Lambda
|
module Lambda = Reducer_Expression_Lambda
|
||||||
|
|
||||||
type environment = ReducerInterface_ExpressionValue.environment
|
type environment = ReducerInterface_InternalExpressionValue.environment
|
||||||
type errorValue = Reducer_ErrorValue.errorValue
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type expressionValue = ExternalExpressionValue.t
|
||||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
type externalBindings = ReducerInterface_ExternalExpressionValue.externalBindings
|
||||||
type lambdaValue = ExpressionValue.lambdaValue
|
type lambdaValue = ExternalExpressionValue.lambdaValue
|
||||||
|
|
||||||
let evaluate = Expression.evaluate
|
let evaluate = Expression.evaluate
|
||||||
let evaluateUsingOptions = Expression.evaluateUsingOptions
|
let evaluateUsingOptions = Expression.evaluateUsingOptions
|
||||||
|
@ -15,13 +16,20 @@ let evaluatePartialUsingExternalBindings = Expression.evaluatePartialUsingExtern
|
||||||
let parse = Expression.parse
|
let parse = Expression.parse
|
||||||
|
|
||||||
let foreignFunctionInterface = (
|
let foreignFunctionInterface = (
|
||||||
lambdaValue: lambdaValue,
|
lambdaValue: ExternalExpressionValue.lambdaValue,
|
||||||
argArray: array<expressionValue>,
|
argArray: array<expressionValue>,
|
||||||
environment: ExpressionValue.environment,
|
environment: ExternalExpressionValue.environment,
|
||||||
) => {
|
) => {
|
||||||
Lambda.foreignFunctionInterface(lambdaValue, argArray, environment, Expression.reduceExpression)
|
let internallambdaValue = InternalExpressionValue.lambdaValueToInternal(lambdaValue)
|
||||||
|
let internalArgArray = argArray->Js.Array2.map(InternalExpressionValue.toInternal)
|
||||||
|
Lambda.foreignFunctionInterface(
|
||||||
|
internallambdaValue,
|
||||||
|
internalArgArray,
|
||||||
|
environment,
|
||||||
|
Expression.reduceExpression,
|
||||||
|
)->Belt.Result.map(InternalExpressionValue.toExternal)
|
||||||
}
|
}
|
||||||
|
|
||||||
let defaultEnvironment = ExpressionValue.defaultEnvironment
|
let defaultEnvironment = ExternalExpressionValue.defaultEnvironment
|
||||||
|
|
||||||
let defaultExternalBindings = ReducerInterface_StdLib.externalStdLib
|
let defaultExternalBindings = ReducerInterface_StdLib.externalStdLib
|
||||||
|
|
|
@ -2,27 +2,29 @@ module ErrorValue = Reducer_ErrorValue
|
||||||
module Expression = Reducer_Expression
|
module Expression = Reducer_Expression
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type environment = ReducerInterface_ExpressionValue.environment
|
type environment = ReducerInterface_ExternalExpressionValue.environment
|
||||||
@genType
|
@genType
|
||||||
type errorValue = Reducer_ErrorValue.errorValue
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
@genType
|
@genType
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type expressionValue = ReducerInterface_ExternalExpressionValue.t
|
||||||
@genType
|
@genType
|
||||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
type externalBindings = ReducerInterface_ExternalExpressionValue.externalBindings
|
||||||
@genType
|
@genType
|
||||||
type lambdaValue = ReducerInterface_ExpressionValue.lambdaValue
|
type lambdaValue = ReducerInterface_ExternalExpressionValue.lambdaValue
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let evaluateUsingOptions: (
|
let evaluateUsingOptions: (
|
||||||
~environment: option<QuriSquiggleLang.ReducerInterface_ExpressionValue.environment>,
|
~environment: option<QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.environment>,
|
||||||
~externalBindings: option<QuriSquiggleLang.ReducerInterface_ExpressionValue.externalBindings>,
|
~externalBindings: option<
|
||||||
|
QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.externalBindings,
|
||||||
|
>,
|
||||||
string,
|
string,
|
||||||
) => result<expressionValue, errorValue>
|
) => result<expressionValue, errorValue>
|
||||||
@genType
|
@genType
|
||||||
let evaluatePartialUsingExternalBindings: (
|
let evaluatePartialUsingExternalBindings: (
|
||||||
string,
|
string,
|
||||||
QuriSquiggleLang.ReducerInterface_ExpressionValue.externalBindings,
|
QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.externalBindings,
|
||||||
QuriSquiggleLang.ReducerInterface_ExpressionValue.environment,
|
QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.environment,
|
||||||
) => result<externalBindings, errorValue>
|
) => result<externalBindings, errorValue>
|
||||||
@genType
|
@genType
|
||||||
let evaluate: string => result<expressionValue, errorValue>
|
let evaluate: string => result<expressionValue, errorValue>
|
||||||
|
@ -31,9 +33,9 @@ let parse: string => result<Expression.expression, errorValue>
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let foreignFunctionInterface: (
|
let foreignFunctionInterface: (
|
||||||
QuriSquiggleLang.ReducerInterface_ExpressionValue.lambdaValue,
|
QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.lambdaValue,
|
||||||
array<QuriSquiggleLang.ReducerInterface_ExpressionValue.expressionValue>,
|
array<QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.t>,
|
||||||
QuriSquiggleLang.ReducerInterface_ExpressionValue.environment,
|
QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.environment,
|
||||||
) => result<expressionValue, errorValue>
|
) => result<expressionValue, errorValue>
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,33 +1,112 @@
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
open ReducerInterface_ExpressionValue
|
open ReducerInterface_InternalExpressionValue
|
||||||
let expressionValueToString = toString
|
let expressionValueToString = toString
|
||||||
|
|
||||||
type t = ExpressionT.bindings
|
type t = ReducerInterface_InternalExpressionValue.nameSpace
|
||||||
|
|
||||||
let typeAliasesKey = "_typeAliases_"
|
let typeAliasesKey = "_typeAliases_"
|
||||||
let typeReferencesKey = "_typeReferences_"
|
let typeReferencesKey = "_typeReferences_"
|
||||||
|
|
||||||
let emptyModule: t = Belt.Map.String.empty
|
let getType = (nameSpace: t, id: string) => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
Belt.Map.String.get(container, typeAliasesKey)->Belt.Option.flatMap(aliases =>
|
||||||
|
switch aliases {
|
||||||
|
| IEvRecord(r) => Belt.Map.String.get(r, id)
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let cloneRecord = (r: record): record => r->Js.Dict.entries->Js.Dict.fromArray
|
let getTypeOf = (nameSpace: t, id: string) => {
|
||||||
let fromRecord = (r: record): t => Js.Dict.entries(r)->Belt.Map.String.fromArray
|
let NameSpace(container) = nameSpace
|
||||||
let toRecord = (container: t): record => Belt.Map.String.toArray(container)->Js.Dict.fromArray
|
Belt.Map.String.get(container, typeReferencesKey)->Belt.Option.flatMap(defs =>
|
||||||
|
switch defs {
|
||||||
|
| IEvRecord(r) => Belt.Map.String.get(r, id)
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let toExpressionValue = (container: t): expressionValue => EvModule(toRecord(container))
|
let getWithDefault = (nameSpace: t, id: string, default) => {
|
||||||
let fromExpressionValue = (aValue: expressionValue): t =>
|
let NameSpace(container) = nameSpace
|
||||||
|
Belt.Map.String.getWithDefault(container, id, default)
|
||||||
|
}
|
||||||
|
|
||||||
|
let get = (nameSpace: t, id: string) => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
Belt.Map.String.get(container, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
let emptyMap: map = Belt.Map.String.empty
|
||||||
|
|
||||||
|
let setTypeAlias = (nameSpace: t, id: string, value): t => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
let rValue = Belt.Map.String.getWithDefault(container, typeAliasesKey, IEvRecord(emptyMap))
|
||||||
|
let r = switch rValue {
|
||||||
|
| IEvRecord(r) => r
|
||||||
|
| _ => emptyMap
|
||||||
|
}
|
||||||
|
let r2 = Belt.Map.String.set(r, id, value)->IEvRecord
|
||||||
|
Belt.Map.String.set(container, typeAliasesKey, r2)->NameSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
let setTypeOf = (nameSpace: t, id: string, value): t => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
let rValue = Belt.Map.String.getWithDefault(container, typeReferencesKey, IEvRecord(emptyMap))
|
||||||
|
let r = switch rValue {
|
||||||
|
| IEvRecord(r) => r
|
||||||
|
| _ => emptyMap
|
||||||
|
}
|
||||||
|
let r2 = Belt.Map.String.set(r, id, value)->IEvRecord
|
||||||
|
Belt.Map.String.set(container, typeReferencesKey, r2)->NameSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
let set = (nameSpace: t, id: string, value): t => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
Belt.Map.String.set(container, id, value)->NameSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
let emptyModule: t = NameSpace(Belt.Map.String.empty)
|
||||||
|
|
||||||
|
let fromTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceFromTypeScriptBindings
|
||||||
|
let toTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceToTypeScriptBindings
|
||||||
|
|
||||||
|
let toExpressionValue = (nameSpace: t): internalExpressionValue => IEvModule(nameSpace)
|
||||||
|
let fromExpressionValue = (aValue: internalExpressionValue): t =>
|
||||||
switch aValue {
|
switch aValue {
|
||||||
| EvModule(r) => fromRecord(r)
|
| IEvModule(nameSpace) => nameSpace
|
||||||
| _ => emptyModule
|
| _ => emptyModule
|
||||||
}
|
}
|
||||||
|
|
||||||
let toString = (container: t): string => container->toRecord->EvRecord->expressionValueToString
|
let fromArray = a => Belt.Map.String.fromArray(a)->NameSpace
|
||||||
|
|
||||||
|
let merge = (nameSpace: t, other: t): t => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
let NameSpace(otherContainer) = other
|
||||||
|
otherContainer
|
||||||
|
->Belt.Map.String.reduce(container, (container, key, value) =>
|
||||||
|
Belt.Map.String.set(container, key, value)
|
||||||
|
)
|
||||||
|
->NameSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
let removeOther = (nameSpace: t, other: t): t => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
let NameSpace(otherContainer) = other
|
||||||
|
let keys = Belt.Map.String.keysToArray(otherContainer)
|
||||||
|
Belt.Map.String.keep(container, (key, _value) => {
|
||||||
|
let removeThis = Js.Array2.includes(keys, key)
|
||||||
|
!removeThis
|
||||||
|
})->NameSpace
|
||||||
|
}
|
||||||
|
|
||||||
// -- Module definition
|
// -- Module definition
|
||||||
let define = (container: t, identifier: string, ev: expressionValue): t =>
|
let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => {
|
||||||
Belt.Map.String.set(container, identifier, ev) // TODO build lambda for polymorphic functions here
|
let NameSpace(container) = nameSpace
|
||||||
|
Belt.Map.String.set(container, identifier, ev)->NameSpace // TODO build lambda for polymorphic functions here
|
||||||
|
}
|
||||||
|
let defineNumber = (nameSpace: t, identifier: string, value: float): t =>
|
||||||
|
nameSpace->define(identifier, IEvNumber(value))
|
||||||
|
|
||||||
let defineNumber = (container: t, identifier: string, value: float): t =>
|
let defineModule = (nameSpace: t, identifier: string, value: t): t =>
|
||||||
container->define(identifier, EvNumber(value))
|
nameSpace->define(identifier, toExpressionValue(value))
|
||||||
|
|
||||||
let defineModule = (container: t, identifier: string, value: t): t =>
|
|
||||||
container->define(identifier, toExpressionValue(value))
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
module ExpressionT = Reducer_Expression_T
|
||||||
|
open ExpressionValue
|
||||||
|
|
||||||
|
let isOfResolvedType = (aType, aValue) => {
|
||||||
|
let caseTypeIdentifier = (aTypeIdentifier0, aValue) => {
|
||||||
|
let valueType = aValue->valueToValueType->valueTypeToString->Js.String2.toLowerCase
|
||||||
|
let aTypeIdentifier = aTypeIdentifier0->Js.String2.toLowerCase
|
||||||
|
aTypeIdentifier === valueType
|
||||||
|
}
|
||||||
|
|
||||||
|
switch aType {
|
||||||
|
| IEvTypeIdentifier(aTypeIdentifier) => caseTypeIdentifier(aTypeIdentifier, aValue)
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
module Bindings = Reducer_Expression_Bindings
|
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExternalLibrary = ReducerInterface.ExternalLibrary
|
module ExternalLibrary = ReducerInterface.ExternalLibrary
|
||||||
module Lambda = Reducer_Expression_Lambda
|
module Lambda = Reducer_Expression_Lambda
|
||||||
module MathJs = Reducer_MathJs
|
module MathJs = Reducer_MathJs
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
open ReducerInterface.ExpressionValue
|
open ReducerInterface_InternalExpressionValue
|
||||||
open Reducer_ErrorValue
|
open Reducer_ErrorValue
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -31,23 +32,29 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
let constructRecord = arrayOfPairs => {
|
let constructRecord = arrayOfPairs => {
|
||||||
Belt.Array.map(arrayOfPairs, pairValue =>
|
Belt.Array.map(arrayOfPairs, pairValue =>
|
||||||
switch pairValue {
|
switch pairValue {
|
||||||
| EvArray([EvString(key), valueValue]) => (key, valueValue)
|
| IEvArray([IEvString(key), valueValue]) => (key, valueValue)
|
||||||
| _ => ("wrong key type", pairValue->toStringWithType->EvString)
|
| _ => ("wrong key type", pairValue->toStringWithType->IEvString)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
->Js.Dict.fromArray
|
->Belt.Map.String.fromArray
|
||||||
->EvRecord
|
->IEvRecord
|
||||||
->Ok
|
->Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
let arrayAtIndex = (aValueArray: array<expressionValue>, fIndex: float) =>
|
let arrayAtIndex = (aValueArray: array<internalExpressionValue>, fIndex: float) =>
|
||||||
switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
|
switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
|
||||||
| Some(value) => value->Ok
|
| Some(value) => value->Ok
|
||||||
| None => REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))->Error
|
| None => REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))->Error
|
||||||
}
|
}
|
||||||
|
|
||||||
let recordAtIndex = (dict: Js.Dict.t<expressionValue>, sIndex) =>
|
let moduleAtIndex = (nameSpace: nameSpace, sIndex) =>
|
||||||
switch Js.Dict.get(dict, sIndex) {
|
switch Module.get(nameSpace, sIndex) {
|
||||||
|
| Some(value) => value->Ok
|
||||||
|
| None => RERecordPropertyNotFound("Module property not found", sIndex)->Error
|
||||||
|
}
|
||||||
|
|
||||||
|
let recordAtIndex = (dict: Belt.Map.String.t<internalExpressionValue>, sIndex) =>
|
||||||
|
switch Belt.Map.String.get(dict, sIndex) {
|
||||||
| Some(value) => value->Ok
|
| Some(value) => value->Ok
|
||||||
| None => RERecordPropertyNotFound("Record property not found", sIndex)->Error
|
| None => RERecordPropertyNotFound("Record property not found", sIndex)->Error
|
||||||
}
|
}
|
||||||
|
@ -55,70 +62,37 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
let doAddArray = (originalA, b) => {
|
let doAddArray = (originalA, b) => {
|
||||||
let a = originalA->Js.Array2.copy
|
let a = originalA->Js.Array2.copy
|
||||||
let _ = Js.Array2.pushMany(a, b)
|
let _ = Js.Array2.pushMany(a, b)
|
||||||
a->EvArray->Ok
|
a->IEvArray->Ok
|
||||||
}
|
}
|
||||||
let doAddString = (a, b) => {
|
let doAddString = (a, b) => {
|
||||||
let answer = Js.String2.concat(a, b)
|
let answer = Js.String2.concat(a, b)
|
||||||
answer->EvString->Ok
|
answer->IEvString->Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
let inspect = (value: expressionValue) => {
|
let inspect = (value: internalExpressionValue) => {
|
||||||
Js.log(value->toString)
|
Js.log(value->toString)
|
||||||
value->Ok
|
value->Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
let inspectLabel = (value: expressionValue, label: string) => {
|
let inspectLabel = (value: internalExpressionValue, label: string) => {
|
||||||
Js.log(`${label}: ${value->toString}`)
|
Js.log(`${label}: ${value->toString}`)
|
||||||
value->Ok
|
value->Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
let doSetBindings = (
|
let doSetBindings = (bindings: nameSpace, symbol: string, value: internalExpressionValue) => {
|
||||||
externalBindings: externalBindings,
|
Module.set(bindings, symbol, value)->IEvModule->Ok
|
||||||
symbol: string,
|
|
||||||
value: expressionValue,
|
|
||||||
) => {
|
|
||||||
Bindings.fromExternalBindings(externalBindings)
|
|
||||||
->Belt.Map.String.set(symbol, value)
|
|
||||||
->Bindings.toExternalBindings
|
|
||||||
->EvRecord
|
|
||||||
->Ok
|
|
||||||
}
|
|
||||||
|
|
||||||
let doSetBindingsInNamespace = (
|
|
||||||
externalBindings: externalBindings,
|
|
||||||
symbol: string,
|
|
||||||
value: expressionValue,
|
|
||||||
namespace: string,
|
|
||||||
) => {
|
|
||||||
let bindings = Bindings.fromExternalBindings(externalBindings)
|
|
||||||
let evAliases = bindings->Belt.Map.String.getWithDefault(namespace, EvRecord(Js.Dict.empty()))
|
|
||||||
let newEvAliases = switch evAliases {
|
|
||||||
| EvRecord(dict) => {
|
|
||||||
Js.Dict.set(dict, symbol, value)
|
|
||||||
dict->EvRecord
|
|
||||||
}
|
|
||||||
| _ => Js.Dict.empty()->EvRecord
|
|
||||||
}
|
|
||||||
bindings
|
|
||||||
->Belt.Map.String.set(namespace, newEvAliases)
|
|
||||||
->Bindings.toExternalBindings
|
|
||||||
->EvRecord
|
|
||||||
->Ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let doSetTypeAliasBindings = (
|
let doSetTypeAliasBindings = (
|
||||||
externalBindings: externalBindings,
|
bindings: nameSpace,
|
||||||
symbol: string,
|
symbol: string,
|
||||||
value: expressionValue,
|
value: internalExpressionValue,
|
||||||
) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeAliasesKey)
|
) => Module.setTypeAlias(bindings, symbol, value)->IEvModule->Ok
|
||||||
|
|
||||||
let doSetTypeOfBindings = (
|
let doSetTypeOfBindings = (bindings: nameSpace, symbol: string, value: internalExpressionValue) =>
|
||||||
externalBindings: externalBindings,
|
Module.setTypeOf(bindings, symbol, value)->IEvModule->Ok
|
||||||
symbol: string,
|
|
||||||
value: expressionValue,
|
|
||||||
) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeReferencesKey)
|
|
||||||
|
|
||||||
let doExportBindings = (externalBindings: externalBindings) => EvRecord(externalBindings)->Ok
|
let doExportBindings = (bindings: nameSpace) => bindings->Module.toExpressionValue->Ok
|
||||||
|
|
||||||
let doKeepArray = (aValueArray, aLambdaValue) => {
|
let doKeepArray = (aValueArray, aLambdaValue) => {
|
||||||
let rMappedList = aValueArray->Belt.Array.reduceReverse(Ok(list{}), (rAcc, elem) =>
|
let rMappedList = aValueArray->Belt.Array.reduceReverse(Ok(list{}), (rAcc, elem) =>
|
||||||
|
@ -126,13 +100,13 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
let rNewElem = Lambda.doLambdaCall(aLambdaValue, list{elem}, environment, reducer)
|
let rNewElem = Lambda.doLambdaCall(aLambdaValue, list{elem}, environment, reducer)
|
||||||
rNewElem->Result.map(newElem =>
|
rNewElem->Result.map(newElem =>
|
||||||
switch newElem {
|
switch newElem {
|
||||||
| EvBool(true) => list{elem, ...acc}
|
| IEvBool(true) => list{elem, ...acc}
|
||||||
| _ => acc
|
| _ => acc
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->EvArray)
|
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->IEvArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
let doMapArray = (aValueArray, aLambdaValue) => {
|
let doMapArray = (aValueArray, aLambdaValue) => {
|
||||||
|
@ -142,35 +116,36 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
rNewElem->Result.map(newElem => list{newElem, ...acc})
|
rNewElem->Result.map(newElem => list{newElem, ...acc})
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->EvArray)
|
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->IEvArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
module SampleMap = {
|
module SampleMap = {
|
||||||
type t = SampleSetDist.t
|
type t = SampleSetDist.t
|
||||||
let doLambdaCall = (aLambdaValue, list) =>
|
let doLambdaCall = (aLambdaValue, list) =>
|
||||||
switch Lambda.doLambdaCall(aLambdaValue, list, environment, reducer) {
|
switch Lambda.doLambdaCall(aLambdaValue, list, environment, reducer) {
|
||||||
| Ok(EvNumber(f)) => Ok(f)
|
| Ok(IEvNumber(f)) => Ok(f)
|
||||||
| _ => Error(Operation.SampleMapNeedsNtoNFunction)
|
| _ => Error(Operation.SampleMapNeedsNtoNFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
let toType = r =>
|
let toType = r =>
|
||||||
switch r {
|
switch r {
|
||||||
| Ok(r) => Ok(EvDistribution(SampleSet(r)))
|
| Ok(r) => Ok(IEvDistribution(SampleSet(r)))
|
||||||
| Error(r) => Error(REDistributionError(SampleSetError(r)))
|
| Error(r) => Error(REDistributionError(SampleSetError(r)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let map1 = (sampleSetDist: t, aLambdaValue) => {
|
let map1 = (sampleSetDist: t, aLambdaValue) => {
|
||||||
let fn = r => doLambdaCall(aLambdaValue, list{EvNumber(r)})
|
let fn = r => doLambdaCall(aLambdaValue, list{IEvNumber(r)})
|
||||||
toType(SampleSetDist.samplesMap(~fn, sampleSetDist))
|
toType(SampleSetDist.samplesMap(~fn, sampleSetDist))
|
||||||
}
|
}
|
||||||
|
|
||||||
let map2 = (t1: t, t2: t, aLambdaValue) => {
|
let map2 = (t1: t, t2: t, aLambdaValue) => {
|
||||||
let fn = (a, b) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b)})
|
let fn = (a, b) => doLambdaCall(aLambdaValue, list{IEvNumber(a), IEvNumber(b)})
|
||||||
SampleSetDist.map2(~fn, ~t1, ~t2)->toType
|
SampleSetDist.map2(~fn, ~t1, ~t2)->toType
|
||||||
}
|
}
|
||||||
|
|
||||||
let map3 = (t1: t, t2: t, t3: t, aLambdaValue) => {
|
let map3 = (t1: t, t2: t, t3: t, aLambdaValue) => {
|
||||||
let fn = (a, b, c) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b), EvNumber(c)})
|
let fn = (a, b, c) =>
|
||||||
|
doLambdaCall(aLambdaValue, list{IEvNumber(a), IEvNumber(b), IEvNumber(c)})
|
||||||
SampleSetDist.map3(~fn, ~t1, ~t2, ~t3)->toType
|
SampleSetDist.map3(~fn, ~t1, ~t2, ~t3)->toType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,132 +167,128 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
}
|
}
|
||||||
|
|
||||||
let typeModifier_memberOf = (aType, anArray) => {
|
let typeModifier_memberOf = (aType, anArray) => {
|
||||||
let newRecord = Js.Dict.fromArray([
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
("typeTag", EvString("typeIdentifier")),
|
("typeTag", IEvString("typeIdentifier")),
|
||||||
("typeIdentifier", aType),
|
("typeIdentifier", aType),
|
||||||
])
|
])
|
||||||
newRecord->Js.Dict.set("memberOf", anArray)
|
newRecord->Belt.Map.String.set("memberOf", anArray)->IEvRecord->Ok
|
||||||
newRecord->EvRecord->Ok
|
|
||||||
}
|
}
|
||||||
let typeModifier_memberOf_update = (aRecord, anArray) => {
|
let typeModifier_memberOf_update = (aRecord, anArray) => {
|
||||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
aRecord->Belt.Map.String.set("memberOf", anArray)->IEvRecord->Ok
|
||||||
newRecord->Js.Dict.set("memberOf", anArray)
|
|
||||||
newRecord->EvRecord->Ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let typeModifier_min = (aType, value) => {
|
let typeModifier_min = (aType, value) => {
|
||||||
let newRecord = Js.Dict.fromArray([
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
("typeTag", EvString("typeIdentifier")),
|
("typeTag", IEvString("typeIdentifier")),
|
||||||
("typeIdentifier", aType),
|
("typeIdentifier", aType),
|
||||||
])
|
])
|
||||||
newRecord->Js.Dict.set("min", value)
|
newRecord->Belt.Map.String.set("min", value)->IEvRecord->Ok
|
||||||
newRecord->EvRecord->Ok
|
|
||||||
}
|
}
|
||||||
let typeModifier_min_update = (aRecord, value) => {
|
let typeModifier_min_update = (aRecord, value) => {
|
||||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
aRecord->Belt.Map.String.set("min", value)->IEvRecord->Ok
|
||||||
newRecord->Js.Dict.set("min", value)
|
|
||||||
newRecord->EvRecord->Ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let typeModifier_max = (aType, value) => {
|
let typeModifier_max = (aType, value) => {
|
||||||
let newRecord = Js.Dict.fromArray([
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
("typeTag", EvString("typeIdentifier")),
|
("typeTag", IEvString("typeIdentifier")),
|
||||||
("typeIdentifier", aType),
|
("typeIdentifier", aType),
|
||||||
])
|
])
|
||||||
newRecord->Js.Dict.set("max", value)
|
newRecord->Belt.Map.String.set("max", value)->IEvRecord->Ok
|
||||||
newRecord->EvRecord->Ok
|
|
||||||
}
|
|
||||||
let typeModifier_max_update = (aRecord, value) => {
|
|
||||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
|
||||||
newRecord->Js.Dict.set("max", value)
|
|
||||||
newRecord->EvRecord->Ok
|
|
||||||
}
|
}
|
||||||
|
let typeModifier_max_update = (aRecord, value) =>
|
||||||
|
aRecord->Belt.Map.String.set("max", value)->IEvRecord->Ok
|
||||||
|
|
||||||
let typeModifier_opaque_update = aRecord => {
|
let typeModifier_opaque_update = aRecord =>
|
||||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
aRecord->Belt.Map.String.set("opaque", IEvBool(true))->IEvRecord->Ok
|
||||||
newRecord->Js.Dict.set("opaque", EvBool(true))
|
|
||||||
newRecord->EvRecord->Ok
|
|
||||||
}
|
|
||||||
|
|
||||||
let typeOr = evArray => {
|
let typeOr = evArray => {
|
||||||
let newRecord = Js.Dict.fromArray([("typeTag", EvString("typeOr")), ("typeOr", evArray)])
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
newRecord->EvRecord->Ok
|
("typeTag", IEvString("typeOr")),
|
||||||
|
("typeOr", evArray),
|
||||||
|
])
|
||||||
|
newRecord->IEvRecord->Ok
|
||||||
}
|
}
|
||||||
let typeFunction = anArray => {
|
let typeFunction = anArray => {
|
||||||
let output = Belt.Array.getUnsafe(anArray, Js.Array2.length(anArray) - 1)
|
let output = Belt.Array.getUnsafe(anArray, Js.Array2.length(anArray) - 1)
|
||||||
let inputs = Js.Array2.slice(anArray, ~start=0, ~end_=-1)
|
let inputs = Js.Array2.slice(anArray, ~start=0, ~end_=-1)
|
||||||
let newRecord = Js.Dict.fromArray([
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
("typeTag", EvString("typeFunction")),
|
("typeTag", IEvString("typeFunction")),
|
||||||
("inputs", EvArray(inputs)),
|
("inputs", IEvArray(inputs)),
|
||||||
("output", output),
|
("output", output),
|
||||||
])
|
])
|
||||||
newRecord->EvRecord->Ok
|
newRecord->IEvRecord->Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
switch call {
|
switch call {
|
||||||
| ("$_atIndex_$", [EvArray(aValueArray), EvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
| ("$_atIndex_$", [IEvArray(aValueArray), IEvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
||||||
| ("$_atIndex_$", [EvModule(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
| ("$_atIndex_$", [IEvModule(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
||||||
| ("$_atIndex_$", [EvRecord(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
| ("$_atIndex_$", [IEvRecord(dict), IEvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||||
| ("$_constructArray_$", [EvArray(aValueArray)]) => EvArray(aValueArray)->Ok
|
| ("$_constructArray_$", [IEvArray(aValueArray)]) => IEvArray(aValueArray)->Ok
|
||||||
| ("$_constructRecord_$", [EvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
| ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||||
| ("$_exportBindings_$", [EvRecord(externalBindings)]) => doExportBindings(externalBindings)
|
| ("$_exportBindings_$", [IEvModule(nameSpace)]) => doExportBindings(nameSpace)
|
||||||
| ("$_setBindings_$", [EvRecord(externalBindings), EvSymbol(symbol), value]) =>
|
| ("$_setBindings_$", [IEvModule(nameSpace), IEvSymbol(symbol), value]) =>
|
||||||
doSetBindings(externalBindings, symbol, value)
|
doSetBindings(nameSpace, symbol, value)
|
||||||
| ("$_setTypeAliasBindings_$", [EvRecord(externalBindings), EvTypeIdentifier(symbol), value]) =>
|
| ("$_setTypeAliasBindings_$", [IEvModule(nameSpace), IEvTypeIdentifier(symbol), value]) =>
|
||||||
doSetTypeAliasBindings(externalBindings, symbol, value)
|
doSetTypeAliasBindings(nameSpace, symbol, value)
|
||||||
| ("$_setTypeOfBindings_$", [EvRecord(externalBindings), EvSymbol(symbol), value]) =>
|
| ("$_setTypeOfBindings_$", [IEvModule(nameSpace), IEvSymbol(symbol), value]) =>
|
||||||
doSetTypeOfBindings(externalBindings, symbol, value)
|
doSetTypeOfBindings(nameSpace, symbol, value)
|
||||||
| ("$_typeModifier_memberOf_$", [EvTypeIdentifier(typeIdentifier), EvArray(arr)]) =>
|
| ("$_typeModifier_memberOf_$", [IEvTypeIdentifier(typeIdentifier), IEvArray(arr)]) =>
|
||||||
typeModifier_memberOf(EvTypeIdentifier(typeIdentifier), EvArray(arr))
|
typeModifier_memberOf(IEvTypeIdentifier(typeIdentifier), IEvArray(arr))
|
||||||
| ("$_typeModifier_memberOf_$", [EvRecord(typeRecord), EvArray(arr)]) =>
|
| ("$_typeModifier_memberOf_$", [IEvRecord(typeRecord), IEvArray(arr)]) =>
|
||||||
typeModifier_memberOf_update(typeRecord, EvArray(arr))
|
typeModifier_memberOf_update(typeRecord, IEvArray(arr))
|
||||||
| ("$_typeModifier_min_$", [EvTypeIdentifier(typeIdentifier), value]) =>
|
| ("$_typeModifier_min_$", [IEvTypeIdentifier(typeIdentifier), value]) =>
|
||||||
typeModifier_min(EvTypeIdentifier(typeIdentifier), value)
|
typeModifier_min(IEvTypeIdentifier(typeIdentifier), value)
|
||||||
| ("$_typeModifier_min_$", [EvRecord(typeRecord), value]) =>
|
| ("$_typeModifier_min_$", [IEvRecord(typeRecord), value]) =>
|
||||||
typeModifier_min_update(typeRecord, value)
|
typeModifier_min_update(typeRecord, value)
|
||||||
| ("$_typeModifier_max_$", [EvTypeIdentifier(typeIdentifier), value]) =>
|
| ("$_typeModifier_max_$", [IEvTypeIdentifier(typeIdentifier), value]) =>
|
||||||
typeModifier_max(EvTypeIdentifier(typeIdentifier), value)
|
typeModifier_max(IEvTypeIdentifier(typeIdentifier), value)
|
||||||
| ("$_typeModifier_max_$", [EvRecord(typeRecord), value]) =>
|
| ("$_typeModifier_max_$", [IEvRecord(typeRecord), value]) =>
|
||||||
typeModifier_max_update(typeRecord, value)
|
typeModifier_max_update(typeRecord, value)
|
||||||
| ("$_typeModifier_opaque_$", [EvRecord(typeRecord)]) => typeModifier_opaque_update(typeRecord)
|
| ("$_typeModifier_opaque_$", [IEvRecord(typeRecord)]) => typeModifier_opaque_update(typeRecord)
|
||||||
| ("$_typeOr_$", [EvArray(arr)]) => typeOr(EvArray(arr))
|
| ("$_typeOr_$", [IEvArray(arr)]) => typeOr(IEvArray(arr))
|
||||||
| ("$_typeFunction_$", [EvArray(arr)]) => typeFunction(arr)
|
| ("$_typeFunction_$", [IEvArray(arr)]) => typeFunction(arr)
|
||||||
| ("concat", [EvArray(aValueArray), EvArray(bValueArray)]) => doAddArray(aValueArray, bValueArray)
|
| ("concat", [IEvArray(aValueArray), IEvArray(bValueArray)]) =>
|
||||||
| ("concat", [EvString(aValueString), EvString(bValueString)]) =>
|
doAddArray(aValueArray, bValueArray)
|
||||||
|
| ("concat", [IEvString(aValueString), IEvString(bValueString)]) =>
|
||||||
doAddString(aValueString, bValueString)
|
doAddString(aValueString, bValueString)
|
||||||
| ("inspect", [value, EvString(label)]) => inspectLabel(value, label)
|
| ("inspect", [value, IEvString(label)]) => inspectLabel(value, label)
|
||||||
| ("inspect", [value]) => inspect(value)
|
| ("inspect", [value]) => inspect(value)
|
||||||
| ("filter", [EvArray(aValueArray), EvLambda(aLambdaValue)]) =>
|
| ("filter", [IEvArray(aValueArray), IEvLambda(aLambdaValue)]) =>
|
||||||
doKeepArray(aValueArray, aLambdaValue)
|
doKeepArray(aValueArray, aLambdaValue)
|
||||||
| ("map", [EvArray(aValueArray), EvLambda(aLambdaValue)]) => doMapArray(aValueArray, aLambdaValue)
|
| ("map", [IEvArray(aValueArray), IEvLambda(aLambdaValue)]) =>
|
||||||
| ("mapSamples", [EvDistribution(SampleSet(dist)), EvLambda(aLambdaValue)]) =>
|
doMapArray(aValueArray, aLambdaValue)
|
||||||
|
| ("mapSamples", [IEvDistribution(SampleSet(dist)), IEvLambda(aLambdaValue)]) =>
|
||||||
SampleMap.map1(dist, aLambdaValue)
|
SampleMap.map1(dist, aLambdaValue)
|
||||||
| (
|
| (
|
||||||
"mapSamples2",
|
"mapSamples2",
|
||||||
[EvDistribution(SampleSet(dist1)), EvDistribution(SampleSet(dist2)), EvLambda(aLambdaValue)],
|
[
|
||||||
|
IEvDistribution(SampleSet(dist1)),
|
||||||
|
IEvDistribution(SampleSet(dist2)),
|
||||||
|
IEvLambda(aLambdaValue),
|
||||||
|
],
|
||||||
) =>
|
) =>
|
||||||
SampleMap.map2(dist1, dist2, aLambdaValue)
|
SampleMap.map2(dist1, dist2, aLambdaValue)
|
||||||
| (
|
| (
|
||||||
"mapSamples3",
|
"mapSamples3",
|
||||||
[
|
[
|
||||||
EvDistribution(SampleSet(dist1)),
|
IEvDistribution(SampleSet(dist1)),
|
||||||
EvDistribution(SampleSet(dist2)),
|
IEvDistribution(SampleSet(dist2)),
|
||||||
EvDistribution(SampleSet(dist3)),
|
IEvDistribution(SampleSet(dist3)),
|
||||||
EvLambda(aLambdaValue),
|
IEvLambda(aLambdaValue),
|
||||||
],
|
],
|
||||||
) =>
|
) =>
|
||||||
SampleMap.map3(dist1, dist2, dist3, aLambdaValue)
|
SampleMap.map3(dist1, dist2, dist3, aLambdaValue)
|
||||||
| ("reduce", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) =>
|
| ("reduce", [IEvArray(aValueArray), initialValue, IEvLambda(aLambdaValue)]) =>
|
||||||
doReduceArray(aValueArray, initialValue, aLambdaValue)
|
doReduceArray(aValueArray, initialValue, aLambdaValue)
|
||||||
| ("reduceReverse", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) =>
|
| ("reduceReverse", [IEvArray(aValueArray), initialValue, IEvLambda(aLambdaValue)]) =>
|
||||||
doReduceReverseArray(aValueArray, initialValue, aLambdaValue)
|
doReduceReverseArray(aValueArray, initialValue, aLambdaValue)
|
||||||
| ("reverse", [EvArray(aValueArray)]) => aValueArray->Belt.Array.reverse->EvArray->Ok
|
| ("reverse", [IEvArray(aValueArray)]) => aValueArray->Belt.Array.reverse->IEvArray->Ok
|
||||||
| (_, [EvBool(_)])
|
| (_, [IEvBool(_)])
|
||||||
| (_, [EvNumber(_)])
|
| (_, [IEvNumber(_)])
|
||||||
| (_, [EvString(_)])
|
| (_, [IEvString(_)])
|
||||||
| (_, [EvBool(_), EvBool(_)])
|
| (_, [IEvBool(_), IEvBool(_)])
|
||||||
| (_, [EvNumber(_), EvNumber(_)])
|
| (_, [IEvNumber(_), IEvNumber(_)])
|
||||||
| (_, [EvString(_), EvString(_)]) =>
|
| (_, [IEvString(_), IEvString(_)]) =>
|
||||||
callMathJs(call)
|
callMathJs(call)
|
||||||
| call =>
|
| call =>
|
||||||
Error(REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)) // Report full type signature as error
|
Error(REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)) // Report full type signature as error
|
||||||
|
@ -328,7 +299,7 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
Reducer uses Result monad while reducing expressions
|
Reducer uses Result monad while reducing expressions
|
||||||
*/
|
*/
|
||||||
let dispatch = (call: functionCall, environment, reducer: ExpressionT.reducerFn): result<
|
let dispatch = (call: functionCall, environment, reducer: ExpressionT.reducerFn): result<
|
||||||
expressionValue,
|
internalExpressionValue,
|
||||||
errorValue,
|
errorValue,
|
||||||
> =>
|
> =>
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -3,19 +3,19 @@
|
||||||
they take expressions as parameters and return a new expression.
|
they take expressions as parameters and return a new expression.
|
||||||
Macros are used to define language building blocks. They are like Lisp macros.
|
Macros are used to define language building blocks. They are like Lisp macros.
|
||||||
*/
|
*/
|
||||||
module Bindings = Reducer_Expression_Bindings
|
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module ErrorValue = Reducer_ErrorValue
|
module ErrorValue = Reducer_ErrorValue
|
||||||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
open Reducer_Expression_ExpressionBuilder
|
open Reducer_Expression_ExpressionBuilder
|
||||||
|
|
||||||
type environment = ExpressionValue.environment
|
type environment = InternalExpressionValue.environment
|
||||||
type errorValue = ErrorValue.errorValue
|
type errorValue = ErrorValue.errorValue
|
||||||
type expression = ExpressionT.expression
|
type expression = ExpressionT.expression
|
||||||
type expressionValue = ExpressionValue.expressionValue
|
|
||||||
type expressionWithContext = ExpressionWithContext.expressionWithContext
|
type expressionWithContext = ExpressionWithContext.expressionWithContext
|
||||||
|
|
||||||
let dispatchMacroCall = (
|
let dispatchMacroCall = (
|
||||||
|
@ -27,13 +27,13 @@ let dispatchMacroCall = (
|
||||||
let useExpressionToSetBindings = (bindingExpr: expression, environment, statement, newCode) => {
|
let useExpressionToSetBindings = (bindingExpr: expression, environment, statement, newCode) => {
|
||||||
let rExternalBindingsValue = reduceExpression(bindingExpr, bindings, environment)
|
let rExternalBindingsValue = reduceExpression(bindingExpr, bindings, environment)
|
||||||
|
|
||||||
rExternalBindingsValue->Result.flatMap(externalBindingsValue => {
|
rExternalBindingsValue->Result.flatMap(nameSpaceValue => {
|
||||||
let newBindings = Bindings.fromValue(externalBindingsValue)
|
let newBindings = Module.fromExpressionValue(nameSpaceValue)
|
||||||
|
|
||||||
let rNewStatement = Bindings.replaceSymbols(newBindings, statement)
|
let rNewStatement = BindingsReplacer.replaceSymbols(newBindings, statement)
|
||||||
rNewStatement->Result.map(boundStatement =>
|
rNewStatement->Result.map(boundStatement =>
|
||||||
ExpressionWithContext.withContext(
|
ExpressionWithContext.withContext(
|
||||||
newCode(newBindings->Bindings.toExternalBindings->eRecord, boundStatement),
|
newCode(newBindings->eModule, boundStatement),
|
||||||
newBindings,
|
newBindings,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -51,7 +51,7 @@ let dispatchMacroCall = (
|
||||||
let doBindStatement = (bindingExpr: expression, statement: expression, environment) => {
|
let doBindStatement = (bindingExpr: expression, statement: expression, environment) => {
|
||||||
let defaultStatement = ErrorValue.REAssignmentExpected->Error
|
let defaultStatement = ErrorValue.REAssignmentExpected->Error
|
||||||
switch statement {
|
switch statement {
|
||||||
| ExpressionT.EList(list{ExpressionT.EValue(EvCall(callName)), symbolExpr, statement}) => {
|
| ExpressionT.EList(list{ExpressionT.EValue(IEvCall(callName)), symbolExpr, statement}) => {
|
||||||
let setBindingsFn = correspondingSetBindingsFn(callName)
|
let setBindingsFn = correspondingSetBindingsFn(callName)
|
||||||
if setBindingsFn !== "" {
|
if setBindingsFn !== "" {
|
||||||
useExpressionToSetBindings(bindingExpr, environment, statement, (
|
useExpressionToSetBindings(bindingExpr, environment, statement, (
|
||||||
|
@ -77,7 +77,7 @@ let dispatchMacroCall = (
|
||||||
) => boundStatement)
|
) => boundStatement)
|
||||||
|
|
||||||
switch statement {
|
switch statement {
|
||||||
| ExpressionT.EList(list{ExpressionT.EValue(EvCall(callName)), symbolExpr, statement}) => {
|
| ExpressionT.EList(list{ExpressionT.EValue(IEvCall(callName)), symbolExpr, statement}) => {
|
||||||
let setBindingsFn = correspondingSetBindingsFn(callName)
|
let setBindingsFn = correspondingSetBindingsFn(callName)
|
||||||
if setBindingsFn !== "" {
|
if setBindingsFn !== "" {
|
||||||
useExpressionToSetBindings(bindingExpr, environment, statement, (
|
useExpressionToSetBindings(bindingExpr, environment, statement, (
|
||||||
|
@ -123,10 +123,7 @@ let dispatchMacroCall = (
|
||||||
bindings: ExpressionT.bindings,
|
bindings: ExpressionT.bindings,
|
||||||
parameters: array<string>,
|
parameters: array<string>,
|
||||||
lambdaDefinition: ExpressionT.expression,
|
lambdaDefinition: ExpressionT.expression,
|
||||||
) =>
|
) => ExpressionWithContext.noContext(eLambda(parameters, bindings, lambdaDefinition))->Ok
|
||||||
ExpressionWithContext.noContext(
|
|
||||||
eLambda(parameters, bindings->Bindings.toExternalBindings, lambdaDefinition),
|
|
||||||
)->Ok
|
|
||||||
|
|
||||||
let doTernary = (
|
let doTernary = (
|
||||||
condition: expression,
|
condition: expression,
|
||||||
|
@ -139,11 +136,11 @@ let dispatchMacroCall = (
|
||||||
let rCondition = reduceExpression(blockCondition, bindings, environment)
|
let rCondition = reduceExpression(blockCondition, bindings, environment)
|
||||||
rCondition->Result.flatMap(conditionValue =>
|
rCondition->Result.flatMap(conditionValue =>
|
||||||
switch conditionValue {
|
switch conditionValue {
|
||||||
| ExpressionValue.EvBool(false) => {
|
| InternalExpressionValue.IEvBool(false) => {
|
||||||
let ifFalseBlock = eBlock(list{ifFalse})
|
let ifFalseBlock = eBlock(list{ifFalse})
|
||||||
ExpressionWithContext.withContext(ifFalseBlock, bindings)->Ok
|
ExpressionWithContext.withContext(ifFalseBlock, bindings)->Ok
|
||||||
}
|
}
|
||||||
| ExpressionValue.EvBool(true) => {
|
| InternalExpressionValue.IEvBool(true) => {
|
||||||
let ifTrueBlock = eBlock(list{ifTrue})
|
let ifTrueBlock = eBlock(list{ifTrue})
|
||||||
ExpressionWithContext.withContext(ifTrueBlock, bindings)->Ok
|
ExpressionWithContext.withContext(ifTrueBlock, bindings)->Ok
|
||||||
}
|
}
|
||||||
|
@ -158,32 +155,32 @@ let dispatchMacroCall = (
|
||||||
> =>
|
> =>
|
||||||
switch aList {
|
switch aList {
|
||||||
| list{
|
| list{
|
||||||
ExpressionT.EValue(EvCall("$$_bindStatement_$$")),
|
ExpressionT.EValue(IEvCall("$$_bindStatement_$$")),
|
||||||
bindingExpr: ExpressionT.expression,
|
bindingExpr: ExpressionT.expression,
|
||||||
statement,
|
statement,
|
||||||
} =>
|
} =>
|
||||||
doBindStatement(bindingExpr, statement, environment)
|
doBindStatement(bindingExpr, statement, environment)
|
||||||
| list{ExpressionT.EValue(EvCall("$$_bindStatement_$$")), statement} =>
|
| list{ExpressionT.EValue(IEvCall("$$_bindStatement_$$")), statement} =>
|
||||||
// bindings of the context are used when there is no binding expression
|
// bindings of the context are used when there is no binding expression
|
||||||
doBindStatement(eRecord(Bindings.toExternalBindings(bindings)), statement, environment)
|
doBindStatement(eModule(bindings), statement, environment)
|
||||||
| list{
|
| list{
|
||||||
ExpressionT.EValue(EvCall("$$_bindExpression_$$")),
|
ExpressionT.EValue(IEvCall("$$_bindExpression_$$")),
|
||||||
bindingExpr: ExpressionT.expression,
|
bindingExpr: ExpressionT.expression,
|
||||||
expression,
|
expression,
|
||||||
} =>
|
} =>
|
||||||
doBindExpression(bindingExpr, expression, environment)
|
doBindExpression(bindingExpr, expression, environment)
|
||||||
| list{ExpressionT.EValue(EvCall("$$_bindExpression_$$")), expression} =>
|
| list{ExpressionT.EValue(IEvCall("$$_bindExpression_$$")), expression} =>
|
||||||
// bindings of the context are used when there is no binding expression
|
// bindings of the context are used when there is no binding expression
|
||||||
doBindExpression(eRecord(Bindings.toExternalBindings(bindings)), expression, environment)
|
doBindExpression(eModule(bindings), expression, environment)
|
||||||
| list{ExpressionT.EValue(EvCall("$$_block_$$")), ...exprs} =>
|
| list{ExpressionT.EValue(IEvCall("$$_block_$$")), ...exprs} =>
|
||||||
doBlock(exprs, bindings, environment)
|
doBlock(exprs, bindings, environment)
|
||||||
| list{
|
| list{
|
||||||
ExpressionT.EValue(EvCall("$$_lambda_$$")),
|
ExpressionT.EValue(IEvCall("$$_lambda_$$")),
|
||||||
ExpressionT.EValue(EvArrayString(parameters)),
|
ExpressionT.EValue(IEvArrayString(parameters)),
|
||||||
lambdaDefinition,
|
lambdaDefinition,
|
||||||
} =>
|
} =>
|
||||||
doLambdaDefinition(bindings, parameters, lambdaDefinition)
|
doLambdaDefinition(bindings, parameters, lambdaDefinition)
|
||||||
| list{ExpressionT.EValue(EvCall("$$_ternary_$$")), condition, ifTrue, ifFalse} =>
|
| list{ExpressionT.EValue(IEvCall("$$_ternary_$$")), condition, ifTrue, ifFalse} =>
|
||||||
doTernary(condition, ifTrue, ifFalse, bindings, environment)
|
doTernary(condition, ifTrue, ifFalse, bindings, environment)
|
||||||
| _ => ExpressionWithContext.noContext(ExpressionT.EList(aList))->Ok
|
| _ => ExpressionWithContext.noContext(ExpressionT.EList(aList))->Ok
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
module Bindings = Reducer_Expression_Bindings
|
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module BuiltIn = Reducer_Dispatch_BuiltIn
|
module BuiltIn = Reducer_Dispatch_BuiltIn
|
||||||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
|
||||||
module Extra = Reducer_Extra
|
module Extra = Reducer_Extra
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module Lambda = Reducer_Expression_Lambda
|
module Lambda = Reducer_Expression_Lambda
|
||||||
module Macro = Reducer_Expression_Macro
|
module Macro = Reducer_Expression_Macro
|
||||||
module MathJs = Reducer_MathJs
|
module MathJs = Reducer_MathJs
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
module T = Reducer_Expression_T
|
module T = Reducer_Expression_T
|
||||||
|
|
||||||
type environment = ReducerInterface_ExpressionValue.environment
|
type environment = InternalExpressionValue.environment
|
||||||
type errorValue = Reducer_ErrorValue.errorValue
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
type expression = T.expression
|
type expression = T.expression
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type internalExpressionValue = InternalExpressionValue.t
|
||||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
type externalExpressionValue = ReducerInterface_ExternalExpressionValue.t
|
||||||
type internalCode = ReducerInterface_ExpressionValue.internalCode
|
|
||||||
type t = expression
|
type t = expression
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -27,7 +27,7 @@ let parse = (peggyCode: string): result<t, errorValue> =>
|
||||||
Recursively evaluate/reduce the expression (Lisp AST)
|
Recursively evaluate/reduce the expression (Lisp AST)
|
||||||
*/
|
*/
|
||||||
let rec reduceExpression = (expression: t, bindings: T.bindings, environment: environment): result<
|
let rec reduceExpression = (expression: t, bindings: T.bindings, environment: environment): result<
|
||||||
expressionValue,
|
internalExpressionValue,
|
||||||
'e,
|
'e,
|
||||||
> => {
|
> => {
|
||||||
// Js.log(`reduce: ${T.toString(expression)} bindings: ${bindings->Bindings.toString}`)
|
// Js.log(`reduce: ${T.toString(expression)} bindings: ${bindings->Bindings.toString}`)
|
||||||
|
@ -35,7 +35,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings, environment: en
|
||||||
| T.EValue(value) => value->Ok
|
| T.EValue(value) => value->Ok
|
||||||
| T.EList(list) =>
|
| T.EList(list) =>
|
||||||
switch list {
|
switch list {
|
||||||
| list{EValue(EvCall(fName)), ..._args} =>
|
| list{EValue(IEvCall(fName)), ..._args} =>
|
||||||
switch Macro.isMacroName(fName) {
|
switch Macro.isMacroName(fName) {
|
||||||
// A macro expands then reduces itself
|
// A macro expands then reduces itself
|
||||||
| true => Macro.doMacroCall(expression, bindings, environment, reduceExpression)
|
| true => Macro.doMacroCall(expression, bindings, environment, reduceExpression)
|
||||||
|
@ -50,11 +50,11 @@ and reduceExpressionList = (
|
||||||
expressions: list<t>,
|
expressions: list<t>,
|
||||||
bindings: T.bindings,
|
bindings: T.bindings,
|
||||||
environment: environment,
|
environment: environment,
|
||||||
): result<expressionValue, 'e> => {
|
): result<internalExpressionValue, 'e> => {
|
||||||
let racc: result<list<expressionValue>, 'e> = expressions->Belt.List.reduceReverse(Ok(list{}), (
|
let racc: result<
|
||||||
racc,
|
list<internalExpressionValue>,
|
||||||
each: expression,
|
'e,
|
||||||
) =>
|
> = expressions->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
|
||||||
racc->Result.flatMap(acc => {
|
racc->Result.flatMap(acc => {
|
||||||
each
|
each
|
||||||
->reduceExpression(bindings, environment)
|
->reduceExpression(bindings, environment)
|
||||||
|
@ -69,12 +69,12 @@ and reduceExpressionList = (
|
||||||
/*
|
/*
|
||||||
After reducing each level of expression(Lisp AST), we have a value list to evaluate
|
After reducing each level of expression(Lisp AST), we have a value list to evaluate
|
||||||
*/
|
*/
|
||||||
and reduceValueList = (valueList: list<expressionValue>, environment): result<
|
and reduceValueList = (valueList: list<internalExpressionValue>, environment): result<
|
||||||
expressionValue,
|
internalExpressionValue,
|
||||||
'e,
|
'e,
|
||||||
> =>
|
> =>
|
||||||
switch valueList {
|
switch valueList {
|
||||||
| list{EvCall(fName), ...args} => {
|
| list{IEvCall(fName), ...args} => {
|
||||||
let rCheckedArgs = switch fName {
|
let rCheckedArgs = switch fName {
|
||||||
| "$_setBindings_$" | "$_setTypeOfBindings_$" | "$_setTypeAliasBindings_$" => args->Ok
|
| "$_setBindings_$" | "$_setTypeOfBindings_$" | "$_setTypeAliasBindings_$" => args->Ok
|
||||||
| _ => args->Lambda.checkIfReduced
|
| _ => args->Lambda.checkIfReduced
|
||||||
|
@ -84,14 +84,14 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
|
||||||
(fName, checkedArgs->Belt.List.toArray)->BuiltIn.dispatch(environment, reduceExpression)
|
(fName, checkedArgs->Belt.List.toArray)->BuiltIn.dispatch(environment, reduceExpression)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
| list{EvLambda(_)} =>
|
| list{IEvLambda(_)} =>
|
||||||
// TODO: remove on solving issue#558
|
// TODO: remove on solving issue#558
|
||||||
valueList
|
valueList
|
||||||
->Lambda.checkIfReduced
|
->Lambda.checkIfReduced
|
||||||
->Result.flatMap(reducedValueList =>
|
->Result.flatMap(reducedValueList =>
|
||||||
reducedValueList->Belt.List.toArray->ExpressionValue.EvArray->Ok
|
reducedValueList->Belt.List.toArray->InternalExpressionValue.IEvArray->Ok
|
||||||
)
|
)
|
||||||
| list{EvLambda(lamdaCall), ...args} =>
|
| list{IEvLambda(lamdaCall), ...args} =>
|
||||||
args
|
args
|
||||||
->Lambda.checkIfReduced
|
->Lambda.checkIfReduced
|
||||||
->Result.flatMap(checkedArgs =>
|
->Result.flatMap(checkedArgs =>
|
||||||
|
@ -102,60 +102,55 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
|
||||||
valueList
|
valueList
|
||||||
->Lambda.checkIfReduced
|
->Lambda.checkIfReduced
|
||||||
->Result.flatMap(reducedValueList =>
|
->Result.flatMap(reducedValueList =>
|
||||||
reducedValueList->Belt.List.toArray->ExpressionValue.EvArray->Ok
|
reducedValueList->Belt.List.toArray->InternalExpressionValue.IEvArray->Ok
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let evalUsingBindingsExpression_ = (aExpression, bindings, environment): result<
|
let evalUsingBindingsExpression_ = (aExpression, bindings, environment): result<
|
||||||
expressionValue,
|
internalExpressionValue,
|
||||||
'e,
|
'e,
|
||||||
> => reduceExpression(aExpression, bindings, environment)
|
> => reduceExpression(aExpression, bindings, environment)
|
||||||
|
|
||||||
let evaluateUsingOptions = (
|
let evaluateUsingOptions = (
|
||||||
~environment: option<ReducerInterface_ExpressionValue.environment>,
|
~environment: option<ReducerInterface_ExternalExpressionValue.environment>,
|
||||||
~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>,
|
~externalBindings: option<ReducerInterface_ExternalExpressionValue.externalBindings>,
|
||||||
code: string,
|
code: string,
|
||||||
): result<expressionValue, errorValue> => {
|
): result<externalExpressionValue, errorValue> => {
|
||||||
let anEnvironment = Belt.Option.getWithDefault(
|
let anEnvironment = Belt.Option.getWithDefault(
|
||||||
environment,
|
environment,
|
||||||
ReducerInterface_ExpressionValue.defaultEnvironment,
|
ReducerInterface_ExternalExpressionValue.defaultEnvironment,
|
||||||
)
|
)
|
||||||
|
|
||||||
let anExternalBindings = switch externalBindings {
|
let mergedBindings: InternalExpressionValue.nameSpace = Module.merge(
|
||||||
| Some(bindings) => {
|
ReducerInterface_StdLib.internalStdLib,
|
||||||
let cloneLib = ReducerInterface_StdLib.externalStdLib->Reducer_Category_Bindings.cloneRecord
|
Belt.Option.map(externalBindings, Module.fromTypeScriptBindings)->Belt.Option.getWithDefault(
|
||||||
Js.Dict.entries(bindings)->Js.Array2.reduce((acc, (key, value)) => {
|
Module.emptyModule,
|
||||||
acc->Js.Dict.set(key, value)
|
),
|
||||||
acc
|
)
|
||||||
}, cloneLib)
|
|
||||||
}
|
|
||||||
| None => ReducerInterface_StdLib.externalStdLib
|
|
||||||
}
|
|
||||||
|
|
||||||
let bindings = anExternalBindings->Bindings.fromExternalBindings
|
parse(code)
|
||||||
|
->Result.flatMap(expr => evalUsingBindingsExpression_(expr, mergedBindings, anEnvironment))
|
||||||
parse(code)->Result.flatMap(expr => evalUsingBindingsExpression_(expr, bindings, anEnvironment))
|
->Result.map(ReducerInterface_InternalExpressionValue.toExternal)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Evaluates Squiggle code and bindings via Reducer and answers the result
|
IEvaluates Squiggle code and bindings via Reducer and answers the result
|
||||||
*/
|
*/
|
||||||
let evaluate = (code: string): result<expressionValue, errorValue> => {
|
let evaluate = (code: string): result<externalExpressionValue, errorValue> => {
|
||||||
evaluateUsingOptions(~environment=None, ~externalBindings=None, code)
|
evaluateUsingOptions(~environment=None, ~externalBindings=None, code)
|
||||||
}
|
}
|
||||||
let eval = evaluate
|
|
||||||
let evaluatePartialUsingExternalBindings = (
|
let evaluatePartialUsingExternalBindings = (
|
||||||
code: string,
|
code: string,
|
||||||
externalBindings: ReducerInterface_ExpressionValue.externalBindings,
|
externalBindings: ReducerInterface_ExternalExpressionValue.externalBindings,
|
||||||
environment: ReducerInterface_ExpressionValue.environment,
|
environment: ReducerInterface_ExternalExpressionValue.environment,
|
||||||
): result<externalBindings, errorValue> => {
|
): result<ReducerInterface_ExternalExpressionValue.externalBindings, errorValue> => {
|
||||||
let rAnswer = evaluateUsingOptions(
|
let rAnswer = evaluateUsingOptions(
|
||||||
~environment=Some(environment),
|
~environment=Some(environment),
|
||||||
~externalBindings=Some(externalBindings),
|
~externalBindings=Some(externalBindings),
|
||||||
code,
|
code,
|
||||||
)
|
)
|
||||||
switch rAnswer {
|
switch rAnswer {
|
||||||
| Ok(EvRecord(externalBindings)) => Ok(externalBindings)
|
| Ok(EvModule(externalBindings)) => Ok(externalBindings)
|
||||||
| Ok(_) =>
|
| Ok(_) =>
|
||||||
Error(Reducer_ErrorValue.RESyntaxError(`Partials must end with an assignment or record`, None))
|
Error(Reducer_ErrorValue.RESyntaxError(`Partials must end with an assignment or record`, None))
|
||||||
| Error(err) => err->Error
|
| Error(err) => err->Error
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
module Bindings = Reducer_Expression_Bindings
|
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module ErrorValue = Reducer_ErrorValue
|
module ErrorValue = Reducer_ErrorValue
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
|
|
||||||
type bindings = ExpressionT.bindings
|
type bindings = ExpressionT.bindings
|
||||||
type context = bindings
|
type context = bindings
|
||||||
type environment = ExpressionValue.environment
|
type environment = InternalExpressionValue.environment
|
||||||
type errorValue = Reducer_ErrorValue.errorValue
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
type expression = ExpressionT.expression
|
type expression = ExpressionT.expression
|
||||||
type expressionValue = ExpressionValue.expressionValue
|
type internalExpressionValue = InternalExpressionValue.t
|
||||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
|
||||||
type reducerFn = ExpressionT.reducerFn
|
type reducerFn = ExpressionT.reducerFn
|
||||||
|
|
||||||
type expressionWithContext =
|
type expressionWithContext =
|
||||||
|
@ -22,7 +22,7 @@ let callReducer = (
|
||||||
bindings: bindings,
|
bindings: bindings,
|
||||||
environment: environment,
|
environment: environment,
|
||||||
reducer: reducerFn,
|
reducer: reducerFn,
|
||||||
): result<expressionValue, errorValue> => {
|
): result<internalExpressionValue, errorValue> => {
|
||||||
switch expressionWithContext {
|
switch expressionWithContext {
|
||||||
| ExpressionNoContext(expr) =>
|
| ExpressionNoContext(expr) =>
|
||||||
// Js.log(`callReducer: bindings ${Bindings.toString(bindings)} expr ${ExpressionT.toString(expr)}`)
|
// Js.log(`callReducer: bindings ${Bindings.toString(bindings)} expr ${ExpressionT.toString(expr)}`)
|
||||||
|
@ -40,7 +40,9 @@ let toString = expressionWithContext =>
|
||||||
switch expressionWithContext {
|
switch expressionWithContext {
|
||||||
| ExpressionNoContext(expr) => ExpressionT.toString(expr)
|
| ExpressionNoContext(expr) => ExpressionT.toString(expr)
|
||||||
| ExpressionWithContext(expr, context) =>
|
| ExpressionWithContext(expr, context) =>
|
||||||
`${ExpressionT.toString(expr)} context: ${Bindings.toString(context)}`
|
`${ExpressionT.toString(expr)} context: ${context
|
||||||
|
->Module.toExpressionValue
|
||||||
|
->InternalExpressionValue.toString}`
|
||||||
}
|
}
|
||||||
|
|
||||||
let toStringResult = rExpressionWithContext =>
|
let toStringResult = rExpressionWithContext =>
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
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 emptyBindings = Reducer_Category_Bindings.emptyBindings
|
|
||||||
|
|
||||||
let typeAliasesKey = Bindings.typeAliasesKey
|
|
||||||
let typeReferencesKey = Bindings.typeReferencesKey
|
|
||||||
|
|
||||||
let toExternalBindings = (bindings: ExpressionT.bindings): externalBindings =>
|
|
||||||
Bindings.toRecord(bindings)
|
|
||||||
|
|
||||||
let fromExternalBindings = (externalBindings: externalBindings): ExpressionT.bindings =>
|
|
||||||
Bindings.fromRecord(externalBindings)
|
|
||||||
|
|
||||||
let fromValue = (aValue: expressionValue) => Bindings.fromExpressionValue(aValue)
|
|
||||||
|
|
||||||
let isMacroName = (fName: string): bool => fName->Js.String2.startsWith("$$")
|
|
||||||
|
|
||||||
let rec replaceSymbols = (bindings: ExpressionT.bindings, expression: expression): result<
|
|
||||||
expression,
|
|
||||||
errorValue,
|
|
||||||
> =>
|
|
||||||
switch expression {
|
|
||||||
| ExpressionT.EValue(value) =>
|
|
||||||
replaceSymbolOnValue(bindings, value)->Result.map(evValue => evValue->ExpressionT.EValue)
|
|
||||||
| ExpressionT.EList(list) =>
|
|
||||||
switch list {
|
|
||||||
| list{EValue(EvCall(fName)), ..._args} =>
|
|
||||||
switch isMacroName(fName) {
|
|
||||||
// A macro reduces itself so we dont dive in it
|
|
||||||
| true => expression->Ok
|
|
||||||
| false => replaceSymbolsOnExpressionList(bindings, list)
|
|
||||||
}
|
|
||||||
| _ => replaceSymbolsOnExpressionList(bindings, list)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
and replaceSymbolsOnExpressionList = (bindings, list) => {
|
|
||||||
let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
|
|
||||||
racc->Result.flatMap(acc => {
|
|
||||||
replaceSymbols(bindings, each)->Result.flatMap(newNode => {
|
|
||||||
acc->Belt.List.add(newNode)->Ok
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)
|
|
||||||
racc->Result.map(acc => acc->ExpressionT.EList)
|
|
||||||
}
|
|
||||||
and replaceSymbolOnValue = (bindings, evValue: expressionValue) =>
|
|
||||||
switch evValue {
|
|
||||||
| EvSymbol(symbol) => Belt.Map.String.getWithDefault(bindings, symbol, evValue)->Ok
|
|
||||||
| EvCall(symbol) => Belt.Map.String.getWithDefault(bindings, symbol, evValue)->checkIfCallable
|
|
||||||
| _ => evValue->Ok
|
|
||||||
}
|
|
||||||
and checkIfCallable = (evValue: expressionValue) =>
|
|
||||||
switch evValue {
|
|
||||||
| EvCall(_) | EvLambda(_) => evValue->Ok
|
|
||||||
| _ => ErrorValue.RENotAFunction(ExpressionValue.toString(evValue))->Error
|
|
||||||
}
|
|
||||||
|
|
||||||
let toString = (bindings: ExpressionT.bindings) =>
|
|
||||||
bindings->toExternalBindings->ExpressionValue.EvRecord->ExpressionValue.toString
|
|
||||||
|
|
||||||
let externalBindingsToString = (externalBindings: externalBindings) =>
|
|
||||||
externalBindings->ExpressionValue.EvRecord->ExpressionValue.toString
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
module ErrorValue = Reducer_ErrorValue
|
||||||
|
module ExpressionT = Reducer_Expression_T
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
module Result = Belt.Result
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
|
|
||||||
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
|
type expression = ExpressionT.expression
|
||||||
|
type internalExpressionValue = InternalExpressionValue.t
|
||||||
|
type externalBindings = ReducerInterface_ExternalExpressionValue.externalBindings
|
||||||
|
|
||||||
|
let isMacroName = (fName: string): bool => fName->Js.String2.startsWith("$$")
|
||||||
|
|
||||||
|
let rec replaceSymbols = (bindings: ExpressionT.bindings, expression: expression): result<
|
||||||
|
expression,
|
||||||
|
errorValue,
|
||||||
|
> =>
|
||||||
|
switch expression {
|
||||||
|
| ExpressionT.EValue(value) =>
|
||||||
|
replaceSymbolOnValue(bindings, value)->Result.map(evValue => evValue->ExpressionT.EValue)
|
||||||
|
| ExpressionT.EList(list) =>
|
||||||
|
switch list {
|
||||||
|
| list{EValue(IEvCall(fName)), ..._args} =>
|
||||||
|
switch isMacroName(fName) {
|
||||||
|
// A macro reduces itself so we dont dive in it
|
||||||
|
| true => expression->Ok
|
||||||
|
| false => replaceSymbolsOnExpressionList(bindings, list)
|
||||||
|
}
|
||||||
|
| _ => replaceSymbolsOnExpressionList(bindings, list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
and replaceSymbolsOnExpressionList = (bindings, list) => {
|
||||||
|
let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
|
||||||
|
racc->Result.flatMap(acc => {
|
||||||
|
replaceSymbols(bindings, each)->Result.flatMap(newNode => {
|
||||||
|
acc->Belt.List.add(newNode)->Ok
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
racc->Result.map(acc => acc->ExpressionT.EList)
|
||||||
|
}
|
||||||
|
and replaceSymbolOnValue = (bindings, evValue: internalExpressionValue) =>
|
||||||
|
switch evValue {
|
||||||
|
| IEvSymbol(symbol) => Module.getWithDefault(bindings, symbol, evValue)->Ok
|
||||||
|
| IEvCall(symbol) => Module.getWithDefault(bindings, symbol, evValue)->checkIfCallable
|
||||||
|
| _ => evValue->Ok
|
||||||
|
}
|
||||||
|
and checkIfCallable = (evValue: internalExpressionValue) =>
|
||||||
|
switch evValue {
|
||||||
|
| IEvCall(_) | IEvLambda(_) => evValue->Ok
|
||||||
|
| _ => ErrorValue.RENotAFunction(InternalExpressionValue.toString(evValue))->Error
|
||||||
|
}
|
|
@ -1,24 +1,28 @@
|
||||||
module BBindings = Reducer_Expression_Bindings
|
module BBindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module BErrorValue = Reducer_ErrorValue
|
module BErrorValue = Reducer_ErrorValue
|
||||||
module BExpressionT = Reducer_Expression_T
|
module BExpressionT = Reducer_Expression_T
|
||||||
module BExpressionValue = ReducerInterface.ExpressionValue
|
module BInternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
module BModule = Reducer_Category_Module
|
||||||
|
|
||||||
type errorValue = BErrorValue.errorValue
|
type errorValue = BErrorValue.errorValue
|
||||||
type expression = BExpressionT.expression
|
type expression = BExpressionT.expression
|
||||||
type internalCode = ReducerInterface_ExpressionValue.internalCode
|
type expressionOrFFI = BExpressionT.expressionOrFFI
|
||||||
|
type ffiFn = BExpressionT.ffiFn
|
||||||
|
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
||||||
|
|
||||||
external castExpressionToInternalCode: expression => internalCode = "%identity"
|
external castExpressionToInternalCode: expressionOrFFI => internalCode = "%identity"
|
||||||
|
|
||||||
let eArray = anArray => anArray->BExpressionValue.EvArray->BExpressionT.EValue
|
let eArray = anArray => anArray->BInternalExpressionValue.IEvArray->BExpressionT.EValue
|
||||||
|
|
||||||
let eArrayString = anArray => anArray->BExpressionValue.EvArrayString->BExpressionT.EValue
|
let eArrayString = anArray => anArray->BInternalExpressionValue.IEvArrayString->BExpressionT.EValue
|
||||||
|
|
||||||
let eBindings = (anArray: array<(string, BExpressionValue.expressionValue)>) =>
|
let eBindings = (anArray: array<(string, BInternalExpressionValue.t)>) =>
|
||||||
anArray->Js.Dict.fromArray->BExpressionValue.EvRecord->BExpressionT.EValue
|
anArray->BModule.fromArray->BModule.toExpressionValue->BExpressionT.EValue
|
||||||
|
|
||||||
let eBool = aBool => aBool->BExpressionValue.EvBool->BExpressionT.EValue
|
let eBool = aBool => aBool->BInternalExpressionValue.IEvBool->BExpressionT.EValue
|
||||||
|
|
||||||
let eCall = (name: string): expression => name->BExpressionValue.EvCall->BExpressionT.EValue
|
let eCall = (name: string): expression =>
|
||||||
|
name->BInternalExpressionValue.IEvCall->BExpressionT.EValue
|
||||||
|
|
||||||
let eFunction = (fName: string, lispArgs: list<expression>): expression => {
|
let eFunction = (fName: string, lispArgs: list<expression>): expression => {
|
||||||
let fn = fName->eCall
|
let fn = fName->eCall
|
||||||
|
@ -27,29 +31,41 @@ let eFunction = (fName: string, lispArgs: list<expression>): expression => {
|
||||||
|
|
||||||
let eLambda = (
|
let eLambda = (
|
||||||
parameters: array<string>,
|
parameters: array<string>,
|
||||||
context: BExpressionValue.externalBindings,
|
context: BInternalExpressionValue.nameSpace,
|
||||||
expr: expression,
|
expr: expression,
|
||||||
) => {
|
) => {
|
||||||
// Js.log(`eLambda context ${BBindings.externalBindingsToString(context)}`)
|
BInternalExpressionValue.IEvLambda({
|
||||||
BExpressionValue.EvLambda({
|
|
||||||
parameters: parameters,
|
parameters: parameters,
|
||||||
context: context,
|
context: context,
|
||||||
body: expr->castExpressionToInternalCode,
|
body: NotFFI(expr)->castExpressionToInternalCode,
|
||||||
})->BExpressionT.EValue
|
})->BExpressionT.EValue
|
||||||
}
|
}
|
||||||
|
|
||||||
let eNumber = aNumber => aNumber->BExpressionValue.EvNumber->BExpressionT.EValue
|
let eLambdaFFI = (parameters: array<string>, ffiFn: ffiFn) => {
|
||||||
|
let context = BModule.emptyModule
|
||||||
|
BInternalExpressionValue.IEvLambda({
|
||||||
|
parameters: parameters,
|
||||||
|
context: context,
|
||||||
|
body: FFI(ffiFn)->castExpressionToInternalCode,
|
||||||
|
})->BExpressionT.EValue
|
||||||
|
}
|
||||||
|
|
||||||
let eRecord = aRecord => aRecord->BExpressionValue.EvRecord->BExpressionT.EValue
|
let eNumber = aNumber => aNumber->BInternalExpressionValue.IEvNumber->BExpressionT.EValue
|
||||||
|
|
||||||
let eString = aString => aString->BExpressionValue.EvString->BExpressionT.EValue
|
let eRecord = aMap => aMap->BInternalExpressionValue.IEvRecord->BExpressionT.EValue
|
||||||
|
|
||||||
let eSymbol = (name: string): expression => name->BExpressionValue.EvSymbol->BExpressionT.EValue
|
let eString = aString => aString->BInternalExpressionValue.IEvString->BExpressionT.EValue
|
||||||
|
|
||||||
|
let eSymbol = (name: string): expression =>
|
||||||
|
name->BInternalExpressionValue.IEvSymbol->BExpressionT.EValue
|
||||||
|
|
||||||
let eList = (list: list<expression>): expression => list->BExpressionT.EList
|
let eList = (list: list<expression>): expression => list->BExpressionT.EList
|
||||||
|
|
||||||
let eBlock = (exprs: list<expression>): expression => eFunction("$$_block_$$", exprs)
|
let eBlock = (exprs: list<expression>): expression => eFunction("$$_block_$$", exprs)
|
||||||
|
|
||||||
|
let eModule = (nameSpace: BInternalExpressionValue.nameSpace): expression =>
|
||||||
|
nameSpace->BInternalExpressionValue.IEvModule->BExpressionT.EValue
|
||||||
|
|
||||||
let eLetStatement = (symbol: string, valueExpression: expression): expression =>
|
let eLetStatement = (symbol: string, valueExpression: expression): expression =>
|
||||||
eFunction("$_let_$", list{eSymbol(symbol), valueExpression})
|
eFunction("$_let_$", list{eSymbol(symbol), valueExpression})
|
||||||
|
|
||||||
|
@ -65,7 +81,8 @@ let eBindExpression = (bindingExpr: expression, expression: expression): express
|
||||||
let eBindExpressionDefault = (expression: expression): expression =>
|
let eBindExpressionDefault = (expression: expression): expression =>
|
||||||
eFunction("$$_bindExpression_$$", list{expression})
|
eFunction("$$_bindExpression_$$", list{expression})
|
||||||
|
|
||||||
let eIdentifier = (name: string): expression => name->BExpressionValue.EvSymbol->BExpressionT.EValue
|
let eIdentifier = (name: string): expression =>
|
||||||
|
name->BInternalExpressionValue.IEvSymbol->BExpressionT.EValue
|
||||||
|
|
||||||
let eTypeIdentifier = (name: string): expression =>
|
let eTypeIdentifier = (name: string): expression =>
|
||||||
name->BExpressionValue.EvTypeIdentifier->BExpressionT.EValue
|
name->BInternalExpressionValue.IEvTypeIdentifier->BExpressionT.EValue
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
module Bindings = Reducer_Expression_Bindings
|
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module ErrorValue = Reducer_ErrorValue
|
module ErrorValue = Reducer_ErrorValue
|
||||||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
module Module = Reducer_Category_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
|
|
||||||
type environment = ReducerInterface_ExpressionValue.environment
|
type environment = ReducerInterface_InternalExpressionValue.environment
|
||||||
type expression = ExpressionT.expression
|
type expression = ExpressionT.expression
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type expressionOrFFI = ExpressionT.expressionOrFFI
|
||||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
type internalExpressionValue = ReducerInterface_InternalExpressionValue.t
|
||||||
type internalCode = ReducerInterface_ExpressionValue.internalCode
|
// type tmpExternalBindings = ReducerInterface_InternalExpressionValue.tmpExternalBindings
|
||||||
|
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
||||||
|
|
||||||
external castInternalCodeToExpression: internalCode => expression = "%identity"
|
external castInternalCodeToExpression: internalCode => expressionOrFFI = "%identity"
|
||||||
|
|
||||||
let checkArity = (lambdaValue: ExpressionValue.lambdaValue, args: list<expressionValue>) => {
|
let checkArity = (
|
||||||
|
lambdaValue: ExpressionValue.lambdaValue,
|
||||||
|
args: list<internalExpressionValue>,
|
||||||
|
) => {
|
||||||
let argsLength = Belt.List.length(args)
|
let argsLength = Belt.List.length(args)
|
||||||
let parametersLength = Js.Array2.length(lambdaValue.parameters)
|
let parametersLength = Js.Array2.length(lambdaValue.parameters)
|
||||||
if argsLength !== parametersLength {
|
if argsLength !== parametersLength {
|
||||||
|
@ -23,34 +28,44 @@ let checkArity = (lambdaValue: ExpressionValue.lambdaValue, args: list<expressio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let checkIfReduced = (args: list<expressionValue>) =>
|
let checkIfReduced = (args: list<internalExpressionValue>) =>
|
||||||
args->Belt.List.reduceReverse(Ok(list{}), (rAcc, arg) =>
|
args->Belt.List.reduceReverse(Ok(list{}), (rAcc, arg) =>
|
||||||
rAcc->Result.flatMap(acc =>
|
rAcc->Result.flatMap(acc =>
|
||||||
switch arg {
|
switch arg {
|
||||||
| EvSymbol(symbol) => ErrorValue.RESymbolNotFound(symbol)->Error
|
| IEvSymbol(symbol) => ErrorValue.RESymbolNotFound(symbol)->Error
|
||||||
| _ => list{arg, ...acc}->Ok
|
| _ => list{arg, ...acc}->Ok
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let caseNotFFI = (lambdaValue: ExpressionValue.lambdaValue, expr, args, environment, reducer) => {
|
||||||
|
let parameterList = lambdaValue.parameters->Belt.List.fromArray
|
||||||
|
let zippedParameterList = parameterList->Belt.List.zip(args)
|
||||||
|
let bindings = Belt.List.reduce(zippedParameterList, lambdaValue.context, (
|
||||||
|
acc,
|
||||||
|
(variable, variableValue),
|
||||||
|
) => acc->Module.set(variable, variableValue))
|
||||||
|
let newExpression = ExpressionBuilder.eBlock(list{expr})
|
||||||
|
reducer(newExpression, bindings, environment)
|
||||||
|
}
|
||||||
|
|
||||||
|
let caseFFI = (ffiFn: ExpressionT.ffiFn, args, environment) => {
|
||||||
|
ffiFn(args->Belt.List.toArray, environment)
|
||||||
|
}
|
||||||
|
|
||||||
let applyParametersToLambda = (
|
let applyParametersToLambda = (
|
||||||
lambdaValue: ExpressionValue.lambdaValue,
|
lambdaValue: ExpressionValue.lambdaValue,
|
||||||
args,
|
args,
|
||||||
environment,
|
environment,
|
||||||
reducer: ExpressionT.reducerFn,
|
reducer: ExpressionT.reducerFn,
|
||||||
): result<expressionValue, 'e> => {
|
): result<internalExpressionValue, 'e> => {
|
||||||
checkArity(lambdaValue, args)->Result.flatMap(args =>
|
checkArity(lambdaValue, args)->Result.flatMap(args =>
|
||||||
checkIfReduced(args)->Result.flatMap(args => {
|
checkIfReduced(args)->Result.flatMap(args => {
|
||||||
let expr = castInternalCodeToExpression(lambdaValue.body)
|
let exprOrFFI = castInternalCodeToExpression(lambdaValue.body)
|
||||||
let parameterList = lambdaValue.parameters->Belt.List.fromArray
|
switch exprOrFFI {
|
||||||
let zippedParameterList = parameterList->Belt.List.zip(args)
|
| NotFFI(expr) => caseNotFFI(lambdaValue, expr, args, environment, reducer)
|
||||||
let bindings = Belt.List.reduce(
|
| FFI(ffiFn) => caseFFI(ffiFn, args, environment)
|
||||||
zippedParameterList,
|
}
|
||||||
lambdaValue.context->Bindings.fromExternalBindings,
|
|
||||||
(acc, (variable, variableValue)) => acc->Belt.Map.String.set(variable, variableValue),
|
|
||||||
)
|
|
||||||
let newExpression = ExpressionBuilder.eBlock(list{expr})
|
|
||||||
reducer(newExpression, bindings, environment)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -60,10 +75,10 @@ let doLambdaCall = (lambdaValue: ExpressionValue.lambdaValue, args, environment,
|
||||||
|
|
||||||
let foreignFunctionInterface = (
|
let foreignFunctionInterface = (
|
||||||
lambdaValue: ExpressionValue.lambdaValue,
|
lambdaValue: ExpressionValue.lambdaValue,
|
||||||
argArray: array<expressionValue>,
|
argArray: array<internalExpressionValue>,
|
||||||
environment: ExpressionValue.environment,
|
environment: ExpressionValue.environment,
|
||||||
reducer: ExpressionT.reducerFn,
|
reducer: ExpressionT.reducerFn,
|
||||||
): result<expressionValue, 'e> => {
|
): result<internalExpressionValue, 'e> => {
|
||||||
let args = argArray->Belt.List.fromArray
|
let args = argArray->Belt.List.fromArray
|
||||||
applyParametersToLambda(lambdaValue, args, environment, reducer)
|
applyParametersToLambda(lambdaValue, args, environment, reducer)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
|
|
||||||
type environment = ExpressionValue.environment
|
type environment = InternalExpressionValue.environment
|
||||||
type expression = ExpressionT.expression
|
type expression = ExpressionT.expression
|
||||||
type expressionValue = ExpressionValue.expressionValue
|
type internalExpressionValue = InternalExpressionValue.t
|
||||||
type expressionWithContext = ExpressionWithContext.expressionWithContext
|
type expressionWithContext = ExpressionWithContext.expressionWithContext
|
||||||
|
|
||||||
let expandMacroCall = (
|
let expandMacroCall = (
|
||||||
|
@ -26,7 +26,7 @@ let doMacroCall = (
|
||||||
bindings: ExpressionT.bindings,
|
bindings: ExpressionT.bindings,
|
||||||
environment: environment,
|
environment: environment,
|
||||||
reduceExpression: ExpressionT.reducerFn,
|
reduceExpression: ExpressionT.reducerFn,
|
||||||
): result<expressionValue, 'e> =>
|
): result<internalExpressionValue, 'e> =>
|
||||||
expandMacroCall(
|
expandMacroCall(
|
||||||
macroExpression,
|
macroExpression,
|
||||||
bindings,
|
bindings,
|
||||||
|
|
|
@ -7,28 +7,28 @@
|
||||||
The act of defining the semantics of a functional language is to write it in terms of Lisp AST.
|
The act of defining the semantics of a functional language is to write it in terms of Lisp AST.
|
||||||
*/
|
*/
|
||||||
module Extra = Reducer_Extra
|
module Extra = Reducer_Extra
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
|
||||||
type expressionValue = ExpressionValue.expressionValue
|
type internalExpressionValue = InternalExpressionValue.t
|
||||||
type environment = ExpressionValue.environment
|
type environment = ReducerInterface_InternalExpressionValue.environment
|
||||||
|
|
||||||
type rec expression =
|
type rec expression =
|
||||||
| EList(list<expression>) // A list to map-reduce
|
| EList(list<expression>) // A list to map-reduce
|
||||||
| EValue(expressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible
|
| EValue(internalExpressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible
|
||||||
and bindings = Belt.Map.String.t<expressionValue>
|
and bindings = InternalExpressionValue.nameSpace
|
||||||
|
|
||||||
type reducerFn = (
|
type reducerFn = (
|
||||||
expression,
|
expression,
|
||||||
bindings,
|
bindings,
|
||||||
environment,
|
environment,
|
||||||
) => result<expressionValue, Reducer_ErrorValue.errorValue>
|
) => result<internalExpressionValue, Reducer_ErrorValue.errorValue>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Converts the expression to String
|
Converts the expression to String
|
||||||
*/
|
*/
|
||||||
let rec toString = expression =>
|
let rec toString = expression =>
|
||||||
switch expression {
|
switch expression {
|
||||||
| EList(list{EValue(EvCall("$$_block_$$")), ...statements}) =>
|
| EList(list{EValue(IEvCall("$$_block_$$")), ...statements}) =>
|
||||||
`{${Belt.List.map(statements, aValue => toString(aValue))
|
`{${Belt.List.map(statements, aValue => toString(aValue))
|
||||||
->Extra.List.interperse("; ")
|
->Extra.List.interperse("; ")
|
||||||
->Belt.List.toArray
|
->Belt.List.toArray
|
||||||
|
@ -38,7 +38,7 @@ let rec toString = expression =>
|
||||||
->Extra.List.interperse(" ")
|
->Extra.List.interperse(" ")
|
||||||
->Belt.List.toArray
|
->Belt.List.toArray
|
||||||
->Js.String.concatMany("")})`
|
->Js.String.concatMany("")})`
|
||||||
| EValue(aValue) => ExpressionValue.toString(aValue)
|
| EValue(aValue) => InternalExpressionValue.toString(aValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
let toStringResult = codeResult =>
|
let toStringResult = codeResult =>
|
||||||
|
@ -65,3 +65,12 @@ let inspectResult = (r: result<expression, Reducer_ErrorValue.errorValue>): resu
|
||||||
Js.log(toStringResult(r))
|
Js.log(toStringResult(r))
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ffiFn = (
|
||||||
|
array<internalExpressionValue>,
|
||||||
|
environment,
|
||||||
|
) => result<internalExpressionValue, Reducer_ErrorValue.errorValue>
|
||||||
|
|
||||||
|
type expressionOrFFI =
|
||||||
|
| NotFFI(expression)
|
||||||
|
| FFI(ffiFn)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
open ReducerInterface.ExpressionValue
|
open ReducerInterface_InternalExpressionValue
|
||||||
open Reducer_ErrorValue
|
open Reducer_ErrorValue
|
||||||
|
|
||||||
external castBool: unit => bool = "%identity"
|
external castBool: unit => bool = "%identity"
|
||||||
|
@ -8,10 +8,10 @@ external castString: unit => string = "%identity"
|
||||||
/*
|
/*
|
||||||
As JavaScript returns us any type, we need to type check and cast type propertype before using it
|
As JavaScript returns us any type, we need to type check and cast type propertype before using it
|
||||||
*/
|
*/
|
||||||
let jsToEv = (jsValue): result<expressionValue, errorValue> =>
|
let jsToIEv = (jsValue): result<internalExpressionValue, errorValue> =>
|
||||||
switch Js.typeof(jsValue) {
|
switch Js.typeof(jsValue) {
|
||||||
| "boolean" => jsValue->castBool->EvBool->Ok
|
| "boolean" => jsValue->castBool->IEvBool->Ok
|
||||||
| "number" => jsValue->castNumber->EvNumber->Ok
|
| "number" => jsValue->castNumber->IEvNumber->Ok
|
||||||
| "string" => jsValue->castString->EvString->Ok
|
| "string" => jsValue->castString->IEvString->Ok
|
||||||
| other => RETodo(`Unhandled MathJs literal type: ${Js.String.make(other)}`)->Error
|
| other => RETodo(`Unhandled MathJs literal type: ${Js.String.make(other)}`)->Error
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module JavaScript = Reducer_Js
|
module JavaScript = Reducer_Js
|
||||||
open ReducerInterface.ExpressionValue
|
open ReducerInterface_InternalExpressionValue
|
||||||
open Reducer_ErrorValue
|
open Reducer_ErrorValue
|
||||||
|
|
||||||
@module("mathjs") external dummy_: string => unit = "evaluate"
|
@module("mathjs") external dummy_: string => unit = "evaluate"
|
||||||
|
@ -17,10 +17,10 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat
|
||||||
/*
|
/*
|
||||||
Call MathJs evaluate and return as a variant
|
Call MathJs evaluate and return as a variant
|
||||||
*/
|
*/
|
||||||
let eval = (expr: string): result<expressionValue, errorValue> => {
|
let eval = (expr: string): result<internalExpressionValue, errorValue> => {
|
||||||
try {
|
try {
|
||||||
let answer = eval__(expr)
|
let answer = eval__(expr)
|
||||||
answer["value"]->JavaScript.Gate.jsToEv
|
answer["value"]->JavaScript.Gate.jsToIEv
|
||||||
} catch {
|
} catch {
|
||||||
| Js.Exn.Error(obj) => REJavaScriptExn(Js.Exn.message(obj), Js.Exn.name(obj))->Error
|
| Js.Exn.Error(obj) => REJavaScriptExn(Js.Exn.message(obj), Js.Exn.name(obj))->Error
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,74 +1,7 @@
|
||||||
// Try in https://peggyjs.org/online
|
// Try in https://peggyjs.org/online
|
||||||
|
|
||||||
{{
|
{{
|
||||||
var toFunction = {
|
const h = require('./helpers');
|
||||||
'-': 'subtract',
|
|
||||||
'->': 'pipe',
|
|
||||||
'!=': 'unequal',
|
|
||||||
'.-': 'dotSubtract',
|
|
||||||
'.*': 'dotMultiply',
|
|
||||||
'./': 'dotDivide',
|
|
||||||
'.^': 'dotPow',
|
|
||||||
'.+': 'dotAdd',
|
|
||||||
'*': 'multiply',
|
|
||||||
'/': 'divide',
|
|
||||||
'&&': 'and',
|
|
||||||
'^': 'pow', // or xor
|
|
||||||
'+': 'add',
|
|
||||||
'<': 'smaller',
|
|
||||||
'<=': 'smallerEq',
|
|
||||||
'==': 'equal',
|
|
||||||
'>': 'larger',
|
|
||||||
'>=': 'largerEq',
|
|
||||||
'||': 'or',
|
|
||||||
'to': 'credibleIntervalToDistribution',
|
|
||||||
}
|
|
||||||
|
|
||||||
var unaryToFunction = {
|
|
||||||
'-': 'unaryMinus',
|
|
||||||
'!': 'not',
|
|
||||||
'.-': 'unaryDotMinus',
|
|
||||||
}
|
|
||||||
|
|
||||||
var postOperatorToFunction = {
|
|
||||||
'.': '$_atIndex_$',
|
|
||||||
'()': '$$_applyAll_$$',
|
|
||||||
'[]': '$_atIndex_$',
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeFunctionCall(fn, args) {
|
|
||||||
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].type = "CallIdentifier"}
|
|
||||||
return nodeExpression(args)
|
|
||||||
} else {
|
|
||||||
return nodeExpression([nodeCallIndentifier(fn), ...args])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function apply(fn, arg) { return makeFunctionCall(fn, [arg]); }
|
|
||||||
function constructArray(elems) { return apply('$_constructArray_$', nodeExpression(elems)); }
|
|
||||||
function constructRecord(elems) { return apply('$_constructRecord_$', nodeExpression(elems)); }
|
|
||||||
|
|
||||||
function nodeBlock(statements) {return{type: 'Block', statements: statements}}
|
|
||||||
function nodeBoolean(value) {return {type: 'Boolean', value: value}}
|
|
||||||
function nodeCallIndentifier(value) {return {type: 'CallIdentifier', value: value}}
|
|
||||||
function nodeExpression(args) {return {type: 'Expression', nodes: args}}
|
|
||||||
function nodeFloat(value) {return {type: 'Float', value: value}}
|
|
||||||
function nodeIdentifier(value) {return {type: 'Identifier', value: value}}
|
|
||||||
function nodeInteger(value) {return {type: 'Integer', value: value}}
|
|
||||||
function nodeKeyValue(key, value) {
|
|
||||||
if (key.type === 'Identifier') {key.type = 'String'}
|
|
||||||
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}}
|
|
||||||
|
|
||||||
function nodeTypeIdentifier(typeValue) {return {type: 'TypeIdentifier', value: typeValue}}
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
start
|
start
|
||||||
|
@ -80,21 +13,21 @@ zeroOMoreArgumentsBlockOrExpression = innerBlockOrExpression / lambda
|
||||||
outerBlock
|
outerBlock
|
||||||
= statements:array_statements finalExpression: (statementSeparator @expression)?
|
= statements:array_statements finalExpression: (statementSeparator @expression)?
|
||||||
{ if (finalExpression != null) { statements.push(finalExpression) }
|
{ if (finalExpression != null) { statements.push(finalExpression) }
|
||||||
return nodeBlock(statements) }
|
return h.nodeBlock(statements) }
|
||||||
/ finalExpression: expression
|
/ finalExpression: expression
|
||||||
{ return nodeBlock([finalExpression])}
|
{ return h.nodeBlock([finalExpression])}
|
||||||
|
|
||||||
innerBlockOrExpression
|
innerBlockOrExpression
|
||||||
= quotedInnerBlock
|
= quotedInnerBlock
|
||||||
/ finalExpression: expression
|
/ finalExpression: expression
|
||||||
{ return nodeBlock([finalExpression])}
|
{ return h.nodeBlock([finalExpression])}
|
||||||
|
|
||||||
quotedInnerBlock
|
quotedInnerBlock
|
||||||
= '{' _nl statements:array_statements finalExpression: (statementSeparator @expression) _nl '}'
|
= '{' _nl statements:array_statements finalExpression: (statementSeparator @expression) _nl '}'
|
||||||
{ statements.push(finalExpression)
|
{ statements.push(finalExpression)
|
||||||
return nodeBlock(statements) }
|
return h.nodeBlock(statements) }
|
||||||
/ '{' _nl finalExpression: expression _nl '}'
|
/ '{' _nl finalExpression: expression _nl '}'
|
||||||
{ return nodeBlock([finalExpression]) }
|
{ return h.nodeBlock([finalExpression]) }
|
||||||
|
|
||||||
array_statements
|
array_statements
|
||||||
= head:statement tail:(statementSeparator @array_statements )
|
= head:statement tail:(statementSeparator @array_statements )
|
||||||
|
@ -109,12 +42,12 @@ statement
|
||||||
|
|
||||||
letStatement
|
letStatement
|
||||||
= variable:identifier _ assignmentOp _nl value:zeroOMoreArgumentsBlockOrExpression
|
= variable:identifier _ assignmentOp _nl value:zeroOMoreArgumentsBlockOrExpression
|
||||||
{ return nodeLetStatment(variable, value) }
|
{ return h.nodeLetStatement(variable, value) }
|
||||||
|
|
||||||
defunStatement
|
defunStatement
|
||||||
= variable:identifier '(' _nl args:array_parameters _nl ')' _ assignmentOp _nl body:innerBlockOrExpression
|
= variable:identifier '(' _nl args:array_parameters _nl ')' _ assignmentOp _nl body:innerBlockOrExpression
|
||||||
{ var value = nodeLambda(args, body)
|
{ var value = h.nodeLambda(args, body)
|
||||||
return nodeLetStatment(variable, value) }
|
return h.nodeLetStatement(variable, value) }
|
||||||
|
|
||||||
assignmentOp "assignment" = '='
|
assignmentOp "assignment" = '='
|
||||||
|
|
||||||
|
@ -128,16 +61,16 @@ ifthenelse
|
||||||
= 'if' __nl condition:logicalAdditive
|
= 'if' __nl condition:logicalAdditive
|
||||||
__nl 'then' __nl trueExpression:innerBlockOrExpression
|
__nl 'then' __nl trueExpression:innerBlockOrExpression
|
||||||
__nl 'else' __nl falseExpression:(ifthenelse/innerBlockOrExpression)
|
__nl 'else' __nl falseExpression:(ifthenelse/innerBlockOrExpression)
|
||||||
{ return nodeTernary(condition, trueExpression, falseExpression) }
|
{ return h.nodeTernary(condition, trueExpression, falseExpression) }
|
||||||
|
|
||||||
ternary
|
ternary
|
||||||
= condition:logicalAdditive _ '?' _nl trueExpression:logicalAdditive _ ':' _nl falseExpression:(ternary/logicalAdditive)
|
= condition:logicalAdditive _ '?' _nl trueExpression:logicalAdditive _ ':' _nl falseExpression:(ternary/logicalAdditive)
|
||||||
{ return nodeTernary(condition, trueExpression, falseExpression) }
|
{ return h.nodeTernary(condition, trueExpression, falseExpression) }
|
||||||
|
|
||||||
logicalAdditive
|
logicalAdditive
|
||||||
= head:logicalMultiplicative tail:(_ operator:logicalAdditiveOp _nl arg:logicalMultiplicative {return {operator: operator, right: arg}})*
|
= head:logicalMultiplicative tail:(_ operator:logicalAdditiveOp _nl arg:logicalMultiplicative {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(toFunction[element.operator], [result, element.right])
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
logicalAdditiveOp "operator" = '||'
|
logicalAdditiveOp "operator" = '||'
|
||||||
|
@ -146,21 +79,21 @@ logicalAdditive
|
||||||
logicalMultiplicative
|
logicalMultiplicative
|
||||||
= head:equality tail:(_ operator:logicalMultiplicativeOp _nl arg:equality {return {operator: operator, right: arg}})*
|
= head:equality tail:(_ operator:logicalMultiplicativeOp _nl arg:equality {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(toFunction[element.operator], [result, element.right])
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
logicalMultiplicativeOp "operator" = '&&'
|
logicalMultiplicativeOp "operator" = '&&'
|
||||||
|
|
||||||
equality
|
equality
|
||||||
= left:relational _ operator:equalityOp _nl right:relational
|
= left:relational _ operator:equalityOp _nl right:relational
|
||||||
{ return makeFunctionCall(toFunction[operator], [left, right])}
|
{ return h.makeFunctionCall(h.toFunction[operator], [left, right])}
|
||||||
/ relational
|
/ relational
|
||||||
|
|
||||||
equalityOp "operator" = '=='/'!='
|
equalityOp "operator" = '=='/'!='
|
||||||
|
|
||||||
relational
|
relational
|
||||||
= left:additive _ operator:relationalOp _nl right:additive
|
= left:additive _ operator:relationalOp _nl right:additive
|
||||||
{ return makeFunctionCall(toFunction[operator], [left, right])}
|
{ return h.makeFunctionCall(h.toFunction[operator], [left, right])}
|
||||||
/ additive
|
/ additive
|
||||||
|
|
||||||
relationalOp "operator" = '<='/'<'/'>='/'>'
|
relationalOp "operator" = '<='/'<'/'>='/'>'
|
||||||
|
@ -168,7 +101,7 @@ relational
|
||||||
additive
|
additive
|
||||||
= head:multiplicative tail:(_ operator:additiveOp _nl arg:multiplicative {return {operator: operator, right: arg}})*
|
= head:multiplicative tail:(_ operator:additiveOp _nl arg:multiplicative {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(toFunction[element.operator], [result, element.right])
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
additiveOp "operator" = '+' / '-' / '.+' / '.-'
|
additiveOp "operator" = '+' / '-' / '.+' / '.-'
|
||||||
|
@ -176,7 +109,7 @@ additive
|
||||||
multiplicative
|
multiplicative
|
||||||
= head:power tail:(_ operator:multiplicativeOp _nl arg:power {return {operator: operator, right: arg}})*
|
= head:power tail:(_ operator:multiplicativeOp _nl arg:power {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(toFunction[element.operator], [result, element.right])
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
multiplicativeOp "operator" = '*' / '/' / '.*' / './'
|
multiplicativeOp "operator" = '*' / '/' / '.*' / './'
|
||||||
|
@ -184,7 +117,7 @@ multiplicative
|
||||||
power
|
power
|
||||||
= head:credibleInterval tail:(_ operator:powerOp _nl arg:credibleInterval {return {operator: operator, right: arg}})*
|
= head:credibleInterval tail:(_ operator:powerOp _nl arg:credibleInterval {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(toFunction[element.operator], [result, element.right])
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
powerOp "operator" = '^' / '.^'
|
powerOp "operator" = '^' / '.^'
|
||||||
|
@ -192,7 +125,7 @@ power
|
||||||
credibleInterval
|
credibleInterval
|
||||||
= head:chainFunctionCall tail:(__ operator:credibleIntervalOp __nl arg:chainFunctionCall {return {operator: operator, right: arg}})*
|
= head:chainFunctionCall tail:(__ operator:credibleIntervalOp __nl arg:chainFunctionCall {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(toFunction[element.operator], [result, element.right])
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
credibleIntervalOp "operator" = 'to'
|
credibleIntervalOp "operator" = 'to'
|
||||||
|
@ -200,7 +133,7 @@ credibleInterval
|
||||||
chainFunctionCall
|
chainFunctionCall
|
||||||
= head:unary tail:(_ ('->'/'|>') _nl chained:chainedFunction {return chained})*
|
= head:unary tail:(_ ('->'/'|>') _nl chained:chainedFunction {return chained})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(element.fnName, [result, ...element.args])
|
return h.makeFunctionCall(element.fnName, [result, ...element.args])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
chainedFunction
|
chainedFunction
|
||||||
|
@ -215,7 +148,7 @@ chainFunctionCall
|
||||||
|
|
||||||
unary
|
unary
|
||||||
= unaryOperator:unaryOperator _nl right:(unary/postOperator)
|
= unaryOperator:unaryOperator _nl right:(unary/postOperator)
|
||||||
{ return apply(unaryToFunction[unaryOperator], right)}
|
{ return h.apply(h.unaryToFunction[unaryOperator], right)}
|
||||||
/ postOperator
|
/ postOperator
|
||||||
|
|
||||||
unaryOperator "unary operator"
|
unaryOperator "unary operator"
|
||||||
|
@ -230,12 +163,12 @@ indexedValue
|
||||||
collectionElement
|
collectionElement
|
||||||
= head:atom &('['/'('/'.')
|
= head:atom &('['/'('/'.')
|
||||||
tail:(
|
tail:(
|
||||||
_ '[' _nl arg:expression _nl ']' {return {fn: postOperatorToFunction['[]'], args: [arg]}}
|
_ '[' _nl arg:expression _nl ']' {return {fn: h.postOperatorToFunction['[]'], args: [arg]}}
|
||||||
/ _ '(' _nl args:array_functionArguments _nl ')' {return {fn: postOperatorToFunction['()'], args: args}}
|
/ _ '(' _nl args:array_functionArguments _nl ')' {return {fn: h.postOperatorToFunction['()'], args: args}}
|
||||||
/ '.' arg:$dollarIdentifier {return {fn: postOperatorToFunction['[]'], args: [nodeString(arg)]}}
|
/ '.' arg:$dollarIdentifier {return {fn: h.postOperatorToFunction['[]'], args: [h.nodeString(arg)]}}
|
||||||
)*
|
)*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(element.fn, [result, ...element.args])
|
return h.makeFunctionCall(element.fn, [result, ...element.args])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
array_functionArguments
|
array_functionArguments
|
||||||
|
@ -261,49 +194,49 @@ dollarIdentifierWithModule 'identifier'
|
||||||
final:$dollarIdentifier
|
final:$dollarIdentifier
|
||||||
{ tail.push(final);
|
{ tail.push(final);
|
||||||
return tail.reduce(function(result, element) {
|
return tail.reduce(function(result, element) {
|
||||||
return makeFunctionCall(postOperatorToFunction['[]'], [result, nodeString(element)])
|
return h.makeFunctionCall(h.postOperatorToFunction['[]'], [result, h.nodeString(element)])
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
identifier 'identifier'
|
identifier 'identifier'
|
||||||
= ([_a-z]+[_a-z0-9]i*) {return nodeIdentifier(text())}
|
= ([_a-z]+[_a-z0-9]i*) {return h.nodeIdentifier(text(), location())}
|
||||||
|
|
||||||
unitIdentifier 'identifier'
|
unitIdentifier 'identifier'
|
||||||
= ([_a-zA-Z]+[_a-z0-9]i*) {return nodeIdentifier(text())}
|
= ([_a-zA-Z]+[_a-z0-9]i*) {return h.nodeIdentifier(text(), location())}
|
||||||
|
|
||||||
dollarIdentifier '$identifier'
|
dollarIdentifier '$identifier'
|
||||||
= ([\$_a-z]+[\$_a-z0-9]i*) {return nodeIdentifier(text())}
|
= ([\$_a-z]+[\$_a-z0-9]i*) {return h.nodeIdentifier(text(), location())}
|
||||||
|
|
||||||
moduleIdentifier 'identifier'
|
moduleIdentifier 'identifier'
|
||||||
= ([A-Z]+[_a-z0-9]i*) {return nodeModuleIdentifier(text())}
|
= ([A-Z]+[_a-z0-9]i*) {return h.nodeModuleIdentifier(text())}
|
||||||
|
|
||||||
|
|
||||||
string 'string'
|
string 'string'
|
||||||
= characters:("'" @([^'])* "'") {return nodeString(characters.join(''))}
|
= characters:("'" @([^'])* "'") {return h.nodeString(characters.join(''))}
|
||||||
/ characters:('"' @([^"])* '"') {return nodeString(characters.join(''))}
|
/ characters:('"' @([^"])* '"') {return h.nodeString(characters.join(''))}
|
||||||
|
|
||||||
number = number:(float / integer) unit:unitIdentifier?
|
number = number:(float / integer) unit:unitIdentifier?
|
||||||
{
|
{
|
||||||
if (unit === null)
|
if (unit === null)
|
||||||
{ return number }
|
{ return number }
|
||||||
else
|
else
|
||||||
{ return apply('fromUnit_'+unit.value, number)
|
{ return h.apply('fromUnit_'+unit.value, number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
integer 'integer'
|
integer 'integer'
|
||||||
= d+ !"\." ![e]i
|
= d+ !"\." ![e]i
|
||||||
{ return nodeInteger(parseInt(text()))}
|
{ return h.nodeInteger(parseInt(text()))}
|
||||||
|
|
||||||
float 'float'
|
float 'float'
|
||||||
= $(((d+ "\." d*) / ("\." d+)) floatExponent? / d+ floatExponent)
|
= $(((d+ "\." d*) / ("\." d+)) floatExponent? / d+ floatExponent)
|
||||||
{ return nodeFloat(parseFloat(text()))}
|
{ return h.nodeFloat(parseFloat(text()))}
|
||||||
|
|
||||||
floatExponent = [e]i '-'? d+
|
floatExponent = [e]i '-'? d+
|
||||||
d = [0-9]
|
d = [0-9]
|
||||||
|
|
||||||
boolean 'boolean'
|
boolean 'boolean'
|
||||||
= ('true'/'false')
|
= ('true'/'false')
|
||||||
{ return nodeBoolean(text() === 'true')}
|
{ return h.nodeBoolean(text() === 'true')}
|
||||||
|
|
||||||
valueConstructor
|
valueConstructor
|
||||||
= recordConstructor
|
= recordConstructor
|
||||||
|
@ -314,15 +247,15 @@ valueConstructor
|
||||||
lambda
|
lambda
|
||||||
= '{' _nl '|' _nl args:array_parameters _nl '|' _nl statements:array_statements finalExpression: (statementSeparator @expression) _nl '}'
|
= '{' _nl '|' _nl args:array_parameters _nl '|' _nl statements:array_statements finalExpression: (statementSeparator @expression) _nl '}'
|
||||||
{ statements.push(finalExpression)
|
{ statements.push(finalExpression)
|
||||||
return nodeLambda(args, nodeBlock(statements)) }
|
return h.nodeLambda(args, h.nodeBlock(statements)) }
|
||||||
/ '{' _nl '|' _nl args:array_parameters _nl '|' _nl finalExpression: expression _nl '}'
|
/ '{' _nl '|' _nl args:array_parameters _nl '|' _nl finalExpression: expression _nl '}'
|
||||||
{ return nodeLambda(args, nodeBlock([finalExpression])) }
|
{ return h.nodeLambda(args, h.nodeBlock([finalExpression])) }
|
||||||
|
|
||||||
arrayConstructor 'array'
|
arrayConstructor 'array'
|
||||||
= '[' _nl ']'
|
= '[' _nl ']'
|
||||||
{ return constructArray([]); }
|
{ return h.constructArray([]); }
|
||||||
/ '[' _nl args:array_elements _nl ']'
|
/ '[' _nl args:array_elements _nl ']'
|
||||||
{ return constructArray(args); }
|
{ return h.constructArray(args); }
|
||||||
|
|
||||||
array_elements
|
array_elements
|
||||||
= head:expression tail:(_ ',' _nl @expression)*
|
= head:expression tail:(_ ',' _nl @expression)*
|
||||||
|
@ -330,7 +263,7 @@ arrayConstructor 'array'
|
||||||
|
|
||||||
recordConstructor 'record'
|
recordConstructor 'record'
|
||||||
= '{' _nl args:array_recordArguments _nl '}'
|
= '{' _nl args:array_recordArguments _nl '}'
|
||||||
{ return constructRecord(args); }
|
{ return h.constructRecord(args); }
|
||||||
|
|
||||||
array_recordArguments
|
array_recordArguments
|
||||||
= head:keyValuePair tail:(_ ',' _nl @keyValuePair)*
|
= head:keyValuePair tail:(_ ',' _nl @keyValuePair)*
|
||||||
|
@ -338,7 +271,7 @@ recordConstructor 'record'
|
||||||
|
|
||||||
keyValuePair
|
keyValuePair
|
||||||
= key:expression _ ':' _nl value:expression
|
= key:expression _ ':' _nl value:expression
|
||||||
{ return nodeKeyValue(key, value)}
|
{ return h.nodeKeyValue(key, value)}
|
||||||
|
|
||||||
// Separators
|
// Separators
|
||||||
|
|
||||||
|
@ -377,30 +310,30 @@ statementSeparator 'statement separator'
|
||||||
noArguments = ('(' _nl ')' )?
|
noArguments = ('(' _nl ')' )?
|
||||||
|
|
||||||
typeIdentifier 'type identifier'
|
typeIdentifier 'type identifier'
|
||||||
= ([a-z]+[_a-z0-9]i*) {return nodeTypeIdentifier(text())}
|
= ([a-z]+[_a-z0-9]i*) {return h.nodeTypeIdentifier(text())}
|
||||||
|
|
||||||
typeConstructorIdentifier 'type constructor identifier'
|
typeConstructorIdentifier 'type constructor identifier'
|
||||||
= ([A-Z]+[_a-z0-9]i*) {return nodeTypeIdentifier(text())}
|
= ([A-Z]+[_a-z0-9]i*) {return h.nodeTypeIdentifier(text())}
|
||||||
|
|
||||||
typeExpression = typePostModifierExpression
|
typeExpression = typePostModifierExpression
|
||||||
|
|
||||||
typePostModifierExpression = head:typeOr tail:(_ '$' _nl @typeModifier)*
|
typePostModifierExpression = head:typeOr tail:(_ '$' _nl @typeModifier)*
|
||||||
{
|
{
|
||||||
return tail.reduce((result, element) => {
|
return tail.reduce((result, element) => {
|
||||||
return makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args])
|
return h.makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args])
|
||||||
}, head)
|
}, head)
|
||||||
}
|
}
|
||||||
|
|
||||||
typeOr = head:typeFunction tail:(_ '|' _nl @typeFunction)*
|
typeOr = head:typeFunction tail:(_ '|' _nl @typeFunction)*
|
||||||
{ return tail.length === 0 ? head : apply('$_typeOr_$', constructArray([head, ...tail])); }
|
{ return tail.length === 0 ? head : h.apply('$_typeOr_$', h.constructArray([head, ...tail])); }
|
||||||
|
|
||||||
typeFunction = head:typeModifierExpression tail:(_ '=>' _nl @typeModifierExpression)*
|
typeFunction = head:typeModifierExpression tail:(_ '=>' _nl @typeModifierExpression)*
|
||||||
{ return tail.length === 0 ? head : apply( '$_typeFunction_$', constructArray([head, ...tail])); }
|
{ return tail.length === 0 ? head : h.apply( '$_typeFunction_$', h.constructArray([head, ...tail])); }
|
||||||
|
|
||||||
typeModifierExpression = head:basicType tail:(_ '<-' _nl @typeModifier)*
|
typeModifierExpression = head:basicType tail:(_ '<-' _nl @typeModifier)*
|
||||||
{
|
{
|
||||||
return tail.reduce((result, element) => {
|
return tail.reduce((result, element) => {
|
||||||
return makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args])
|
return h.makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args])
|
||||||
}, head)
|
}, head)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,10 +346,10 @@ typeModifierExpression = head:basicType tail:(_ '<-' _nl @typeModifier)*
|
||||||
basicType = typeConstructor / typeArray / typeRecord / typeInParanthesis / typeIdentifier
|
basicType = typeConstructor / typeArray / typeRecord / typeInParanthesis / typeIdentifier
|
||||||
|
|
||||||
typeArray = '[' _nl elem:typeExpression _nl ']'
|
typeArray = '[' _nl elem:typeExpression _nl ']'
|
||||||
{return apply('$_typeArray_$', elem)}
|
{return h.apply('$_typeArray_$', elem)}
|
||||||
|
|
||||||
typeRecord = '{' _nl elems:array_typeRecordArguments _nl '}'
|
typeRecord = '{' _nl elems:array_typeRecordArguments _nl '}'
|
||||||
{ return apply('$_typeRecord_$', constructRecord(elems)); }
|
{ return h.apply('$_typeRecord_$', h.constructRecord(elems)); }
|
||||||
|
|
||||||
array_typeRecordArguments
|
array_typeRecordArguments
|
||||||
= head:typeKeyValuePair tail:(_ ',' _nl @typeKeyValuePair)*
|
= head:typeKeyValuePair tail:(_ ',' _nl @typeKeyValuePair)*
|
||||||
|
@ -424,22 +357,22 @@ typeRecord = '{' _nl elems:array_typeRecordArguments _nl '}'
|
||||||
|
|
||||||
typeKeyValuePair
|
typeKeyValuePair
|
||||||
= key:identifier _ ':' _nl value:typeExpression
|
= key:identifier _ ':' _nl value:typeExpression
|
||||||
{ return nodeKeyValue(key, value)}
|
{ return h.nodeKeyValue(key, value)}
|
||||||
|
|
||||||
typeConstructor
|
typeConstructor
|
||||||
= constructor:typeConstructorIdentifier _ '(' _nl args:array_types _nl ')'
|
= constructor:typeConstructorIdentifier _ '(' _nl args:array_types _nl ')'
|
||||||
{ return makeFunctionCall('$_typeConstructor_$', [constructor, constructArray(args)]); }
|
{ return h.makeFunctionCall('$_typeConstructor_$', [constructor, h.constructArray(args)]); }
|
||||||
/ constructor:typeConstructorIdentifier _ noArguments
|
/ constructor:typeConstructorIdentifier _ noArguments
|
||||||
{ return makeFunctionCall('$_typeConstructor_$', [constructor, constructArray([])]); }
|
{ return h.makeFunctionCall('$_typeConstructor_$', [constructor, h.constructArray([])]); }
|
||||||
|
|
||||||
array_types = head:typeExpression tail:(_ ',' _nl @typeExpression)*
|
array_types = head:typeExpression tail:(_ ',' _nl @typeExpression)*
|
||||||
{ return [head, ...tail]; }
|
{ return [head, ...tail]; }
|
||||||
|
|
||||||
typeStatement = typeAliasStatement / typeOfStatement
|
typeStatement = typeAliasStatement / typeOfStatement
|
||||||
typeAliasStatement = 'type' __nl typeIdentifier:typeIdentifier _nl '=' _nl typeExpression:typeExpression
|
typeAliasStatement = 'type' __nl typeIdentifier:typeIdentifier _nl '=' _nl typeExpression:typeExpression
|
||||||
{ return makeFunctionCall('$_typeAlias_$', [typeIdentifier, typeExpression])}
|
{ return h.makeFunctionCall('$_typeAlias_$', [typeIdentifier, typeExpression])}
|
||||||
typeOfStatement = identifier:identifier _ ':' _nl typeExpression:typeExpression
|
typeOfStatement = identifier:identifier _ ':' _nl typeExpression:typeExpression
|
||||||
{ return makeFunctionCall('$_typeOf_$', [identifier, typeExpression])}
|
{ return h.makeFunctionCall('$_typeOf_$', [identifier, typeExpression])}
|
||||||
|
|
||||||
typeInParanthesis = '(' _nl typeExpression:typeExpression _nl ')' {return typeExpression}
|
typeInParanthesis = '(' _nl typeExpression:typeExpression _nl ')' {return typeExpression}
|
||||||
|
|
||||||
|
@ -447,4 +380,4 @@ typeInParanthesis = '(' _nl typeExpression:typeExpression _nl ')' {return typeEx
|
||||||
// TODO: Example of foo = {a: 2, b: 5}; type fooKeys = string $ memberOf(foo->keys)
|
// TODO: Example of foo = {a: 2, b: 5}; type fooKeys = string $ memberOf(foo->keys)
|
||||||
// TODO: Example of memberOf( [1,2,3] )
|
// TODO: Example of memberOf( [1,2,3] )
|
||||||
// TODO: Example of $
|
// TODO: Example of $
|
||||||
// TODO: Cons(a, list) | EmptyList
|
// TODO: Cons(a, list) | EmptyList
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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[]) {
|
||||||
|
return apply("$_constructArray_$", nodeExpression(elems));
|
||||||
|
}
|
||||||
|
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 };
|
||||||
|
}
|
|
@ -1,2 +1,4 @@
|
||||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
module ExternalExpressionValue = ReducerInterface_ExternalExpressionValue
|
||||||
module ExternalLibrary = ReducerInterface_ExternalLibrary
|
module ExternalLibrary = ReducerInterface_ExternalLibrary
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
module StdLib = ReducerInterface_StdLib
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
module EV = ReducerInterface_ExpressionValue
|
module IEV = ReducerInterface_InternalExpressionValue
|
||||||
type expressionValue = EV.expressionValue
|
type internalExpressionValue = IEV.t
|
||||||
|
|
||||||
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
let dispatch = (call: IEV.functionCall, _: DistributionOperation.env): option<
|
||||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
result<internalExpressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||||
> => {
|
> => {
|
||||||
switch call {
|
switch call {
|
||||||
| ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some
|
| ("toString", [IEvDate(t)]) => IEV.IEvString(DateTime.Date.toString(t))->Ok->Some
|
||||||
| ("makeDateFromYear", [EvNumber(year)]) =>
|
| ("makeDateFromYear", [IEvNumber(year)]) =>
|
||||||
switch DateTime.Date.makeFromYear(year) {
|
switch DateTime.Date.makeFromYear(year) {
|
||||||
| Ok(t) => EV.EvDate(t)->Ok->Some
|
| Ok(t) => IEV.IEvDate(t)->Ok->Some
|
||||||
| Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
|
| Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
|
||||||
}
|
}
|
||||||
| ("dateFromNumber", [EvNumber(f)]) => EV.EvDate(DateTime.Date.fromFloat(f))->Ok->Some
|
| ("dateFromNumber", [IEvNumber(f)]) => IEV.IEvDate(DateTime.Date.fromFloat(f))->Ok->Some
|
||||||
| ("toNumber", [EvDate(f)]) => EV.EvNumber(DateTime.Date.toFloat(f))->Ok->Some
|
| ("toNumber", [IEvDate(f)]) => IEV.IEvNumber(DateTime.Date.toFloat(f))->Ok->Some
|
||||||
| ("subtract", [EvDate(d1), EvDate(d2)]) =>
|
| ("subtract", [IEvDate(d1), IEvDate(d2)]) =>
|
||||||
switch DateTime.Date.subtract(d1, d2) {
|
switch DateTime.Date.subtract(d1, d2) {
|
||||||
| Ok(d) => EV.EvTimeDuration(d)->Ok
|
| Ok(d) => IEV.IEvTimeDuration(d)->Ok
|
||||||
| Error(e) => Error(RETodo(e))
|
| Error(e) => Error(RETodo(e))
|
||||||
}->Some
|
}->Some
|
||||||
| ("subtract", [EvDate(d1), EvTimeDuration(d2)]) =>
|
| ("subtract", [IEvDate(d1), IEvTimeDuration(d2)]) =>
|
||||||
EV.EvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
|
IEV.IEvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
|
||||||
| ("add", [EvDate(d1), EvTimeDuration(d2)]) =>
|
| ("add", [IEvDate(d1), IEvTimeDuration(d2)]) =>
|
||||||
EV.EvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
|
IEV.IEvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,36 @@
|
||||||
module EV = ReducerInterface_ExpressionValue
|
module IEV = ReducerInterface_InternalExpressionValue
|
||||||
type expressionValue = EV.expressionValue
|
type internalExpressionValue = IEV.t
|
||||||
|
|
||||||
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
let dispatch = (call: IEV.functionCall, _: DistributionOperation.env): option<
|
||||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
result<internalExpressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||||
> => {
|
> => {
|
||||||
switch call {
|
switch call {
|
||||||
| ("toString", [EvTimeDuration(t)]) => EV.EvString(DateTime.Duration.toString(t))->Ok->Some
|
| ("toString", [IEvTimeDuration(t)]) => IEV.IEvString(DateTime.Duration.toString(t))->Ok->Some
|
||||||
| ("minutes", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
| ("minutes", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
||||||
| ("fromUnit_minutes", [EvNumber(f)]) =>
|
| ("fromUnit_minutes", [IEvNumber(f)]) =>
|
||||||
EV.EvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
IEV.IEvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
||||||
| ("hours", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
| ("hours", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||||
| ("fromUnit_hours", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
| ("fromUnit_hours", [IEvNumber(f)]) =>
|
||||||
| ("days", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
IEV.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||||
| ("fromUnit_days", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
| ("days", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||||
| ("years", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
| ("fromUnit_days", [IEvNumber(f)]) =>
|
||||||
| ("fromUnit_years", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
IEV.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||||
| ("toHours", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toHours(f))->Ok->Some
|
| ("years", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||||
| ("toMinutes", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toMinutes(f))->Ok->Some
|
| ("fromUnit_years", [IEvNumber(f)]) =>
|
||||||
| ("toDays", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toDays(f))->Ok->Some
|
IEV.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||||
| ("toYears", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toYears(f))->Ok->Some
|
| ("toHours", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toHours(f))->Ok->Some
|
||||||
| ("add", [EvTimeDuration(d1), EvTimeDuration(d2)]) =>
|
| ("toMinutes", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toMinutes(f))->Ok->Some
|
||||||
EV.EvTimeDuration(DateTime.Duration.add(d1, d2))->Ok->Some
|
| ("toDays", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toDays(f))->Ok->Some
|
||||||
| ("subtract", [EvTimeDuration(d1), EvTimeDuration(d2)]) =>
|
| ("toYears", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toYears(f))->Ok->Some
|
||||||
EV.EvTimeDuration(DateTime.Duration.subtract(d1, d2))->Ok->Some
|
| ("add", [IEvTimeDuration(d1), IEvTimeDuration(d2)]) =>
|
||||||
| ("multiply", [EvTimeDuration(d1), EvNumber(d2)]) =>
|
IEV.IEvTimeDuration(DateTime.Duration.add(d1, d2))->Ok->Some
|
||||||
EV.EvTimeDuration(DateTime.Duration.multiply(d1, d2))->Ok->Some
|
| ("subtract", [IEvTimeDuration(d1), IEvTimeDuration(d2)]) =>
|
||||||
| ("divide", [EvTimeDuration(d1), EvNumber(d2)]) =>
|
IEV.IEvTimeDuration(DateTime.Duration.subtract(d1, d2))->Ok->Some
|
||||||
EV.EvTimeDuration(DateTime.Duration.divide(d1, d2))->Ok->Some
|
| ("multiply", [IEvTimeDuration(d1), IEvNumber(d2)]) =>
|
||||||
| ("divide", [EvTimeDuration(d1), EvTimeDuration(d2)]) => EV.EvNumber(d1 /. d2)->Ok->Some
|
IEV.IEvTimeDuration(DateTime.Duration.multiply(d1, d2))->Ok->Some
|
||||||
|
| ("divide", [IEvTimeDuration(d1), IEvNumber(d2)]) =>
|
||||||
|
IEV.IEvTimeDuration(DateTime.Duration.divide(d1, d2))->Ok->Some
|
||||||
|
| ("divide", [IEvTimeDuration(d1), IEvTimeDuration(d2)]) => IEV.IEvNumber(d1 /. d2)->Ok->Some
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ module ErrorValue = Reducer_ErrorValue
|
||||||
type internalCode = Object
|
type internalCode = Object
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type rec expressionValue =
|
type rec externalExpressionValue =
|
||||||
| EvArray(array<expressionValue>)
|
| EvArray(array<externalExpressionValue>)
|
||||||
| EvArrayString(array<string>)
|
| EvArrayString(array<string>)
|
||||||
| EvBool(bool)
|
| EvBool(bool)
|
||||||
| EvCall(string) // External function call
|
| EvCall(string) // External function call
|
||||||
|
@ -24,7 +24,7 @@ type rec expressionValue =
|
||||||
| EvDeclaration(lambdaDeclaration)
|
| EvDeclaration(lambdaDeclaration)
|
||||||
| EvTypeIdentifier(string)
|
| EvTypeIdentifier(string)
|
||||||
| EvModule(record)
|
| EvModule(record)
|
||||||
and record = Js.Dict.t<expressionValue>
|
and record = Js.Dict.t<externalExpressionValue>
|
||||||
and externalBindings = record
|
and externalBindings = record
|
||||||
and lambdaValue = {
|
and lambdaValue = {
|
||||||
parameters: array<string>,
|
parameters: array<string>,
|
||||||
|
@ -33,7 +33,10 @@ and lambdaValue = {
|
||||||
}
|
}
|
||||||
and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
||||||
|
|
||||||
type functionCall = (string, array<expressionValue>)
|
@genType
|
||||||
|
type t = externalExpressionValue
|
||||||
|
|
||||||
|
type functionCall = (string, array<externalExpressionValue>)
|
||||||
|
|
||||||
let rec toString = aValue =>
|
let rec toString = aValue =>
|
||||||
switch aValue {
|
switch aValue {
|
||||||
|
@ -68,26 +71,7 @@ and toStringRecord = aRecord => {
|
||||||
`{${pairs}}`
|
`{${pairs}}`
|
||||||
}
|
}
|
||||||
|
|
||||||
let toStringWithType = aValue =>
|
let argsToString = (args: array<externalExpressionValue>): string => {
|
||||||
switch aValue {
|
|
||||||
| EvArray(_) => `Array::${toString(aValue)}`
|
|
||||||
| EvArrayString(_) => `ArrayString::${toString(aValue)}`
|
|
||||||
| EvBool(_) => `Bool::${toString(aValue)}`
|
|
||||||
| EvCall(_) => `Call::${toString(aValue)}`
|
|
||||||
| EvDistribution(_) => `Distribution::${toString(aValue)}`
|
|
||||||
| EvLambda(_) => `Lambda::${toString(aValue)}`
|
|
||||||
| EvNumber(_) => `Number::${toString(aValue)}`
|
|
||||||
| EvRecord(_) => `Record::${toString(aValue)}`
|
|
||||||
| EvString(_) => `String::${toString(aValue)}`
|
|
||||||
| EvSymbol(_) => `Symbol::${toString(aValue)}`
|
|
||||||
| EvDate(_) => `Date::${toString(aValue)}`
|
|
||||||
| EvTimeDuration(_) => `Date::${toString(aValue)}`
|
|
||||||
| EvDeclaration(_) => `Declaration::${toString(aValue)}`
|
|
||||||
| EvTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}`
|
|
||||||
| EvModule(_) => `Module::${toString(aValue)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
let argsToString = (args: array<expressionValue>): string => {
|
|
||||||
args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString
|
args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,18 +83,6 @@ let toStringResult = x =>
|
||||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||||
}
|
}
|
||||||
|
|
||||||
let toStringResultOkless = (codeResult: result<expressionValue, ErrorValue.errorValue>): string =>
|
|
||||||
switch codeResult {
|
|
||||||
| Ok(a) => toString(a)
|
|
||||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
|
||||||
}
|
|
||||||
|
|
||||||
let toStringResultRecord = x =>
|
|
||||||
switch x {
|
|
||||||
| Ok(a) => `Ok(${toStringRecord(a)})`
|
|
||||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
|
||||||
}
|
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type environment = DistributionOperation.env
|
type environment = DistributionOperation.env
|
||||||
|
|
||||||
|
@ -141,14 +113,14 @@ type functionDefinitionSignature =
|
||||||
let valueToValueType = value =>
|
let valueToValueType = value =>
|
||||||
switch value {
|
switch value {
|
||||||
| EvArray(_) => EvtArray
|
| EvArray(_) => EvtArray
|
||||||
| EvArrayString(_) => EvtArray
|
| EvArrayString(_) => EvtArrayString
|
||||||
| EvBool(_) => EvtBool
|
| EvBool(_) => EvtBool
|
||||||
| EvCall(_) => EvtCall
|
| EvCall(_) => EvtCall
|
||||||
| EvDistribution(_) => EvtDistribution
|
| EvDistribution(_) => EvtDistribution
|
||||||
| EvLambda(_) => EvtLambda
|
| EvLambda(_) => EvtLambda
|
||||||
| EvNumber(_) => EvtNumber
|
| EvNumber(_) => EvtNumber
|
||||||
| EvRecord(_) => EvtRecord
|
| EvRecord(_) => EvtRecord
|
||||||
| EvString(_) => EvtArray
|
| EvString(_) => EvtString
|
||||||
| EvSymbol(_) => EvtSymbol
|
| EvSymbol(_) => EvtSymbol
|
||||||
| EvDate(_) => EvtDate
|
| EvDate(_) => EvtDate
|
||||||
| EvTimeDuration(_) => EvtTimeDuration
|
| EvTimeDuration(_) => EvtTimeDuration
|
|
@ -1,6 +1,6 @@
|
||||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
|
||||||
type expressionValue = ExpressionValue.expressionValue
|
type internalExpressionValue = InternalExpressionValue.t
|
||||||
|
|
||||||
// module Sample = {
|
// module Sample = {
|
||||||
// // In real life real libraries should be somewhere else
|
// // In real life real libraries should be somewhere else
|
||||||
|
@ -17,14 +17,14 @@ type expressionValue = ExpressionValue.expressionValue
|
||||||
// I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call.
|
// I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call.
|
||||||
let registry = FunctionRegistry_Library.registry
|
let registry = FunctionRegistry_Library.registry
|
||||||
|
|
||||||
let tryRegistry = ((fnName, args): ExpressionValue.functionCall, env) => {
|
let tryRegistry = ((fnName, args): InternalExpressionValue.functionCall, env) => {
|
||||||
FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap(
|
FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap(
|
||||||
E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)),
|
E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<
|
let dispatch = (call: InternalExpressionValue.functionCall, environment, chain): result<
|
||||||
expressionValue,
|
internalExpressionValue,
|
||||||
'e,
|
'e,
|
||||||
> => {
|
> => {
|
||||||
E.A.O.firstSomeFn([
|
E.A.O.firstSomeFn([
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
module IEV = ReducerInterface_InternalExpressionValue
|
||||||
type expressionValue = ExpressionValue.expressionValue
|
type internalExpressionValue = IEV.t
|
||||||
|
|
||||||
module Helpers = {
|
module Helpers = {
|
||||||
let arithmeticMap = r =>
|
let arithmeticMap = r =>
|
||||||
|
@ -18,14 +18,14 @@ module Helpers = {
|
||||||
| _ => #Multiply
|
| _ => #Multiply
|
||||||
}
|
}
|
||||||
|
|
||||||
let catchAndConvertTwoArgsToDists = (args: array<expressionValue>): option<(
|
let catchAndConvertTwoArgsToDists = (args: array<internalExpressionValue>): option<(
|
||||||
DistributionTypes.genericDist,
|
DistributionTypes.genericDist,
|
||||||
DistributionTypes.genericDist,
|
DistributionTypes.genericDist,
|
||||||
)> =>
|
)> =>
|
||||||
switch args {
|
switch args {
|
||||||
| [EvDistribution(a), EvDistribution(b)] => Some((a, b))
|
| [IEvDistribution(a), IEvDistribution(b)] => Some((a, b))
|
||||||
| [EvNumber(a), EvDistribution(b)] => Some((GenericDist.fromFloat(a), b))
|
| [IEvNumber(a), IEvDistribution(b)] => Some((GenericDist.fromFloat(a), b))
|
||||||
| [EvDistribution(a), EvNumber(b)] => Some((a, GenericDist.fromFloat(b)))
|
| [IEvDistribution(a), IEvNumber(b)] => Some((a, GenericDist.fromFloat(b)))
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,23 +80,28 @@ module Helpers = {
|
||||||
)->DistributionOperation.run(~env)
|
)->DistributionOperation.run(~env)
|
||||||
}
|
}
|
||||||
|
|
||||||
let parseNumber = (args: expressionValue): Belt.Result.t<float, string> =>
|
let parseNumber = (args: internalExpressionValue): Belt.Result.t<float, string> =>
|
||||||
switch args {
|
switch args {
|
||||||
| EvNumber(x) => Ok(x)
|
| IEvNumber(x) => Ok(x)
|
||||||
| _ => Error("Not a number")
|
| _ => Error("Not a number")
|
||||||
}
|
}
|
||||||
|
|
||||||
let parseNumberArray = (ags: array<expressionValue>): Belt.Result.t<array<float>, string> =>
|
let parseNumberArray = (ags: array<internalExpressionValue>): Belt.Result.t<
|
||||||
E.A.fmap(parseNumber, ags) |> E.A.R.firstErrorOrOpen
|
array<float>,
|
||||||
|
string,
|
||||||
|
> => E.A.fmap(parseNumber, ags) |> E.A.R.firstErrorOrOpen
|
||||||
|
|
||||||
let parseDist = (args: expressionValue): Belt.Result.t<DistributionTypes.genericDist, string> =>
|
let parseDist = (args: internalExpressionValue): Belt.Result.t<
|
||||||
|
DistributionTypes.genericDist,
|
||||||
|
string,
|
||||||
|
> =>
|
||||||
switch args {
|
switch args {
|
||||||
| EvDistribution(x) => Ok(x)
|
| IEvDistribution(x) => Ok(x)
|
||||||
| EvNumber(x) => Ok(GenericDist.fromFloat(x))
|
| IEvNumber(x) => Ok(GenericDist.fromFloat(x))
|
||||||
| _ => Error("Not a distribution")
|
| _ => Error("Not a distribution")
|
||||||
}
|
}
|
||||||
|
|
||||||
let parseDistributionArray = (ags: array<expressionValue>): Belt.Result.t<
|
let parseDistributionArray = (ags: array<internalExpressionValue>): Belt.Result.t<
|
||||||
array<DistributionTypes.genericDist>,
|
array<DistributionTypes.genericDist>,
|
||||||
string,
|
string,
|
||||||
> => E.A.fmap(parseDist, ags) |> E.A.R.firstErrorOrOpen
|
> => E.A.fmap(parseDist, ags) |> E.A.R.firstErrorOrOpen
|
||||||
|
@ -122,18 +127,18 @@ module Helpers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mixture = (
|
let mixture = (
|
||||||
args: array<expressionValue>,
|
args: array<internalExpressionValue>,
|
||||||
~env: DistributionOperation.env,
|
~env: DistributionOperation.env,
|
||||||
): DistributionOperation.outputType => {
|
): DistributionOperation.outputType => {
|
||||||
let error = (err: string): DistributionOperation.outputType =>
|
let error = (err: string): DistributionOperation.outputType =>
|
||||||
err->DistributionTypes.ArgumentError->GenDistError
|
err->DistributionTypes.ArgumentError->GenDistError
|
||||||
switch args {
|
switch args {
|
||||||
| [EvArray(distributions)] =>
|
| [IEvArray(distributions)] =>
|
||||||
switch parseDistributionArray(distributions) {
|
switch parseDistributionArray(distributions) {
|
||||||
| Ok(distrs) => mixtureWithDefaultWeights(distrs, ~env)
|
| Ok(distrs) => mixtureWithDefaultWeights(distrs, ~env)
|
||||||
| Error(err) => error(err)
|
| Error(err) => error(err)
|
||||||
}
|
}
|
||||||
| [EvArray(distributions), EvArray(weights)] =>
|
| [IEvArray(distributions), IEvArray(weights)] =>
|
||||||
switch (parseDistributionArray(distributions), parseNumberArray(weights)) {
|
switch (parseDistributionArray(distributions), parseNumberArray(weights)) {
|
||||||
| (Ok(distrs), Ok(wghts)) => mixtureWithGivenWeights(distrs, wghts, ~env)
|
| (Ok(distrs), Ok(wghts)) => mixtureWithGivenWeights(distrs, wghts, ~env)
|
||||||
| (Error(err), Ok(_)) => error(err)
|
| (Error(err), Ok(_)) => error(err)
|
||||||
|
@ -142,7 +147,7 @@ module Helpers = {
|
||||||
}
|
}
|
||||||
| _ =>
|
| _ =>
|
||||||
switch E.A.last(args) {
|
switch E.A.last(args) {
|
||||||
| Some(EvArray(b)) => {
|
| Some(IEvArray(b)) => {
|
||||||
let weights = parseNumberArray(b)
|
let weights = parseNumberArray(b)
|
||||||
let distributions = parseDistributionArray(
|
let distributions = parseDistributionArray(
|
||||||
Belt.Array.slice(args, ~offset=0, ~len=E.A.length(args) - 1),
|
Belt.Array.slice(args, ~offset=0, ~len=E.A.length(args) - 1),
|
||||||
|
@ -152,8 +157,8 @@ module Helpers = {
|
||||||
| Error(err) => error(err)
|
| Error(err) => error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| Some(EvNumber(_))
|
| Some(IEvNumber(_))
|
||||||
| Some(EvDistribution(_)) =>
|
| Some(IEvDistribution(_)) =>
|
||||||
switch parseDistributionArray(args) {
|
switch parseDistributionArray(args) {
|
||||||
| Ok(distributions) => mixtureWithDefaultWeights(distributions, ~env)
|
| Ok(distributions) => mixtureWithDefaultWeights(distributions, ~env)
|
||||||
| Error(err) => error(err)
|
| Error(err) => error(err)
|
||||||
|
@ -194,20 +199,19 @@ module SymbolicConstructors = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatchToGenericOutput = (
|
let dispatchToGenericOutput = (call: IEV.functionCall, env: DistributionOperation.env): option<
|
||||||
call: ExpressionValue.functionCall,
|
DistributionOperation.outputType,
|
||||||
env: DistributionOperation.env,
|
> => {
|
||||||
): option<DistributionOperation.outputType> => {
|
|
||||||
let (fnName, args) = call
|
let (fnName, args) = call
|
||||||
switch (fnName, args) {
|
switch (fnName, args) {
|
||||||
| ("triangular" as fnName, [EvNumber(f1), EvNumber(f2), EvNumber(f3)]) =>
|
| ("triangular" as fnName, [IEvNumber(f1), IEvNumber(f2), IEvNumber(f3)]) =>
|
||||||
SymbolicConstructors.threeFloat(fnName)
|
SymbolicConstructors.threeFloat(fnName)
|
||||||
->E.R.bind(r => r(f1, f2, f3))
|
->E.R.bind(r => r(f1, f2, f3))
|
||||||
->SymbolicConstructors.symbolicResultToOutput
|
->SymbolicConstructors.symbolicResultToOutput
|
||||||
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
|
| ("sample", [IEvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
|
||||||
| ("sampleN", [EvDistribution(dist), EvNumber(n)]) =>
|
| ("sampleN", [IEvDistribution(dist), IEvNumber(n)]) =>
|
||||||
Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
|
Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
|
||||||
| (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [EvDistribution(dist)]) => {
|
| (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [IEvDistribution(dist)]) => {
|
||||||
let fn = switch op {
|
let fn = switch op {
|
||||||
| "mean" => #Mean
|
| "mean" => #Mean
|
||||||
| "stdev" => #Stdev
|
| "stdev" => #Stdev
|
||||||
|
@ -219,13 +223,13 @@ let dispatchToGenericOutput = (
|
||||||
}
|
}
|
||||||
Helpers.toFloatFn(fn, dist, ~env)
|
Helpers.toFloatFn(fn, dist, ~env)
|
||||||
}
|
}
|
||||||
| ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
| ("integralSum", [IEvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
||||||
| ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
| ("toString", [IEvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
||||||
| ("sparkline", [EvDistribution(dist)]) =>
|
| ("sparkline", [IEvDistribution(dist)]) =>
|
||||||
Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env)
|
Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env)
|
||||||
| ("sparkline", [EvDistribution(dist), EvNumber(n)]) =>
|
| ("sparkline", [IEvDistribution(dist), IEvNumber(n)]) =>
|
||||||
Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist, ~env)
|
Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist, ~env)
|
||||||
| ("exp", [EvDistribution(a)]) =>
|
| ("exp", [IEvDistribution(a)]) =>
|
||||||
// https://mathjs.org/docs/reference/functions/exp.html
|
// https://mathjs.org/docs/reference/functions/exp.html
|
||||||
Helpers.twoDiststoDistFn(
|
Helpers.twoDiststoDistFn(
|
||||||
Algebraic(AsDefault),
|
Algebraic(AsDefault),
|
||||||
|
@ -234,55 +238,62 @@ let dispatchToGenericOutput = (
|
||||||
a,
|
a,
|
||||||
~env,
|
~env,
|
||||||
)->Some
|
)->Some
|
||||||
| ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env)
|
| ("normalize", [IEvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env)
|
||||||
| ("klDivergence", [EvDistribution(prediction), EvDistribution(answer)]) =>
|
| ("klDivergence", [IEvDistribution(prediction), IEvDistribution(answer)]) =>
|
||||||
Some(DistributionOperation.run(FromDist(ToScore(KLDivergence(answer)), prediction), ~env))
|
Some(DistributionOperation.run(FromDist(ToScore(KLDivergence(answer)), prediction), ~env))
|
||||||
| ("klDivergence", [EvDistribution(prediction), EvDistribution(answer), EvDistribution(prior)]) =>
|
| (
|
||||||
|
"klDivergence",
|
||||||
|
[IEvDistribution(prediction), IEvDistribution(answer), IEvDistribution(prior)],
|
||||||
|
) =>
|
||||||
Helpers.klDivergenceWithPrior(prediction, answer, prior, env)
|
Helpers.klDivergenceWithPrior(prediction, answer, prior, env)
|
||||||
| (
|
| (
|
||||||
"logScoreWithPointAnswer",
|
"logScoreWithPointAnswer",
|
||||||
[EvDistribution(prediction), EvNumber(answer), EvDistribution(prior)],
|
[IEvDistribution(prediction), IEvNumber(answer), IEvDistribution(prior)],
|
||||||
)
|
)
|
||||||
| (
|
| (
|
||||||
"logScoreWithPointAnswer",
|
"logScoreWithPointAnswer",
|
||||||
[EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer))), EvDistribution(prior)],
|
[
|
||||||
|
IEvDistribution(prediction),
|
||||||
|
IEvDistribution(Symbolic(#Float(answer))),
|
||||||
|
IEvDistribution(prior),
|
||||||
|
],
|
||||||
) =>
|
) =>
|
||||||
DistributionOperation.run(
|
DistributionOperation.run(
|
||||||
FromDist(ToScore(LogScore(answer, prior->Some)), prediction),
|
FromDist(ToScore(LogScore(answer, prior->Some)), prediction),
|
||||||
~env,
|
~env,
|
||||||
)->Some
|
)->Some
|
||||||
| ("logScoreWithPointAnswer", [EvDistribution(prediction), EvNumber(answer)])
|
| ("logScoreWithPointAnswer", [IEvDistribution(prediction), IEvNumber(answer)])
|
||||||
| (
|
| (
|
||||||
"logScoreWithPointAnswer",
|
"logScoreWithPointAnswer",
|
||||||
[EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer)))],
|
[IEvDistribution(prediction), IEvDistribution(Symbolic(#Float(answer)))],
|
||||||
) =>
|
) =>
|
||||||
DistributionOperation.run(FromDist(ToScore(LogScore(answer, None)), prediction), ~env)->Some
|
DistributionOperation.run(FromDist(ToScore(LogScore(answer, None)), prediction), ~env)->Some
|
||||||
| ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env)
|
| ("isNormalized", [IEvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env)
|
||||||
| ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env)
|
| ("toPointSet", [IEvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env)
|
||||||
| ("scaleLog", [EvDistribution(dist)]) =>
|
| ("scaleLog", [IEvDistribution(dist)]) =>
|
||||||
Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist, ~env)
|
Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist, ~env)
|
||||||
| ("scaleLog10", [EvDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env)
|
| ("scaleLog10", [IEvDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env)
|
||||||
| ("scaleLog", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("scaleLog", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||||
Helpers.toDistFn(Scale(#Logarithm, float), dist, ~env)
|
Helpers.toDistFn(Scale(#Logarithm, float), dist, ~env)
|
||||||
| ("scaleLogWithThreshold", [EvDistribution(dist), EvNumber(base), EvNumber(eps)]) =>
|
| ("scaleLogWithThreshold", [IEvDistribution(dist), IEvNumber(base), IEvNumber(eps)]) =>
|
||||||
Helpers.toDistFn(Scale(#LogarithmWithThreshold(eps), base), dist, ~env)
|
Helpers.toDistFn(Scale(#LogarithmWithThreshold(eps), base), dist, ~env)
|
||||||
| ("scaleMultiply", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("scaleMultiply", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||||
Helpers.toDistFn(Scale(#Multiply, float), dist, ~env)
|
Helpers.toDistFn(Scale(#Multiply, float), dist, ~env)
|
||||||
| ("scalePow", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("scalePow", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||||
Helpers.toDistFn(Scale(#Power, float), dist, ~env)
|
Helpers.toDistFn(Scale(#Power, float), dist, ~env)
|
||||||
| ("scaleExp", [EvDistribution(dist)]) =>
|
| ("scaleExp", [IEvDistribution(dist)]) =>
|
||||||
Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist, ~env)
|
Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist, ~env)
|
||||||
| ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env)
|
| ("cdf", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env)
|
||||||
| ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env)
|
| ("pdf", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env)
|
||||||
| ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env)
|
| ("inv", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env)
|
||||||
| ("quantile", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("quantile", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||||
Helpers.toFloatFn(#Inv(float), dist, ~env)
|
Helpers.toFloatFn(#Inv(float), dist, ~env)
|
||||||
| ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("toSampleSet", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||||
Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env)
|
Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env)
|
||||||
| ("toSampleSet", [EvDistribution(dist)]) =>
|
| ("toSampleSet", [IEvDistribution(dist)]) =>
|
||||||
Helpers.toDistFn(ToSampleSet(env.sampleCount), dist, ~env)
|
Helpers.toDistFn(ToSampleSet(env.sampleCount), dist, ~env)
|
||||||
| ("toList", [EvDistribution(SampleSet(dist))]) => Some(FloatArray(SampleSetDist.T.get(dist)))
|
| ("toList", [IEvDistribution(SampleSet(dist))]) => Some(FloatArray(SampleSetDist.T.get(dist)))
|
||||||
| ("fromSamples", [EvArray(inputArray)]) => {
|
| ("fromSamples", [IEvArray(inputArray)]) => {
|
||||||
let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x)
|
let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x)
|
||||||
let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors)
|
let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors)
|
||||||
switch parsedArray {
|
switch parsedArray {
|
||||||
|
@ -290,15 +301,15 @@ let dispatchToGenericOutput = (
|
||||||
| Error(e) => GenDistError(SampleSetError(e))
|
| Error(e) => GenDistError(SampleSetError(e))
|
||||||
}->Some
|
}->Some
|
||||||
}
|
}
|
||||||
| ("inspect", [EvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env)
|
| ("inspect", [IEvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env)
|
||||||
| ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("truncateLeft", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||||
Helpers.toDistFn(Truncate(Some(float), None), dist, ~env)
|
Helpers.toDistFn(Truncate(Some(float), None), dist, ~env)
|
||||||
| ("truncateRight", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("truncateRight", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||||
Helpers.toDistFn(Truncate(None, Some(float)), dist, ~env)
|
Helpers.toDistFn(Truncate(None, Some(float)), dist, ~env)
|
||||||
| ("truncate", [EvDistribution(dist), EvNumber(float1), EvNumber(float2)]) =>
|
| ("truncate", [IEvDistribution(dist), IEvNumber(float1), IEvNumber(float2)]) =>
|
||||||
Helpers.toDistFn(Truncate(Some(float1), Some(float2)), dist, ~env)
|
Helpers.toDistFn(Truncate(Some(float1), Some(float2)), dist, ~env)
|
||||||
| ("mx" | "mixture", args) => Helpers.mixture(args, ~env)->Some
|
| ("mx" | "mixture", args) => Helpers.mixture(args, ~env)->Some
|
||||||
| ("log", [EvDistribution(a)]) =>
|
| ("log", [IEvDistribution(a)]) =>
|
||||||
Helpers.twoDiststoDistFn(
|
Helpers.twoDiststoDistFn(
|
||||||
Algebraic(AsDefault),
|
Algebraic(AsDefault),
|
||||||
"log",
|
"log",
|
||||||
|
@ -306,7 +317,7 @@ let dispatchToGenericOutput = (
|
||||||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||||
~env,
|
~env,
|
||||||
)->Some
|
)->Some
|
||||||
| ("log10", [EvDistribution(a)]) =>
|
| ("log10", [IEvDistribution(a)]) =>
|
||||||
Helpers.twoDiststoDistFn(
|
Helpers.twoDiststoDistFn(
|
||||||
Algebraic(AsDefault),
|
Algebraic(AsDefault),
|
||||||
"log",
|
"log",
|
||||||
|
@ -314,7 +325,7 @@ let dispatchToGenericOutput = (
|
||||||
GenericDist.fromFloat(10.0),
|
GenericDist.fromFloat(10.0),
|
||||||
~env,
|
~env,
|
||||||
)->Some
|
)->Some
|
||||||
| ("unaryMinus", [EvDistribution(a)]) =>
|
| ("unaryMinus", [IEvDistribution(a)]) =>
|
||||||
Helpers.twoDiststoDistFn(
|
Helpers.twoDiststoDistFn(
|
||||||
Algebraic(AsDefault),
|
Algebraic(AsDefault),
|
||||||
"multiply",
|
"multiply",
|
||||||
|
@ -337,7 +348,7 @@ let dispatchToGenericOutput = (
|
||||||
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||||
Helpers.twoDiststoDistFn(Pointwise, arithmetic, fst, snd, ~env)
|
Helpers.twoDiststoDistFn(Pointwise, arithmetic, fst, snd, ~env)
|
||||||
)
|
)
|
||||||
| ("dotExp", [EvDistribution(a)]) =>
|
| ("dotExp", [IEvDistribution(a)]) =>
|
||||||
Helpers.twoDiststoDistFn(
|
Helpers.twoDiststoDistFn(
|
||||||
Pointwise,
|
Pointwise,
|
||||||
"dotPow",
|
"dotPow",
|
||||||
|
@ -350,17 +361,18 @@ let dispatchToGenericOutput = (
|
||||||
}
|
}
|
||||||
|
|
||||||
let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
|
let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
|
||||||
expressionValue,
|
internalExpressionValue,
|
||||||
Reducer_ErrorValue.errorValue,
|
Reducer_ErrorValue.errorValue,
|
||||||
> =>
|
> =>
|
||||||
switch o {
|
switch o {
|
||||||
| Dist(d) => Ok(ReducerInterface_ExpressionValue.EvDistribution(d))
|
| Dist(d) => Ok(ReducerInterface_InternalExpressionValue.IEvDistribution(d))
|
||||||
| Float(d) => Ok(EvNumber(d))
|
| Float(d) => Ok(IEvNumber(d))
|
||||||
| String(d) => Ok(EvString(d))
|
| String(d) => Ok(IEvString(d))
|
||||||
| Bool(d) => Ok(EvBool(d))
|
| Bool(d) => Ok(IEvBool(d))
|
||||||
| FloatArray(d) => Ok(EvArray(d |> E.A.fmap(r => ReducerInterface_ExpressionValue.EvNumber(r))))
|
| FloatArray(d) =>
|
||||||
|
Ok(IEvArray(d |> E.A.fmap(r => ReducerInterface_InternalExpressionValue.IEvNumber(r))))
|
||||||
| GenDistError(err) => Error(REDistributionError(err))
|
| GenDistError(err) => Error(REDistributionError(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatch = (call: ExpressionValue.functionCall, environment) =>
|
let dispatch = (call: IEV.functionCall, environment) =>
|
||||||
dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue)
|
dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
let dispatch: (
|
let dispatch: (
|
||||||
ReducerInterface_ExpressionValue.functionCall,
|
ReducerInterface_InternalExpressionValue.functionCall,
|
||||||
ReducerInterface_ExpressionValue.environment,
|
ReducerInterface_ExternalExpressionValue.environment,
|
||||||
) => option<result<ReducerInterface_ExpressionValue.expressionValue, Reducer_ErrorValue.errorValue>>
|
) => option<result<ReducerInterface_InternalExpressionValue.t, Reducer_ErrorValue.errorValue>>
|
||||||
|
|
|
@ -0,0 +1,259 @@
|
||||||
|
module ErrorValue = Reducer_ErrorValue
|
||||||
|
module ExternalExpressionValue = ReducerInterface_ExternalExpressionValue
|
||||||
|
module Extra_Array = Reducer_Extra_Array
|
||||||
|
type internalCode = ExternalExpressionValue.internalCode
|
||||||
|
type environment = ExternalExpressionValue.environment
|
||||||
|
|
||||||
|
let defaultEnvironment = ExternalExpressionValue.defaultEnvironment
|
||||||
|
|
||||||
|
type rec t =
|
||||||
|
| IEvArray(array<t>) // FIXME: Convert
|
||||||
|
| IEvArrayString(array<string>) // FIXME: Convert
|
||||||
|
| IEvBool(bool)
|
||||||
|
| IEvCall(string) // External function call
|
||||||
|
| IEvDate(Js.Date.t)
|
||||||
|
| IEvDeclaration(lambdaDeclaration)
|
||||||
|
| IEvDistribution(DistributionTypes.genericDist)
|
||||||
|
| IEvLambda(lambdaValue)
|
||||||
|
| IEvModule(nameSpace)
|
||||||
|
| IEvNumber(float)
|
||||||
|
| IEvRecord(map)
|
||||||
|
| IEvString(string)
|
||||||
|
| IEvSymbol(string)
|
||||||
|
| IEvTimeDuration(float)
|
||||||
|
| IEvTypeIdentifier(string)
|
||||||
|
and map = Belt.Map.String.t<t>
|
||||||
|
and nameSpace = NameSpace(Belt.Map.String.t<t>)
|
||||||
|
and lambdaValue = {
|
||||||
|
parameters: array<string>,
|
||||||
|
context: nameSpace,
|
||||||
|
body: internalCode,
|
||||||
|
}
|
||||||
|
and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
||||||
|
|
||||||
|
type internalExpressionValue = t
|
||||||
|
|
||||||
|
type functionCall = (string, array<t>)
|
||||||
|
|
||||||
|
let rec toString = aValue =>
|
||||||
|
switch aValue {
|
||||||
|
| IEvArray(anArray) => {
|
||||||
|
let args = anArray->Js.Array2.map(each => toString(each))->Js.Array2.toString
|
||||||
|
`[${args}]`
|
||||||
|
}
|
||||||
|
| IEvArrayString(anArray) => {
|
||||||
|
let args = anArray->Js.Array2.toString
|
||||||
|
`[${args}]`
|
||||||
|
}
|
||||||
|
| IEvBool(aBool) => Js.String.make(aBool)
|
||||||
|
| IEvCall(fName) => `:${fName}`
|
||||||
|
| IEvDate(date) => DateTime.Date.toString(date)
|
||||||
|
| IEvDeclaration(d) => Declaration.toString(d, r => toString(IEvLambda(r)))
|
||||||
|
| IEvDistribution(dist) => GenericDist.toString(dist)
|
||||||
|
| IEvLambda(lambdaValue) => `lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)`
|
||||||
|
| IEvModule(m) => `@${m->toStringNameSpace}`
|
||||||
|
| IEvNumber(aNumber) => Js.String.make(aNumber)
|
||||||
|
| IEvRecord(aMap) => aMap->toStringMap
|
||||||
|
| IEvString(aString) => `'${aString}'`
|
||||||
|
| IEvSymbol(aString) => `:${aString}`
|
||||||
|
| IEvTimeDuration(t) => DateTime.Duration.toString(t)
|
||||||
|
| IEvTypeIdentifier(id) => `#${id}`
|
||||||
|
}
|
||||||
|
and toStringMap = aMap => {
|
||||||
|
let pairs =
|
||||||
|
aMap
|
||||||
|
->Belt.Map.String.toArray
|
||||||
|
->Js.Array2.map(((eachKey, eachValue)) => `${eachKey}: ${toString(eachValue)}`)
|
||||||
|
->Js.Array2.toString
|
||||||
|
`{${pairs}}`
|
||||||
|
}
|
||||||
|
and toStringNameSpace = nameSpace => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
container->toStringMap
|
||||||
|
}
|
||||||
|
|
||||||
|
let toStringWithType = aValue =>
|
||||||
|
switch aValue {
|
||||||
|
| IEvArray(_) => `Array::${toString(aValue)}`
|
||||||
|
| IEvArrayString(_) => `ArrayString::${toString(aValue)}`
|
||||||
|
| IEvBool(_) => `Bool::${toString(aValue)}`
|
||||||
|
| IEvCall(_) => `Call::${toString(aValue)}`
|
||||||
|
| IEvDistribution(_) => `Distribution::${toString(aValue)}`
|
||||||
|
| IEvLambda(_) => `Lambda::${toString(aValue)}`
|
||||||
|
| IEvNumber(_) => `Number::${toString(aValue)}`
|
||||||
|
| IEvRecord(_) => `Record::${toString(aValue)}`
|
||||||
|
| IEvString(_) => `String::${toString(aValue)}`
|
||||||
|
| IEvSymbol(_) => `Symbol::${toString(aValue)}`
|
||||||
|
| IEvDate(_) => `Date::${toString(aValue)}`
|
||||||
|
| IEvTimeDuration(_) => `Date::${toString(aValue)}`
|
||||||
|
| IEvDeclaration(_) => `Declaration::${toString(aValue)}`
|
||||||
|
| IEvTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}`
|
||||||
|
| IEvModule(_) => `Module::${toString(aValue)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
let argsToString = (args: array<t>): string => {
|
||||||
|
args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString
|
||||||
|
}
|
||||||
|
|
||||||
|
let toStringFunctionCall = ((fn, args)): string => `${fn}(${argsToString(args)})`
|
||||||
|
|
||||||
|
let toStringResult = x =>
|
||||||
|
switch x {
|
||||||
|
| Ok(a) => `Ok(${toString(a)})`
|
||||||
|
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||||
|
}
|
||||||
|
|
||||||
|
let toStringResultOkless = (codeResult: result<t, ErrorValue.errorValue>): string =>
|
||||||
|
switch codeResult {
|
||||||
|
| Ok(a) => toString(a)
|
||||||
|
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||||
|
}
|
||||||
|
|
||||||
|
let toStringResultRecord = x =>
|
||||||
|
switch x {
|
||||||
|
| Ok(a) => `Ok(${ExternalExpressionValue.toStringRecord(a)})`
|
||||||
|
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||||
|
}
|
||||||
|
|
||||||
|
type internalExpressionValueType =
|
||||||
|
| EvtArray
|
||||||
|
| EvtArrayString
|
||||||
|
| EvtBool
|
||||||
|
| EvtCall
|
||||||
|
| EvtDistribution
|
||||||
|
| EvtLambda
|
||||||
|
| EvtNumber
|
||||||
|
| EvtRecord
|
||||||
|
| EvtString
|
||||||
|
| EvtSymbol
|
||||||
|
| EvtDate
|
||||||
|
| EvtTimeDuration
|
||||||
|
| EvtDeclaration
|
||||||
|
| EvtTypeIdentifier
|
||||||
|
| EvtModule
|
||||||
|
|
||||||
|
type functionCallSignature = CallSignature(string, array<internalExpressionValueType>)
|
||||||
|
type functionDefinitionSignature =
|
||||||
|
FunctionDefinitionSignature(functionCallSignature, internalExpressionValueType)
|
||||||
|
|
||||||
|
let valueToValueType = value =>
|
||||||
|
switch value {
|
||||||
|
| IEvArray(_) => EvtArray
|
||||||
|
| IEvArrayString(_) => EvtArrayString
|
||||||
|
| IEvBool(_) => EvtBool
|
||||||
|
| IEvCall(_) => EvtCall
|
||||||
|
| IEvDistribution(_) => EvtDistribution
|
||||||
|
| IEvLambda(_) => EvtLambda
|
||||||
|
| IEvNumber(_) => EvtNumber
|
||||||
|
| IEvRecord(_) => EvtRecord
|
||||||
|
| IEvString(_) => EvtString
|
||||||
|
| IEvSymbol(_) => EvtSymbol
|
||||||
|
| IEvDate(_) => EvtDate
|
||||||
|
| IEvTimeDuration(_) => EvtTimeDuration
|
||||||
|
| IEvDeclaration(_) => EvtDeclaration
|
||||||
|
| IEvTypeIdentifier(_) => EvtTypeIdentifier
|
||||||
|
| IEvModule(_) => EvtModule
|
||||||
|
}
|
||||||
|
|
||||||
|
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
||||||
|
let (fn, args) = functionCall
|
||||||
|
CallSignature(fn, args->Js.Array2.map(valueToValueType))
|
||||||
|
}
|
||||||
|
|
||||||
|
let valueTypeToString = (valueType: internalExpressionValueType): string =>
|
||||||
|
switch valueType {
|
||||||
|
| EvtArray => `Array`
|
||||||
|
| EvtArrayString => `ArrayString`
|
||||||
|
| EvtBool => `Bool`
|
||||||
|
| EvtCall => `Call`
|
||||||
|
| EvtDistribution => `Distribution`
|
||||||
|
| EvtLambda => `Lambda`
|
||||||
|
| EvtNumber => `Number`
|
||||||
|
| EvtRecord => `Record`
|
||||||
|
| EvtString => `String`
|
||||||
|
| EvtSymbol => `Symbol`
|
||||||
|
| EvtDate => `Date`
|
||||||
|
| EvtTimeDuration => `Duration`
|
||||||
|
| EvtDeclaration => `Declaration`
|
||||||
|
| EvtTypeIdentifier => `TypeIdentifier`
|
||||||
|
| EvtModule => `Module`
|
||||||
|
}
|
||||||
|
|
||||||
|
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
||||||
|
let CallSignature(fn, args) = functionCallSignature
|
||||||
|
`${fn}(${args->Js.Array2.map(valueTypeToString)->Js.Array2.toString})`
|
||||||
|
}
|
||||||
|
|
||||||
|
let rec toExternal = (iev: t): ExternalExpressionValue.t => {
|
||||||
|
switch iev {
|
||||||
|
| IEvArray(v) => v->Belt.Array.map(e => toExternal(e))->EvArray
|
||||||
|
| IEvArrayString(v) => EvArrayString(v)
|
||||||
|
| IEvBool(v) => EvBool(v)
|
||||||
|
| IEvCall(v) => EvCall(v)
|
||||||
|
| IEvDistribution(v) => EvDistribution(v)
|
||||||
|
| IEvLambda(v) => EvLambda(lambdaValueToExternal(v))
|
||||||
|
| IEvNumber(v) => EvNumber(v)
|
||||||
|
| IEvRecord(v) => v->mapToExternal->EvRecord
|
||||||
|
| IEvString(v) => EvString(v)
|
||||||
|
| IEvSymbol(v) => EvSymbol(v)
|
||||||
|
| IEvDate(v) => EvDate(v)
|
||||||
|
| IEvTimeDuration(v) => EvTimeDuration(v)
|
||||||
|
| IEvDeclaration(v) => {
|
||||||
|
let fn = lambdaValueToExternal(v.fn)
|
||||||
|
let args = v.args
|
||||||
|
EvDeclaration({fn: fn, args: args})
|
||||||
|
}
|
||||||
|
| IEvTypeIdentifier(v) => EvTypeIdentifier(v)
|
||||||
|
| IEvModule(v) => v->nameSpaceToTypeScriptBindings->EvModule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
and mapToExternal = v =>
|
||||||
|
v->Belt.Map.String.map(e => toExternal(e))->Belt.Map.String.toArray->Js.Dict.fromArray
|
||||||
|
and lambdaValueToExternal = v => {
|
||||||
|
let p = v.parameters
|
||||||
|
let c = v.context->nameSpaceToTypeScriptBindings
|
||||||
|
let b = v.body
|
||||||
|
{parameters: p, context: c, body: b}
|
||||||
|
}
|
||||||
|
and nameSpaceToTypeScriptBindings = (
|
||||||
|
nameSpace: nameSpace,
|
||||||
|
): ReducerInterface_ExternalExpressionValue.externalBindings => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
Belt.Map.String.map(container, e => toExternal(e))->Belt.Map.String.toArray->Js.Dict.fromArray
|
||||||
|
}
|
||||||
|
|
||||||
|
let rec toInternal = (ev: ExternalExpressionValue.t): t => {
|
||||||
|
switch ev {
|
||||||
|
| EvArray(v) => v->Belt.Array.map(e => toInternal(e))->IEvArray
|
||||||
|
| EvArrayString(v) => IEvArrayString(v)
|
||||||
|
| EvBool(v) => IEvBool(v)
|
||||||
|
| EvCall(v) => IEvCall(v)
|
||||||
|
| EvDistribution(v) => IEvDistribution(v)
|
||||||
|
| EvLambda(v) => IEvLambda(lambdaValueToInternal(v))
|
||||||
|
| EvNumber(v) => IEvNumber(v)
|
||||||
|
| EvRecord(v) => v->recordToInternal->IEvRecord
|
||||||
|
| EvString(v) => IEvString(v)
|
||||||
|
| EvSymbol(v) => IEvSymbol(v)
|
||||||
|
| EvDate(v) => IEvDate(v)
|
||||||
|
| EvTimeDuration(v) => IEvTimeDuration(v)
|
||||||
|
| EvDeclaration(v) => {
|
||||||
|
let fn = lambdaValueToInternal(v.fn)
|
||||||
|
let args = v.args
|
||||||
|
IEvDeclaration({fn: fn, args: args})
|
||||||
|
}
|
||||||
|
| EvTypeIdentifier(v) => IEvTypeIdentifier(v)
|
||||||
|
| EvModule(v) => v->nameSpaceFromTypeScriptBindings->IEvModule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
and recordToInternal = v =>
|
||||||
|
v->Js.Dict.entries->Belt.Map.String.fromArray->Belt.Map.String.map(e => toInternal(e))
|
||||||
|
and lambdaValueToInternal = v => {
|
||||||
|
let p = v.parameters
|
||||||
|
let c = v.context->nameSpaceFromTypeScriptBindings
|
||||||
|
let b = v.body
|
||||||
|
{parameters: p, context: c, body: b}
|
||||||
|
}
|
||||||
|
and nameSpaceFromTypeScriptBindings = (
|
||||||
|
r: ReducerInterface_ExternalExpressionValue.externalBindings,
|
||||||
|
): nameSpace =>
|
||||||
|
r->Js.Dict.entries->Belt.Map.String.fromArray->Belt.Map.String.map(e => toInternal(e))->NameSpace
|
|
@ -1,5 +1,5 @@
|
||||||
module EV = ReducerInterface_ExpressionValue
|
module IEV = ReducerInterface_InternalExpressionValue
|
||||||
type expressionValue = EV.expressionValue
|
type internalExpressionValue = IEV.t
|
||||||
|
|
||||||
module ScientificUnit = {
|
module ScientificUnit = {
|
||||||
let nameToMultiplier = str =>
|
let nameToMultiplier = str =>
|
||||||
|
@ -24,8 +24,8 @@ module ScientificUnit = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
let dispatch = (call: IEV.functionCall, _: DistributionOperation.env): option<
|
||||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
result<internalExpressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||||
> => {
|
> => {
|
||||||
switch call {
|
switch call {
|
||||||
| (
|
| (
|
||||||
|
@ -37,9 +37,9 @@ let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
||||||
| "fromUnit_G"
|
| "fromUnit_G"
|
||||||
| "fromUnit_T"
|
| "fromUnit_T"
|
||||||
| "fromUnit_P") as op,
|
| "fromUnit_P") as op,
|
||||||
[EvNumber(f)],
|
[IEvNumber(f)],
|
||||||
) =>
|
) =>
|
||||||
op->ScientificUnit.getMultiplier->E.O2.fmap(multiplier => EV.EvNumber(f *. multiplier)->Ok)
|
op->ScientificUnit.getMultiplier->E.O2.fmap(multiplier => IEV.IEvNumber(f *. multiplier)->Ok)
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Bindings = Reducer_Category_Bindings
|
module Module = Reducer_Category_Module
|
||||||
|
|
||||||
let internalStdLib = Bindings.emptyBindings->SquiggleLibrary_Math.makeBindings
|
let internalStdLib = Module.emptyModule->SquiggleLibrary_Math.makeBindings
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let externalStdLib = internalStdLib->Bindings.toRecord
|
let externalStdLib = internalStdLib->Module.toTypeScriptBindings
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module Bindings = Reducer_Category_Bindings
|
module Bindings = Reducer_Category_Module
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Category_Module
|
||||||
|
|
||||||
let availableNumbers: array<(string, float)> = [
|
let availableNumbers: array<(string, float)> = [
|
||||||
|
@ -14,10 +14,10 @@ let availableNumbers: array<(string, float)> = [
|
||||||
("tau", 6.283185307179586),
|
("tau", 6.283185307179586),
|
||||||
]
|
]
|
||||||
|
|
||||||
let mathBindings: Bindings.ExpressionT.bindings =
|
let mathBindings: Bindings.t =
|
||||||
availableNumbers
|
availableNumbers
|
||||||
->E.A2.fmap(((name, v)) => (name, ReducerInterface_ExpressionValue.EvNumber(v)))
|
->E.A2.fmap(((name, v)) => (name, ReducerInterface_InternalExpressionValue.IEvNumber(v)))
|
||||||
->Belt.Map.String.fromArray
|
->Bindings.fromArray
|
||||||
|
|
||||||
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
||||||
previousBindings->Bindings.defineModule("Math", mathBindings)
|
previousBindings->Bindings.defineModule("Math", mathBindings)
|
||||||
|
|
|
@ -50,10 +50,10 @@ let evaluatePartialUsingExternalBindings = Reducer.evaluatePartialUsingExternalB
|
||||||
type externalBindings = Reducer.externalBindings
|
type externalBindings = Reducer.externalBindings
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type expressionValue = ReducerInterface_ExternalExpressionValue.t
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type recordEV = ReducerInterface_ExpressionValue.record
|
type recordEV = ReducerInterface_ExternalExpressionValue.record
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type errorValue = Reducer_ErrorValue.errorValue
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
|
@ -77,19 +77,19 @@ let errorValueToString = Reducer_ErrorValue.errorToString
|
||||||
let distributionErrorToString = DistributionTypes.Error.toString
|
let distributionErrorToString = DistributionTypes.Error.toString
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type lambdaValue = ReducerInterface_ExpressionValue.lambdaValue
|
type lambdaValue = ReducerInterface_ExternalExpressionValue.lambdaValue
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type lambdaDeclaration = ReducerInterface_ExpressionValue.lambdaDeclaration
|
type lambdaDeclaration = ReducerInterface_ExternalExpressionValue.lambdaDeclaration
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let defaultSamplingEnv = DistributionOperation.defaultEnv
|
let defaultSamplingEnv = DistributionOperation.defaultEnv
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type environment = ReducerInterface_ExpressionValue.environment
|
type environment = ReducerInterface_ExternalExpressionValue.environment
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let defaultEnvironment = ReducerInterface_ExpressionValue.defaultEnvironment
|
let defaultEnvironment = ReducerInterface_ExternalExpressionValue.defaultEnvironment
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let foreignFunctionInterface = Reducer.foreignFunctionInterface
|
let foreignFunctionInterface = Reducer.foreignFunctionInterface
|
||||||
|
|
|
@ -4,6 +4,7 @@ import * as vscode from "vscode";
|
||||||
import { startClient, stopClient } from "./client";
|
import { startClient, stopClient } from "./client";
|
||||||
|
|
||||||
import { SquiggleEditorProvider } from "./editor";
|
import { SquiggleEditorProvider } from "./editor";
|
||||||
|
import { registerSemanticHighlight } from "./highlight";
|
||||||
import { registerPreviewCommand } from "./preview";
|
import { registerPreviewCommand } from "./preview";
|
||||||
|
|
||||||
// this method is called when your extension is activated
|
// this method is called when your extension is activated
|
||||||
|
@ -13,6 +14,8 @@ export function activate(context: vscode.ExtensionContext) {
|
||||||
|
|
||||||
registerPreviewCommand(context);
|
registerPreviewCommand(context);
|
||||||
|
|
||||||
|
registerSemanticHighlight();
|
||||||
|
|
||||||
startClient(context);
|
startClient(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
96
packages/vscode-ext/client/src/highlight.ts
Normal file
96
packages/vscode-ext/client/src/highlight.ts
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import * as vscode from "vscode";
|
||||||
|
|
||||||
|
import { parse } from "@quri/squiggle-lang";
|
||||||
|
import { AnyPeggyNode } from "@quri/squiggle-lang/dist/src/rescript/Reducer/Reducer_Peggy/helpers";
|
||||||
|
|
||||||
|
const tokenTypes = ["enum", "function", "variable", "property"];
|
||||||
|
const tokenModifiers = ["declaration", "documentation"];
|
||||||
|
const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers);
|
||||||
|
|
||||||
|
const convertRange = (
|
||||||
|
range: Extract<AnyPeggyNode, { type: "Identifier" }>["location"]
|
||||||
|
) =>
|
||||||
|
new vscode.Range(
|
||||||
|
new vscode.Position(range.start.line - 1, range.start.column - 1),
|
||||||
|
new vscode.Position(range.end.line - 1, range.end.column - 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
const populateTokensBuilder = (
|
||||||
|
tokensBuilder: vscode.SemanticTokensBuilder,
|
||||||
|
node: AnyPeggyNode
|
||||||
|
// bindings: { [key: string]: boolean }
|
||||||
|
) => {
|
||||||
|
switch (node.type) {
|
||||||
|
case "Expression":
|
||||||
|
for (const child of node.nodes) {
|
||||||
|
populateTokensBuilder(tokensBuilder, child);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Block":
|
||||||
|
for (const child of node.statements) {
|
||||||
|
populateTokensBuilder(tokensBuilder, child);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "LetStatement":
|
||||||
|
tokensBuilder.push(
|
||||||
|
convertRange(node.variable.location),
|
||||||
|
node.value.type === "Lambda" ? "function" : "variable",
|
||||||
|
["declaration"]
|
||||||
|
);
|
||||||
|
populateTokensBuilder(tokensBuilder, node.value);
|
||||||
|
break;
|
||||||
|
case "Lambda":
|
||||||
|
for (const arg of node.args) {
|
||||||
|
populateTokensBuilder(tokensBuilder, arg);
|
||||||
|
}
|
||||||
|
populateTokensBuilder(tokensBuilder, node.body);
|
||||||
|
break;
|
||||||
|
case "Ternary":
|
||||||
|
populateTokensBuilder(tokensBuilder, node.condition);
|
||||||
|
populateTokensBuilder(tokensBuilder, node.trueExpression);
|
||||||
|
populateTokensBuilder(tokensBuilder, node.falseExpression);
|
||||||
|
break;
|
||||||
|
case "KeyValue":
|
||||||
|
if (node.key.type === "String" && node.key.location) {
|
||||||
|
tokensBuilder.push(convertRange(node.key.location), "property", [
|
||||||
|
"declaration",
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
populateTokensBuilder(tokensBuilder, node.key);
|
||||||
|
}
|
||||||
|
populateTokensBuilder(tokensBuilder, node.value);
|
||||||
|
break;
|
||||||
|
case "Identifier":
|
||||||
|
tokensBuilder.push(convertRange(node.location), "variable");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const registerSemanticHighlight = () => {
|
||||||
|
const provider: vscode.DocumentSemanticTokensProvider = {
|
||||||
|
provideDocumentSemanticTokens(
|
||||||
|
document: vscode.TextDocument
|
||||||
|
): vscode.ProviderResult<vscode.SemanticTokens> {
|
||||||
|
const parseResult = parse(document.getText());
|
||||||
|
|
||||||
|
const tokensBuilder = new vscode.SemanticTokensBuilder(legend);
|
||||||
|
if (parseResult.tag === "Ok") {
|
||||||
|
populateTokensBuilder(
|
||||||
|
tokensBuilder,
|
||||||
|
parseResult.value
|
||||||
|
// {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokensBuilder.build();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const selector = { language: "squiggle", scheme: "file" };
|
||||||
|
|
||||||
|
vscode.languages.registerDocumentSemanticTokensProvider(
|
||||||
|
selector,
|
||||||
|
provider,
|
||||||
|
legend
|
||||||
|
);
|
||||||
|
};
|
|
@ -13,6 +13,10 @@ import { parse } from "@quri/squiggle-lang";
|
||||||
|
|
||||||
import { TextDocument } from "vscode-languageserver-textdocument";
|
import { TextDocument } from "vscode-languageserver-textdocument";
|
||||||
|
|
||||||
|
// Documentation:
|
||||||
|
// - https://code.visualstudio.com/api/language-extensions/language-server-extension-guide
|
||||||
|
// - https://microsoft.github.io/language-server-protocol/specifications/specification-current
|
||||||
|
|
||||||
// Create a connection for the server, using Node's IPC as a transport.
|
// Create a connection for the server, using Node's IPC as a transport.
|
||||||
// Also include all preview / proposed LSP features.
|
// Also include all preview / proposed LSP features.
|
||||||
let connection = createConnection(ProposedFeatures.all);
|
let connection = createConnection(ProposedFeatures.all);
|
||||||
|
@ -23,17 +27,7 @@ documents.onDidChangeContent((change) => {
|
||||||
validateSquiggleDocument(change.document);
|
validateSquiggleDocument(change.document);
|
||||||
});
|
});
|
||||||
|
|
||||||
let hasDiagnosticRelatedInformationCapability = false;
|
|
||||||
|
|
||||||
connection.onInitialize((params: InitializeParams) => {
|
connection.onInitialize((params: InitializeParams) => {
|
||||||
const capabilities = params.capabilities;
|
|
||||||
|
|
||||||
hasDiagnosticRelatedInformationCapability = !!(
|
|
||||||
capabilities.textDocument &&
|
|
||||||
capabilities.textDocument.publishDiagnostics &&
|
|
||||||
capabilities.textDocument.publishDiagnostics.relatedInformation
|
|
||||||
);
|
|
||||||
|
|
||||||
const result: InitializeResult = {
|
const result: InitializeResult = {
|
||||||
capabilities: {
|
capabilities: {
|
||||||
textDocumentSync: TextDocumentSyncKind.Incremental,
|
textDocumentSync: TextDocumentSyncKind.Incremental,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user