comparison core/src/luan/impl/LuanParser.java @ 663:b438a47196bc

finish compiling function blocks
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 07 Apr 2016 00:01:10 -0600
parents ee00a619eec1
children 71f8f5075df8
comparison
equal deleted inserted replaced
662:ee00a619eec1 663:b438a47196bc
172 if( exprs instanceof Expr ) 172 if( exprs instanceof Expr )
173 return (Expr)exprs; 173 return (Expr)exprs;
174 return new ExpressionsExpr(exprs); 174 return new ExpressionsExpr(exprs);
175 } 175 }
176 176
177 private FnDef newFnDef(int start,Stmt stmt) { 177 private FnDef newFnDef(int start,StmtString stmt) {
178 return new FnDef( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); 178 if( !stmt.hasReturn )
179 stmt = new StmtString( stmt.code + "return LuanFunction.NOTHING;\n" );
180 return new FnDef( toExpressions(stmt), frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
179 } 181 }
180 182
181 FnDef Expression() throws ParseException { 183 FnDef Expression() throws ParseException {
182 Spaces(In.NOTHING); 184 Spaces(In.NOTHING);
183 int start = parser.begin(); 185 int start = parser.begin();
184 ExpString expr = ExprZ(In.NOTHING); 186 ExpString expr = ExprZ(In.NOTHING);
185 if( expr != null && parser.endOfInput() ) { 187 if( expr != null && parser.endOfInput() ) {
186 String code = "luan.returnValues = " + expr.code + ";\n"; 188 String code = "return " + expr.code + ";\n";
187 Stmt stmt = stmt( new StmtString(code) ); 189 StmtString stmt = new StmtString(code);
188 return parser.success(newFnDef(start,stmt)); 190 return parser.success(newFnDef(start,stmt));
189 } 191 }
190 return parser.failure(null); 192 return parser.failure(null);
191 } 193 }
192 194
193 FnDef RequiredModule() throws ParseException { 195 FnDef RequiredModule() throws ParseException {
194 Spaces(In.NOTHING); 196 Spaces(In.NOTHING);
195 int start = parser.begin(); 197 int start = parser.begin();
196 frame.isVarArg = true; 198 frame.isVarArg = true;
197 Stmt stmt = stmt(RequiredBlock()); 199 StmtString stmt = RequiredBlock();
198 if( parser.endOfInput() ) 200 if( parser.endOfInput() )
199 return parser.success(newFnDef(start,stmt)); 201 return parser.success(newFnDef(start,stmt));
200 throw parser.exception(); 202 throw parser.exception();
201 } 203 }
202 204
203 private StmtString RequiredBlock() throws ParseException { 205 private StmtString RequiredBlock() throws ParseException {
204 StringBuilder stmts = new StringBuilder(); 206 StringBuilder stmts = new StringBuilder();
205 int stackStart = symbolsSize(); 207 int stackStart = symbolsSize();
206 Stmt(stmts); 208 boolean isReturn = Stmt(stmts);
207 while( StmtSep(stmts) ) { 209 while( !isReturn && StmtSep(stmts) ) {
208 Spaces(In.NOTHING); 210 Spaces(In.NOTHING);
209 Stmt(stmts); 211 isReturn = Stmt(stmts);
210 } 212 }
213 StmtSep(null);
214 Spaces(In.NOTHING);
211 int stackEnd = symbolsSize(); 215 int stackEnd = symbolsSize();
212 popSymbols( stackEnd - stackStart ); 216 popSymbols( stackEnd - stackStart );
213 if( stmts.length() == 0 ) 217 if( stmts.length() == 0 )
214 return EMPTY_STMT; 218 return EMPTY_STMT;
215 String code = stmts.toString(); 219 String code = stmts.toString();
219 + code 223 + code
220 +"} finally {\n" 224 +"} finally {\n"
221 +" luan.stackClear("+stackStart+","+stackEnd+");\n" 225 +" luan.stackClear("+stackStart+","+stackEnd+");\n"
222 +"}\n" 226 +"}\n"
223 ; 227 ;
224 return new StmtString(code); 228 StmtString stmt = new StmtString(code);
229 stmt.hasReturn = isReturn;
230 return stmt;
225 } 231 }
226 232
227 private boolean StmtSep(StringBuilder stmts) throws ParseException { 233 private boolean StmtSep(StringBuilder stmts) throws ParseException {
228 parser.begin(); 234 parser.begin();
229 if( parser.match( ';' ) ) 235 if( parser.match( ';' ) )
230 return parser.success(); 236 return parser.success();
231 if( EndOfLine() ) 237 if( EndOfLine() )
232 return parser.success(); 238 return parser.success();
233 parser.rollback(); 239 if( stmts != null ) {
234 StmtString stmt = TemplateStmt(); 240 // parser.rollback();
235 if( stmt != null ) { 241 StmtString stmt = TemplateStmt();
236 stmts.append(stmt.code); 242 if( stmt != null ) {
237 return parser.success(); 243 stmts.append(stmt.code);
244 return parser.success();
245 }
238 } 246 }
239 return parser.failure(); 247 return parser.failure();
240 } 248 }
241 249
242 private boolean EndOfLine() { 250 private boolean EndOfLine() {
243 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); 251 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' );
244 } 252 }
245 253
246 private void Stmt(StringBuilder stmts) throws ParseException { 254 private boolean Stmt(StringBuilder stmts) throws ParseException {
247 if( LocalStmt(stmts) ) 255 if( LocalStmt(stmts) )
248 return; 256 return false;
249 StmtString stmt; 257 StmtString stmt;
250 if( (stmt=ReturnStmt()) != null 258 if( (stmt=ReturnStmt()) != null ) {
251 || (stmt=FunctionStmt()) != null 259 stmts.append(stmt.code);
260 return true;
261 }
262 if( (stmt=FunctionStmt()) != null
252 || (stmt=LocalFunctionStmt()) != null 263 || (stmt=LocalFunctionStmt()) != null
253 || (stmt=BreakStmt()) != null 264 || (stmt=BreakStmt()) != null
254 || (stmt=ForStmt()) != null 265 || (stmt=ForStmt()) != null
255 || (stmt=DoStmt()) != null 266 || (stmt=DoStmt()) != null
256 || (stmt=WhileStmt()) != null 267 || (stmt=WhileStmt()) != null
259 || (stmt=SetStmt()) != null 270 || (stmt=SetStmt()) != null
260 || (stmt=ExpressionsStmt()) != null 271 || (stmt=ExpressionsStmt()) != null
261 ) { 272 ) {
262 stmts.append(stmt.code); 273 stmts.append(stmt.code);
263 } 274 }
275 return false;
264 } 276 }
265 277
266 private ExpString indexExpStr(ExpString exp1,ExpString exp2) { 278 private ExpString indexExpStr(ExpString exp1,ExpString exp2) {
267 String code = "luan.index(" + exp1.expr().code + "," + exp2.expr().code + ")"; 279 String code = "luan.index(" + exp1.expr().code + "," + exp2.expr().code + ")";
268 return new ExpString(code,true,false); 280 return new ExpString(code,true,false);
331 private StmtString ReturnStmt() throws ParseException { 343 private StmtString ReturnStmt() throws ParseException {
332 parser.begin(); 344 parser.begin();
333 if( !Keyword("return",In.NOTHING) ) 345 if( !Keyword("return",In.NOTHING) )
334 return parser.failure(null); 346 return parser.failure(null);
335 ExpString exprs = ExpStringList(In.NOTHING); 347 ExpString exprs = ExpStringList(In.NOTHING);
336 String code = "luan.returnValues = " + (exprs!=null ? exprs.code : "LuanFunction.NOTHING") + ";\n" 348 String code = "return " + (exprs!=null ? exprs.code : "LuanFunction.NOTHING") + ";\n";
337 +"return;\n";
338 return parser.success( new StmtString(code) ); 349 return parser.success( new StmtString(code) );
339 } 350 }
340 351
341 private StmtString FunctionStmt() throws ParseException { 352 private StmtString FunctionStmt() throws ParseException {
342 parser.begin(); 353 parser.begin();
866 Spaces(inParens); 877 Spaces(inParens);
867 frame.isVarArg = true; 878 frame.isVarArg = true;
868 } 879 }
869 RequiredMatch(')'); 880 RequiredMatch(')');
870 Spaces(in); 881 Spaces(in);
871 Stmt block = stmt(RequiredBlock()); 882 StmtString block = RequiredBlock();
872 RequiredKeyword("end",in); 883 RequiredKeyword("end",in);
873 FnDef fnDef = newFnDef(start,block); 884 FnDef fnDef = newFnDef(start,block);
874 frame = frame.parent; 885 frame = frame.parent;
875 return parser.success(fnDef); 886 return parser.success(fnDef);
876 } 887 }
1563 } 1574 }
1564 } 1575 }
1565 1576
1566 private static class StmtString { 1577 private static class StmtString {
1567 final String code; 1578 final String code;
1579 boolean hasReturn = false;
1568 /* 1580 /*
1569 StmtString(Stmt stmt) { 1581 StmtString(Stmt stmt) {
1570 if( stmt==null ) throw new NullPointerException(); 1582 if( stmt==null ) throw new NullPointerException();
1571 int i = LuanImpl.addStmt(stmt); 1583 int i = LuanImpl.addStmt(stmt);
1572 code = "LuanImpl.getStmt(" + i + ").eval(luan);\n"; 1584 code = "LuanImpl.getStmt(" + i + ").eval(luan);\n";
1612 private static Stmt stmt(StmtString stmtStr) { 1624 private static Stmt stmt(StmtString stmtStr) {
1613 return stmtStr==null ? null : stmtStr.toStmt(); 1625 return stmtStr==null ? null : stmtStr.toStmt();
1614 } 1626 }
1615 1627
1616 1628
1629 static Expressions toExpressions(StmtString stmt) {
1630 String className = "EXP" + ++classCounter;
1631 String classCode = ""
1632 +"package luan.impl;\n"
1633 +"import luan.Luan;\n"
1634 +"import luan.LuanFunction;\n"
1635 +"import luan.LuanException;\n"
1636 +"import luan.modules.PackageLuan;\n"
1637 +"\n"
1638 +"public class " + className +" implements Expressions {\n"
1639 +" @Override public Object eval(LuanStateImpl luan) throws LuanException {\n"
1640 +" Object t;\n"
1641 +" " + stmt.code
1642 +" }\n"
1643 +"}\n"
1644 ;
1645 try {
1646 Class cls = LuanJavaCompiler.compile("luan.impl."+className,"code",classCode);
1647 return (Expressions)cls.newInstance();
1648 } catch(ClassNotFoundException e) {
1649 throw new RuntimeException(e);
1650 } catch(InstantiationException e) {
1651 throw new RuntimeException(e);
1652 } catch(IllegalAccessException e) {
1653 throw new RuntimeException(e);
1654 }
1655 }
1656
1657
1617 private static class SettableString { 1658 private static class SettableString {
1618 final String code; 1659 final String code;
1619 1660
1620 SettableString(Settable settable) { 1661 SettableString(Settable settable) {
1621 if( settable==null ) throw new NullPointerException(); 1662 if( settable==null ) throw new NullPointerException();