hidden macros
This commit is contained in:
parent
b165ccac9f
commit
870b0c9d4e
|
@ -68,37 +68,37 @@ describe("bindExpression", () => {
|
|||
|
||||
describe("block", () => {
|
||||
// Block with a single expression
|
||||
testMacro([], eBlock(list{exampleExpression}), "Ok((:$$bindExpression 1))")
|
||||
testMacro([], eBlock(list{exampleExpression}), "Ok((:$$_bindExpression_$$ 1))")
|
||||
testMacroEval([], eBlock(list{exampleExpression}), "Ok(1)")
|
||||
// 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})")
|
||||
// Block with a statement and an expression
|
||||
testMacro(
|
||||
[],
|
||||
eBlock(list{exampleStatementY, exampleExpressionY}),
|
||||
"Ok((:$$bindExpression (:$$bindStatement (:$let :y 1)) :y))",
|
||||
"Ok((:$$_bindExpression_$$ (:$$_bindStatement_$$ (:$let :y 1)) :y))",
|
||||
)
|
||||
testMacroEval([], eBlock(list{exampleStatementY, exampleExpressionY}), "Ok(1)")
|
||||
// Block with a statement and another statement
|
||||
testMacro(
|
||||
[],
|
||||
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})")
|
||||
// Block inside a block
|
||||
testMacro(
|
||||
[],
|
||||
eBlock(list{eBlock(list{exampleExpression})}),
|
||||
"Ok((:$$bindExpression (:$$block 1)))",
|
||||
"Ok((:$$_bindExpression_$$ (:$$_block_$$ 1)))",
|
||||
)
|
||||
testMacroEval([], eBlock(list{eBlock(list{exampleExpression})}), "Ok(1)")
|
||||
// Block assigned to a variable
|
||||
testMacro(
|
||||
[],
|
||||
eBlock(list{eLetStatement("z", eBlock(list{eBlock(list{exampleExpressionY})}))}),
|
||||
"Ok((:$$bindExpression (:$let :z (:$$block (:$$block :y)))))",
|
||||
"Ok((:$$_bindExpression_$$ (:$let :z (:$$_block_$$ (:$$_block_$$ :y)))))",
|
||||
)
|
||||
testMacroEval(
|
||||
[],
|
||||
|
@ -107,7 +107,7 @@ describe("block", () => {
|
|||
)
|
||||
// Empty block
|
||||
testMacro([], eBlock(list{}), "Ok(:undefined block)") //TODO: should be an error
|
||||
// :$$block (:$$block (:$let :y (:add :x 1)) :y)"
|
||||
// :$$_block_$$ (:$$_block_$$ (:$let :y (:add :x 1)) :y)"
|
||||
testMacro(
|
||||
[],
|
||||
eBlock(list{
|
||||
|
@ -116,7 +116,7 @@ describe("block", () => {
|
|||
eSymbol("y"),
|
||||
}),
|
||||
}),
|
||||
"Ok((:$$bindExpression (:$$block (:$let :y (:add :x 1)) :y)))",
|
||||
"Ok((:$$_bindExpression_$$ (:$$_block_$$ (:$let :y (:add :x 1)) :y)))",
|
||||
)
|
||||
testMacroEval(
|
||||
[("x", EvNumber(1.))],
|
||||
|
@ -132,17 +132,17 @@ describe("block", () => {
|
|||
|
||||
describe("lambda", () => {
|
||||
// assign a lambda to a variable
|
||||
let lambdaExpression = eFunction("$$lambda", list{eArrayString(["y"]), exampleExpressionY})
|
||||
let lambdaExpression = eFunction("$$_lambda_$$", list{eArrayString(["y"]), exampleExpressionY})
|
||||
testMacro([], lambdaExpression, "Ok(lambda(y=>internal code))")
|
||||
// call a lambda
|
||||
let callLambdaExpression = list{lambdaExpression, eNumber(1.)}->ExpressionT.EList
|
||||
testMacro([], callLambdaExpression, "Ok(((:$$lambda [y] :y) 1))")
|
||||
testMacro([], callLambdaExpression, "Ok(((:$$_lambda_$$ [y] :y) 1))")
|
||||
testMacroEval([], callLambdaExpression, "Ok(1)")
|
||||
// Parameters shadow the outer scope
|
||||
testMacroEval([("y", EvNumber(666.))], callLambdaExpression, "Ok(1)")
|
||||
// When not shadowed by the parameters, the outer scope variables are available
|
||||
let lambdaExpression = eFunction(
|
||||
"$$lambda",
|
||||
"$$_lambda_$$",
|
||||
list{eArrayString(["z"]), eFunction("add", list{eSymbol("y"), eSymbol("z")})},
|
||||
)
|
||||
let callLambdaExpression = eList(list{lambdaExpression, eNumber(1.)})
|
||||
|
|
|
@ -130,16 +130,16 @@ describe("Peggy parse", () => {
|
|||
})
|
||||
|
||||
describe("ternary operator", () => {
|
||||
testParse("true ? 2 : 3", "{(::$$ternary true 2 3)}")
|
||||
testParse("false ? 2 : false ? 4 : 5", "{(::$$ternary false 2 (::$$ternary false 4 5))}") // nested ternary
|
||||
testParse("true ? 2 : 3", "{(::$$_ternary_$$ true 2 3)}")
|
||||
testParse("false ? 2 : false ? 4 : 5", "{(::$$_ternary_$$ false 2 (::$$_ternary_$$ false 4 5))}") // nested ternary
|
||||
})
|
||||
|
||||
describe("if then else", () => {
|
||||
testParse("if true then 2 else 3", "{(::$$ternary true {2} {3})}")
|
||||
testParse("if false then {2} else {3}", "{(::$$ternary false {2} {3})}")
|
||||
testParse("if true then 2 else 3", "{(::$$_ternary_$$ true {2} {3})}")
|
||||
testParse("if false then {2} else {3}", "{(::$$_ternary_$$ false {2} {3})}")
|
||||
testParse(
|
||||
"if false then {2} else if false then {4} else {5}",
|
||||
"{(::$$ternary false {2} (::$$ternary false {4} {5}))}",
|
||||
"{(::$$_ternary_$$ false {2} (::$$_ternary_$$ false {4} {5}))}",
|
||||
) //nested if
|
||||
})
|
||||
|
||||
|
@ -172,7 +172,7 @@ describe("Peggy parse", () => {
|
|||
)
|
||||
testParse(
|
||||
"a && b<1+2*3 || d ? true : false",
|
||||
"{(::$$ternary (::or (::and :a (::smaller :b (::add 1 (::multiply 2 3)))) :d) true false)}",
|
||||
"{(::$$_ternary_$$ (::or (::and :a (::smaller :b (::add 1 (::multiply 2 3)))) :d) true false)}",
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -221,7 +221,7 @@ describe("Peggy parse", () => {
|
|||
testParse("{|x| x}", "{{|:x| {:x}}}")
|
||||
testParse("f={|x| x}", "{:f = {{|:x| {:x}}}}")
|
||||
testParse("f(x)=x", "{:f = {|:x| {:x}}}") // Function definitions are lambda assignments
|
||||
testParse("f(x)=x ? 1 : 0", "{:f = {|:x| {(::$$ternary :x 1 0)}}}") // Function definitions are lambda assignments
|
||||
testParse("f(x)=x ? 1 : 0", "{:f = {|:x| {(::$$_ternary_$$ :x 1 0)}}}") // Function definitions are lambda assignments
|
||||
})
|
||||
|
||||
describe("Using lambda as value", () => {
|
||||
|
|
|
@ -40,61 +40,61 @@ module MyOnly = {
|
|||
describe("Peggy to Expression", () => {
|
||||
describe("literals operators parenthesis", () => {
|
||||
// Note that there is always an outer block. Otherwise, external bindings are ignrored at the first statement
|
||||
testToExpression("1", "(:$$block 1)", ~v="1", ())
|
||||
testToExpression("'hello'", "(:$$block 'hello')", ~v="'hello'", ())
|
||||
testToExpression("true", "(:$$block true)", ~v="true", ())
|
||||
testToExpression("1+2", "(:$$block (:add 1 2))", ~v="3", ())
|
||||
testToExpression("add(1,2)", "(:$$block (:add 1 2))", ~v="3", ())
|
||||
testToExpression("(1)", "(:$$block 1)", ())
|
||||
testToExpression("(1+2)", "(:$$block (:add 1 2))", ())
|
||||
testToExpression("1", "(:$$_block_$$ 1)", ~v="1", ())
|
||||
testToExpression("'hello'", "(:$$_block_$$ 'hello')", ~v="'hello'", ())
|
||||
testToExpression("true", "(:$$_block_$$ true)", ~v="true", ())
|
||||
testToExpression("1+2", "(:$$_block_$$ (:add 1 2))", ~v="3", ())
|
||||
testToExpression("add(1,2)", "(:$$_block_$$ (:add 1 2))", ~v="3", ())
|
||||
testToExpression("(1)", "(:$$_block_$$ 1)", ())
|
||||
testToExpression("(1+2)", "(:$$_block_$$ (:add 1 2))", ())
|
||||
})
|
||||
|
||||
describe("unary", () => {
|
||||
testToExpression("-1", "(:$$block (:unaryMinus 1))", ~v="-1", ())
|
||||
testToExpression("!true", "(:$$block (:not true))", ~v="false", ())
|
||||
testToExpression("1 + -1", "(:$$block (:add 1 (:unaryMinus 1)))", ~v="0", ())
|
||||
testToExpression("-a[0]", "(:$$block (:unaryMinus (:$atIndex :a 0)))", ())
|
||||
testToExpression("-1", "(:$$_block_$$ (:unaryMinus 1))", ~v="-1", ())
|
||||
testToExpression("!true", "(:$$_block_$$ (:not true))", ~v="false", ())
|
||||
testToExpression("1 + -1", "(:$$_block_$$ (:add 1 (:unaryMinus 1)))", ~v="0", ())
|
||||
testToExpression("-a[0]", "(:$$_block_$$ (:unaryMinus (:$atIndex :a 0)))", ())
|
||||
})
|
||||
|
||||
describe("multi-line", () => {
|
||||
testToExpression("x=1; 2", "(:$$block (:$let :x (:$$block 1)) 2)", ~v="2", ())
|
||||
testToExpression("x=1; 2", "(:$$_block_$$ (:$let :x (:$$_block_$$ 1)) 2)", ~v="2", ())
|
||||
testToExpression(
|
||||
"x=1; y=2",
|
||||
"(:$$block (:$let :x (:$$block 1)) (:$let :y (:$$block 2)))",
|
||||
"(:$$_block_$$ (:$let :x (:$$_block_$$ 1)) (:$let :y (:$$_block_$$ 2)))",
|
||||
~v="{x: 1,y: 2}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
||||
describe("variables", () => {
|
||||
testToExpression("x = 1", "(:$$block (:$let :x (:$$block 1)))", ~v="{x: 1}", ())
|
||||
testToExpression("x", "(:$$block :x)", ~v=":x", ()) //TODO: value should return error
|
||||
testToExpression("x = 1; x", "(:$$block (:$let :x (:$$block 1)) :x)", ~v="1", ())
|
||||
testToExpression("x = 1", "(:$$_block_$$ (:$let :x (:$$_block_$$ 1)))", ~v="{x: 1}", ())
|
||||
testToExpression("x", "(:$$_block_$$ :x)", ~v=":x", ()) //TODO: value should return error
|
||||
testToExpression("x = 1; x", "(:$$_block_$$ (:$let :x (:$$_block_$$ 1)) :x)", ~v="1", ())
|
||||
})
|
||||
|
||||
describe("functions", () => {
|
||||
testToExpression(
|
||||
"identity(x) = x",
|
||||
"(:$$block (:$let :identity (:$$lambda [x] (:$$block :x))))",
|
||||
"(:$$_block_$$ (:$let :identity (:$$_lambda_$$ [x] (:$$_block_$$ :x))))",
|
||||
~v="{identity: lambda(x=>internal code)}",
|
||||
(),
|
||||
) // Function definitions become lambda assignments
|
||||
testToExpression("identity(x)", "(:$$block (:identity :x))", ()) // Note value returns error properly
|
||||
testToExpression("f(x) = x> 2 ? 0 : 1; f(3)", "(:$$block (:$let :f (:$$lambda [x] (:$$block (:$$ternary (:larger :x 2) 0 1)))) (:f 3))", ~v="0", ())
|
||||
testToExpression("identity(x)", "(:$$_block_$$ (:identity :x))", ()) // Note value returns error properly
|
||||
testToExpression("f(x) = x> 2 ? 0 : 1; f(3)", "(:$$_block_$$ (:$let :f (:$$_lambda_$$ [x] (:$$_block_$$ (:$$_ternary_$$ (:larger :x 2) 0 1)))) (:f 3))", ~v="0", ())
|
||||
})
|
||||
|
||||
describe("arrays", () => {
|
||||
testToExpression("[]", "(:$$block (:$constructArray ()))", ~v="[]", ())
|
||||
testToExpression("[0, 1, 2]", "(:$$block (:$constructArray (0 1 2)))", ~v="[0,1,2]", ())
|
||||
testToExpression("[]", "(:$$_block_$$ (:$constructArray ()))", ~v="[]", ())
|
||||
testToExpression("[0, 1, 2]", "(:$$_block_$$ (:$constructArray (0 1 2)))", ~v="[0,1,2]", ())
|
||||
testToExpression(
|
||||
"['hello', 'world']",
|
||||
"(:$$block (:$constructArray ('hello' 'world')))",
|
||||
"(:$$_block_$$ (:$constructArray ('hello' 'world')))",
|
||||
~v="['hello','world']",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"([0,1,2])[1]",
|
||||
"(:$$block (:$atIndex (:$constructArray (0 1 2)) 1))",
|
||||
"(:$$_block_$$ (:$atIndex (:$constructArray (0 1 2)) 1))",
|
||||
~v="1",
|
||||
(),
|
||||
)
|
||||
|
@ -103,43 +103,43 @@ describe("Peggy to Expression", () => {
|
|||
describe("records", () => {
|
||||
testToExpression(
|
||||
"{a: 1, b: 2}",
|
||||
"(:$$block (:$constructRecord (('a' 1) ('b' 2))))",
|
||||
"(:$$_block_$$ (:$constructRecord (('a' 1) ('b' 2))))",
|
||||
~v="{a: 1,b: 2}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"{1+0: 1, 2+0: 2}",
|
||||
"(:$$block (:$constructRecord (((:add 1 0) 1) ((:add 2 0) 2))))",
|
||||
"(:$$_block_$$ (:$constructRecord (((:add 1 0) 1) ((:add 2 0) 2))))",
|
||||
(),
|
||||
) // key can be any expression
|
||||
testToExpression("record.property", "(:$$block (:$atIndex :record 'property'))", ())
|
||||
testToExpression("record.property", "(:$$_block_$$ (:$atIndex :record 'property'))", ())
|
||||
testToExpression(
|
||||
"record={property: 1}; record.property",
|
||||
"(:$$block (:$let :record (:$$block (:$constructRecord (('property' 1))))) (:$atIndex :record 'property'))",
|
||||
"(:$$_block_$$ (:$let :record (:$$_block_$$ (:$constructRecord (('property' 1))))) (:$atIndex :record 'property'))",
|
||||
~v="1",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
||||
describe("comments", () => {
|
||||
testToExpression("1 # This is a line comment", "(:$$block 1)", ~v="1", ())
|
||||
testToExpression("1 // This is a line comment", "(:$$block 1)", ~v="1", ())
|
||||
testToExpression("1 /* This is a multi line comment */", "(:$$block 1)", ~v="1", ())
|
||||
testToExpression("/* This is a multi line comment */ 1", "(:$$block 1)", ~v="1", ())
|
||||
testToExpression("1 # This is a line comment", "(:$$_block_$$ 1)", ~v="1", ())
|
||||
testToExpression("1 // This is a line comment", "(:$$_block_$$ 1)", ~v="1", ())
|
||||
testToExpression("1 /* This is a multi line comment */", "(:$$_block_$$ 1)", ~v="1", ())
|
||||
testToExpression("/* This is a multi line comment */ 1", "(:$$_block_$$ 1)", ~v="1", ())
|
||||
})
|
||||
|
||||
describe("ternary operator", () => {
|
||||
testToExpression("true ? 1 : 0", "(:$$block (:$$ternary true 1 0))", ~v="1", ())
|
||||
testToExpression("false ? 1 : 0", "(:$$block (:$$ternary false 1 0))", ~v="0", ())
|
||||
testToExpression("true ? 1 : 0", "(:$$_block_$$ (:$$_ternary_$$ true 1 0))", ~v="1", ())
|
||||
testToExpression("false ? 1 : 0", "(:$$_block_$$ (:$$_ternary_$$ false 1 0))", ~v="0", ())
|
||||
testToExpression(
|
||||
"true ? 1 : false ? 2 : 0",
|
||||
"(:$$block (:$$ternary true 1 (:$$ternary false 2 0)))",
|
||||
"(:$$_block_$$ (:$$_ternary_$$ true 1 (:$$_ternary_$$ false 2 0)))",
|
||||
~v="1",
|
||||
(),
|
||||
) // nested ternary
|
||||
testToExpression(
|
||||
"false ? 1 : false ? 2 : 0",
|
||||
"(:$$block (:$$ternary false 1 (:$$ternary false 2 0)))",
|
||||
"(:$$_block_$$ (:$$_ternary_$$ false 1 (:$$_ternary_$$ false 2 0)))",
|
||||
~v="0",
|
||||
(),
|
||||
) // nested ternary
|
||||
|
@ -148,29 +148,29 @@ describe("Peggy to Expression", () => {
|
|||
describe("if then else", () => {
|
||||
testToExpression(
|
||||
"if true then 2 else 3",
|
||||
"(:$$block (:$$ternary true (:$$block 2) (:$$block 3)))",
|
||||
"(:$$_block_$$ (:$$_ternary_$$ true (:$$_block_$$ 2) (:$$_block_$$ 3)))",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"if true then {2} else {3}",
|
||||
"(:$$block (:$$ternary true (:$$block 2) (:$$block 3)))",
|
||||
"(:$$_block_$$ (:$$_ternary_$$ true (:$$_block_$$ 2) (:$$_block_$$ 3)))",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"if false then {2} else if false then {4} else {5}",
|
||||
"(:$$block (:$$ternary false (:$$block 2) (:$$ternary false (:$$block 4) (:$$block 5))))",
|
||||
"(:$$_block_$$ (:$$_ternary_$$ false (:$$_block_$$ 2) (:$$_ternary_$$ false (:$$_block_$$ 4) (:$$_block_$$ 5))))",
|
||||
(),
|
||||
) //nested if
|
||||
})
|
||||
|
||||
describe("pipe", () => {
|
||||
testToExpression("1 -> add(2)", "(:$$block (:add 1 2))", ~v="3", ())
|
||||
testToExpression("-1 -> add(2)", "(:$$block (:add (:unaryMinus 1) 2))", ~v="1", ()) // note that unary has higher priority naturally
|
||||
testToExpression("1 -> add(2) * 3", "(:$$block (:multiply (:add 1 2) 3))", ~v="9", ())
|
||||
testToExpression("1 -> add(2)", "(:$$_block_$$ (:add 1 2))", ~v="3", ())
|
||||
testToExpression("-1 -> add(2)", "(:$$_block_$$ (:add (:unaryMinus 1) 2))", ~v="1", ()) // note that unary has higher priority naturally
|
||||
testToExpression("1 -> add(2) * 3", "(:$$_block_$$ (:multiply (:add 1 2) 3))", ~v="9", ())
|
||||
})
|
||||
|
||||
describe("elixir pipe", () => {
|
||||
testToExpression("1 |> add(2)", "(:$$block (:add 1 2))", ~v="3", ())
|
||||
testToExpression("1 |> add(2)", "(:$$_block_$$ (:add 1 2))", ~v="3", ())
|
||||
})
|
||||
|
||||
// see testParse for priorities of to and credibleIntervalToDistribution
|
||||
|
@ -180,7 +180,7 @@ describe("Peggy to Expression", () => {
|
|||
// Like lambdas they have a local scope.
|
||||
testToExpression(
|
||||
"y=99; x={y=1; y}",
|
||||
"(:$$block (:$let :y (:$$block 99)) (:$let :x (:$$block (:$let :y (:$$block 1)) :y)))",
|
||||
"(:$$_block_$$ (:$let :y (:$$_block_$$ 99)) (:$let :x (:$$_block_$$ (:$let :y (:$$_block_$$ 1)) :y)))",
|
||||
~v="{x: 1,y: 99}",
|
||||
(),
|
||||
)
|
||||
|
@ -190,25 +190,25 @@ describe("Peggy to Expression", () => {
|
|||
describe("lambda", () => {
|
||||
testToExpression(
|
||||
"{|x| x}",
|
||||
"(:$$block (:$$lambda [x] (:$$block :x)))",
|
||||
"(:$$_block_$$ (:$$_lambda_$$ [x] (:$$_block_$$ :x)))",
|
||||
~v="lambda(x=>internal code)",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"f={|x| x}",
|
||||
"(:$$block (:$let :f (:$$block (:$$lambda [x] (:$$block :x)))))",
|
||||
"(:$$_block_$$ (:$let :f (:$$_block_$$ (:$$_lambda_$$ [x] (:$$_block_$$ :x)))))",
|
||||
~v="{f: lambda(x=>internal code)}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"f(x)=x",
|
||||
"(:$$block (:$let :f (:$$lambda [x] (:$$block :x))))",
|
||||
"(:$$_block_$$ (:$let :f (:$$_lambda_$$ [x] (:$$_block_$$ :x))))",
|
||||
~v="{f: lambda(x=>internal code)}",
|
||||
(),
|
||||
) // Function definitions are lambda assignments
|
||||
testToExpression(
|
||||
"f(x)=x ? 1 : 0",
|
||||
"(:$$block (:$let :f (:$$lambda [x] (:$$block (:$$ternary :x 1 0)))))",
|
||||
"(:$$_block_$$ (:$let :f (:$$_lambda_$$ [x] (:$$_block_$$ (:$$_ternary_$$ :x 1 0)))))",
|
||||
~v="{f: lambda(x=>internal code)}",
|
||||
(),
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@ open Reducer_TestHelpers
|
|||
describe("Eval with Bindings", () => {
|
||||
testEvalBindingsToBe("x", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(1)")
|
||||
testEvalBindingsToBe("x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||
testParseToBe("y = x+1; y", "Ok((:$$block (:$let :y (:$$block (:add :x 1))) :y))")
|
||||
testParseToBe("y = x+1; y", "Ok((:$$_block_$$ (:$let :y (:$$_block_$$ (:add :x 1))) :y))")
|
||||
testEvalBindingsToBe("y = x+1; y", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||
testEvalBindingsToBe("y = x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok({x: 1,y: 2})")
|
||||
})
|
||||
|
|
|
@ -2,8 +2,8 @@ open Jest
|
|||
open Reducer_TestHelpers
|
||||
|
||||
describe("Parse function assignment", () => {
|
||||
testParseToBe("f(x)=x", "Ok((:$$block (:$let :f (:$$lambda [x] (:$$block :x)))))")
|
||||
testParseToBe("f(x)=2*x", "Ok((:$$block (:$let :f (:$$lambda [x] (:$$block (:multiply 2 :x))))))")
|
||||
testParseToBe("f(x)=x", "Ok((:$$_block_$$ (:$let :f (:$$_lambda_$$ [x] (:$$_block_$$ :x)))))")
|
||||
testParseToBe("f(x)=2*x", "Ok((:$$_block_$$ (:$let :f (:$$_lambda_$$ [x] (:$$_block_$$ (:multiply 2 :x))))))")
|
||||
//MathJs does not allow blocks in function definitions
|
||||
})
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ describe("call and bindings", () => {
|
|||
)
|
||||
testParseToBe(
|
||||
"f=99; g(x)=f; g(2)",
|
||||
"Ok((:$$block (:$let :f (:$$block 99)) (:$let :g (:$$lambda [x] (:$$block :f))) (:g 2)))",
|
||||
"Ok((:$$_block_$$ (:$let :f (:$$_block_$$ 99)) (:$let :g (:$$_lambda_$$ [x] (:$$_block_$$ :f))) (:g 2)))",
|
||||
)
|
||||
testEvalToBe("f=99; g(x)=f; g(2)", "Ok(99)")
|
||||
testEvalToBe("f(x)=x; g(x)=f(x); g(2)", "Ok(2)")
|
||||
|
|
|
@ -2,7 +2,7 @@ open Jest
|
|||
open Reducer_TestHelpers
|
||||
|
||||
describe("Parse ternary operator", () => {
|
||||
testParseToBe("true ? 'YES' : 'NO'", "Ok((:$$block (:$$ternary true 'YES' 'NO')))")
|
||||
testParseToBe("true ? 'YES' : 'NO'", "Ok((:$$_block_$$ (:$$_ternary_$$ true 'YES' 'NO')))")
|
||||
})
|
||||
|
||||
describe("Evaluate ternary operator", () => {
|
||||
|
|
|
@ -123,34 +123,34 @@ describe("eval on distribution functions", () => {
|
|||
|
||||
describe("parse on distribution functions", () => {
|
||||
describe("power", () => {
|
||||
testParse("normal(5,2) ^ normal(5,1)", "Ok((:$$block (:pow (:normal 5 2) (:normal 5 1))))")
|
||||
testParse("3 ^ normal(5,1)", "Ok((:$$block (:pow 3 (:normal 5 1))))")
|
||||
testParse("normal(5,2) ^ 3", "Ok((:$$block (:pow (:normal 5 2) 3)))")
|
||||
testParse("normal(5,2) ^ normal(5,1)", "Ok((:$$_block_$$ (:pow (:normal 5 2) (:normal 5 1))))")
|
||||
testParse("3 ^ normal(5,1)", "Ok((:$$_block_$$ (:pow 3 (:normal 5 1))))")
|
||||
testParse("normal(5,2) ^ 3", "Ok((:$$_block_$$ (:pow (:normal 5 2) 3)))")
|
||||
})
|
||||
describe("subtraction", () => {
|
||||
testParse("10 - normal(5,1)", "Ok((:$$block (:subtract 10 (:normal 5 1))))")
|
||||
testParse("normal(5,1) - 10", "Ok((:$$block (:subtract (:normal 5 1) 10)))")
|
||||
testParse("10 - normal(5,1)", "Ok((:$$_block_$$ (:subtract 10 (:normal 5 1))))")
|
||||
testParse("normal(5,1) - 10", "Ok((:$$_block_$$ (:subtract (:normal 5 1) 10)))")
|
||||
})
|
||||
describe("pointwise arithmetic expressions", () => {
|
||||
testParse(~skip=true, "normal(5,2) .+ normal(5,1)", "Ok((:dotAdd (:normal 5 2) (:normal 5 1)))")
|
||||
testParse(
|
||||
~skip=true,
|
||||
"normal(5,2) .- normal(5,1)",
|
||||
"Ok((:$$block (:dotSubtract (:normal 5 2) (:normal 5 1))))",
|
||||
// TODO: !!! returns "Ok((:$$block (:dotPow (:normal 5 2) (:normal 5 1))))"
|
||||
"Ok((:$$_block_$$ (:dotSubtract (:normal 5 2) (:normal 5 1))))",
|
||||
// TODO: !!! returns "Ok((:$$_block_$$ (:dotPow (:normal 5 2) (:normal 5 1))))"
|
||||
)
|
||||
testParse(
|
||||
"normal(5,2) .* normal(5,1)",
|
||||
"Ok((:$$block (:dotMultiply (:normal 5 2) (:normal 5 1))))",
|
||||
"Ok((:$$_block_$$ (:dotMultiply (:normal 5 2) (:normal 5 1))))",
|
||||
)
|
||||
testParse(
|
||||
"normal(5,2) ./ normal(5,1)",
|
||||
"Ok((:$$block (:dotDivide (:normal 5 2) (:normal 5 1))))",
|
||||
"Ok((:$$_block_$$ (:dotDivide (:normal 5 2) (:normal 5 1))))",
|
||||
)
|
||||
testParse("normal(5,2) .^ normal(5,1)", "Ok((:$$block (:dotPow (:normal 5 2) (:normal 5 1))))")
|
||||
testParse("normal(5,2) .^ normal(5,1)", "Ok((:$$_block_$$ (:dotPow (:normal 5 2) (:normal 5 1))))")
|
||||
})
|
||||
describe("equality", () => {
|
||||
testParse("5 == normal(5,2)", "Ok((:$$block (:equal 5 (:normal 5 2))))")
|
||||
testParse("5 == normal(5,2)", "Ok((:$$_block_$$ (:equal 5 (:normal 5 2))))")
|
||||
})
|
||||
describe("pointwise adding two normals", () => {
|
||||
testParse(~skip=true, "normal(5,2) .+ normal(5,1)", "Ok((:dotAdd (:normal 5 2) (:normal 5 1)))")
|
||||
|
|
|
@ -157,31 +157,31 @@ let dispatchMacroCall = (
|
|||
> =>
|
||||
switch aList {
|
||||
| list{
|
||||
ExpressionT.EValue(EvCall("$$bindStatement")),
|
||||
ExpressionT.EValue(EvCall("$$_bindStatement_$$")),
|
||||
bindingExpr: ExpressionT.expression,
|
||||
statement,
|
||||
} =>
|
||||
doBindStatement(bindingExpr, statement, environment)
|
||||
| list{ExpressionT.EValue(EvCall("$$bindStatement")), statement} =>
|
||||
| list{ExpressionT.EValue(EvCall("$$_bindStatement_$$")), statement} =>
|
||||
// bindings of the context are used when there is no binding expression
|
||||
doBindStatement(eRecord(Bindings.toExternalBindings(bindings)), statement, environment)
|
||||
| list{
|
||||
ExpressionT.EValue(EvCall("$$bindExpression")),
|
||||
ExpressionT.EValue(EvCall("$$_bindExpression_$$")),
|
||||
bindingExpr: ExpressionT.expression,
|
||||
expression,
|
||||
} =>
|
||||
doBindExpression(bindingExpr, expression, environment)
|
||||
| list{ExpressionT.EValue(EvCall("$$bindExpression")), expression} =>
|
||||
| list{ExpressionT.EValue(EvCall("$$_bindExpression_$$")), expression} =>
|
||||
// bindings of the context are used when there is no binding expression
|
||||
doBindExpression(eRecord(Bindings.toExternalBindings(bindings)), expression, environment)
|
||||
| list{ExpressionT.EValue(EvCall("$$block")), ...exprs} => doBlock(exprs, bindings, environment)
|
||||
| list{ExpressionT.EValue(EvCall("$$_block_$$")), ...exprs} => doBlock(exprs, bindings, environment)
|
||||
| list{
|
||||
ExpressionT.EValue(EvCall("$$lambda")),
|
||||
ExpressionT.EValue(EvCall("$$_lambda_$$")),
|
||||
ExpressionT.EValue(EvArrayString(parameters)),
|
||||
lambdaDefinition,
|
||||
} =>
|
||||
doLambdaDefinition(bindings, parameters, lambdaDefinition)
|
||||
| list{ExpressionT.EValue(EvCall("$$ternary")), condition, ifTrue, ifFalse} =>
|
||||
| list{ExpressionT.EValue(EvCall("$$_ternary_$$")), condition, ifTrue, ifFalse} =>
|
||||
doTernary(condition, ifTrue, ifFalse, bindings, environment)
|
||||
| _ => ExpressionWithContext.noContext(ExpressionT.EList(aList))->Ok
|
||||
}
|
||||
|
|
|
@ -48,19 +48,19 @@ let eSymbol = (name: string): expression => name->BExpressionValue.EvSymbol->BEx
|
|||
|
||||
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 eLetStatement = (symbol: string, valueExpression: expression): expression =>
|
||||
eFunction("$let", list{eSymbol(symbol), valueExpression})
|
||||
|
||||
let eBindStatement = (bindingExpr: expression, letStatement: expression): expression =>
|
||||
eFunction("$$bindStatement", list{bindingExpr, letStatement})
|
||||
eFunction("$$_bindStatement_$$", list{bindingExpr, letStatement})
|
||||
|
||||
let eBindStatementDefault = (letStatement: expression): expression =>
|
||||
eFunction("$$bindStatement", list{letStatement})
|
||||
eFunction("$$_bindStatement_$$", list{letStatement})
|
||||
|
||||
let eBindExpression = (bindingExpr: expression, expression: expression): expression =>
|
||||
eFunction("$$bindExpression", list{bindingExpr, expression})
|
||||
eFunction("$$_bindExpression_$$", list{bindingExpr, expression})
|
||||
|
||||
let eBindExpressionDefault = (expression: expression): expression =>
|
||||
eFunction("$$bindExpression", list{expression})
|
||||
eFunction("$$_bindExpression_$$", list{expression})
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
var postOperatorToFunction = {
|
||||
'.': '$atIndex',
|
||||
'()': '$$applyAll',
|
||||
'()': '$$_applyAll_$$',
|
||||
'[]': '$atIndex',
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,10 @@
|
|||
function nodeExpression(args) {return {type: 'Expression', nodes: args}}
|
||||
function nodeFloat(value) {return {type: 'Float', value: value}}
|
||||
function makeFunctionCall(fn, args) {
|
||||
if (fn === '$$applyAll') {
|
||||
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.
|
||||
// So we remove the redundant $$_applyAll_$$.
|
||||
if (args[0].type === "Identifier") {args[0].type = "CallIdentifier"}
|
||||
return nodeExpression(args)
|
||||
} else {
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
var postOperatorToFunction = {
|
||||
'.': '$atIndex',
|
||||
'()': '$$applyAll',
|
||||
'()': '$$_applyAll_$$',
|
||||
'[]': '$atIndex',
|
||||
}
|
||||
|
||||
|
@ -42,10 +42,10 @@
|
|||
function nodeExpression(args) {return {type: 'Expression', nodes: args}}
|
||||
function nodeFloat(value) {return {type: 'Float', value: value}}
|
||||
function makeFunctionCall(fn, args) {
|
||||
if (fn === '$$applyAll') {
|
||||
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.
|
||||
// So we remove the redundant $$_applyAll_$$.
|
||||
if (args[0].type === "Identifier") {args[0].type = "CallIdentifier"}
|
||||
return nodeExpression(args)
|
||||
} else {
|
||||
|
|
|
@ -92,7 +92,7 @@ let rec pgToString = (peggyNode: peggyNode): string => {
|
|||
pgToString(PgNodeIdentifier(node["variable"])) ++ " = " ++ toString(node["value"])
|
||||
| PgNodeString(node) => `'${node["value"]->Js.String.make}'`
|
||||
| PgNodeTernary(node) =>
|
||||
"(::$$ternary " ++
|
||||
"(::$$_ternary_$$ " ++
|
||||
toString(node["condition"]) ++
|
||||
" " ++
|
||||
toString(node["trueExpression"]) ++
|
||||
|
|
|
@ -14,7 +14,7 @@ let rec fromNode = (node: Parse.node): expression => {
|
|||
->Js.Array2.map((argNode: Parse.nodeIdentifier) => argNode["value"])
|
||||
->ExpressionBuilder.eArrayString
|
||||
let body = nodeLambda["body"]->caseBlock
|
||||
ExpressionBuilder.eFunction("$$lambda", list{args, body})
|
||||
ExpressionBuilder.eFunction("$$_lambda_$$", list{args, body})
|
||||
}
|
||||
|
||||
switch Parse.castNodeType(node) {
|
||||
|
@ -37,7 +37,7 @@ let rec fromNode = (node: Parse.node): expression => {
|
|||
| PgNodeString(nodeString) => ExpressionBuilder.eString(nodeString["value"])
|
||||
| PgNodeTernary(nodeTernary) =>
|
||||
ExpressionBuilder.eFunction(
|
||||
"$$ternary",
|
||||
"$$_ternary_$$",
|
||||
list{
|
||||
fromNode(nodeTernary["condition"]),
|
||||
fromNode(nodeTernary["trueExpression"]),
|
||||
|
|
Loading…
Reference in New Issue
Block a user