Artifact c82fe33ef6c72ef2d8fd482f0ba0d40abbd4e77f:
0000: ef bb bf 2f 2a 2a 0d 0a 20 2a 20 41 75 74 68 6f .../**.. * Autho
0010: 72 73 3a 20 6b 2e 69 6e 61 62 61 0d 0a 20 2a 20 rs: k.inaba.. *
0020: 4c 69 63 65 6e 73 65 3a 20 4e 59 53 4c 20 30 2e License: NYSL 0.
0030: 39 39 38 32 20 68 74 74 70 3a 2f 2f 77 77 77 2e 9982 http://www.
0040: 6b 6d 6f 6e 6f 73 2e 6e 65 74 2f 6e 79 73 6c 2f kmonos.net/nysl/
0050: 0d 0a 20 2a 0d 0a 20 2a 20 45 76 61 6c 75 61 74 .. *.. * Evaluat
0060: 6f 72 20 66 6f 72 20 50 6f 6c 65 6d 79 20 70 72 or for Polemy pr
0070: 6f 67 72 61 6d 6d 69 6e 67 20 6c 61 6e 67 75 61 ogramming langua
0080: 67 65 2e 0d 0a 20 2a 2f 0d 0a 6d 6f 64 75 6c 65 ge... */..module
0090: 20 70 6f 6c 65 6d 79 2e 65 76 61 6c 3b 0d 0a 69 polemy.eval;..i
00a0: 6d 70 6f 72 74 20 70 6f 6c 65 6d 79 2e 5f 63 6f mport polemy._co
00b0: 6d 6d 6f 6e 3b 0d 0a 69 6d 70 6f 72 74 20 70 6f mmon;..import po
00c0: 6c 65 6d 79 2e 61 73 74 3b 0d 0a 69 6d 70 6f 72 lemy.ast;..impor
00d0: 74 20 70 6f 6c 65 6d 79 2e 72 75 6e 74 69 6d 65 t polemy.runtime
00e0: 3b 0d 0a 0d 0a 43 6f 6e 74 65 78 74 20 65 76 61 ;....Context eva
00f0: 6c 28 50 72 6f 67 72 61 6d 20 70 72 6f 67 29 0d l(Program prog).
0100: 0a 7b 0d 0a 09 72 65 74 75 72 6e 20 65 76 61 6c .{...return eval
0110: 28 70 72 6f 67 2c 20 6e 65 77 20 43 6f 6e 74 65 (prog, new Conte
0120: 78 74 29 3b 0d 0a 7d 0d 0a 0d 0a 43 6f 6e 74 65 xt);..}....Conte
0130: 78 74 20 65 76 61 6c 28 50 72 6f 67 72 61 6d 20 xt eval(Program
0140: 70 72 6f 67 2c 20 43 6f 6e 74 65 78 74 20 63 74 prog, Context ct
0150: 78 29 0d 0a 7b 0d 0a 09 66 6f 72 65 61 63 68 28 x)..{...foreach(
0160: 73 3b 20 70 72 6f 67 29 0d 0a 09 09 63 74 78 20 s; prog)....ctx
0170: 3d 20 65 76 61 6c 28 73 2c 20 63 74 78 29 3b 0d = eval(s, ctx);.
0180: 0a 09 72 65 74 75 72 6e 20 63 74 78 3b 0d 0a 7d ..return ctx;..}
0190: 0d 0a 0d 0a 43 6f 6e 74 65 78 74 20 65 76 61 6c ....Context eval
01a0: 28 53 74 61 74 65 6d 65 6e 74 20 5f 73 2c 20 43 (Statement _s, C
01b0: 6f 6e 74 65 78 74 20 63 74 78 29 0d 0a 7b 0d 0a ontext ctx)..{..
01c0: 09 69 66 28 20 61 75 74 6f 20 73 20 3d 20 63 61 .if( auto s = ca
01d0: 73 74 28 44 65 63 6c 53 74 61 74 65 6d 65 6e 74 st(DeclStatement
01e0: 29 5f 73 20 29 0d 0a 09 7b 0d 0a 09 09 61 75 74 )_s )...{....aut
01f0: 6f 20 76 20 3d 20 65 76 61 6c 28 73 2e 65 78 70 o v = eval(s.exp
0200: 72 2c 20 63 74 78 29 3b 0d 0a 09 09 63 74 78 2e r, ctx);....ctx.
0210: 61 64 64 28 73 2e 76 61 72 2c 20 76 29 3b 0d 0a add(s.var, v);..
0220: 09 09 72 65 74 75 72 6e 20 63 74 78 3b 0d 0a 09 ..return ctx;...
0230: 7d 0d 0a 09 65 6c 73 65 0d 0a 09 69 66 28 20 61 }...else...if( a
0240: 75 74 6f 20 73 20 3d 20 63 61 73 74 28 45 78 70 uto s = cast(Exp
0250: 72 53 74 61 74 65 6d 65 6e 74 29 5f 73 20 29 0d rStatement)_s ).
0260: 0a 09 7b 0d 0a 09 09 65 76 61 6c 28 73 2e 65 78 ..{....eval(s.ex
0270: 70 72 2c 20 63 74 78 29 3b 0d 0a 09 09 72 65 74 pr, ctx);....ret
0280: 75 72 6e 20 63 74 78 3b 0d 0a 09 7d 0d 0a 09 74 urn ctx;...}...t
0290: 68 72 6f 77 20 6e 65 77 20 50 6f 6c 65 6d 79 52 hrow new PolemyR
02a0: 75 6e 74 69 6d 65 45 78 63 65 70 74 69 6f 6e 28 untimeException(
02b0: 73 70 72 69 6e 74 66 21 22 55 6e 6b 6e 6f 77 6e sprintf!"Unknown
02c0: 20 4b 69 6e 64 20 6f 66 20 53 74 61 74 65 6d 65 Kind of Stateme
02d0: 6e 74 20 25 73 20 61 74 20 5b 25 73 5d 22 28 74 nt %s at [%s]"(t
02e0: 79 70 65 69 64 28 5f 73 29 2c 20 5f 73 2e 70 6f ypeid(_s), _s.po
02f0: 73 29 29 3b 0d 0a 7d 0d 0a 0d 0a 56 61 6c 75 65 s));..}....Value
0300: 20 65 76 61 6c 28 45 78 70 72 65 73 73 69 6f 6e eval(Expression
0310: 20 5f 65 2c 20 43 6f 6e 74 65 78 74 20 63 74 78 _e, Context ctx
0320: 29 0d 0a 7b 0d 0a 09 69 66 28 20 61 75 74 6f 20 )..{...if( auto
0330: 65 20 3d 20 63 61 73 74 28 53 74 72 4c 69 74 65 e = cast(StrLite
0340: 72 61 6c 45 78 70 72 65 73 73 69 6f 6e 29 5f 65 ralExpression)_e
0350: 20 29 0d 0a 09 7b 0d 0a 09 09 72 65 74 75 72 6e )...{....return
0360: 20 6e 65 77 20 53 74 72 56 61 6c 75 65 28 65 2e new StrValue(e.
0370: 64 61 74 61 29 3b 0d 0a 09 7d 0d 0a 09 65 6c 73 data);...}...els
0380: 65 0d 0a 09 69 66 28 20 61 75 74 6f 20 65 20 3d e...if( auto e =
0390: 20 63 61 73 74 28 49 6e 74 4c 69 74 65 72 61 6c cast(IntLiteral
03a0: 45 78 70 72 65 73 73 69 6f 6e 29 5f 65 20 29 0d Expression)_e ).
03b0: 0a 09 7b 0d 0a 09 09 72 65 74 75 72 6e 20 6e 65 ..{....return ne
03c0: 77 20 49 6e 74 56 61 6c 75 65 28 65 2e 64 61 74 w IntValue(e.dat
03d0: 61 29 3b 0d 0a 09 7d 0d 0a 09 65 6c 73 65 0d 0a a);...}...else..
03e0: 09 69 66 28 20 61 75 74 6f 20 65 20 3d 20 63 61 .if( auto e = ca
03f0: 73 74 28 56 61 72 45 78 70 72 65 73 73 69 6f 6e st(VarExpression
0400: 29 5f 65 20 29 0d 0a 09 7b 0d 0a 09 09 72 65 74 )_e )...{....ret
0410: 75 72 6e 20 63 74 78 5b 65 2e 76 61 72 5d 3b 0d urn ctx[e.var];.
0420: 0a 09 7d 0d 0a 09 65 6c 73 65 0d 0a 09 69 66 28 ..}...else...if(
0430: 20 61 75 74 6f 20 65 20 3d 20 63 61 73 74 28 42 auto e = cast(B
0440: 69 6e 4f 70 45 78 70 72 65 73 73 69 6f 6e 29 5f inOpExpression)_
0450: 65 20 29 0d 0a 09 7b 0d 0a 09 09 69 66 28 20 65 e )...{....if( e
0460: 2e 6f 70 20 3d 3d 20 22 3d 22 20 29 0d 0a 09 09 .op == "=" )....
0470: 7b 0d 0a 09 09 09 69 66 28 20 61 75 74 6f 20 65 {.....if( auto e
0480: 76 20 3d 20 63 61 73 74 28 56 61 72 45 78 70 72 v = cast(VarExpr
0490: 65 73 73 69 6f 6e 29 65 2e 6c 68 73 20 29 0d 0a ession)e.lhs )..
04a0: 09 09 09 7b 0d 0a 09 09 09 09 56 61 6c 75 65 20 ...{......Value
04b0: 72 20 3d 20 65 76 61 6c 28 65 2e 72 68 73 2c 20 r = eval(e.rhs,
04c0: 63 74 78 29 3b 0d 0a 09 09 09 09 63 74 78 5b 65 ctx);......ctx[e
04d0: 76 2e 76 61 72 5d 20 3d 20 72 3b 0d 0a 09 09 09 v.var] = r;.....
04e0: 09 72 65 74 75 72 6e 20 72 3b 0d 0a 09 09 09 7d .return r;.....}
04f0: 0d 0a 09 09 09 74 68 72 6f 77 20 6e 65 77 20 50 .....throw new P
0500: 6f 6c 65 6d 79 52 75 6e 74 69 6d 65 45 78 63 65 olemyRuntimeExce
0510: 70 74 69 6f 6e 28 73 70 72 69 6e 74 66 21 22 4c ption(sprintf!"L
0520: 68 73 20 6f 66 20 61 73 73 69 67 6e 6d 65 6e 74 hs of assignment
0530: 20 6d 75 73 74 20 62 65 20 61 20 76 61 72 69 61 must be a varia
0540: 62 6c 65 3a 20 25 73 22 28 65 2e 70 6f 73 29 29 ble: %s"(e.pos))
0550: 3b 0d 0a 09 09 7d 0d 0a 0d 0a 09 09 56 61 6c 75 ;....}......Valu
0560: 65 20 6c 20 3d 20 65 76 61 6c 28 65 2e 6c 68 73 e l = eval(e.lhs
0570: 2c 20 63 74 78 29 3b 0d 0a 09 09 56 61 6c 75 65 , ctx);....Value
0580: 20 72 20 3d 20 65 76 61 6c 28 65 2e 72 68 73 2c r = eval(e.rhs,
0590: 20 63 74 78 29 3b 0d 0a 09 09 69 66 28 20 61 75 ctx);....if( au
05a0: 74 6f 20 6c 76 20 3d 20 63 61 73 74 28 49 6e 74 to lv = cast(Int
05b0: 56 61 6c 75 65 29 6c 20 29 0d 0a 09 09 09 69 66 Value)l ).....if
05c0: 28 20 61 75 74 6f 20 72 76 20 3d 20 63 61 73 74 ( auto rv = cast
05d0: 28 49 6e 74 56 61 6c 75 65 29 72 20 29 0d 0a 09 (IntValue)r )...
05e0: 09 09 09 66 69 6e 61 6c 20 73 77 69 74 63 68 28 ...final switch(
05f0: 65 2e 6f 70 29 0d 0a 09 09 09 09 7b 0d 0a 09 09 e.op)......{....
0600: 09 09 63 61 73 65 20 22 2b 22 3a 20 72 65 74 75 ..case "+": retu
0610: 72 6e 20 6e 65 77 20 49 6e 74 56 61 6c 75 65 28 rn new IntValue(
0620: 6c 76 2e 64 61 74 61 2b 72 76 2e 64 61 74 61 29 lv.data+rv.data)
0630: 3b 0d 0a 09 09 09 09 63 61 73 65 20 22 2d 22 3a ;......case "-":
0640: 20 72 65 74 75 72 6e 20 6e 65 77 20 49 6e 74 56 return new IntV
0650: 61 6c 75 65 28 6c 76 2e 64 61 74 61 2d 72 76 2e alue(lv.data-rv.
0660: 64 61 74 61 29 3b 0d 0a 09 09 09 09 63 61 73 65 data);......case
0670: 20 22 2a 22 3a 20 72 65 74 75 72 6e 20 6e 65 77 "*": return new
0680: 20 49 6e 74 56 61 6c 75 65 28 6c 76 2e 64 61 74 IntValue(lv.dat
0690: 61 2a 72 76 2e 64 61 74 61 29 3b 0d 0a 09 09 09 a*rv.data);.....
06a0: 09 63 61 73 65 20 22 2f 22 3a 20 72 65 74 75 72 .case "/": retur
06b0: 6e 20 6e 65 77 20 49 6e 74 56 61 6c 75 65 28 6c n new IntValue(l
06c0: 76 2e 64 61 74 61 2f 72 76 2e 64 61 74 61 29 3b v.data/rv.data);
06d0: 0d 0a 09 09 09 09 7d 0d 0a 09 09 09 65 6c 73 65 ......}.....else
06e0: 0d 0a 09 09 09 09 74 68 72 6f 77 20 6e 65 77 20 ......throw new
06f0: 50 6f 6c 65 6d 79 52 75 6e 74 69 6d 65 45 78 63 PolemyRuntimeExc
0700: 65 70 74 69 6f 6e 28 73 70 72 69 6e 74 66 21 22 eption(sprintf!"
0710: 72 68 73 20 6f 66 20 25 73 20 6d 75 73 74 20 62 rhs of %s must b
0720: 65 20 61 6e 20 69 6e 74 65 67 65 72 20 62 75 74 e an integer but
0730: 20 77 61 73 20 25 73 20 61 74 20 5b 25 73 5d 22 was %s at [%s]"
0740: 28 65 2e 6f 70 2c 20 74 79 70 65 69 64 28 72 29 (e.op, typeid(r)
0750: 2c 20 65 2e 72 68 73 2e 70 6f 73 29 29 3b 0d 0a , e.rhs.pos));..
0760: 09 09 65 6c 73 65 0d 0a 09 09 09 74 68 72 6f 77 ..else.....throw
0770: 20 6e 65 77 20 50 6f 6c 65 6d 79 52 75 6e 74 69 new PolemyRunti
0780: 6d 65 45 78 63 65 70 74 69 6f 6e 28 73 70 72 69 meException(spri
0790: 6e 74 66 21 22 6c 68 73 20 6f 66 20 25 73 20 6d ntf!"lhs of %s m
07a0: 75 73 74 20 62 65 20 61 6e 20 69 6e 74 65 67 65 ust be an intege
07b0: 72 20 62 75 74 20 77 61 73 20 25 73 20 61 74 20 r but was %s at
07c0: 5b 25 73 5d 22 28 65 2e 6f 70 2c 20 74 79 70 65 [%s]"(e.op, type
07d0: 69 64 28 6c 29 2c 20 65 2e 6c 68 73 2e 70 6f 73 id(l), e.lhs.pos
07e0: 29 29 3b 0d 0a 09 7d 0d 0a 09 74 68 72 6f 77 20 ));...}...throw
07f0: 6e 65 77 20 50 6f 6c 65 6d 79 52 75 6e 74 69 6d new PolemyRuntim
0800: 65 45 78 63 65 70 74 69 6f 6e 28 73 70 72 69 6e eException(sprin
0810: 74 66 21 22 55 6e 6b 6e 6f 77 6e 20 4b 69 6e 64 tf!"Unknown Kind
0820: 20 6f 66 20 45 78 70 72 65 73 73 69 6f 6e 20 25 of Expression %
0830: 73 20 61 74 20 5b 25 73 5d 22 28 74 79 70 65 69 s at [%s]"(typei
0840: 64 28 5f 65 29 2c 20 5f 65 2e 70 6f 73 29 29 3b d(_e), _e.pos));
0850: 0d 0a 7d 0d 0a 0d 0a 0d 0a 76 65 72 73 69 6f 6e ..}......version
0860: 28 75 6e 69 74 74 65 73 74 29 20 69 6d 70 6f 72 (unittest) impor
0870: 74 20 70 6f 6c 65 6d 79 2e 70 61 72 73 65 3b 0d t polemy.parse;.
0880: 0a 76 65 72 73 69 6f 6e 28 75 6e 69 74 74 65 73 .version(unittes
0890: 74 29 20 69 6d 70 6f 72 74 20 73 74 64 2e 73 74 t) import std.st
08a0: 64 69 6f 3b 0d 0a 76 65 72 73 69 6f 6e 28 75 6e dio;..version(un
08b0: 69 74 74 65 73 74 29 20 69 6d 70 6f 72 74 20 73 ittest) import s
08c0: 74 64 2e 65 78 63 65 70 74 69 6f 6e 3b 0d 0a 75 td.exception;..u
08d0: 6e 69 74 74 65 73 74 0d 0a 7b 0d 0a 09 61 75 74 nittest..{...aut
08e0: 6f 20 70 61 72 73 65 72 20 3d 20 70 61 72 73 65 o parser = parse
08f0: 72 46 72 6f 6d 53 74 72 69 6e 67 28 60 76 61 72 rFromString(`var
0900: 20 78 20 3d 20 32 31 3b 20 78 20 3d 20 78 20 2b x = 21; x = x +
0910: 20 78 2a 78 3b 60 29 3b 0d 0a 09 61 75 74 6f 20 x*x;`);...auto
0920: 70 72 6f 67 20 3d 20 70 61 72 73 65 72 2e 70 61 prog = parser.pa
0930: 72 73 65 50 72 6f 67 72 61 6d 28 29 3b 0d 0a 09 rseProgram();...
0940: 61 75 74 6f 20 63 74 78 20 3d 20 65 76 61 6c 28 auto ctx = eval(
0950: 70 72 6f 67 29 3b 0d 0a 09 61 73 73 65 72 74 28 prog);...assert(
0960: 20 63 74 78 5b 22 78 22 5d 20 3d 3d 20 6e 65 77 ctx["x"] == new
0970: 20 49 6e 74 56 61 6c 75 65 28 42 69 67 49 6e 74 IntValue(BigInt
0980: 28 32 31 2b 32 31 2a 32 31 29 29 20 29 3b 0d 0a (21+21*21)) );..
0990: 09 61 73 73 65 72 74 28 20 21 63 6f 6c 6c 65 63 .assert( !collec
09a0: 74 45 78 63 65 70 74 69 6f 6e 28 63 74 78 5b 22 tException(ctx["
09b0: 78 22 5d 29 20 29 3b 0d 0a 09 61 73 73 65 72 74 x"]) );...assert
09c0: 28 20 63 6f 6c 6c 65 63 74 45 78 63 65 70 74 69 ( collectExcepti
09d0: 6f 6e 28 63 74 78 5b 22 79 22 5d 29 20 29 3b 0d on(ctx["y"]) );.
09e0: 0a 7d 0d 0a 75 6e 69 74 74 65 73 74 0d 0a 7b 0d .}..unittest..{.
09f0: 0a 09 61 75 74 6f 20 70 61 72 73 65 72 20 3d 20 ..auto parser =
0a00: 70 61 72 73 65 72 46 72 6f 6d 53 74 72 69 6e 67 parserFromString
0a10: 28 60 76 61 72 20 78 20 3d 20 32 31 3b 20 78 20 (`var x = 21; x
0a20: 3d 20 78 20 2b 20 78 2a 79 3b 60 29 3b 0d 0a 09 = x + x*y;`);...
0a30: 61 75 74 6f 20 70 72 6f 67 20 3d 20 70 61 72 73 auto prog = pars
0a40: 65 72 2e 70 61 72 73 65 50 72 6f 67 72 61 6d 28 er.parseProgram(
0a50: 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 63 6f 6c );...assert( col
0a60: 6c 65 63 74 45 78 63 65 70 74 69 6f 6e 28 65 76 lectException(ev
0a70: 61 6c 28 70 72 6f 67 29 29 20 29 3b 0d 0a 7d 0d al(prog)) );..}.
0a80: 0a 75 6e 69 74 74 65 73 74 0d 0a 7b 0d 0a 09 61 .unittest..{...a
0a90: 75 74 6f 20 70 61 72 73 65 72 20 3d 20 70 61 72 uto parser = par
0aa0: 73 65 72 46 72 6f 6d 53 74 72 69 6e 67 28 60 76 serFromString(`v
0ab0: 61 72 20 78 20 3d 20 32 31 3b 20 79 20 3d 20 78 ar x = 21; y = x
0ac0: 20 2b 20 78 2a 78 3b 60 29 3b 0d 0a 09 61 75 74 + x*x;`);...aut
0ad0: 6f 20 70 72 6f 67 20 3d 20 70 61 72 73 65 72 2e o prog = parser.
0ae0: 70 61 72 73 65 50 72 6f 67 72 61 6d 28 29 3b 0d parseProgram();.
0af0: 0a 09 61 73 73 65 72 74 28 20 63 6f 6c 6c 65 63 ..assert( collec
0b00: 74 45 78 63 65 70 74 69 6f 6e 28 65 76 61 6c 28 tException(eval(
0b10: 70 72 6f 67 29 29 20 29 3b 0d 0a 7d 0d 0a prog)) );..}..