Mercurial Hosting > luan
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(); |