Merge branch 'develop' into more-graph-settings

This commit is contained in:
Sam Nolan 2022-07-05 17:35:50 +10:00
commit 04188a55f1
63 changed files with 1638 additions and 986 deletions

4
.github/CODEOWNERS vendored
View File

@ -9,8 +9,8 @@
# This also holds true for GitHub teams. # This also holds true for GitHub teams.
# Rescript # Rescript
*.res @OAGr @quinn-dougherty *.res @OAGr
*.resi @OAGr @quinn-dougherty *.resi @OAGr
# Typescript # Typescript
*.tsx @Hazelfire @OAGr *.tsx @Hazelfire @OAGr

View File

@ -5,14 +5,14 @@
"dependencies": { "dependencies": {
"@headlessui/react": "^1.6.5", "@headlessui/react": "^1.6.5",
"@heroicons/react": "^1.0.6", "@heroicons/react": "^1.0.6",
"@hookform/resolvers": "^2.9.1", "@hookform/resolvers": "^2.9.3",
"@quri/squiggle-lang": "^0.2.8", "@quri/squiggle-lang": "^0.2.8",
"@react-hook/size": "^2.1.2", "@react-hook/size": "^2.1.2",
"clsx": "^1.1.1", "clsx": "^1.2.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "^18.1.0", "react": "^18.1.0",
"react-ace": "^10.1.0", "react-ace": "^10.1.0",
"react-hook-form": "^7.32.2", "react-hook-form": "^7.33.0",
"react-use": "^17.4.0", "react-use": "^17.4.0",
"react-vega": "^7.5.1", "react-vega": "^7.5.1",
"vega": "^5.22.1", "vega": "^5.22.1",

View File

@ -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>
); );
} }

View File

@ -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

View File

@ -0,0 +1,4 @@
open Jest
open Expect
test("todo", () => expect("1")->toBe("1"))

View File

@ -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)")
}) })

View File

@ -1,4 +1,4 @@
module ExpressionValue = ReducerInterface.ExpressionValue module ExpressionValue = ReducerInterface.ExternalExpressionValue
open Jest open Jest
open Expect open Expect

View File

@ -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)

View File

@ -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", () => {

View File

@ -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))
} }

View File

@ -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)}",
(), (),
) )
}) })

View File

@ -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]}",
(), (),
) )
}) })

View File

@ -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)

View File

@ -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)

View File

@ -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})",
)
}) })

View File

@ -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)")

View File

@ -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})")
}) })
}) })

View File

@ -1,4 +1,4 @@
open ReducerInterface.ExpressionValue open ReducerInterface.ExternalExpressionValue
open Jest open Jest
open Expect open Expect

View File

@ -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",
@ -40,7 +42,7 @@
"@stdlib/stats": "^0.0.13", "@stdlib/stats": "^0.0.13",
"jstat": "^1.9.5", "jstat": "^1.9.5",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mathjs": "^10.6.0", "mathjs": "^10.6.4",
"pdfast": "^0.2.0" "pdfast": "^0.2.0"
}, },
"devDependencies": { "devDependencies": {
@ -51,7 +53,7 @@
"bisect_ppx": "^2.7.1", "bisect_ppx": "^2.7.1",
"chalk": "^5.0.1", "chalk": "^5.0.1",
"codecov": "^3.8.3", "codecov": "^3.8.3",
"fast-check": "^3.0.0", "fast-check": "^3.0.1",
"gentype": "^4.4.0", "gentype": "^4.4.0",
"jest": "^27.5.1", "jest": "^27.5.1",
"moduleserve": "^0.9.1", "moduleserve": "^0.9.1",

View File

@ -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);

View 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 };
}
}

View File

@ -1,3 +1,4 @@
@@warning("-27") //TODO: Remove and fix the warning
open Distributions open Distributions
type t = PointSetTypes.discreteShape type t = PointSetTypes.discreteShape

View File

@ -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

View File

@ -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)

View File

@ -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
} }

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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))

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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
} }

View File

@ -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

View File

@ -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 =>

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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)
} }

View File

@ -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,

View File

@ -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)

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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 };
}

View File

@ -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

View File

@ -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
} }
} }

View File

@ -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
} }
} }

View File

@ -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

View File

@ -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([

View File

@ -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)

View File

@ -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>>

View File

@ -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

View File

@ -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
} }
} }

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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);
} }

View 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
);
};

View File

@ -139,8 +139,8 @@
"@types/glob": "^7.2.0", "@types/glob": "^7.2.0",
"@types/node": "18.x", "@types/node": "18.x",
"@types/vscode": "^1.68.0", "@types/vscode": "^1.68.0",
"@typescript-eslint/eslint-plugin": "^5.27.0", "@typescript-eslint/eslint-plugin": "^5.30.4",
"@typescript-eslint/parser": "^5.27.0", "@typescript-eslint/parser": "^5.30.4",
"eslint": "^8.18.0", "eslint": "^8.18.0",
"glob": "^8.0.3", "glob": "^8.0.3",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",

View File

@ -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,

View File

@ -16,10 +16,10 @@
"@docusaurus/preset-classic": "2.0.0-beta.21", "@docusaurus/preset-classic": "2.0.0-beta.21",
"@quri/squiggle-components": "^0.2.20", "@quri/squiggle-components": "^0.2.20",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"clsx": "^1.1.1", "clsx": "^1.2.0",
"hast-util-is-element": "2.1.2", "hast-util-is-element": "2.1.2",
"pako": "^2.0.4", "pako": "^2.0.4",
"prism-react-renderer": "^1.3.3", "prism-react-renderer": "^1.3.5",
"react": "^18.1.0", "react": "^18.1.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"rehype-katex": "^5", "rehype-katex": "^5",

144
yarn.lock
View File

@ -1239,10 +1239,10 @@
core-js-pure "^3.20.2" core-js-pure "^3.20.2"
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.18.3" version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580"
integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
@ -1852,10 +1852,10 @@
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324" resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324"
integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ== integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==
"@hookform/resolvers@^2.9.1": "@hookform/resolvers@^2.9.3":
version "2.9.1" version "2.9.3"
resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.1.tgz#59121e38d8fc95d2fd1f41c9631393cd21e10b65" resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.3.tgz#13f6934cfe705e24fac094da377e0621adcfc424"
integrity sha512-80lyFFcExEB7A09PFnl8k7A3obQyDF6MyO/FThtwetk+MTedYMs08Aqf7mgWnOawFGyz5QF+TZXJSYiIZW2tEg== integrity sha512-Eqc/qgjq0VX/TU0a5D2O+yR/kAKflnjaVlYFC1wI2qBm/sgjKTXxv27ijLwHUoHPIF+MUkB/VuQqHJ5DcmbCww==
"@humanwhocodes/config-array@^0.9.2": "@humanwhocodes/config-array@^0.9.2":
version "0.9.5" version "0.9.5"
@ -4532,14 +4532,14 @@
dependencies: dependencies:
"@types/yargs-parser" "*" "@types/yargs-parser" "*"
"@typescript-eslint/eslint-plugin@^5.27.0", "@typescript-eslint/eslint-plugin@^5.5.0": "@typescript-eslint/eslint-plugin@^5.30.4", "@typescript-eslint/eslint-plugin@^5.5.0":
version "5.29.0" version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz#c67794d2b0fd0b4a47f50266088acdc52a08aab6" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.4.tgz#a46c8c0ab755a936cb63786a6222876ce51675e4"
integrity sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w== integrity sha512-xjujQISAIa4HAaos8fcMZXmqkuZqMx6icdxkI88jMM/eNe4J8AuTLYnLK+zdm0mBYLyctdFf//UE4/xFCcQzYQ==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.29.0" "@typescript-eslint/scope-manager" "5.30.4"
"@typescript-eslint/type-utils" "5.29.0" "@typescript-eslint/type-utils" "5.30.4"
"@typescript-eslint/utils" "5.29.0" "@typescript-eslint/utils" "5.30.4"
debug "^4.3.4" debug "^4.3.4"
functional-red-black-tree "^1.0.1" functional-red-black-tree "^1.0.1"
ignore "^5.2.0" ignore "^5.2.0"
@ -4554,14 +4554,14 @@
dependencies: dependencies:
"@typescript-eslint/utils" "5.29.0" "@typescript-eslint/utils" "5.29.0"
"@typescript-eslint/parser@^5.27.0", "@typescript-eslint/parser@^5.5.0": "@typescript-eslint/parser@^5.30.4", "@typescript-eslint/parser@^5.5.0":
version "5.29.0" version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.29.0.tgz#41314b195b34d44ff38220caa55f3f93cfca43cf" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.4.tgz#659411e8700b22c8d5400798ef24838425bf4567"
integrity sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw== integrity sha512-/ge1HtU63wVoED4VnlU2o+FPFmi017bPYpeSrCmd8Ycsti4VSxXrmcpXXm7JpI4GT0Aa7qviabv1PEp6L5bboQ==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.29.0" "@typescript-eslint/scope-manager" "5.30.4"
"@typescript-eslint/types" "5.29.0" "@typescript-eslint/types" "5.30.4"
"@typescript-eslint/typescript-estree" "5.29.0" "@typescript-eslint/typescript-estree" "5.30.4"
debug "^4.3.4" debug "^4.3.4"
"@typescript-eslint/scope-manager@5.29.0": "@typescript-eslint/scope-manager@5.29.0":
@ -4572,12 +4572,20 @@
"@typescript-eslint/types" "5.29.0" "@typescript-eslint/types" "5.29.0"
"@typescript-eslint/visitor-keys" "5.29.0" "@typescript-eslint/visitor-keys" "5.29.0"
"@typescript-eslint/type-utils@5.29.0": "@typescript-eslint/scope-manager@5.30.4":
version "5.29.0" version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz#241918001d164044020b37d26d5b9f4e37cc3d5d" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.4.tgz#8140efd2bc12d41d74e8af23872a89f3edbe552e"
integrity sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg== integrity sha512-DNzlQwGSiGefz71JwaHrpcaAX3zYkEcy8uVuan3YMKOa6qeW/y+7SaD8KIsIAruASwq6P+U4BjWBWtM2O+mwBQ==
dependencies: dependencies:
"@typescript-eslint/utils" "5.29.0" "@typescript-eslint/types" "5.30.4"
"@typescript-eslint/visitor-keys" "5.30.4"
"@typescript-eslint/type-utils@5.30.4":
version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.4.tgz#00ff19073cd01f7d27e9af49ce08d6a69f1e4f01"
integrity sha512-55cf1dZviwwv+unDB+mF8vZkfta5muTK6bppPvenWWCD7slZZ0DEsXUjZerqy7Rq8s3J4SXdg4rMIY8ngCtTmA==
dependencies:
"@typescript-eslint/utils" "5.30.4"
debug "^4.3.4" debug "^4.3.4"
tsutils "^3.21.0" tsutils "^3.21.0"
@ -4586,6 +4594,11 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.29.0.tgz#7861d3d288c031703b2d97bc113696b4d8c19aab" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.29.0.tgz#7861d3d288c031703b2d97bc113696b4d8c19aab"
integrity sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg== integrity sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==
"@typescript-eslint/types@5.30.4":
version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.4.tgz#3bc99eca8ba3fcfd6a21480e216b09dab81c3999"
integrity sha512-NTEvqc+Vvu8Q6JeAKryHk2eqLKqsr2St3xhIjhOjQv5wQUBhaTuix4WOSacqj0ONWfKVU12Eug3LEAB95GBkMA==
"@typescript-eslint/typescript-estree@5.29.0": "@typescript-eslint/typescript-estree@5.29.0":
version "5.29.0" version "5.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz#e83d19aa7fd2e74616aab2f25dfbe4de4f0b5577" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz#e83d19aa7fd2e74616aab2f25dfbe4de4f0b5577"
@ -4599,7 +4612,20 @@
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/utils@5.29.0", "@typescript-eslint/utils@^5.13.0": "@typescript-eslint/typescript-estree@5.30.4":
version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.4.tgz#ac4be8a2f8fb1f1c3b346d5992a36163121ddb3f"
integrity sha512-V4VnEs6/J9/nNizaA12IeU4SAeEYaiKr7XndLNfV5+3zZSB4hIu6EhHJixTKhvIqA+EEHgBl6re8pivBMLLO1w==
dependencies:
"@typescript-eslint/types" "5.30.4"
"@typescript-eslint/visitor-keys" "5.30.4"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.29.0":
version "5.29.0" version "5.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.29.0.tgz#775046effd5019667bd086bcf326acbe32cd0082" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.29.0.tgz#775046effd5019667bd086bcf326acbe32cd0082"
integrity sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A== integrity sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==
@ -4611,6 +4637,18 @@
eslint-scope "^5.1.1" eslint-scope "^5.1.1"
eslint-utils "^3.0.0" eslint-utils "^3.0.0"
"@typescript-eslint/utils@5.30.4", "@typescript-eslint/utils@^5.13.0":
version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.4.tgz#07a2b7ce80b2527ea506829f190591b76c70ba9f"
integrity sha512-a+GQrJzOUhn4WT1mUumXDyam+22Oo4c5K/jnZ+6r/4WTQF3q8e4CsC9PLHb4SnOClzOqo/5GLZWvkE1aa5UGKQ==
dependencies:
"@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.30.4"
"@typescript-eslint/types" "5.30.4"
"@typescript-eslint/typescript-estree" "5.30.4"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@5.29.0": "@typescript-eslint/visitor-keys@5.29.0":
version "5.29.0" version "5.29.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz#7a4749fa7ef5160c44a451bf060ac1dc6dfb77ee" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz#7a4749fa7ef5160c44a451bf060ac1dc6dfb77ee"
@ -4619,6 +4657,14 @@
"@typescript-eslint/types" "5.29.0" "@typescript-eslint/types" "5.29.0"
eslint-visitor-keys "^3.3.0" eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@5.30.4":
version "5.30.4"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.4.tgz#b4969df1a440cc999d4bb7f7b7932dce05537089"
integrity sha512-ulKGse3mruSc8x6l8ORSc6+1ORyJzKmZeIaRTu/WpaF/jx3vHvEn5XZUKF9XaVg2710mFmTAUlLcLYLPp/Zf/Q==
dependencies:
"@typescript-eslint/types" "5.30.4"
eslint-visitor-keys "^3.3.0"
"@webassemblyjs/ast@1.11.1": "@webassemblyjs/ast@1.11.1":
version "1.11.1" version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
@ -6580,10 +6626,10 @@ clone@~2.1.2:
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
clsx@^1.1.1: clsx@^1.1.1, clsx@^1.2.0:
version "1.1.1" version "1.2.0"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.0.tgz#b0e415ea7537dbac01b169c5cec1caeb11d86566"
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== integrity sha512-EPRP7XJsM1y0iCU3Z7C7jFKdQboXSeHgEfzQUTlz7m5NP3hDrlz48aUsmNGp4pC+JOW9WA3vIRqlYuo/bl4Drw==
co@^4.6.0: co@^4.6.0:
version "4.6.0" version "4.6.0"
@ -8713,10 +8759,10 @@ fast-check@^2.17.0:
dependencies: dependencies:
pure-rand "^5.0.1" pure-rand "^5.0.1"
fast-check@^3.0.0: fast-check@^3.0.1:
version "3.0.0" version "3.0.1"
resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.0.0.tgz#6ea28d584e9ffebd7ecd0f06c163cd6af593ecfd" resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.0.1.tgz#b9e7b57c4643a4e62893aca85e21c270591d0eac"
integrity sha512-uujtrFJEQQqnIMO52ARwzPcuV4omiL1OJBUBLE9WnNFeu0A97sREXDOmCIHY+Z6KLVcemUf09rWr0q0Xy/Y/Ew== integrity sha512-AriFDYpYVOBynpPZq/quxSLumFOo2hPB2H5Nz2vc1QlNfjOaA62zX8USNXcOY5nwKHEq7lZ84dG9M1W+LAND1g==
dependencies: dependencies:
pure-rand "^5.0.1" pure-rand "^5.0.1"
@ -11914,12 +11960,12 @@ markdown-it@^8.3.1:
mdurl "^1.0.1" mdurl "^1.0.1"
uc.micro "^1.0.5" uc.micro "^1.0.5"
mathjs@^10.6.0: mathjs@^10.6.4:
version "10.6.1" version "10.6.4"
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.6.1.tgz#95b34178eed65cbf7a63d35c468ad3ac912f7ddf" resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.6.4.tgz#1b87a1268781d64f0c8b4e5e1b36cf7ecf58bb05"
integrity sha512-8iZp6uUKKBoCFoUHze9ydsrSji9/IOEzMhwURyoQXaLL1+ILEZnraw4KzZnUBt/XN6lPJPV+7JO94oil3AmosQ== integrity sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA==
dependencies: dependencies:
"@babel/runtime" "^7.18.3" "@babel/runtime" "^7.18.6"
complex.js "^2.1.1" complex.js "^2.1.1"
decimal.js "^10.3.1" decimal.js "^10.3.1"
escape-latex "^1.2.0" escape-latex "^1.2.0"
@ -14092,10 +14138,10 @@ pretty-time@^1.1.0:
resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e"
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
prism-react-renderer@^1.3.3: prism-react-renderer@^1.3.3, prism-react-renderer@^1.3.5:
version "1.3.3" version "1.3.5"
resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.3.tgz#9b5a4211a6756eee3c96fee9a05733abc0b0805c" resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085"
integrity sha512-Viur/7tBTCH2HmYzwCHmt2rEFn+rdIWNIINXyg0StiISbDiIhHKhrFuEK8eMkKgvsIYSjgGqy/hNyucHp6FpoQ== integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==
prismjs@^1.27.0, prismjs@^1.28.0: prismjs@^1.27.0, prismjs@^1.28.0:
version "1.28.0" version "1.28.0"
@ -14523,10 +14569,10 @@ react-helmet-async@*, react-helmet-async@^1.3.0:
react-fast-compare "^3.2.0" react-fast-compare "^3.2.0"
shallowequal "^1.1.0" shallowequal "^1.1.0"
react-hook-form@^7.32.2: react-hook-form@^7.33.0:
version "7.32.2" version "7.33.0"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.32.2.tgz#58ec2ab0239ce97969baa2faa03ced13fae913ac" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.33.0.tgz#44a87ddd630f00ebeb0f15aa978f69ca74b8a77b"
integrity sha512-F1A6n762xaRhvtQH5SkQQhMr19cCkHZYesTcKJJeNmrphiZp/cYFTIzC05FnQry0SspM54oPJ9tXFXlzya8VNQ== integrity sha512-h8XoeUHQs1Snx1s/sSvM+eVTSKkWQt8TcrbL+3/Rt5gugxpy4ueL5ZZkubffyNpUyyTz0qM0kwOi2c+JgGTjLA==
react-inspector@^5.1.0: react-inspector@^5.1.0:
version "5.1.1" version "5.1.1"