comparison core/src/luan/impl/LuanParser.java @ 652:067d9470184d

compile SetStmt and ForStmt
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 04 Apr 2016 23:26:06 -0600
parents 140cc5191b7a
children 538b0ae08faa
comparison
equal deleted inserted replaced
651:140cc5191b7a 652:067d9470184d
247 return; 247 return;
248 StmtString stmt; 248 StmtString stmt;
249 if( (stmt=stmtStr(ReturnStmt())) != null 249 if( (stmt=stmtStr(ReturnStmt())) != null
250 || (stmt=stmtStr(FunctionStmt())) != null 250 || (stmt=stmtStr(FunctionStmt())) != null
251 || (stmt=stmtStr(LocalFunctionStmt())) != null 251 || (stmt=stmtStr(LocalFunctionStmt())) != null
252 || (stmt=stmtStr(BreakStmt())) != null 252 || (stmt=BreakStmt()) != null
253 || (stmt=stmtStr(ForStmt())) != null 253 || (stmt=ForStmt()) != null
254 || (stmt=DoStmt()) != null 254 || (stmt=DoStmt()) != null
255 || (stmt=WhileStmt()) != null 255 || (stmt=WhileStmt()) != null
256 || (stmt=RepeatStmt()) != null 256 || (stmt=RepeatStmt()) != null
257 || (stmt=stmtStr(IfStmt())) != null 257 || (stmt=stmtStr(IfStmt())) != null
258 || (stmt=stmtStr(SetStmt())) != null 258 || (stmt=SetStmt()) != null
259 || (stmt=ExpressionsStmt()) != null 259 || (stmt=ExpressionsStmt()) != null
260 ) { 260 ) {
261 stmts.append(stmt.code); 261 stmts.append(stmt.code);
262 } 262 }
263 } 263 }
343 addSymbol( name ); 343 addSymbol( name );
344 FnDef fnDef = RequiredFunction(In.NOTHING); 344 FnDef fnDef = RequiredFunction(In.NOTHING);
345 return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) ); 345 return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) );
346 } 346 }
347 347
348 private Stmt BreakStmt() throws ParseException { 348 private StmtString BreakStmt() throws ParseException {
349 parser.begin(); 349 parser.begin();
350 if( !Keyword("break",In.NOTHING) ) 350 if( !Keyword("break",In.NOTHING) )
351 return parser.failure(null); 351 return parser.failure(null);
352 if( frame.loops <= 0 ) 352 if( frame.loops <= 0 )
353 throw parser.exception("'break' outside of loop"); 353 throw parser.exception("'break' outside of loop");
354 return parser.success( new BreakStmt() ); 354 // return parser.success( new StmtString("break;\n") );
355 } 355 return parser.success( new StmtString(new BreakStmt()) );
356 356 }
357 private Stmt ForStmt() throws ParseException { 357
358 int forCounter = 0;
359
360 private StmtString ForStmt() throws ParseException {
358 parser.begin(); 361 parser.begin();
359 int stackStart = symbolsSize(); 362 int stackStart = symbolsSize();
360 if( !Keyword("for",In.NOTHING) ) 363 if( !Keyword("for",In.NOTHING) )
361 return parser.failure(null); 364 return parser.failure(null);
362 List<String> names = RequiredNameList(In.NOTHING); 365 List<String> names = RequiredNameList(In.NOTHING);
363 if( !Keyword("in",In.NOTHING) ) 366 if( !Keyword("in",In.NOTHING) )
364 return parser.failure(null); 367 return parser.failure(null);
365 Expr expr = expr(exp(RequiredExpr(In.NOTHING))); 368 ExpString expr = RequiredExpr(In.NOTHING).expr();
366 RequiredKeyword("do",In.NOTHING); 369 RequiredKeyword("do",In.NOTHING);
370
371 SetLocalVar[] vars = new SetLocalVar[names.size()];
372 for( int i=0; i<vars.length; i++ ) {
373 vars[i] = new SetLocalVar(stackStart+i);
374 }
375 String varsStr = varsToString(vars);
376
377 ExpString firstVar = new ExpString(new GetLocalVar(stackStart));
367 addSymbols(names); 378 addSymbols(names);
368 Stmt loop = stmt(RequiredLoopBlock()); 379 StmtString loop = RequiredLoopBlock();
369 RequiredKeyword("end",In.NOTHING); 380 RequiredKeyword("end",In.NOTHING);
370 Stmt stmt = new ForStmt( stackStart, symbolsSize() - stackStart, expr, loop ); 381 String fnVar = "$fn"+ ++forCounter;
382 String code = ""
383 +"try {\n"
384 +"LuanFunction "+fnVar+" = $Luan.checkFunction(" + expr.code + ");\n"
385 +"while(true) {\n"
386 +"for( int i="+stackStart+"; i<"+symbolsSize()+"; i++ ) {\n"
387 +"$luan.stackSet(i,null);\n"
388 +"}\n"
389 +"$Luan.set($luan," + varsStr + ", "+fnVar+".call($luan) );\n"
390 +"if( " + firstVar.code + "==null ) break;\n"
391 + loop.code
392 +"}"
393 +"} catch(BreakException e) {\n"
394 +"} finally {\n"
395 +"$luan.stackClear("+stackStart+","+symbolsSize()+");\n"
396 +"}\n"
397 ;
398 StmtString stmt = new StmtString(code);
371 popSymbols( symbolsSize() - stackStart ); 399 popSymbols( symbolsSize() - stackStart );
372 return parser.success(stmt); 400 return parser.success(stmt);
373 } 401 }
374 402
375 private StmtString DoStmt() throws ParseException { 403 private StmtString DoStmt() throws ParseException {
391 return parser.failure(); // handled later 419 return parser.failure(); // handled later
392 throw parser.exception("Invalid local statement"); 420 throw parser.exception("Invalid local statement");
393 } 421 }
394 if( parser.match( '=' ) ) { 422 if( parser.match( '=' ) ) {
395 Spaces(In.NOTHING); 423 Spaces(In.NOTHING);
396 Expressions values = ExpList(In.NOTHING); 424 ExpString values = ExpStringList(In.NOTHING);
397 if( values==null ) 425 if( values==null )
398 throw parser.exception("Expressions expected"); 426 throw parser.exception("Expressions expected");
399 SetLocalVar[] vars = new SetLocalVar[names.size()]; 427 SetLocalVar[] vars = new SetLocalVar[names.size()];
400 int stackStart = symbolsSize(); 428 int stackStart = symbolsSize();
401 for( int i=0; i<vars.length; i++ ) { 429 for( int i=0; i<vars.length; i++ ) {
402 vars[i] = new SetLocalVar(stackStart+i); 430 vars[i] = new SetLocalVar(stackStart+i);
403 } 431 }
404 stmts.append( new StmtString(new SetStmt( vars, values )).code ); 432 String varsStr = varsToString(vars);
433 String code = "$Luan.set($luan," + varsStr + "," + values.code + ");\n";
434 stmts.append(code);
405 } 435 }
406 addSymbols(names); 436 addSymbols(names);
407 return parser.success(); 437 return parser.success();
408 } 438 }
409 439
500 RequiredKeyword("end",In.NOTHING); 530 RequiredKeyword("end",In.NOTHING);
501 } 531 }
502 return new IfStmt(cnd,thenBlock,elseBlock); 532 return new IfStmt(cnd,thenBlock,elseBlock);
503 } 533 }
504 534
505 private Stmt SetStmt() throws ParseException { 535 private StmtString SetStmt() throws ParseException {
506 parser.begin(); 536 parser.begin();
507 List<Settable> vars = new ArrayList<Settable>(); 537 List<Settable> vars = new ArrayList<Settable>();
508 Settable s = SettableVar(); 538 Settable s = SettableVar();
509 if( s == null ) 539 if( s == null )
510 return parser.failure(null); 540 return parser.failure(null);
517 vars.add(s); 547 vars.add(s);
518 } 548 }
519 if( !parser.match( '=' ) ) 549 if( !parser.match( '=' ) )
520 return parser.failure(null); 550 return parser.failure(null);
521 Spaces(In.NOTHING); 551 Spaces(In.NOTHING);
522 Expressions values = ExpList(In.NOTHING); 552 ExpString values = ExpStringList(In.NOTHING);
523 if( values==null ) 553 if( values==null )
524 // throw parser.exception("Expressions expected"); 554 // throw parser.exception("Expressions expected");
525 return parser.failure(null); 555 return parser.failure(null);
526 return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); 556 String varsStr = varsToString(vars.toArray(new Settable[0]));
557 String code = "$Luan.set($luan," + varsStr + "," + values.code + "); ";
558 return parser.success( new StmtString(code) );
559 //qqq
560 }
561
562 private static String varsToString(Settable[] vars) {
563 StringBuilder sb = new StringBuilder();
564 sb.append( "new Settable[]{" );
565 for( Settable v : vars ) {
566 sb.append( new SettableString(v).code ).append( ',' );
567 }
568 sb.append( "}" );
569 return sb.toString();
527 } 570 }
528 571
529 private StmtString ExpressionsStmt() throws ParseException { 572 private StmtString ExpressionsStmt() throws ParseException {
530 parser.begin(); 573 parser.begin();
531 ExpString exp = ExprZ(In.NOTHING); 574 ExpString exp = ExprZ(In.NOTHING);
906 exp2 = NameExpr(in); 949 exp2 = NameExpr(in);
907 if( exp2!=null ) 950 if( exp2!=null )
908 return parser.success(indexVar(expr(exp1),exp2)); 951 return parser.success(indexVar(expr(exp1),exp2));
909 return parser.failure(null); 952 return parser.failure(null);
910 } 953 }
911 FnCall fnCall = Args( in, expr(exp1), new ArrayList<Expressions>() ); 954 FnCall fnCall = Args( in, expr(exp1), new ArrayList<ExpString>() );
912 if( fnCall != null ) 955 if( fnCall != null )
913 return parser.success(exprVar(fnCall)); 956 return parser.success(exprVar(fnCall));
914 return parser.failure(null); 957 return parser.failure(null);
915 } 958 }
916 959
986 return new SetTableEntry(table,key); 1029 return new SetTableEntry(table,key);
987 } 1030 }
988 }; 1031 };
989 } 1032 }
990 1033
991 private FnCall Args(In in,Expr fn,List<Expressions> builder) throws ParseException { 1034 private FnCall Args(In in,Expr fn,List<ExpString> builder) throws ParseException {
992 parser.begin(); 1035 parser.begin();
993 return args(in,builder) 1036 return args(in,builder)
994 ? parser.success( new FnCall( fn, ExpList.build(builder) ) ) 1037 ? parser.success( new FnCall( fn, ExpList.build(expList(builder)) ) )
995 : parser.failure((FnCall)null); 1038 : parser.failure((FnCall)null);
996 } 1039 }
997 1040
998 private boolean args(In in,List<Expressions> builder) throws ParseException { 1041 private boolean args(In in,List<ExpString> builder) throws ParseException {
999 parser.begin(); 1042 parser.begin();
1000 if( parser.match('(') ) { 1043 if( parser.match('(') ) {
1001 In inParens = in.parens(); 1044 In inParens = in.parens();
1002 Spaces(inParens); 1045 Spaces(inParens);
1003 ExpList(inParens,builder); // optional 1046 ExpList(inParens,builder); // optional
1006 Spaces(in); 1049 Spaces(in);
1007 return parser.success(); 1050 return parser.success();
1008 } 1051 }
1009 Expr exp = TableExpr(in); 1052 Expr exp = TableExpr(in);
1010 if( exp != null ) { 1053 if( exp != null ) {
1011 builder.add(exp); 1054 builder.add(new ExpString(exp));
1012 return parser.success(); 1055 return parser.success();
1013 } 1056 }
1014 String s = StringLiteral(in); 1057 String s = StringLiteral(in);
1015 if( s != null ) { 1058 if( s != null ) {
1016 builder.add( new ConstExpr(s) ); 1059 builder.add( new ExpString(new ConstExpr(s)) );
1017 return parser.success(); 1060 return parser.success();
1018 } 1061 }
1019 /* 1062 /*
1020 Expressions exps = TemplateExpressions(in); 1063 Expressions exps = TemplateExpressions(in);
1021 if( exps != null ) { 1064 if( exps != null ) {
1025 */ 1068 */
1026 return parser.failure(); 1069 return parser.failure();
1027 } 1070 }
1028 1071
1029 private Expressions ExpList(In in) throws ParseException { 1072 private Expressions ExpList(In in) throws ParseException {
1030 List<Expressions> builder = new ArrayList<Expressions>(); 1073 List<ExpString> builder = new ArrayList<ExpString>();
1031 return ExpList(in,builder) ? ExpList.build(builder) : null; 1074 return ExpList(in,builder) ? ExpList.build(expList(builder)) : null;
1032 } 1075 }
1033 1076
1034 private boolean ExpList(In in,List<Expressions> builder) throws ParseException { 1077 private ExpString ExpStringList(In in) throws ParseException {
1078 List<ExpString> builder = new ArrayList<ExpString>();
1079 return ExpList(in,builder) ? exp(builder) : null;
1080 }
1081
1082 private boolean ExpList(In in,List<ExpString> builder) throws ParseException {
1035 parser.begin(); 1083 parser.begin();
1036 Expressions exp = TemplateExpressions(in); 1084 Expressions exp = TemplateExpressions(in);
1037 if( exp != null ) { 1085 if( exp != null ) {
1038 builder.add(exp); 1086 builder.add(new ExpString(exp));
1039 return parser.success(); 1087 return parser.success();
1040 } 1088 }
1041 exp = exp(ExprZ(in)); 1089 ExpString es = ExprZ(in);
1042 if( exp==null ) 1090 if( es==null )
1043 return parser.failure(); 1091 return parser.failure();
1044 builder.add(exp); 1092 builder.add(es);
1045 while( parser.match(',') ) { 1093 while( parser.match(',') ) {
1046 Spaces(in); 1094 Spaces(in);
1047 exp = TemplateExpressions(in); 1095 exp = TemplateExpressions(in);
1048 if( exp != null ) { 1096 if( exp != null ) {
1049 builder.add(exp); 1097 builder.add(new ExpString(exp));
1050 return parser.success(); 1098 return parser.success();
1051 } 1099 }
1052 builder.add( exp(RequiredExpr(in)) ); 1100 builder.add( RequiredExpr(in) );
1053 } 1101 }
1054 return parser.success(); 1102 return parser.success();
1055 } 1103 }
1056 1104
1057 private Expr SubExpr(In in) throws ParseException { 1105 private Expr SubExpr(In in) throws ParseException {
1467 1515
1468 private static Expressions exp(ExpString expStr) { 1516 private static Expressions exp(ExpString expStr) {
1469 return expStr==null ? null : expStr.toExpressions(); 1517 return expStr==null ? null : expStr.toExpressions();
1470 } 1518 }
1471 1519
1520 private ExpString exp(List<ExpString> list) {
1521 switch(list.size()) {
1522 case 0:
1523 return new ExpString("null",true,false);
1524 case 1:
1525 return list.get(0).expr();
1526 default:
1527 int lastI = list.size() - 1;
1528 StringBuilder sb = new StringBuilder();
1529 sb.append( "new Object[]{" );
1530 for( int i=0; i<lastI; i++ ) {
1531 sb.append( list.get(i).expr().code ).append( ',' );
1532 }
1533 ExpString last = list.get(lastI);
1534 if( last.isExpr ) {
1535 sb.append( last.code ).append( '}' );
1536 return new ExpString(sb.toString(),false,false);
1537 } else {
1538 sb.append( '}' );
1539 String s = "$Luan.concatArgs(" + sb + "," + last.code + ")";
1540 return new ExpString(s,false,false);
1541 }
1542 }
1543 }
1544
1545 private static List<Expressions> expList(List<ExpString> esList) {
1546 List<Expressions> list = new ArrayList<Expressions>();
1547 for( ExpString es : esList ) {
1548 list.add(exp(es));
1549 }
1550 return list;
1551 }
1472 1552
1473 private static class StmtString { 1553 private static class StmtString {
1474 final String code; 1554 final String code;
1475 1555
1476 StmtString(Stmt stmt) { 1556 StmtString(Stmt stmt) {
1479 code = "$Luan.getStmt(" + i + ").eval($luan);\n"; 1559 code = "$Luan.getStmt(" + i + ").eval($luan);\n";
1480 } 1560 }
1481 1561
1482 StmtString(String code) { 1562 StmtString(String code) {
1483 this.code = code; 1563 this.code = code;
1564 if( code.contains("LuanParser") ) throw new RuntimeException("\n"+code);
1484 } 1565 }
1485 1566
1486 Stmt toStmt() { 1567 Stmt toStmt() {
1487 String className = "EXP" + ++classCounter; 1568 String className = "EXP" + ++classCounter;
1488 String classCode = "" 1569 String classCode = ""
1489 +"package luan.impl;\n" 1570 +"package luan.impl;\n"
1571 +"import luan.LuanFunction;\n"
1490 +"import luan.LuanException;\n" 1572 +"import luan.LuanException;\n"
1491 +"\n" 1573 +"\n"
1492 +"public class " + className +" implements Stmt {\n" 1574 +"public class " + className +" implements Stmt {\n"
1493 +" @Override public void eval(LuanStateImpl $luan) throws LuanException {\n" 1575 +" @Override public void eval(LuanStateImpl $luan) throws LuanException {\n"
1494 +" Object $cnd;\n" 1576 +" Object $cnd;\n"
1496 +" }\n" 1578 +" }\n"
1497 +"}\n" 1579 +"}\n"
1498 ; 1580 ;
1499 //System.out.println(code); 1581 //System.out.println(code);
1500 try { 1582 try {
1501 Class cls = LuanJavaCompiler.compile("luan.impl."+className,code,classCode); 1583 Class cls = LuanJavaCompiler.compile("luan.impl."+className,"code",classCode);
1502 return (Stmt)cls.newInstance(); 1584 return (Stmt)cls.newInstance();
1503 } catch(ClassNotFoundException e) { 1585 } catch(ClassNotFoundException e) {
1504 throw new RuntimeException(e); 1586 throw new RuntimeException(e);
1505 } catch(InstantiationException e) { 1587 } catch(InstantiationException e) {
1506 throw new RuntimeException(e); 1588 throw new RuntimeException(e);
1518 1600
1519 private static StmtString stmtStr(Stmt stmt) { 1601 private static StmtString stmtStr(Stmt stmt) {
1520 return stmt==null ? null : new StmtString(stmt); 1602 return stmt==null ? null : new StmtString(stmt);
1521 } 1603 }
1522 1604
1605
1606 private static class SettableString {
1607 final String code;
1608
1609 SettableString(Settable settable) {
1610 if( settable==null ) throw new NullPointerException();
1611 int i = $Luan.addSettable(settable);
1612 code = "$Luan.getSettable(" + i + ")";
1613 }
1614
1615 SettableString(String code) {
1616 this.code = code;
1617 }
1618
1619 }
1620
1523 } 1621 }