format
This commit is contained in:
parent
57c2fba791
commit
a51e4be528
|
@ -16,7 +16,11 @@ testMacro([], exampleExpression, "Ok(1)")
|
|||
|
||||
describe("bindStatement", () => {
|
||||
// A statement is bound by the bindings created by the previous statement
|
||||
testMacro([], eBindStatement(eBindings([]), exampleStatementY), "Ok((:$setBindings {} :y 1) context: {})")
|
||||
testMacro(
|
||||
[],
|
||||
eBindStatement(eBindings([]), exampleStatementY),
|
||||
"Ok((:$setBindings {} :y 1) context: {})",
|
||||
)
|
||||
// Then it answers the bindings for the next statement when reduced
|
||||
testMacroEval([], eBindStatement(eBindings([]), exampleStatementY), "Ok({y: 1})")
|
||||
// Now let's feed a binding to see what happens
|
||||
|
@ -31,13 +35,17 @@ describe("bindStatement", () => {
|
|||
testMacro(
|
||||
[("z", EvNumber(99.))],
|
||||
eBindStatementDefault(exampleStatementY),
|
||||
"Ok((:$setBindings {z: 99} :y 1) context: {z: 99})",
|
||||
"Ok((:$setBindings {z: 99} :y 1) context: {z: 99})",
|
||||
)
|
||||
})
|
||||
|
||||
describe("bindExpression", () => {
|
||||
// x is simply bound in the expression
|
||||
testMacro([], eBindExpression(eBindings([("x", EvNumber(2.))]), eSymbol("x")), "Ok(2 context: {x: 2})")
|
||||
testMacro(
|
||||
[],
|
||||
eBindExpression(eBindings([("x", EvNumber(2.))]), eSymbol("x")),
|
||||
"Ok(2 context: {x: 2})",
|
||||
)
|
||||
// When an let statement is the end expression then bindings are returned
|
||||
testMacro(
|
||||
[],
|
||||
|
|
|
@ -60,7 +60,10 @@ describe("Peggy parse", () => {
|
|||
testParse("1 * 2 - 3 / 4", "{(::subtract (::multiply 1 2) (::divide 3 4))}")
|
||||
testParse("1 * 2 - 3 ./ 4", "{(::subtract (::multiply 1 2) (::dotDivide 3 4))}")
|
||||
testParse("1 * 2 - 3 * 4^5", "{(::subtract (::multiply 1 2) (::multiply 3 (::pow 4 5)))}")
|
||||
testParse("1 * 2 - 3 * 4^5^6", "{(::subtract (::multiply 1 2) (::multiply 3 (::pow (::pow 4 5) 6)))}")
|
||||
testParse(
|
||||
"1 * 2 - 3 * 4^5^6",
|
||||
"{(::subtract (::multiply 1 2) (::multiply 3 (::pow (::pow 4 5) 6)))}",
|
||||
)
|
||||
testParse("1 * -a[-2]", "{(::multiply 1 (::unaryMinus (::$atIndex :a (::unaryMinus 2))))}")
|
||||
})
|
||||
|
||||
|
@ -93,7 +96,7 @@ describe("Peggy parse", () => {
|
|||
testParse("record.property", "{(::$atIndex :record 'property')}")
|
||||
})
|
||||
|
||||
describe("post operators", ()=>{
|
||||
describe("post operators", () => {
|
||||
//function call, array and record access are post operators with higher priority than unary operators
|
||||
testParse("a==!b(1)", "{(::equal :a (::not (::b 1)))}")
|
||||
testParse("a==!b[1]", "{(::equal :a (::not (::$atIndex :b 1)))}")
|
||||
|
@ -105,11 +108,14 @@ describe("Peggy parse", () => {
|
|||
testParse("1 // This is a line comment", "{1}")
|
||||
testParse("1 /* This is a multi line comment */", "{1}")
|
||||
testParse("/* This is a multi line comment */ 1", "{1}")
|
||||
testParse(`
|
||||
testParse(
|
||||
`
|
||||
/* This is
|
||||
a multi line
|
||||
comment */
|
||||
1`, "{1}")
|
||||
1`,
|
||||
"{1}",
|
||||
)
|
||||
})
|
||||
|
||||
describe("ternary operator", () => {
|
||||
|
@ -126,7 +132,7 @@ describe("Peggy parse", () => {
|
|||
) //nested if
|
||||
})
|
||||
|
||||
describe("logical", ()=> {
|
||||
describe("logical", () => {
|
||||
testParse("true || false", "{(::or true false)}")
|
||||
testParse("true && false", "{(::and true false)}")
|
||||
testParse("a && b || c", "{(::and :a (::or :b :c))}")
|
||||
|
@ -144,9 +150,18 @@ describe("Peggy parse", () => {
|
|||
testParse("a && b<c.i || d", "{(::and :a (::or (::smaller :b (::$atIndex :c 'i')) :d))}")
|
||||
testParse("a && b<c(i) || d", "{(::and :a (::or (::smaller :b (::c :i)) :d))}")
|
||||
testParse("a && b<1+2 || d", "{(::and :a (::or (::smaller :b (::add 1 2)) :d))}")
|
||||
testParse("a && b<1+2*3 || d", "{(::and :a (::or (::smaller :b (::add 1 (::multiply 2 3))) :d))}")
|
||||
testParse("a && b<1+2*-3+4 || d", "{(::and :a (::or (::smaller :b (::add (::add 1 (::multiply 2 (::unaryMinus 3))) 4)) :d))}")
|
||||
testParse("a && b<1+2*3 || d ? true : false", "{(::$$ternary (::and :a (::or (::smaller :b (::add 1 (::multiply 2 3))) :d)) true false)}")
|
||||
testParse(
|
||||
"a && b<1+2*3 || d",
|
||||
"{(::and :a (::or (::smaller :b (::add 1 (::multiply 2 3))) :d))}",
|
||||
)
|
||||
testParse(
|
||||
"a && b<1+2*-3+4 || d",
|
||||
"{(::and :a (::or (::smaller :b (::add (::add 1 (::multiply 2 (::unaryMinus 3))) 4)) :d))}",
|
||||
)
|
||||
testParse(
|
||||
"a && b<1+2*3 || d ? true : false",
|
||||
"{(::$$ternary (::and :a (::or (::smaller :b (::add 1 (::multiply 2 3))) :d)) true false)}",
|
||||
)
|
||||
})
|
||||
|
||||
describe("pipe", () => {
|
||||
|
@ -194,67 +209,111 @@ describe("Peggy parse", () => {
|
|||
})
|
||||
|
||||
describe("Using lambda as value", () => {
|
||||
testParse("myadd(x,y)=x+y; z=myadd; z", "{:myadd = {|:x,:y| {(::add :x :y)}}; :z = {:myadd}; :z}")
|
||||
testParse("myadd(x,y)=x+y; z=[myadd]; z", "{:myadd = {|:x,:y| {(::add :x :y)}}; :z = {(::$constructArray (:myadd))}; :z}")
|
||||
testParse("myaddd(x,y)=x+y; z={x: myaddd}; z", "{:myaddd = {|:x,:y| {(::add :x :y)}}; :z = {(::$constructRecord ('x': :myaddd))}; :z}")
|
||||
testParse(
|
||||
"myadd(x,y)=x+y; z=myadd; z",
|
||||
"{:myadd = {|:x,:y| {(::add :x :y)}}; :z = {:myadd}; :z}",
|
||||
)
|
||||
testParse(
|
||||
"myadd(x,y)=x+y; z=[myadd]; z",
|
||||
"{:myadd = {|:x,:y| {(::add :x :y)}}; :z = {(::$constructArray (:myadd))}; :z}",
|
||||
)
|
||||
testParse(
|
||||
"myaddd(x,y)=x+y; z={x: myaddd}; z",
|
||||
"{:myaddd = {|:x,:y| {(::add :x :y)}}; :z = {(::$constructRecord ('x': :myaddd))}; :z}",
|
||||
)
|
||||
testParse("f({|x| x+1})", "{(::f {|:x| {(::add :x 1)}})}")
|
||||
testParse("map(arr, {|x| x+1})", "{(::map :arr {|:x| {(::add :x 1)}})}")
|
||||
testParse("map([1,2,3], {|x| x+1})", "{(::map (::$constructArray (1 2 3)) {|:x| {(::add :x 1)}})}")
|
||||
testParse("[1,2,3]->map({|x| x+1})", "{(::map (::$constructArray (1 2 3)) {|:x| {(::add :x 1)}})}")
|
||||
testParse(
|
||||
"map([1,2,3], {|x| x+1})",
|
||||
"{(::map (::$constructArray (1 2 3)) {|:x| {(::add :x 1)}})}",
|
||||
)
|
||||
testParse(
|
||||
"[1,2,3]->map({|x| x+1})",
|
||||
"{(::map (::$constructArray (1 2 3)) {|:x| {(::add :x 1)}})}",
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("parsing new line", ()=>{
|
||||
testParse(`
|
||||
describe("parsing new line", () => {
|
||||
testParse(
|
||||
`
|
||||
a +
|
||||
b`, "{(::add :a :b)}")
|
||||
testParse(`
|
||||
b`,
|
||||
"{(::add :a :b)}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
x=
|
||||
1`, "{:x = {1}}")
|
||||
testParse(`
|
||||
1`,
|
||||
"{:x = {1}}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
x=1
|
||||
y=2`, "{:x = {1}; :y = {2}}")
|
||||
testParse(`
|
||||
y=2`,
|
||||
"{:x = {1}; :y = {2}}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
x={
|
||||
y=2;
|
||||
y }
|
||||
x`, "{:x = {:y = {2}; :y}; :x}")
|
||||
testParse(`
|
||||
x`,
|
||||
"{:x = {:y = {2}; :y}; :x}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
x={
|
||||
y=2
|
||||
y }
|
||||
x`, "{:x = {:y = {2}; :y}; :x}")
|
||||
testParse(`
|
||||
x`,
|
||||
"{:x = {:y = {2}; :y}; :x}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
x={
|
||||
y=2
|
||||
y
|
||||
}
|
||||
x`, "{:x = {:y = {2}; :y}; :x}")
|
||||
testParse(`
|
||||
x`,
|
||||
"{:x = {:y = {2}; :y}; :x}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
x=1
|
||||
y=2
|
||||
z=3
|
||||
`, "{:x = {1}; :y = {2}; :z = {3}}")
|
||||
testParse(`
|
||||
`,
|
||||
"{:x = {1}; :y = {2}; :z = {3}}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
f={
|
||||
x=1
|
||||
y=2
|
||||
z=3
|
||||
x+y+z
|
||||
}
|
||||
`, "{:f = {:x = {1}; :y = {2}; :z = {3}; (::add (::add :x :y) :z)}}")
|
||||
testParse(`
|
||||
`,
|
||||
"{:f = {:x = {1}; :y = {2}; :z = {3}; (::add (::add :x :y) :z)}}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
a |>
|
||||
b |>
|
||||
c |>
|
||||
d
|
||||
`, "{(::d (::c (::b :a)))}")
|
||||
testParse(`
|
||||
`,
|
||||
"{(::d (::c (::b :a)))}",
|
||||
)
|
||||
testParse(
|
||||
`
|
||||
a |>
|
||||
b |>
|
||||
c |>
|
||||
d +
|
||||
e
|
||||
`, "{(::add (::d (::c (::b :a))) :e)}")
|
||||
`,
|
||||
"{(::add (::d (::c (::b :a))) :e)}",
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
@ -9,27 +9,32 @@ open Jest
|
|||
open Expect
|
||||
|
||||
let expectToExpressionToBe = (expr, answer, ~v="_", ()) => {
|
||||
let rExpr = Parse.parse(expr)
|
||||
->Result.map(ToExpression.fromNode)
|
||||
let rExpr = Parse.parse(expr)->Result.map(ToExpression.fromNode)
|
||||
let a1 = rExpr->ExpressionT.toStringResultOkless
|
||||
if (v=="_") {
|
||||
if v == "_" {
|
||||
a1->expect->toBe(answer)
|
||||
} else {
|
||||
let a2 = rExpr->Result.flatMap(
|
||||
expr => Expression.reduceExpression(expr, Belt.Map.String.empty, ExpressionValue.defaultEnvironment)
|
||||
)->ExpressionValue.toStringResultOkless
|
||||
let a2 =
|
||||
rExpr
|
||||
->Result.flatMap(expr =>
|
||||
Expression.reduceExpression(expr, Belt.Map.String.empty, ExpressionValue.defaultEnvironment)
|
||||
)
|
||||
->ExpressionValue.toStringResultOkless
|
||||
(a1, a2)->expect->toEqual((answer, v))
|
||||
}
|
||||
}
|
||||
|
||||
let testToExpression = (expr, answer, ~v="_", ()) => test(expr, () => expectToExpressionToBe(expr, answer, ~v=v, ()))
|
||||
let testToExpression = (expr, answer, ~v="_", ()) =>
|
||||
test(expr, () => expectToExpressionToBe(expr, answer, ~v, ()))
|
||||
|
||||
module MySkip = {
|
||||
let testToExpression = (expr, answer, ~v="_", ()) => Skip.test(expr, () => expectToExpressionToBe(expr, answer, ~v=v, ()))
|
||||
let testToExpression = (expr, answer, ~v="_", ()) =>
|
||||
Skip.test(expr, () => expectToExpressionToBe(expr, answer, ~v, ()))
|
||||
}
|
||||
|
||||
module MyOnly = {
|
||||
let testToExpression = (expr, answer, ~v="_", ()) => Only.test(expr, () => expectToExpressionToBe(expr, answer, ~v=v, ()))
|
||||
let testToExpression = (expr, answer, ~v="_", ()) =>
|
||||
Only.test(expr, () => expectToExpressionToBe(expr, answer, ~v, ()))
|
||||
}
|
||||
|
||||
describe("Peggy to Expression", () => {
|
||||
|
@ -53,7 +58,12 @@ describe("Peggy to Expression", () => {
|
|||
|
||||
describe("multi-line", () => {
|
||||
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)))", ~v="{x: 1,y: 2}", ())
|
||||
testToExpression(
|
||||
"x=1; y=2",
|
||||
"(:$$block (:$let :x (:$$block 1)) (:$let :y (:$$block 2)))",
|
||||
~v="{x: 1,y: 2}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
||||
describe("variables", () => {
|
||||
|
@ -63,22 +73,51 @@ describe("Peggy to Expression", () => {
|
|||
})
|
||||
|
||||
describe("functions", () => {
|
||||
testToExpression("identity(x) = x", "(:$$block (:$let :identity (:$$lambda [x] (:$$block :x))))", ~v="{identity: lambda(x=>internal code)}", ()) // Function definitions become lambda assignments
|
||||
testToExpression(
|
||||
"identity(x) = 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
|
||||
})
|
||||
|
||||
describe("arrays", () => {
|
||||
testToExpression("[]", "(:$$block (:$constructArray ()))", ~v="[]", ())
|
||||
testToExpression("[0, 1, 2]", "(:$$block (:$constructArray (0 1 2)))", ~v="[0,1,2]", ())
|
||||
testToExpression("['hello', 'world']", "(:$$block (:$constructArray ('hello' 'world')))", ~v="['hello','world']", ())
|
||||
testToExpression("([0,1,2])[1]", "(:$$block (:$atIndex (:$constructArray (0 1 2)) 1))", ~v="1", ())
|
||||
testToExpression(
|
||||
"['hello', 'world']",
|
||||
"(:$$block (:$constructArray ('hello' 'world')))",
|
||||
~v="['hello','world']",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"([0,1,2])[1]",
|
||||
"(:$$block (:$atIndex (:$constructArray (0 1 2)) 1))",
|
||||
~v="1",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
||||
describe("records", () => {
|
||||
testToExpression("{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))))", ()) // key can be any expression
|
||||
testToExpression(
|
||||
"{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))))",
|
||||
(),
|
||||
) // key can be any expression
|
||||
testToExpression("record.property", "(:$$block (:$atIndex :record 'property'))", ())
|
||||
testToExpression("record={property: 1}; record.property", "(:$$block (:$let :record (:$$block (:$constructRecord (('property' 1))))) (:$atIndex :record 'property'))", ~v="1", ())
|
||||
testToExpression(
|
||||
"record={property: 1}; record.property",
|
||||
"(:$$block (:$let :record (:$$block (:$constructRecord (('property' 1))))) (:$atIndex :record 'property'))",
|
||||
~v="1",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
||||
describe("comments", () => {
|
||||
|
@ -91,16 +130,35 @@ describe("Peggy to Expression", () => {
|
|||
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 : 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)))", ~v="0", ()) // nested ternary
|
||||
testToExpression(
|
||||
"true ? 1 : 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)))",
|
||||
~v="0",
|
||||
(),
|
||||
) // nested ternary
|
||||
})
|
||||
|
||||
describe("if then else", () => {
|
||||
testToExpression("if true then 2 else 3", "(:$$block (:$$ternary true (:$$block 2) (:$$block 3)))", ())
|
||||
testToExpression("if true then {2} else {3}", "(:$$block (:$$ternary true (:$$block 2) (:$$block 3)))", ())
|
||||
testToExpression(
|
||||
"if true then 2 else 3",
|
||||
"(:$$block (:$$ternary true (:$$block 2) (:$$block 3)))",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"if true then {2} else {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
|
||||
})
|
||||
|
||||
|
@ -119,15 +177,38 @@ describe("Peggy to Expression", () => {
|
|||
describe("inner block", () => {
|
||||
// inner blocks are 0 argument lambdas. They can be used whenever a value is required.
|
||||
// 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)))", ~v="{x: 1,y: 99}", ())
|
||||
testToExpression(
|
||||
"y=99; x={y=1; y}",
|
||||
"(:$$block (:$let :y (:$$block 99)) (:$let :x (:$$block (:$let :y (:$$block 1)) :y)))",
|
||||
~v="{x: 1,y: 99}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
||||
describe("lambda", () => {
|
||||
testToExpression("{|x| x}", "(:$$block (:$$lambda [x] (:$$block :x)))", ~v="lambda(x=>internal code)", ())
|
||||
testToExpression("f={|x| 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))))", ~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)))))", ~v="{f: lambda(x=>internal code)}", ())
|
||||
testToExpression(
|
||||
"{|x| x}",
|
||||
"(:$$block (:$$lambda [x] (:$$block :x)))",
|
||||
~v="lambda(x=>internal code)",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"f={|x| 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))))",
|
||||
~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)))))",
|
||||
~v="{f: lambda(x=>internal code)}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -9,4 +9,3 @@ describe("Eval with Bindings", () => {
|
|||
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})")
|
||||
})
|
||||
|
||||
|
|
|
@ -68,21 +68,23 @@ describe("function tricks", () => {
|
|||
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+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(1, 1)", "Ok(2)")
|
||||
testEvalToBe("myadd(x,y)=x+y; z=myadd; z", "Ok(lambda(x,y=>internal code))")
|
||||
testEvalToBe("myadd(x,y)=x+y; z=myadd; z(1, 1)", "Ok(2)")
|
||||
})
|
||||
|
||||
describe("lambda in structures", () => {
|
||||
testEvalToBe("myadd(x,y)=x+y; z=[myadd]", "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](3,2)", "Ok(5)")
|
||||
testEvalToBe("myaddd(x,y)=x+y; z={x: myaddd}; z", "Ok({x: lambda(x,y=>internal code)})")
|
||||
testEvalToBe("myaddd(x,y)=x+y; z={x: myaddd}; z.x", "Ok(lambda(x,y=>internal code))")
|
||||
testEvalToBe("myaddd(x,y)=x+y; z={x: myaddd}; z.x(3,2)", "Ok(5)")
|
||||
testEvalToBe(
|
||||
"myadd(x,y)=x+y; z=[myadd]",
|
||||
"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](3,2)", "Ok(5)")
|
||||
testEvalToBe("myaddd(x,y)=x+y; z={x: myaddd}; z", "Ok({x: lambda(x,y=>internal code)})")
|
||||
testEvalToBe("myaddd(x,y)=x+y; z={x: myaddd}; z.x", "Ok(lambda(x,y=>internal code))")
|
||||
testEvalToBe("myaddd(x,y)=x+y; z={x: myaddd}; z.x(3,2)", "Ok(5)")
|
||||
})
|
||||
|
||||
describe("ternary and bindings", () => {
|
||||
testEvalToBe("f(x)=x ? 1 : 0; f(true)", "Ok(1)")
|
||||
testEvalToBe("f(x)=x>2 ? 1 : 0; f(3)", "Ok(1)")
|
||||
})
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ describe("eval", () => {
|
|||
test("define", () => expectEvalToBe("{a: 1, b: 2}", "Ok({a: 1,b: 2})"))
|
||||
test("index", () => expectEvalToBe("r = {a: 1}; r.a", "Ok(1)"))
|
||||
test("index", () => expectEvalToBe("r = {a: 1}; r.b", "Error(Record property not found: b)"))
|
||||
testEvalError("{a: 1}.b") // invalid syntax
|
||||
testEvalError("{a: 1}.b") // invalid syntax
|
||||
})
|
||||
|
||||
describe("multi-line", () => {
|
||||
|
|
|
@ -21,7 +21,9 @@ type t = expression
|
|||
Converts a Squigle code to expression
|
||||
*/
|
||||
let parse = (peggyCode: string): result<t, errorValue> =>
|
||||
peggyCode->Reducer_Peggy_Parse.parse->Result.map(node => Reducer_Peggy_ToExpression.fromNode(node))
|
||||
peggyCode
|
||||
->Reducer_Peggy_Parse.parse
|
||||
->Result.map(node => Reducer_Peggy_ToExpression.fromNode(node))
|
||||
|
||||
/*
|
||||
Recursively evaluate/reduce the expression (Lisp AST)
|
||||
|
@ -72,7 +74,7 @@ and reduceExpressionList = (
|
|||
and reduceValueList = (valueList: list<expressionValue>, environment): result<
|
||||
expressionValue,
|
||||
'e,
|
||||
> =>
|
||||
> =>
|
||||
switch valueList {
|
||||
| list{EvCall(fName), ...args} =>
|
||||
(fName, args->Belt.List.toArray)->BuiltIn.dispatch(environment, reduceExpression)
|
||||
|
|
|
@ -5,7 +5,6 @@ module Parse = Reducer_Peggy_Parse
|
|||
type expression = ExpressionT.expression
|
||||
|
||||
let rec fromNode = (node: Parse.node): expression => {
|
||||
|
||||
let caseBlock = nodeBlock =>
|
||||
ExpressionBuilder.eBlock(nodeBlock["statements"]->Js.Array2.map(fromNode)->Belt.List.fromArray)
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ let toStringResult = x =>
|
|||
let toStringResultOkless = codeResult =>
|
||||
switch codeResult {
|
||||
| Ok(a) => toString(a)
|
||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
}
|
||||
|
||||
let toStringResultRecord = x =>
|
||||
|
|
Loading…
Reference in New Issue
Block a user