Overview
SHA1 Hash: | 3f5dc76a75ae8b8ecbee3c1b287f449cf312e595 |
---|---|
Date: | 2010-11-07 21:46:23 |
User: | kinaba |
Comment: | Added funcall expression parser and function literal parser. |
Timelines: | family | ancestors | descendants | both | trunk |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [f65680e1d2]
- sym-trunk inherited from [f65680e1d2]
Changes
Modified polemy/ast.d from [e79569cb2ae94b8c] to [a264a204623245e6].
62 class AssignExpression : Expression 62 class AssignExpression : Expression 63 { 63 { 64 Expression lhs; 64 Expression lhs; 65 Expression rhs; 65 Expression rhs; 66 mixin SimpleConstructor; 66 mixin SimpleConstructor; 67 mixin SimpleCompare; // do not take "pos" into account 67 mixin SimpleCompare; // do not take "pos" into account 68 } 68 } > 69 69 class FuncallExpression : Expression 70 class FuncallExpression : Expression 70 { 71 { 71 Expression fun; 72 Expression fun; 72 Expression[] args; 73 Expression[] args; 73 this(immutable LexPosition pos, Expression fun, Expression[] args...) 74 this(immutable LexPosition pos, Expression fun, Expression[] args...) 74 { super(pos); this.fun=fun; this.args=args.dup; } 75 { super(pos); this.fun=fun; this.args=args.dup; } 75 mixin SimpleCompare; // do not take "pos" into account 76 mixin SimpleCompare; // do not take "pos" into account 76 } 77 } > 78 > 79 class FunLiteralExpression : Expression > 80 { > 81 string[] params; > 82 Program funbody; > 83 mixin SimpleConstructor; > 84 mixin SimpleCompare; // do not take "pos" into account > 85 }
Modified polemy/eval.d from [0a7ac481ec249b42] to [c5ee9ab6830c78bd].
3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 * 4 * 5 * Evaluator for Polemy programming language. 5 * Evaluator for Polemy programming language. 6 */ 6 */ 7 module polemy.eval; 7 module polemy.eval; 8 import polemy._common; 8 import polemy._common; 9 import polemy.ast; 9 import polemy.ast; > 10 import polemy.parse; 10 import polemy.runtime; 11 import polemy.runtime; 11 12 12 Context createGlobalContext() 13 Context createGlobalContext() 13 { 14 { 14 auto ctx = new Context; 15 auto ctx = new Context; 15 ctx.add("+", new PrimitiveFunction(delegate Value(Value[] args){ 16 ctx.add("+", new PrimitiveFunction(delegate Value(Value[] args){ 16 if( args.length != 2 ) 17 if( args.length != 2 ) ................................................................................................................................................................................ 42 if( auto x = cast(IntValue)args[0] ) 43 if( auto x = cast(IntValue)args[0] ) 43 if( auto y = cast(IntValue)args[1] ) 44 if( auto y = cast(IntValue)args[1] ) 44 return new IntValue(x.data/y.data); 45 return new IntValue(x.data/y.data); 45 throw new PolemyRuntimeException("cannot add non-integers"); // 46 throw new PolemyRuntimeException("cannot add non-integers"); // 46 })); 47 })); 47 return ctx; 48 return ctx; 48 } 49 } > 50 > 51 Context evalString(T...)(T params) > 52 { > 53 return eval( parserFromString(params).parseProgram() ); > 54 } > 55 > 56 Context evalFile(T...)(T params) > 57 { > 58 return eval( parserFromFile(params).parseProgram() ); > 59 } 49 60 50 Context eval(Program prog) 61 Context eval(Program prog) 51 { 62 { 52 return eval(prog, createGlobalContext()); 63 return eval(prog, createGlobalContext()); 53 } 64 } 54 65 55 Context eval(Program prog, Context ctx) 66 Context eval(Program prog, Context ctx) ................................................................................................................................................................................ 120 131 121 132 122 version(unittest) import polemy.parse; 133 version(unittest) import polemy.parse; 123 version(unittest) import std.stdio; 134 version(unittest) import std.stdio; 124 version(unittest) import std.exception; 135 version(unittest) import std.exception; 125 unittest 136 unittest 126 { 137 { 127 auto parser = parserFromString(`var x = 21; x = x + x*x;`); | 138 auto ctx = evalString(`var x = 21; x = x + x*x;`); 128 auto prog = parser.parseProgram(); < 129 auto ctx = eval(prog); < 130 assert( ctx["x"] == new IntValue(BigInt(21+21*21)) ); 139 assert( ctx["x"] == new IntValue(BigInt(21+21*21)) ); 131 assert( !collectException(ctx["x"]) ); 140 assert( !collectException(ctx["x"]) ); 132 assert( collectException(ctx["y"]) ); 141 assert( collectException(ctx["y"]) ); 133 } 142 } 134 unittest 143 unittest 135 { 144 { 136 auto parser = parserFromString(`var x = 21; x = x + x*y;`); < 137 auto prog = parser.parseProgram(); < 138 assert( collectException(eval(prog)) ); | 145 assert( collectException(evalString(`var x = 21; x = x + x*y;`)) ); 139 } 146 } 140 unittest 147 unittest 141 { 148 { 142 auto parser = parserFromString(`var x = 21; y = x + x*x;`); < 143 auto prog = parser.parseProgram(); < 144 assert( collectException(eval(prog)) ); | 149 assert( collectException(evalString(`var x = 21; y = x + x*x;`)) ); 145 } 150 }
Modified polemy/parse.d from [a819ba1b27fdc13d] to [4856c979362ef435].
95 auto saved = lex.save; 95 auto saved = lex.save; 96 scope(failure) lex = saved; 96 scope(failure) lex = saved; 97 return parseE(0); 97 return parseE(0); 98 } 98 } 99 99 100 // [TODO] multi-char operators are not supported by the lexer... 100 // [TODO] multi-char operators are not supported by the lexer... 101 static immutable string[][] operator_perferences = [ 101 static immutable string[][] operator_perferences = [ 102 [","], | 102 ["="], 103 ["="], // caution! left associative < 104 ["or"], 103 ["or"], 105 ["and"], 104 ["and"], 106 ["!="], 105 ["!="], 107 ["=="], 106 ["=="], 108 ["<","<=",">",">="], 107 ["<","<=",">",">="], 109 ["|"], 108 ["|"], 110 ["^"], 109 ["^"], ................................................................................................................................................................................ 142 } 141 } 143 142 144 Expression parseBaseExpression() 143 Expression parseBaseExpression() 145 { 144 { 146 if( lex.empty ) 145 if( lex.empty ) 147 throw new ParserException("EOF during parsing an express 146 throw new ParserException("EOF during parsing an express 148 auto pos = lex.front.pos; 147 auto pos = lex.front.pos; > 148 Expression e = parseBaseBaseExpression(); > 149 while( tryEat("(") ) // funcall > 150 { > 151 Expression[] args; > 152 while( !tryEat(")") ) { > 153 if( lex.empty ) { > 154 auto ex = ParserException.create(lex,"Un > 155 throw ex; > 156 } > 157 args ~= parseE(); > 158 if( !tryEat(",") ) { > 159 eat(")", "after function parameters"); > 160 break; > 161 } > 162 } > 163 e = new FuncallExpression(pos, e, args); > 164 } > 165 return e; > 166 } > 167 > 168 Expression parseBaseBaseExpression() > 169 { > 170 if( lex.empty ) > 171 throw new ParserException("EOF during parsing an express > 172 auto pos = lex.front.pos; 149 173 150 if( lex.front.kind == Token.Kind.number ) 174 if( lex.front.kind == Token.Kind.number ) 151 { 175 { 152 scope(exit) lex.popFront; 176 scope(exit) lex.popFront; 153 return new IntLiteralExpression(pos, BigInt(cast(string) 177 return new IntLiteralExpression(pos, BigInt(cast(string) 154 } 178 } 155 if( lex.front.kind == Token.Kind.stringLiteral ) 179 if( lex.front.kind == Token.Kind.stringLiteral ) ................................................................................................................................................................................ 159 } 183 } 160 if( tryEat("(") ) 184 if( tryEat("(") ) 161 { 185 { 162 auto e = parseE(); 186 auto e = parseE(); 163 eat(")", "after parenthesized expression"); 187 eat(")", "after parenthesized expression"); 164 return e; 188 return e; 165 } 189 } > 190 > 191 if( tryEat("fun") ) > 192 { > 193 eat("(", "after fun"); > 194 string[] params; > 195 for(;;) > 196 { > 197 if( lex.empty ) { > 198 auto e = ParserException.create(lex,"Une > 199 throw e; > 200 } > 201 if( lex.front.kind != Token.Kind.identifier ) { > 202 auto e = ParserException.create(lex,"Ide > 203 throw e; > 204 } > 205 params ~= lex.front.str; > 206 lex.popFront; > 207 if( !tryEat(",") ) { > 208 eat(")", "after function parameters"); > 209 break; > 210 } > 211 } > 212 eat("{", "after function parameters"); > 213 Statement[] funbody; > 214 while(!tryEat("}")) { > 215 if( lex.empty ) { > 216 auto e = ParserException.create(lex,"Une > 217 throw e; > 218 } > 219 funbody ~= parseStatement(); > 220 } > 221 return new FunLiteralExpression(pos, params, funbody); > 222 } 166 scope(exit) lex.popFront; 223 scope(exit) lex.popFront; 167 return new VarExpression(pos, lex.front.str); 224 return new VarExpression(pos, lex.front.str); 168 } 225 } 169 226 170 private: 227 private: 171 Lexer lex; 228 Lexer lex; 172 229 ................................................................................................................................................................................ 226 283 227 Program prog = p.parseProgram(); 284 Program prog = p.parseProgram(); 228 assert( prog.length == 3 ); 285 assert( prog.length == 3 ); 229 assert( prog[0] == s0 ); 286 assert( prog[0] == s0 ); 230 assert( prog[1] == s1 ); 287 assert( prog[1] == s1 ); 231 assert( prog[2] == s2 ); 288 assert( prog[2] == s2 ); 232 } 289 } > 290 > 291 unittest > 292 { > 293 auto p = parserFromString(` > 294 var f = fun(x,y){x+y;}; > 295 f(1,fun(abc){}(4)); > 296 `); > 297 Program prog = p.parseProgram(); > 298 assert( prog.length == 2 ); > 299 assert( prog[0] == new DeclStatement(null, "f", new FunLiteralExpression > 300 ["x","y"], [new ExprStatement(null, > 301 new FuncallExpression(null, new VarExpression(null, "+") > 302 new VarExpression(null, "x"), new VarExpression(null, "y > 303 ))); > 304 assert( prog[1] == new ExprStatement(null, new FuncallExpression(null, > 305 new VarExpression(null, "f"), > 306 new IntLiteralExpression(null, BigInt(1)), > 307 new FuncallExpression(null, > 308 new FunLiteralExpression(null, ["abc"], [ > 309 ]), > 310 new IntLiteralExpression(null, BigInt(4)) > 311 )))); > 312 }