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
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +41,11 @@ describe("bindStatement", () => {
 | 
			
		|||
 | 
			
		||||
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})")
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,10 @@ describe("function tricks", () => {
 | 
			
		|||
})
 | 
			
		||||
 | 
			
		||||
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]",
 | 
			
		||||
    "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)})")
 | 
			
		||||
| 
						 | 
				
			
			@ -85,4 +88,3 @@ 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)")
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user