Artifact bedecb22284cfae99f749134b33261f03f7ca92b:
0000: ef bb bf 6d 6f 64 75 6c 65 20 70 6f 6c 65 6d 79 ...module polemy
0010: 2e 65 76 61 6c 3b 0d 0a 69 6d 70 6f 72 74 20 70 .eval;..import p
0020: 6f 6c 65 6d 79 2e 5f 63 6f 6d 6d 6f 6e 3b 0d 0a olemy._common;..
0030: 2f 2a 0d 0a 20 2a 20 41 75 74 68 6f 72 3a 20 20 /*.. * Author:
0040: 6b 2e 69 6e 61 62 61 0d 0a 20 2a 20 4c 69 63 65 k.inaba.. * Lice
0050: 6e 73 65 3a 20 4e 59 53 4c 20 30 2e 39 39 38 32 nse: NYSL 0.9982
0060: 20 28 68 74 74 70 3a 2f 2f 77 77 77 2e 6b 6d 6f (http://www.kmo
0070: 6e 6f 73 2e 6e 65 74 2f 6e 79 73 6c 2f 0d 0a 20 nos.net/nysl/..
0080: 2a 20 20 20 45 76 61 6c 75 61 74 6f 72 20 66 6f * Evaluator fo
0090: 72 20 74 68 65 20 70 6f 6c 65 6d 79 20 70 72 6f r the polemy pro
00a0: 67 72 61 6d 6d 69 6e 67 20 6c 61 6e 67 75 61 67 gramming languag
00b0: 65 0d 0a 20 2a 2f 0d 0a 69 6d 70 6f 72 74 20 70 e.. */..import p
00c0: 6f 6c 65 6d 79 2e 61 73 74 3b 0d 0a 69 6d 70 6f olemy.ast;..impo
00d0: 72 74 20 70 6f 6c 65 6d 79 2e 72 75 6e 74 69 6d rt polemy.runtim
00e0: 65 3b 0d 0a 0d 0a 43 6f 6e 74 65 78 74 20 65 76 e;....Context ev
00f0: 61 6c 28 50 72 6f 67 72 61 6d 20 70 72 6f 67 29 al(Program prog)
0100: 0d 0a 7b 0d 0a 09 72 65 74 75 72 6e 20 65 76 61 ..{...return eva
0110: 6c 28 70 72 6f 67 2c 20 6e 65 77 20 43 6f 6e 74 l(prog, new Cont
0120: 65 78 74 29 3b 0d 0a 7d 0d 0a 0d 0a 43 6f 6e 74 ext);..}....Cont
0130: 65 78 74 20 65 76 61 6c 28 50 72 6f 67 72 61 6d ext eval(Program
0140: 20 70 72 6f 67 2c 20 43 6f 6e 74 65 78 74 20 63 prog, Context c
0150: 74 78 29 0d 0a 7b 0d 0a 09 66 6f 72 65 61 63 68 tx)..{...foreach
0160: 28 73 3b 20 70 72 6f 67 29 0d 0a 09 09 63 74 78 (s; prog)....ctx
0170: 20 3d 20 65 76 61 6c 28 73 2c 20 63 74 78 29 3b = eval(s, ctx);
0180: 0d 0a 09 72 65 74 75 72 6e 20 63 74 78 3b 0d 0a ...return ctx;..
0190: 7d 0d 0a 0d 0a 43 6f 6e 74 65 78 74 20 65 76 61 }....Context eva
01a0: 6c 28 53 74 61 74 65 6d 65 6e 74 20 5f 73 2c 20 l(Statement _s,
01b0: 43 6f 6e 74 65 78 74 20 63 74 78 29 0d 0a 7b 0d Context ctx)..{.
01c0: 0a 09 69 66 28 20 61 75 74 6f 20 73 20 3d 20 63 ..if( auto s = c
01d0: 61 73 74 28 44 65 63 6c 53 74 61 74 65 6d 65 6e ast(DeclStatemen
01e0: 74 29 5f 73 20 29 0d 0a 09 7b 0d 0a 09 09 61 75 t)_s )...{....au
01f0: 74 6f 20 76 20 3d 20 65 76 61 6c 28 73 2e 65 78 to v = eval(s.ex
0200: 70 72 2c 20 63 74 78 29 3b 0d 0a 09 09 63 74 78 pr, ctx);....ctx
0210: 2e 61 64 64 28 73 2e 76 61 72 2c 20 76 29 3b 0d .add(s.var, v);.
0220: 0a 09 09 72 65 74 75 72 6e 20 63 74 78 3b 0d 0a ...return ctx;..
0230: 09 7d 0d 0a 09 65 6c 73 65 0d 0a 09 69 66 28 20 .}...else...if(
0240: 61 75 74 6f 20 73 20 3d 20 63 61 73 74 28 45 78 auto s = cast(Ex
0250: 70 72 53 74 61 74 65 6d 65 6e 74 29 5f 73 20 29 prStatement)_s )
0260: 0d 0a 09 7b 0d 0a 09 09 65 76 61 6c 28 73 2e 65 ...{....eval(s.e
0270: 78 70 72 2c 20 63 74 78 29 3b 0d 0a 09 09 72 65 xpr, ctx);....re
0280: 74 75 72 6e 20 63 74 78 3b 0d 0a 09 7d 0d 0a 09 turn ctx;...}...
0290: 74 68 72 6f 77 20 6e 65 77 20 50 6f 6c 65 6d 79 throw new Polemy
02a0: 52 75 6e 74 69 6d 65 45 78 63 65 70 74 69 6f 6e RuntimeException
02b0: 28 73 70 72 69 6e 74 66 21 22 55 6e 6b 6e 6f 77 (sprintf!"Unknow
02c0: 6e 20 4b 69 6e 64 20 6f 66 20 53 74 61 74 65 6d n Kind of Statem
02d0: 65 6e 74 20 25 73 20 61 74 20 5b 25 73 5d 22 28 ent %s at [%s]"(
02e0: 74 79 70 65 69 64 28 5f 73 29 2c 20 5f 73 2e 70 typeid(_s), _s.p
02f0: 6f 73 29 29 3b 0d 0a 7d 0d 0a 0d 0a 56 61 6c 75 os));..}....Valu
0300: 65 20 65 76 61 6c 28 45 78 70 72 65 73 73 69 6f e eval(Expressio
0310: 6e 20 5f 65 2c 20 43 6f 6e 74 65 78 74 20 63 74 n _e, Context ct
0320: 78 29 0d 0a 7b 0d 0a 09 69 66 28 20 61 75 74 6f x)..{...if( auto
0330: 20 65 20 3d 20 63 61 73 74 28 53 74 72 4c 69 74 e = cast(StrLit
0340: 65 72 61 6c 45 78 70 72 65 73 73 69 6f 6e 29 5f eralExpression)_
0350: 65 20 29 0d 0a 09 7b 0d 0a 09 09 72 65 74 75 72 e )...{....retur
0360: 6e 20 6e 65 77 20 53 74 72 56 61 6c 75 65 28 65 n new StrValue(e
0370: 2e 64 61 74 61 29 3b 0d 0a 09 7d 0d 0a 09 65 6c .data);...}...el
0380: 73 65 0d 0a 09 69 66 28 20 61 75 74 6f 20 65 20 se...if( auto e
0390: 3d 20 63 61 73 74 28 49 6e 74 4c 69 74 65 72 61 = cast(IntLitera
03a0: 6c 45 78 70 72 65 73 73 69 6f 6e 29 5f 65 20 29 lExpression)_e )
03b0: 0d 0a 09 7b 0d 0a 09 09 72 65 74 75 72 6e 20 6e ...{....return n
03c0: 65 77 20 49 6e 74 56 61 6c 75 65 28 65 2e 64 61 ew IntValue(e.da
03d0: 74 61 29 3b 0d 0a 09 7d 0d 0a 09 65 6c 73 65 0d ta);...}...else.
03e0: 0a 09 69 66 28 20 61 75 74 6f 20 65 20 3d 20 63 ..if( auto e = c
03f0: 61 73 74 28 56 61 72 45 78 70 72 65 73 73 69 6f ast(VarExpressio
0400: 6e 29 5f 65 20 29 0d 0a 09 7b 0d 0a 09 09 72 65 n)_e )...{....re
0410: 74 75 72 6e 20 63 74 78 5b 65 2e 76 61 72 5d 3b turn ctx[e.var];
0420: 0d 0a 09 7d 0d 0a 09 65 6c 73 65 0d 0a 09 69 66 ...}...else...if
0430: 28 20 61 75 74 6f 20 65 20 3d 20 63 61 73 74 28 ( auto e = cast(
0440: 42 69 6e 4f 70 45 78 70 72 65 73 73 69 6f 6e 29 BinOpExpression)
0450: 5f 65 20 29 0d 0a 09 7b 0d 0a 09 09 69 66 28 20 _e )...{....if(
0460: 65 2e 6f 70 20 3d 3d 20 22 3d 22 20 29 0d 0a 09 e.op == "=" )...
0470: 09 7b 0d 0a 09 09 09 69 66 28 20 61 75 74 6f 20 .{.....if( auto
0480: 65 76 20 3d 20 63 61 73 74 28 56 61 72 45 78 70 ev = cast(VarExp
0490: 72 65 73 73 69 6f 6e 29 65 2e 6c 68 73 20 29 0d ression)e.lhs ).
04a0: 0a 09 09 09 7b 0d 0a 09 09 09 09 56 61 6c 75 65 ....{......Value
04b0: 20 72 20 3d 20 65 76 61 6c 28 65 2e 72 68 73 2c r = eval(e.rhs,
04c0: 20 63 74 78 29 3b 0d 0a 09 09 09 09 63 74 78 5b ctx);......ctx[
04d0: 65 76 2e 76 61 72 5d 20 3d 20 72 3b 0d 0a 09 09 ev.var] = r;....
04e0: 09 09 72 65 74 75 72 6e 20 72 3b 0d 0a 09 09 09 ..return r;.....
04f0: 7d 0d 0a 09 09 09 74 68 72 6f 77 20 6e 65 77 20 }.....throw new
0500: 50 6f 6c 65 6d 79 52 75 6e 74 69 6d 65 45 78 63 PolemyRuntimeExc
0510: 65 70 74 69 6f 6e 28 73 70 72 69 6e 74 66 21 22 eption(sprintf!"
0520: 4c 68 73 20 6f 66 20 61 73 73 69 67 6e 6d 65 6e Lhs of assignmen
0530: 74 20 6d 75 73 74 20 62 65 20 61 20 76 61 72 69 t must be a vari
0540: 61 62 6c 65 3a 20 25 73 22 28 65 2e 70 6f 73 29 able: %s"(e.pos)
0550: 29 3b 0d 0a 09 09 7d 0d 0a 0d 0a 09 09 56 61 6c );....}......Val
0560: 75 65 20 6c 20 3d 20 65 76 61 6c 28 65 2e 6c 68 ue l = eval(e.lh
0570: 73 2c 20 63 74 78 29 3b 0d 0a 09 09 56 61 6c 75 s, ctx);....Valu
0580: 65 20 72 20 3d 20 65 76 61 6c 28 65 2e 72 68 73 e r = eval(e.rhs
0590: 2c 20 63 74 78 29 3b 0d 0a 09 09 69 66 28 20 61 , ctx);....if( a
05a0: 75 74 6f 20 6c 76 20 3d 20 63 61 73 74 28 49 6e uto lv = cast(In
05b0: 74 56 61 6c 75 65 29 6c 20 29 0d 0a 09 09 09 69 tValue)l ).....i
05c0: 66 28 20 61 75 74 6f 20 72 76 20 3d 20 63 61 73 f( auto rv = cas
05d0: 74 28 49 6e 74 56 61 6c 75 65 29 72 20 29 0d 0a t(IntValue)r )..
05e0: 09 09 09 09 66 69 6e 61 6c 20 73 77 69 74 63 68 ....final switch
05f0: 28 65 2e 6f 70 29 0d 0a 09 09 09 09 7b 0d 0a 09 (e.op)......{...
0600: 09 09 09 63 61 73 65 20 22 2b 22 3a 20 72 65 74 ...case "+": ret
0610: 75 72 6e 20 6e 65 77 20 49 6e 74 56 61 6c 75 65 urn new IntValue
0620: 28 6c 76 2e 64 61 74 61 2b 72 76 2e 64 61 74 61 (lv.data+rv.data
0630: 29 3b 0d 0a 09 09 09 09 63 61 73 65 20 22 2d 22 );......case "-"
0640: 3a 20 72 65 74 75 72 6e 20 6e 65 77 20 49 6e 74 : return new Int
0650: 56 61 6c 75 65 28 6c 76 2e 64 61 74 61 2d 72 76 Value(lv.data-rv
0660: 2e 64 61 74 61 29 3b 0d 0a 09 09 09 09 63 61 73 .data);......cas
0670: 65 20 22 2a 22 3a 20 72 65 74 75 72 6e 20 6e 65 e "*": return ne
0680: 77 20 49 6e 74 56 61 6c 75 65 28 6c 76 2e 64 61 w IntValue(lv.da
0690: 74 61 2a 72 76 2e 64 61 74 61 29 3b 0d 0a 09 09 ta*rv.data);....
06a0: 09 09 63 61 73 65 20 22 2f 22 3a 20 72 65 74 75 ..case "/": retu
06b0: 72 6e 20 6e 65 77 20 49 6e 74 56 61 6c 75 65 28 rn new IntValue(
06c0: 6c 76 2e 64 61 74 61 2f 72 76 2e 64 61 74 61 29 lv.data/rv.data)
06d0: 3b 0d 0a 09 09 09 09 7d 0d 0a 09 09 09 65 6c 73 ;......}.....els
06e0: 65 0d 0a 09 09 09 09 74 68 72 6f 77 20 6e 65 77 e......throw new
06f0: 20 50 6f 6c 65 6d 79 52 75 6e 74 69 6d 65 45 78 PolemyRuntimeEx
0700: 63 65 70 74 69 6f 6e 28 73 70 72 69 6e 74 66 21 ception(sprintf!
0710: 22 72 68 73 20 6f 66 20 25 73 20 6d 75 73 74 20 "rhs of %s must
0720: 62 65 20 61 6e 20 69 6e 74 65 67 65 72 20 62 75 be an integer bu
0730: 74 20 77 61 73 20 25 73 20 61 74 20 5b 25 73 5d t was %s at [%s]
0740: 22 28 65 2e 6f 70 2c 20 74 79 70 65 69 64 28 72 "(e.op, typeid(r
0750: 29 2c 20 65 2e 72 68 73 2e 70 6f 73 29 29 3b 0d ), e.rhs.pos));.
0760: 0a 09 09 65 6c 73 65 0d 0a 09 09 09 74 68 72 6f ...else.....thro
0770: 77 20 6e 65 77 20 50 6f 6c 65 6d 79 52 75 6e 74 w new PolemyRunt
0780: 69 6d 65 45 78 63 65 70 74 69 6f 6e 28 73 70 72 imeException(spr
0790: 69 6e 74 66 21 22 6c 68 73 20 6f 66 20 25 73 20 intf!"lhs of %s
07a0: 6d 75 73 74 20 62 65 20 61 6e 20 69 6e 74 65 67 must be an integ
07b0: 65 72 20 62 75 74 20 77 61 73 20 25 73 20 61 74 er but was %s at
07c0: 20 5b 25 73 5d 22 28 65 2e 6f 70 2c 20 74 79 70 [%s]"(e.op, typ
07d0: 65 69 64 28 6c 29 2c 20 65 2e 6c 68 73 2e 70 6f eid(l), e.lhs.po
07e0: 73 29 29 3b 0d 0a 09 7d 0d 0a 09 74 68 72 6f 77 s));...}...throw
07f0: 20 6e 65 77 20 50 6f 6c 65 6d 79 52 75 6e 74 69 new PolemyRunti
0800: 6d 65 45 78 63 65 70 74 69 6f 6e 28 73 70 72 69 meException(spri
0810: 6e 74 66 21 22 55 6e 6b 6e 6f 77 6e 20 4b 69 6e ntf!"Unknown Kin
0820: 64 20 6f 66 20 45 78 70 72 65 73 73 69 6f 6e 20 d of Expression
0830: 25 73 20 61 74 20 5b 25 73 5d 22 28 74 79 70 65 %s at [%s]"(type
0840: 69 64 28 5f 65 29 2c 20 5f 65 2e 70 6f 73 29 29 id(_e), _e.pos))
0850: 3b 0d 0a 7d 0d 0a 0d 0a 0d 0a 76 65 72 73 69 6f ;..}......versio
0860: 6e 28 75 6e 69 74 74 65 73 74 29 20 69 6d 70 6f n(unittest) impo
0870: 72 74 20 70 6f 6c 65 6d 79 2e 70 61 72 73 65 3b rt polemy.parse;
0880: 0d 0a 76 65 72 73 69 6f 6e 28 75 6e 69 74 74 65 ..version(unitte
0890: 73 74 29 20 69 6d 70 6f 72 74 20 73 74 64 2e 73 st) import std.s
08a0: 74 64 69 6f 3b 0d 0a 76 65 72 73 69 6f 6e 28 75 tdio;..version(u
08b0: 6e 69 74 74 65 73 74 29 20 69 6d 70 6f 72 74 20 nittest) import
08c0: 73 74 64 2e 65 78 63 65 70 74 69 6f 6e 3b 0d 0a std.exception;..
08d0: 75 6e 69 74 74 65 73 74 0d 0a 7b 0d 0a 09 61 75 unittest..{...au
08e0: 74 6f 20 70 61 72 73 65 72 20 3d 20 70 61 72 73 to parser = pars
08f0: 65 72 46 72 6f 6d 53 74 72 69 6e 67 28 60 76 61 erFromString(`va
0900: 72 20 78 20 3d 20 32 31 3b 20 78 20 3d 20 78 20 r x = 21; x = x
0910: 2b 20 78 2a 78 3b 60 29 3b 0d 0a 09 61 75 74 6f + x*x;`);...auto
0920: 20 70 72 6f 67 20 3d 20 70 61 72 73 65 72 2e 70 prog = parser.p
0930: 61 72 73 65 50 72 6f 67 72 61 6d 28 29 3b 0d 0a arseProgram();..
0940: 09 61 75 74 6f 20 63 74 78 20 3d 20 65 76 61 6c .auto ctx = eval
0950: 28 70 72 6f 67 29 3b 0d 0a 09 61 73 73 65 72 74 (prog);...assert
0960: 28 20 63 74 78 5b 22 78 22 5d 20 3d 3d 20 6e 65 ( ctx["x"] == ne
0970: 77 20 49 6e 74 56 61 6c 75 65 28 42 69 67 49 6e w IntValue(BigIn
0980: 74 28 32 31 2b 32 31 2a 32 31 29 29 20 29 3b 0d t(21+21*21)) );.
0990: 0a 09 61 73 73 65 72 74 28 20 21 63 6f 6c 6c 65 ..assert( !colle
09a0: 63 74 45 78 63 65 70 74 69 6f 6e 28 63 74 78 5b ctException(ctx[
09b0: 22 78 22 5d 29 20 29 3b 0d 0a 09 61 73 73 65 72 "x"]) );...asser
09c0: 74 28 20 63 6f 6c 6c 65 63 74 45 78 63 65 70 74 t( collectExcept
09d0: 69 6f 6e 28 63 74 78 5b 22 79 22 5d 29 20 29 3b ion(ctx["y"]) );
09e0: 0d 0a 7d 0d 0a 75 6e 69 74 74 65 73 74 0d 0a 7b ..}..unittest..{
09f0: 0d 0a 09 61 75 74 6f 20 70 61 72 73 65 72 20 3d ...auto parser =
0a00: 20 70 61 72 73 65 72 46 72 6f 6d 53 74 72 69 6e parserFromStrin
0a10: 67 28 60 76 61 72 20 78 20 3d 20 32 31 3b 20 78 g(`var x = 21; x
0a20: 20 3d 20 78 20 2b 20 78 2a 79 3b 60 29 3b 0d 0a = x + x*y;`);..
0a30: 09 61 75 74 6f 20 70 72 6f 67 20 3d 20 70 61 72 .auto prog = par
0a40: 73 65 72 2e 70 61 72 73 65 50 72 6f 67 72 61 6d ser.parseProgram
0a50: 28 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 63 6f ();...assert( co
0a60: 6c 6c 65 63 74 45 78 63 65 70 74 69 6f 6e 28 65 llectException(e
0a70: 76 61 6c 28 70 72 6f 67 29 29 20 29 3b 0d 0a 7d val(prog)) );..}
0a80: 0d 0a 75 6e 69 74 74 65 73 74 0d 0a 7b 0d 0a 09 ..unittest..{...
0a90: 61 75 74 6f 20 70 61 72 73 65 72 20 3d 20 70 61 auto parser = pa
0aa0: 72 73 65 72 46 72 6f 6d 53 74 72 69 6e 67 28 60 rserFromString(`
0ab0: 76 61 72 20 78 20 3d 20 32 31 3b 20 79 20 3d 20 var x = 21; y =
0ac0: 78 20 2b 20 78 2a 78 3b 60 29 3b 0d 0a 09 61 75 x + x*x;`);...au
0ad0: 74 6f 20 70 72 6f 67 20 3d 20 70 61 72 73 65 72 to prog = parser
0ae0: 2e 70 61 72 73 65 50 72 6f 67 72 61 6d 28 29 3b .parseProgram();
0af0: 0d 0a 09 61 73 73 65 72 74 28 20 63 6f 6c 6c 65 ...assert( colle
0b00: 63 74 45 78 63 65 70 74 69 6f 6e 28 65 76 61 6c ctException(eval
0b10: 28 70 72 6f 67 29 29 20 29 3b 0d 0a 7d 0d 0a (prog)) );..}..