Replace $$_block__$$ with {}

More redable language tests
This commit is contained in:
Umur Ozkul 2022-05-29 17:00:16 +02:00
parent 178ec6f89d
commit ac3fa859c0
8 changed files with 73 additions and 68 deletions

View File

@ -91,14 +91,14 @@ describe("block", () => {
testMacro(
[],
eBlock(list{eBlock(list{exampleExpression})}),
"Ok((:$$_bindExpression_$$ (:$$_block_$$ 1)))",
"Ok((:$$_bindExpression_$$ {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 {{:y}})))",
)
testMacroEval(
[],
@ -116,7 +116,7 @@ describe("block", () => {
eSymbol("y"),
}),
}),
"Ok((:$$_bindExpression_$$ (:$$_block_$$ (:$_let_$ :y (:add :x 1)) :y)))",
"Ok((:$$_bindExpression_$$ {(:$_let_$ :y (:add :x 1)); :y}))",
)
testMacroEval(
[("x", EvNumber(1.))],

View File

@ -40,66 +40,66 @@ 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", "{1}", ~v="1", ())
testToExpression("'hello'", "{'hello'}", ~v="'hello'", ())
testToExpression("true", "{true}", ~v="true", ())
testToExpression("1+2", "{(:add 1 2)}", ~v="3", ())
testToExpression("add(1,2)", "{(:add 1 2)}", ~v="3", ())
testToExpression("(1)", "{1}", ())
testToExpression("(1+2)", "{(: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", "{(:unaryMinus 1)}", ~v="-1", ())
testToExpression("!true", "{(:not true)}", ~v="false", ())
testToExpression("1 + -1", "{(:add 1 (:unaryMinus 1))}", ~v="0", ())
testToExpression("-a[0]", "{(:unaryMinus (:$_atIndex_$ :a 0))}", ())
})
describe("multi-line", () => {
testToExpression("x=1; 2", "(:$$_block_$$ (:$_let_$ :x (:$$_block_$$ 1)) 2)", ~v="2", ())
testToExpression("x=1; 2", "{(:$_let_$ :x {1}); 2}", ~v="2", ())
testToExpression(
"x=1; y=2",
"(:$$_block_$$ (:$_let_$ :x (:$$_block_$$ 1)) (:$_let_$ :y (:$$_block_$$ 2)))",
"{(:$_let_$ :x {1}); (:$_let_$ :y {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", "{(:$_let_$ :x {1})}", ~v="{x: 1}", ())
testToExpression("x", "{:x}", ~v=":x", ()) //TODO: value should return error
testToExpression("x = 1; x", "{(:$_let_$ :x {1}); :x}", ~v="1", ())
})
describe("functions", () => {
testToExpression(
"identity(x) = x",
"(:$$_block_$$ (:$_let_$ :identity (:$$_lambda_$$ [x] (:$$_block_$$ :x))))",
"{(:$_let_$ :identity (:$$_lambda_$$ [x] {:x}))}",
~v="{identity: lambda(x=>internal code)}",
(),
) // Function definitions become lambda assignments
testToExpression("identity(x)", "(:$$_block_$$ (:identity :x))", ()) // Note value returns error properly
testToExpression("identity(x)", "{(: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))",
"{(:$_let_$ :f (:$$_lambda_$$ [x] {(:$$_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("[]", "{(:$_constructArray_$ ())}", ~v="[]", ())
testToExpression("[0, 1, 2]", "{(:$_constructArray_$ (0 1 2))}", ~v="[0,1,2]", ())
testToExpression(
"['hello', 'world']",
"(:$$_block_$$ (:$_constructArray_$ ('hello' 'world')))",
"{(:$_constructArray_$ ('hello' 'world'))}",
~v="['hello','world']",
(),
)
testToExpression(
"([0,1,2])[1]",
"(:$$_block_$$ (:$_atIndex_$ (:$_constructArray_$ (0 1 2)) 1))",
"{(:$_atIndex_$ (:$_constructArray_$ (0 1 2)) 1)}",
~v="1",
(),
)
@ -108,43 +108,43 @@ describe("Peggy to Expression", () => {
describe("records", () => {
testToExpression(
"{a: 1, b: 2}",
"(:$$_block_$$ (:$_constructRecord_$ (('a' 1) ('b' 2))))",
"{(:$_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))))",
"{(:$_constructRecord_$ (((:add 1 0) 1) ((:add 2 0) 2)))}",
(),
) // key can be any expression
testToExpression("record.property", "(:$$_block_$$ (:$_atIndex_$ :record 'property'))", ())
testToExpression("record.property", "{(:$_atIndex_$ :record 'property')}", ())
testToExpression(
"record={property: 1}; record.property",
"(:$$_block_$$ (:$_let_$ :record (:$$_block_$$ (:$_constructRecord_$ (('property' 1))))) (:$_atIndex_$ :record 'property'))",
"{(:$_let_$ :record {(:$_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", "{1}", ~v="1", ())
testToExpression("1 // This is a line comment", "{1}", ~v="1", ())
testToExpression("1 /* This is a multi line comment */", "{1}", ~v="1", ())
testToExpression("/* This is a multi line comment */ 1", "{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", "{(:$$_ternary_$$ true 1 0)}", ~v="1", ())
testToExpression("false ? 1 : 0", "{(:$$_ternary_$$ false 1 0)}", ~v="0", ())
testToExpression(
"true ? 1 : false ? 2 : 0",
"(:$$_block_$$ (:$$_ternary_$$ true 1 (:$$_ternary_$$ false 2 0)))",
"{(:$$_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)))",
"{(:$$_ternary_$$ false 1 (:$$_ternary_$$ false 2 0))}",
~v="0",
(),
) // nested ternary
@ -152,21 +152,21 @@ describe("Peggy to Expression", () => {
testToExpression(
// expression binding
"f(a) = a > 5 ? 1 : 0; f(6)",
"(:$$_block_$$ (:$_let_$ :f (:$$_lambda_$$ [a] (:$$_block_$$ (:$$_ternary_$$ (:larger :a 5) 1 0)))) (:f 6))",
"{(:$_let_$ :f (:$$_lambda_$$ [a] {(:$$_ternary_$$ (:larger :a 5) 1 0)})); (:f 6)}",
~v="1",
(),
)
testToExpression(
// when true binding
"f(a) = a > 5 ? a : 0; f(6)",
"(:$$_block_$$ (:$_let_$ :f (:$$_lambda_$$ [a] (:$$_block_$$ (:$$_ternary_$$ (:larger :a 5) :a 0)))) (:f 6))",
"{(:$_let_$ :f (:$$_lambda_$$ [a] {(:$$_ternary_$$ (:larger :a 5) :a 0)})); (:f 6)}",
~v="6",
(),
)
testToExpression(
// when false binding
"f(a) = a < 5 ? 1 : a; f(6)",
"(:$$_block_$$ (:$_let_$ :f (:$$_lambda_$$ [a] (:$$_block_$$ (:$$_ternary_$$ (:smaller :a 5) 1 :a)))) (:f 6))",
"{(:$_let_$ :f (:$$_lambda_$$ [a] {(:$$_ternary_$$ (:smaller :a 5) 1 :a)})); (:f 6)}",
~v="6",
(),
)
@ -176,29 +176,29 @@ describe("Peggy to Expression", () => {
describe("if then else", () => {
testToExpression(
"if true then 2 else 3",
"(:$$_block_$$ (:$$_ternary_$$ true (:$$_block_$$ 2) (:$$_block_$$ 3)))",
"{(:$$_ternary_$$ true {2} {3})}",
(),
)
testToExpression(
"if true then {2} else {3}",
"(:$$_block_$$ (:$$_ternary_$$ true (:$$_block_$$ 2) (:$$_block_$$ 3)))",
"{(:$$_ternary_$$ true {2} {3})}",
(),
)
testToExpression(
"if false then {2} else if false then {4} else {5}",
"(:$$_block_$$ (:$$_ternary_$$ false (:$$_block_$$ 2) (:$$_ternary_$$ false (:$$_block_$$ 4) (:$$_block_$$ 5))))",
"{(:$$_ternary_$$ false {2} (:$$_ternary_$$ false {4} {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)", "{(:add 1 2)}", ~v="3", ())
testToExpression("-1 -> add(2)", "{(:add (:unaryMinus 1) 2)}", ~v="1", ()) // note that unary has higher priority naturally
testToExpression("1 -> add(2) * 3", "{(:multiply (:add 1 2) 3)}", ~v="9", ())
})
describe("elixir pipe", () => {
testToExpression("1 |> add(2)", "(:$$_block_$$ (:add 1 2))", ~v="3", ())
testToExpression("1 |> add(2)", "{(:add 1 2)}", ~v="3", ())
})
// see testParse for priorities of to and credibleIntervalToDistribution
@ -208,7 +208,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)))",
"{(:$_let_$ :y {99}); (:$_let_$ :x {(:$_let_$ :y {1}); :y})}",
~v="{x: 1,y: 99}",
(),
)
@ -217,25 +217,25 @@ describe("Peggy to Expression", () => {
describe("lambda", () => {
testToExpression(
"{|x| x}",
"(:$$_block_$$ (:$$_lambda_$$ [x] (:$$_block_$$ :x)))",
"{(:$$_lambda_$$ [x] {:x})}",
~v="lambda(x=>internal code)",
(),
)
testToExpression(
"f={|x| x}",
"(:$$_block_$$ (:$_let_$ :f (:$$_block_$$ (:$$_lambda_$$ [x] (:$$_block_$$ :x)))))",
"{(:$_let_$ :f {(:$$_lambda_$$ [x] {:x})})}",
~v="{f: lambda(x=>internal code)}",
(),
)
testToExpression(
"f(x)=x",
"(:$$_block_$$ (:$_let_$ :f (:$$_lambda_$$ [x] (:$$_block_$$ :x))))",
"{(:$_let_$ :f (:$$_lambda_$$ [x] {: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)))))",
"{(:$_let_$ :f (:$$_lambda_$$ [x] {(:$$_ternary_$$ :x 1 0)}))}",
~v="{f: lambda(x=>internal code)}",
(),
)

View File

@ -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({(:$_let_$ :y {(: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})")
})

View File

@ -2,10 +2,10 @@ open Jest
open Reducer_TestHelpers
describe("Parse function assignment", () => {
testParseToBe("f(x)=x", "Ok((:$$_block_$$ (:$_let_$ :f (:$$_lambda_$$ [x] (:$$_block_$$ :x)))))")
testParseToBe("f(x)=x", "Ok({(:$_let_$ :f (:$$_lambda_$$ [x] {:x}))})")
testParseToBe(
"f(x)=2*x",
"Ok((:$$_block_$$ (:$_let_$ :f (:$$_lambda_$$ [x] (:$$_block_$$ (:multiply 2 :x))))))",
"Ok({(:$_let_$ :f (:$$_lambda_$$ [x] {(:multiply 2 :x)}))})",
)
//MathJs does not allow blocks in function definitions
})

View File

@ -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({(:$_let_$ :f {99}); (:$_let_$ :g (:$$_lambda_$$ [x] {: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)")

View File

@ -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({(:$$_ternary_$$ true 'YES' 'NO')})")
})
describe("Evaluate ternary operator", () => {

View File

@ -123,13 +123,13 @@ 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({(:pow (:normal 5 2) (:normal 5 1))})")
testParse("3 ^ normal(5,1)", "Ok({(:pow 3 (:normal 5 1))})")
testParse("normal(5,2) ^ 3", "Ok({(: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({(:subtract 10 (:normal 5 1))})")
testParse("normal(5,1) - 10", "Ok({(: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)))")
@ -137,23 +137,23 @@ describe("parse on distribution functions", () => {
~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))))"
// TODO: !!! returns "Ok({(:dotPow (:normal 5 2) (:normal 5 1))})"
)
testParse(
"normal(5,2) .* normal(5,1)",
"Ok((:$$_block_$$ (:dotMultiply (:normal 5 2) (:normal 5 1))))",
"Ok({(:dotMultiply (:normal 5 2) (:normal 5 1))})",
)
testParse(
"normal(5,2) ./ normal(5,1)",
"Ok((:$$_block_$$ (:dotDivide (:normal 5 2) (:normal 5 1))))",
"Ok({(:dotDivide (:normal 5 2) (:normal 5 1))})",
)
testParse(
"normal(5,2) .^ normal(5,1)",
"Ok((:$$_block_$$ (:dotPow (:normal 5 2) (:normal 5 1))))",
"Ok({(: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({(: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)))")

View File

@ -28,6 +28,11 @@ type reducerFn = (
*/
let rec toString = expression =>
switch expression {
| EList(list{EValue(EvCall("$$_block_$$")), ...statements}) =>
`{${Belt.List.map(statements, aValue => toString(aValue))
->Extra.List.interperse("; ")
->Belt.List.toArray
->Js.String.concatMany("")}}`
| EList(aList) =>
`(${Belt.List.map(aList, aValue => toString(aValue))
->Extra.List.interperse(" ")