8e318a8aa9
removed some extra array references rename Builder to ExpressionBuilder Expression Builder Trash Warning remove parsePartial/Outer, add context to lambda format module Bindings simplify types module Macro reduceValueList do macro call result map bindings stop replacing on macro calls Macro Test doBindStatement bind a statement bindings tested. TODO bind shadowing in lambda block tests defined block tests defined blocks tested macro lambda test defined
103 lines
3.8 KiB
Plaintext
103 lines
3.8 KiB
Plaintext
open Jest
|
|
open Reducer_TestHelpers
|
|
|
|
describe("reducer using mathjs parse", () => {
|
|
// Test the MathJs parser compatibility
|
|
// Those tests toString that there is a semantic mapping from MathJs to Expression
|
|
// Reducer.parse is called by Reducer.eval
|
|
// See https://mathjs.org/docs/expressions/syntax.html
|
|
// See https://mathjs.org/docs/reference/functions.html
|
|
// Those tests toString that we are converting mathjs parse tree to what we need
|
|
|
|
describe("expressions", () => {
|
|
testParseToBe("1", "Ok((:$$block 1))")
|
|
testParseToBe("(1)", "Ok((:$$block 1))")
|
|
testParseToBe("1+2", "Ok((:$$block (:add 1 2)))")
|
|
testParseToBe("1+2*3", "Ok((:$$block (:add 1 (:multiply 2 3))))")
|
|
})
|
|
describe("arrays", () => {
|
|
//Note. () is a empty list in Lisp
|
|
// The only builtin structure in Lisp is list. There are no arrays
|
|
// [1,2,3] becomes (1 2 3)
|
|
testDescriptionParseToBe("empty", "[]", "Ok((:$$block ()))")
|
|
testParseToBe("[1, 2, 3]", "Ok((:$$block (1 2 3)))")
|
|
testParseToBe("['hello', 'world']", "Ok((:$$block ('hello' 'world')))")
|
|
testDescriptionParseToBe("index", "([0,1,2])[1]", "Ok((:$$block (:$atIndex (0 1 2) (1))))")
|
|
})
|
|
describe("records", () => {
|
|
testDescriptionParseToBe(
|
|
"define",
|
|
"{a: 1, b: 2}",
|
|
"Ok((:$$block (:$constructRecord (('a' 1) ('b' 2)))))",
|
|
)
|
|
testDescriptionParseToBe(
|
|
"use",
|
|
"{a: 1, b: 2}.a",
|
|
"Ok((:$$block (:$atIndex (:$constructRecord (('a' 1) ('b' 2))) ('a'))))",
|
|
)
|
|
})
|
|
describe("multi-line", () => {
|
|
testParseToBe("1; 2", "Ok((:$$block (:$$block 1 2)))")
|
|
testParseToBe("1+1; 2+1", "Ok((:$$block (:$$block (:add 1 1) (:add 2 1))))")
|
|
})
|
|
describe("assignment", () => {
|
|
testParseToBe("x=1; x", "Ok((:$$block (:$$block (:$let :x 1) :x)))")
|
|
testParseToBe("x=1+1; x+1", "Ok((:$$block (:$$block (:$let :x (:add 1 1)) (:add :x 1))))")
|
|
})
|
|
})
|
|
|
|
describe("eval", () => {
|
|
// All MathJs operators and functions are builtin for string, float and boolean
|
|
// .e.g + - / * > >= < <= == /= not and or
|
|
// See https://mathjs.org/docs/expressions/syntax.html
|
|
// See https://mathjs.org/docs/reference/functions.html
|
|
describe("expressions", () => {
|
|
testEvalToBe("1", "Ok(1)")
|
|
testEvalToBe("1+2", "Ok(3)")
|
|
testEvalToBe("(1+2)*3", "Ok(9)")
|
|
testEvalToBe("2>1", "Ok(true)")
|
|
testEvalToBe("concat('a ', 'b')", "Ok('a b')")
|
|
testEvalToBe("log(10)", "Ok(2.302585092994046)")
|
|
testEvalToBe("cos(10)", "Ok(-0.8390715290764524)")
|
|
// TODO more built ins
|
|
})
|
|
describe("arrays", () => {
|
|
test("empty array", () => expectEvalToBe("[]", "Ok([])"))
|
|
testEvalToBe("[1, 2, 3]", "Ok([1,2,3])")
|
|
testEvalToBe("['hello', 'world']", "Ok(['hello','world'])")
|
|
testEvalToBe("([0,1,2])[1]", "Ok(1)")
|
|
testDescriptionEvalToBe("index not found", "([0,1,2])[10]", "Error(Array index not found: 10)")
|
|
})
|
|
describe("records", () => {
|
|
test("define", () => expectEvalToBe("{a: 1, b: 2}", "Ok({a: 1,b: 2})"))
|
|
test("index", () => expectEvalToBe("{a: 1}.a", "Ok(1)"))
|
|
test("index not found", () => expectEvalToBe("{a: 1}.b", "Error(Record property not found: b)"))
|
|
})
|
|
|
|
describe("multi-line", () => {
|
|
testEvalToBe("1; 2", "Error(Assignment expected)")
|
|
testEvalToBe("1+1; 2+1", "Error(Assignment expected)")
|
|
})
|
|
describe("assignment", () => {
|
|
testEvalToBe("x=1; x", "Ok(1)")
|
|
testEvalToBe("x=1+1; x+1", "Ok(3)")
|
|
testEvalToBe("x=1; y=x+1; y+1", "Ok(3)")
|
|
testEvalToBe("1; x=1", "Error(Assignment expected)")
|
|
testEvalToBe("1; 1", "Error(Assignment expected)")
|
|
testEvalToBe("x=1; x=1", "Ok({x: 1})")
|
|
})
|
|
})
|
|
|
|
describe("test exceptions", () => {
|
|
testDescriptionEvalToBe(
|
|
"javascript exception",
|
|
"javascriptraise('div by 0')",
|
|
"Error(JS Exception: Error: 'div by 0')",
|
|
)
|
|
testDescriptionEvalToBe(
|
|
"rescript exception",
|
|
"rescriptraise()",
|
|
"Error(TODO: unhandled rescript exception)",
|
|
)
|
|
})
|