Index: polemy/eval.d ================================================================== --- polemy/eval.d +++ polemy/eval.d @@ -99,11 +99,11 @@ { Table ctx = createGlobalContext(); return typeof(return)(eval(e, ctx), ctx); } -Value eval(AST _e, Table ctx, bool splitCtx = true) +Value eval(AST _e, Table ctx, bool splitCtx = false) { if( auto e = cast(StrLiteral)_e ) { return new StrValue(e.data); } @@ -121,10 +121,12 @@ if( auto e = cast(LetExpression)_e ) { // for letrec, we need this, but should avoid overwriting???? // ctx.set(e.var, "@val", new UndefinedValue, e.pos); Value v = eval(e.init, ctx, true); + if(splitCtx) + ctx = new Table(ctx, Table.Kind.NotPropagateSet); ctx.set(e.var, "@val", v, e.pos); return eval(e.expr, ctx); } else if( auto e = cast(FuncallExpression)_e ) @@ -172,10 +174,15 @@ } unittest { assert_nothrow( evalString(`print("Hello, world!");`) ); assert_nothrow( evalString(`print(fun(){});`) ); +} +unittest +{ + assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(BigInt(1)) ); + assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new IntValue(BigInt(2)) ); } unittest { assert_nothrow( evalString(`var fac = fun(x){ 1; Index: polemy/parse.d ================================================================== --- polemy/parse.d +++ polemy/parse.d @@ -66,11 +66,11 @@ if( kwd == "@" ) kwd ~= eatId("after @"); immutable LexPosition varpos = (lex.empty ? null : lex.front.pos); string var = eatId("after "~kwd); eat("=", "after "~kwd); - kwd = (kwd[0]=='@' ? kwd : "@val"); + kwd = (kwd[0]=='@' ? kwd : ""); // "let, var, def ==> neutral layer" auto e = E(0); if( tryEat(";") && !lex.empty && (lex.front.quoted || (lex.front.str!="}" && lex.front.str!=")")) ) return new LetExpression(pos, var, kwd, e, Body()); else return new LetExpression(pos, var, kwd, e, new VarExpression(varpos, var)); @@ -261,13 +261,13 @@ assert_eq(parseString(`fun(x){1}`), fun(["x"],intl(1))); assert_eq(parseString("\u03BB(){1}"), fun([],intl(1))); assert_eq(parseString("\u03BB(x){1}"), fun(["x"],intl(1))); assert_eq(parseString(`1;2`), let("_","@val",intl(1),intl(2))); assert_eq(parseString(`1;2;`), let("_","@val",intl(1),intl(2))); - assert_eq(parseString(`let x=1;2`), let("x","@val",intl(1),intl(2))); - assert_eq(parseString(`var x=1;2;`), let("x","@val",intl(1),intl(2))); - assert_eq(parseString(`def x=1`), let("x","@val",intl(1),var("x"))); + assert_eq(parseString(`let x=1;2`), let("x","",intl(1),intl(2))); + assert_eq(parseString(`var x=1;2;`), let("x","",intl(1),intl(2))); + assert_eq(parseString(`def x=1`), let("x","",intl(1),var("x"))); assert_eq(parseString(`@val x=1;`), let("x","@val",intl(1),var("x"))); assert_eq(parseString(`@typ x="#int";`), let("x","@typ",strl("#int"),var("x"))); assert_eq(parseString(`f(1,2)`), call(var("f"),intl(1),intl(2))); assert_eq(parseString(`if(1){2}`), call(var("if"),intl(1),fun([],intl(2)),fun([],intl(178)))); assert_eq(parseString(`if(1){2}else{3}`), call(var("if"),intl(1),fun([],intl(2)),fun([],intl(3)))); @@ -281,18 +281,18 @@ assert_eq(parseString(` let x = 100; #comment let y = 200; #comment!!!!! x+y `), - let("x", "@val", intl(100), let("y", "@val", intl(200), call(var("+"), var("x"), var("y")))) + let("x", "", intl(100), let("y", "", intl(200), call(var("+"), var("x"), var("y")))) ); assert_eq(parseString(` var fac = fun(x){ if(x <= 1) {1} else {x*fac(x-1)} }; fac(10) `), - let("fac", "@val", fun(["x"], + let("fac", "", fun(["x"], call(var("if"), call(var("<="), var("x"), intl(1)), fun([], intl(1)), fun([], call(var("*"), var("x"), call(var("fac"),call(var("-"),var("x"),intl(1))))) )), Index: tricks/test.d ================================================================== --- tricks/test.d +++ tricks/test.d @@ -56,11 +56,11 @@ { try { if( mixin("a"~op~"b") ) return; } catch(Throwable e) { onAssertErrorMsg(fn, ln, msg.length ? msg : "exception ["~e.toString()~"]"); } - onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op~to!string(b)); + onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op~" "~to!string(b)); } } alias assertOp!(`==`) assert_eq; alias assertOp!(`!=`) assert_ne;