Mercurial Hosting > luan
comparison core/src/luan/impl/LuanParser.java @ 670:58ebfec6178b
all luan now compiles
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 12 Apr 2016 01:05:57 -0600 |
parents | e320488819b6 |
children | 82f130eba7b0 |
comparison
equal
deleted
inserted
replaced
669:e320488819b6 | 670:58ebfec6178b |
---|---|
3 import java.util.Set; | 3 import java.util.Set; |
4 import java.util.HashSet; | 4 import java.util.HashSet; |
5 import java.util.Arrays; | 5 import java.util.Arrays; |
6 import java.util.List; | 6 import java.util.List; |
7 import java.util.ArrayList; | 7 import java.util.ArrayList; |
8 import java.util.Scanner; | |
9 import luan.Luan; | 8 import luan.Luan; |
10 import luan.LuanState; | 9 import luan.LuanState; |
11 import luan.LuanTable; | 10 import luan.LuanTable; |
12 import luan.modules.PackageLuan; | 11 import luan.modules.PackageLuan; |
13 | 12 |
14 | 13 |
15 final class LuanParser { | 14 final class LuanParser { |
16 | 15 |
17 private static final class Frame { | 16 private interface Sym { |
17 public ExpString exp(); | |
18 } | |
19 | |
20 private int symCounter = 0; | |
21 | |
22 private class LocalSym implements Sym { | |
23 final String name; | |
24 final String javaName; | |
25 String pointer = null; | |
26 | |
27 LocalSym(String name) { | |
28 this.name = name; | |
29 this.javaName = name + "_" + (++symCounter); | |
30 } | |
31 | |
32 String declaration() { | |
33 if( pointer==null ) | |
34 return "Object " + javaName + " = null;\n"; | |
35 else | |
36 return "final Pointer " + javaName + " = " + pointer + ";\n"; | |
37 } | |
38 | |
39 String ref() { | |
40 if( pointer==null ) | |
41 return javaName; | |
42 else | |
43 return javaName + ".o"; | |
44 } | |
45 | |
46 @Override public ExpString exp() { | |
47 ExpString exp = new ExpString(true,false); | |
48 exp.list.add( new Object() { | |
49 @Override public String toString() { | |
50 return ref(); | |
51 } | |
52 } ); | |
53 return exp; | |
54 } | |
55 } | |
56 | |
57 private class UpSym implements Sym { | |
58 final String name; | |
59 final int i; | |
60 final String value; | |
61 | |
62 UpSym(String name,int i,String value) { | |
63 this.name = name; | |
64 this.i = i; | |
65 this.value = value; | |
66 } | |
67 | |
68 String init() { | |
69 return "upValues[" + i + "] = " + value + ";\n"; | |
70 } | |
71 | |
72 String ref() { | |
73 return "upValues[" + i + "].o"; | |
74 } | |
75 | |
76 @Override public ExpString exp() { | |
77 ExpString exp = new ExpString(true,false); | |
78 exp.list.add( new Object() { | |
79 @Override public String toString() { | |
80 return ref(); | |
81 } | |
82 } ); | |
83 return exp; | |
84 } | |
85 } | |
86 | |
87 private final class Frame { | |
18 final Frame parent; | 88 final Frame parent; |
19 final List<String> symbols = new ArrayList<String>(); | 89 final List<LocalSym> symbols = new ArrayList<LocalSym>(); |
20 int stackSize = 0; | |
21 int loops = 0; | 90 int loops = 0; |
22 boolean isVarArg = false; | 91 boolean isVarArg = false; |
23 final List<String> upValueSymbols = new ArrayList<String>(); | 92 final List<UpSym> upValueSymbols = new ArrayList<UpSym>(); |
24 final List<UpValue.Getter> upValueGetters = new ArrayList<UpValue.Getter>(); | 93 |
25 | 94 Frame() { |
26 Frame(LuanTable java) { | |
27 this.parent = null; | 95 this.parent = null; |
28 upValueSymbols.add(JAVA); | |
29 upValueGetters.add(new UpValue.ValueGetter(java)); | |
30 } | 96 } |
31 | 97 |
32 Frame(Frame parent) { | 98 Frame(Frame parent) { |
33 this.parent = parent; | 99 this.parent = parent; |
34 if( upValueIndex(JAVA) != 0 ) | 100 } |
35 throw new RuntimeException(); | 101 |
36 } | 102 LocalSym addLocalSym(String name) { |
37 | 103 LocalSym sym = new LocalSym(name); |
38 int stackIndex(String name) { | 104 symbols.add(sym); |
105 return sym; | |
106 } | |
107 | |
108 UpSym addUpSym(String name,String value) { | |
109 UpSym sym = new UpSym( name, upValueSymbols.size(), value ); | |
110 upValueSymbols.add(sym); | |
111 return sym; | |
112 } | |
113 | |
114 LocalSym getLocalSym(String name) { | |
39 int i = symbols.size(); | 115 int i = symbols.size(); |
40 while( --i >= 0 ) { | 116 while( --i >= 0 ) { |
41 if( symbols.get(i).equals(name) ) | 117 LocalSym sym = symbols.get(i); |
42 return i; | 118 if( sym.name.equals(name) ) |
43 } | 119 return sym; |
44 return -1; | 120 } |
45 } | 121 return null; |
46 | 122 } |
47 int upValueIndex(String name) { | 123 |
48 int i = upValueSymbols.size(); | 124 UpSym getUpSym(String name) { |
49 while( --i >= 0 ) { | 125 for( UpSym upSym : upValueSymbols ) { |
50 if( upValueSymbols.get(i).equals(name) ) | 126 if( upSym.name.equals(name) ) |
51 return i; | 127 return upSym; |
52 } | 128 } |
53 if( parent==null ) | 129 for( Frame f=parent; f!=null; f=f.parent ) { |
54 return -1; | 130 LocalSym sym = f.getLocalSym(name); |
55 i = parent.stackIndex(name); | 131 if( sym != null ) { |
56 if( i != -1 ) { | 132 sym.pointer = "new Pointer()"; |
57 upValueGetters.add(new UpValue.StackGetter(i)); | 133 return addUpSym(name,sym.javaName); |
58 } else { | 134 } |
59 i = parent.upValueIndex(name); | 135 } |
60 if( i == -1 ) | 136 return null; |
61 return -1; | 137 } |
62 upValueGetters.add(new UpValue.NestedGetter(i)); | 138 |
63 } | 139 Sym getSym(String name) { |
64 upValueSymbols.add(name); | 140 Sym sym = getLocalSym(name); |
65 return upValueSymbols.size() - 1; | 141 return sym != null ? sym : getUpSym(name); |
66 } | 142 } |
67 | 143 |
68 void addUpValueGetter(String name,UpValue.Getter upValueGetter) { | |
69 upValueSymbols.add(name); | |
70 upValueGetters.add(upValueGetter); | |
71 } | |
72 } | 144 } |
73 | 145 |
74 private static class In { | 146 private static class In { |
75 static final In NOTHING = new In(false,false); | 147 static final In NOTHING = new In(false,false); |
76 | 148 |
89 In template() { | 161 In template() { |
90 return template ? this : new In(false,true); | 162 return template ? this : new In(false,true); |
91 } | 163 } |
92 } | 164 } |
93 | 165 |
94 private static final String JAVA = "-JAVA-"; // inaccessible from Luan | |
95 private static final String _ENV = "_ENV"; | |
96 private static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0]; | |
97 | |
98 // final LuanSource source; | 166 // final LuanSource source; |
99 private Frame frame; | 167 private Frame frame; |
100 private final Parser parser; | 168 private final Parser parser; |
101 | 169 private final StmtString top = new StmtString(); |
102 LuanParser(String sourceName,String sourceText,LuanTable env) { | 170 |
171 LuanParser(String sourceName,String sourceText) { | |
103 // this.source = source; | 172 // this.source = source; |
104 this.frame = new Frame( env!=null ? env : new LuanTable() ); | 173 this.frame = new Frame(); |
105 this.parser = new Parser(sourceName,sourceText); | 174 this.parser = new Parser(sourceName,sourceText); |
106 if( env != null ) | 175 } |
107 addVar(_ENV,env); | 176 |
108 } | 177 void addVar(String name) { |
109 | 178 UpSym upSym = frame.addUpSym( "-ADDED-" ,"new Pointer()"); |
110 void addVar(String name,Object value) { | 179 if( name != null ) { |
111 frame.addUpValueGetter(name,new UpValue.ValueGetter(value)); | 180 LocalSym sym = frame.addLocalSym( name ); |
112 } | 181 sym.pointer = "upValues[" + upSym.i + "]"; |
113 | 182 top.list.add( sym.declaration() ); |
114 private List<String> symbols() { | 183 } |
115 return frame.symbols; | |
116 } | 184 } |
117 | 185 |
118 private int symbolsSize() { | 186 private int symbolsSize() { |
119 return frame.symbols.size(); | 187 return frame.symbols.size(); |
120 } | 188 } |
121 | 189 |
122 private void addSymbol(String name) { | 190 private void addSymbol(String name,StmtString stmt) { |
123 frame.symbols.add(name); | 191 final LocalSym sym = frame.addLocalSym(name); |
124 if( frame.stackSize < symbolsSize() ) | 192 stmt.list.add( new Object() { |
125 frame.stackSize = symbolsSize(); | 193 @Override public String toString() { |
126 } | 194 return sym.declaration(); |
127 | 195 } |
128 private void addSymbols(List<String> names) { | 196 } ); |
129 frame.symbols.addAll(names); | 197 } |
130 if( frame.stackSize < symbolsSize() ) | 198 |
131 frame.stackSize = symbolsSize(); | 199 private void addSymbols(List<String> names,StmtString stmt) { |
132 } | 200 for( String name : names ) { |
133 | 201 addSymbol(name,stmt); |
134 private int stackIndex(String name) { | 202 } |
135 return frame.stackIndex(name); | 203 } |
204 | |
205 private Sym getSym(String name) { | |
206 return frame.getSym(name); | |
136 } | 207 } |
137 | 208 |
138 private void popSymbols(int n) { | 209 private void popSymbols(int n) { |
139 List<String> symbols = frame.symbols; | 210 List<LocalSym> symbols = frame.symbols; |
140 while( n-- > 0 ) { | 211 while( n-- > 0 ) { |
141 symbols.remove(symbols.size()-1); | 212 symbols.remove(symbols.size()-1); |
142 } | 213 } |
143 } | |
144 | |
145 private int upValueIndex(String name) { | |
146 return frame.upValueIndex(name); | |
147 } | 214 } |
148 | 215 |
149 private void incLoops() { | 216 private void incLoops() { |
150 frame.loops++; | 217 frame.loops++; |
151 } | 218 } |
175 } | 242 } |
176 | 243 |
177 private Class newFnClass(int start,StmtString stmt) { | 244 private Class newFnClass(int start,StmtString stmt) { |
178 if( !stmt.hasReturn ) | 245 if( !stmt.hasReturn ) |
179 stmt.list.add( "return LuanFunction.NOTHING;\n" ); | 246 stmt.list.add( "return LuanFunction.NOTHING;\n" ); |
180 return toFnClass( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); | 247 return toFnClass( stmt, frame.upValueSymbols ); |
181 } | 248 } |
182 | 249 |
183 private ExpString newFnExpStr(int start,StmtString stmt) { | 250 private ExpString newFnExpStr(int start,StmtString stmt) { |
184 if( !stmt.hasReturn ) | 251 if( !stmt.hasReturn ) |
185 stmt.list.add( "return LuanFunction.NOTHING;\n" ); | 252 stmt.list.add( "return LuanFunction.NOTHING;\n" ); |
186 return toFnExpStr( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); | 253 return toFnExpStr( stmt, frame.upValueSymbols ); |
187 } | 254 } |
188 | 255 |
189 Class Expression() throws ParseException { | 256 Class Expression() throws ParseException { |
190 Spaces(In.NOTHING); | 257 Spaces(In.NOTHING); |
191 int start = parser.begin(); | 258 int start = parser.begin(); |
192 ExpString expr = ExprZ(In.NOTHING); | 259 ExpString expr = ExprZ(In.NOTHING); |
193 if( expr != null && parser.endOfInput() ) { | 260 if( expr != null && parser.endOfInput() ) { |
194 StmtString stmt = new StmtString(); | 261 top.list.add( "return " ); |
195 stmt.list.add( "return " ); | 262 top.list.addAll( expr.list ); |
196 stmt.list.addAll( expr.list ); | 263 top.list.add( ";\n" ); |
197 stmt.list.add( ";\n" ); | 264 top.hasReturn = true; |
198 stmt.hasReturn = true; | 265 return parser.success(newFnClass(start,top)); |
199 return parser.success(newFnClass(start,stmt)); | |
200 } | 266 } |
201 return parser.failure(null); | 267 return parser.failure(null); |
202 } | 268 } |
203 | 269 |
204 Class RequiredModule() throws ParseException { | 270 Class RequiredModule() throws ParseException { |
205 Spaces(In.NOTHING); | 271 Spaces(In.NOTHING); |
206 int start = parser.begin(); | 272 int start = parser.begin(); |
207 frame.isVarArg = true; | 273 frame.isVarArg = true; |
208 StmtString stmt = RequiredBlock(); | 274 top.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" ); |
275 StmtString block = RequiredBlock(); | |
276 top.list.addAll( block.list ); | |
277 top.hasReturn = block.hasReturn; | |
209 if( parser.endOfInput() ) | 278 if( parser.endOfInput() ) |
210 return parser.success(newFnClass(start,stmt)); | 279 return parser.success(newFnClass(start,top)); |
211 throw parser.exception(); | 280 throw parser.exception(); |
212 } | 281 } |
213 | 282 |
214 private StmtString RequiredBlock() throws ParseException { | 283 private StmtString RequiredBlock() throws ParseException { |
215 StmtString stmts = new StmtString(); | 284 StmtString stmts = new StmtString(); |
221 } | 290 } |
222 while( StmtSep(null) ) | 291 while( StmtSep(null) ) |
223 Spaces(In.NOTHING); | 292 Spaces(In.NOTHING); |
224 int stackEnd = symbolsSize(); | 293 int stackEnd = symbolsSize(); |
225 popSymbols( stackEnd - stackStart ); | 294 popSymbols( stackEnd - stackStart ); |
226 if( stmts.list.isEmpty() ) | |
227 return stmts; | |
228 String code = stmts.toString(); | |
229 if( stackStart < stackEnd ) { | |
230 stmts.list.add( 0, "try {\n" ); | |
231 stmts.list.add( "" | |
232 +"} finally {\n" | |
233 +" luan.stackClear("+stackStart+","+stackEnd+");\n" | |
234 +"}\n" | |
235 ); | |
236 } | |
237 stmts.hasReturn = isReturn; | 295 stmts.hasReturn = isReturn; |
238 return stmts; | 296 return stmts; |
239 } | 297 } |
240 | 298 |
241 private boolean StmtSep(StmtString stmts) throws ParseException { | 299 private boolean StmtSep(StmtString stmts) throws ParseException { |
258 private boolean EndOfLine() { | 316 private boolean EndOfLine() { |
259 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); | 317 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); |
260 } | 318 } |
261 | 319 |
262 private boolean Stmt(StmtString stmts) throws ParseException { | 320 private boolean Stmt(StmtString stmts) throws ParseException { |
263 if( LocalStmt(stmts) ) | |
264 return false; | |
265 StmtString stmt; | 321 StmtString stmt; |
266 if( (stmt=ReturnStmt()) != null ) { | 322 if( (stmt=ReturnStmt()) != null ) { |
267 stmts.list.addAll(stmt.list); | 323 stmts.list.addAll(stmt.list); |
268 return true; | 324 return true; |
269 } | 325 } |
270 if( (stmt=FunctionStmt()) != null | 326 if( (stmt=FunctionStmt()) != null |
327 || (stmt=LocalStmt()) != null | |
271 || (stmt=LocalFunctionStmt()) != null | 328 || (stmt=LocalFunctionStmt()) != null |
272 || (stmt=BreakStmt()) != null | 329 || (stmt=BreakStmt()) != null |
273 || (stmt=ForStmt()) != null | 330 || (stmt=ForStmt()) != null |
274 || (stmt=DoStmt()) != null | 331 || (stmt=DoStmt()) != null |
275 || (stmt=WhileStmt()) != null | 332 || (stmt=WhileStmt()) != null |
385 | 442 |
386 private StmtString LocalFunctionStmt() throws ParseException { | 443 private StmtString LocalFunctionStmt() throws ParseException { |
387 parser.begin(); | 444 parser.begin(); |
388 if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) ) | 445 if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) ) |
389 return parser.failure(null); | 446 return parser.failure(null); |
447 StmtString stmt = new StmtString(); | |
390 String name = RequiredName(In.NOTHING); | 448 String name = RequiredName(In.NOTHING); |
391 addSymbol( name ); | 449 addSymbol( name, stmt ); |
392 ExpString fnDef = RequiredFunction(In.NOTHING); | 450 ExpString fnDef = RequiredFunction(In.NOTHING); |
451 stmt.list.addAll( nameVar(name).set( fnDef ).list ); | |
452 /* | |
393 Settable s = new SetLocalVar(symbolsSize()-1); | 453 Settable s = new SetLocalVar(symbolsSize()-1); |
394 StmtString stmt = new StmtString(); | 454 StmtString stmt = new StmtString(); |
395 stmt.list.add( settableToString(s) ); | 455 stmt.list.add( settableToString(s) ); |
396 stmt.list.add( ".set(luan," ); | 456 stmt.list.add( ".set(luan," ); |
397 stmt.list.addAll( fnDef.list ); | 457 stmt.list.addAll( fnDef.list ); |
398 stmt.list.add( ");\n" ); | 458 stmt.list.add( ");\n" ); |
459 */ | |
399 return parser.success( stmt ); | 460 return parser.success( stmt ); |
400 } | 461 } |
401 | 462 |
402 private StmtString BreakStmt() throws ParseException { | 463 private StmtString BreakStmt() throws ParseException { |
403 parser.begin(); | 464 parser.begin(); |
421 if( !Keyword("in",In.NOTHING) ) | 482 if( !Keyword("in",In.NOTHING) ) |
422 return parser.failure(null); | 483 return parser.failure(null); |
423 ExpString expr = RequiredExpr(In.NOTHING).expr(); | 484 ExpString expr = RequiredExpr(In.NOTHING).expr(); |
424 RequiredKeyword("do",In.NOTHING); | 485 RequiredKeyword("do",In.NOTHING); |
425 | 486 |
426 SetLocalVar[] vars = new SetLocalVar[names.size()]; | |
427 for( int i=0; i<vars.length; i++ ) { | |
428 vars[i] = new SetLocalVar(stackStart+i); | |
429 } | |
430 String varsStr = varsToString(vars); | |
431 | |
432 ExpString firstVar = new ExpString(new GetLocalVar(stackStart)); | |
433 addSymbols(names); | |
434 StmtString loop = RequiredLoopBlock(); | |
435 RequiredKeyword("end",In.NOTHING); | |
436 String fnVar = "fn"+ ++forCounter; | 487 String fnVar = "fn"+ ++forCounter; |
488 ExpString fnExp = new ExpString(false,false); | |
489 fnExp.list.add( fnVar + ".call(luan)" ); | |
437 StmtString stmt = new StmtString(); | 490 StmtString stmt = new StmtString(); |
438 stmt.list.add( "" | 491 stmt.list.add( "" |
439 +"try {\n" | |
440 +"LuanFunction "+fnVar+" = Luan.checkFunction(" | 492 +"LuanFunction "+fnVar+" = Luan.checkFunction(" |
441 ); | 493 ); |
442 stmt.list.addAll( expr.list ); | 494 stmt.list.addAll( expr.list ); |
443 stmt.list.add( "" | 495 stmt.list.add( ");\n" ); |
444 + ");\n" | 496 stmt.list.add( "while(true) {\n" ); |
445 +"while(true) {\n" | 497 List<Var> vars = new ArrayList<Var>(); |
446 +"for( int i="+stackStart+"; i<"+symbolsSize()+"; i++ ) {\n" | 498 for( String name : names ) { |
447 +"luan.stackSet(i,null);\n" | 499 addSymbol(name, stmt); |
448 +"}\n" | 500 vars.add(nameVar(name)); |
449 +"LuanImpl.set(luan," + varsStr + ", "+fnVar+".call(luan) );\n" | 501 } |
450 +"if( " | 502 ExpString firstVar = vars.get(0).exp(); |
451 ); | 503 stmt.list.addAll( makeSetStmt(vars,fnExp).list ); |
504 stmt.list.add( "if( " ); | |
452 stmt.list.addAll( firstVar.list ); | 505 stmt.list.addAll( firstVar.list ); |
453 stmt.list.add( "==null ) break;\n" ); | 506 stmt.list.add( "==null ) break;\n" ); |
507 StmtString loop = RequiredLoopBlock(); | |
508 RequiredKeyword("end",In.NOTHING); | |
454 stmt.list.addAll( loop.list ); | 509 stmt.list.addAll( loop.list ); |
455 stmt.list.add( "" | 510 stmt.list.add( "}\n" ); |
456 +"}" | |
457 +"} finally {\n" | |
458 +"luan.stackClear("+stackStart+","+symbolsSize()+");\n" | |
459 +"}\n" | |
460 ); | |
461 popSymbols( symbolsSize() - stackStart ); | 511 popSymbols( symbolsSize() - stackStart ); |
462 return parser.success(stmt); | 512 return parser.success(stmt); |
463 } | 513 } |
464 | 514 |
465 private StmtString DoStmt() throws ParseException { | 515 private StmtString DoStmt() throws ParseException { |
469 StmtString stmt = RequiredBlock(); | 519 StmtString stmt = RequiredBlock(); |
470 RequiredKeyword("end",In.NOTHING); | 520 RequiredKeyword("end",In.NOTHING); |
471 return parser.success(stmt); | 521 return parser.success(stmt); |
472 } | 522 } |
473 | 523 |
474 private boolean LocalStmt(StmtString stmts) throws ParseException { | 524 private StmtString LocalStmt() throws ParseException { |
475 parser.begin(); | 525 parser.begin(); |
476 if( !Keyword("local",In.NOTHING) ) | 526 if( !Keyword("local",In.NOTHING) ) |
477 return parser.failure(); | 527 return parser.failure(null); |
478 List<String> names = NameList(In.NOTHING); | 528 List<String> names = NameList(In.NOTHING); |
479 if( names==null ) { | 529 if( names==null ) { |
480 if( Keyword("function",In.NOTHING) ) | 530 if( Keyword("function",In.NOTHING) ) |
481 return parser.failure(); // handled later | 531 return parser.failure(null); // handled later |
482 throw parser.exception("Invalid local statement"); | 532 throw parser.exception("Invalid local statement"); |
483 } | 533 } |
534 StmtString stmt = new StmtString(); | |
535 addSymbols(names,stmt); | |
484 if( parser.match( '=' ) ) { | 536 if( parser.match( '=' ) ) { |
485 Spaces(In.NOTHING); | 537 Spaces(In.NOTHING); |
486 ExpString values = ExpStringList(In.NOTHING); | 538 ExpString values = ExpStringList(In.NOTHING); |
487 if( values==null ) | 539 if( values==null ) |
488 throw parser.exception("Expressions expected"); | 540 throw parser.exception("Expressions expected"); |
489 SetLocalVar[] vars = new SetLocalVar[names.size()]; | 541 List<Var> vars = new ArrayList<Var>(); |
490 int stackStart = symbolsSize(); | 542 for( String name : names ) { |
491 for( int i=0; i<vars.length; i++ ) { | 543 vars.add(nameVar(name)); |
492 vars[i] = new SetLocalVar(stackStart+i); | 544 } |
493 } | 545 stmt.list.addAll( makeSetStmt(vars,values).list ); |
494 String varsStr = varsToString(vars); | 546 } |
495 stmts.list.add( "LuanImpl.set(luan," + varsStr + "," ); | 547 return parser.success(stmt); |
496 stmts.list.addAll( values.list ); | |
497 stmts.list.add( ");\n" ); | |
498 } | |
499 addSymbols(names); | |
500 return parser.success(); | |
501 } | 548 } |
502 | 549 |
503 private List<String> RequiredNameList(In in) throws ParseException { | 550 private List<String> RequiredNameList(In in) throws ParseException { |
504 parser.begin(); | 551 parser.begin(); |
505 List<String> names = NameList(in); | 552 List<String> names = NameList(in); |
623 Spaces(In.NOTHING); | 670 Spaces(In.NOTHING); |
624 ExpString values = ExpStringList(In.NOTHING); | 671 ExpString values = ExpStringList(In.NOTHING); |
625 if( values==null ) | 672 if( values==null ) |
626 // throw parser.exception("Expressions expected"); | 673 // throw parser.exception("Expressions expected"); |
627 return parser.failure(null); | 674 return parser.failure(null); |
675 return parser.success( makeSetStmt(vars,values) ); | |
676 } | |
677 | |
678 private StmtString makeSetStmt(List<Var> vars,ExpString values) throws ParseException { | |
628 int n = vars.size(); | 679 int n = vars.size(); |
629 if( n == 1 ) | 680 if( n == 1 ) |
630 return parser.success( vars.get(0).set(values) ); | 681 return vars.get(0).set(values); |
631 StmtString stmt = new StmtString(); | 682 StmtString stmt = new StmtString(); |
632 stmt.list.add( "t = " ); | 683 stmt.list.add( "t = " ); |
633 stmt.list.addAll( values.list ); | 684 stmt.list.addAll( values.list ); |
634 stmt.list.add( ";\n" ); | 685 stmt.list.add( ";\n" ); |
635 ExpString t = new ExpString(true,false); | 686 ExpString t = new ExpString(values.isExpr,false); |
636 t.list.add( "t" ); | 687 t.list.add( "t" ); |
637 stmt.list.addAll( vars.get(0).set(t).list ); | 688 stmt.list.addAll( vars.get(0).set(t).list ); |
638 for( int i=1; i<n; i++ ) { | 689 for( int i=1; i<n; i++ ) { |
639 t.list.clear(); | 690 t.list.clear(); |
640 t.list.add( "LuanImpl.pick(t,"+i+")" ); | 691 t.list.add( "LuanImpl.pick(t,"+i+")" ); |
641 stmt.list.addAll( vars.get(i).set(t).list ); | 692 stmt.list.addAll( vars.get(i).set(t).list ); |
642 } | 693 } |
643 return parser.success( stmt ); | 694 return stmt; |
644 } | 695 } |
645 | 696 /* |
646 private static String varsToString(Settable[] vars) { | 697 private static String varsToString(Settable[] vars) { |
647 StringBuilder sb = new StringBuilder(); | 698 StringBuilder sb = new StringBuilder(); |
648 sb.append( "new Settable[]{" ); | 699 sb.append( "new Settable[]{" ); |
649 for( Settable v : vars ) { | 700 for( Settable v : vars ) { |
650 sb.append( settableToString(v) ).append( ',' ); | 701 sb.append( settableToString(v) ).append( ',' ); |
651 } | 702 } |
652 sb.append( "}" ); | 703 sb.append( "}" ); |
653 return sb.toString(); | 704 return sb.toString(); |
654 } | 705 } |
655 | 706 */ |
656 private StmtString ExpressionsStmt() throws ParseException { | 707 private StmtString ExpressionsStmt() throws ParseException { |
657 parser.begin(); | 708 parser.begin(); |
658 ExpString exp = ExprZ(In.NOTHING); | 709 ExpString exp = ExprZ(In.NOTHING); |
659 if( exp != null && exp.isStmt ) { | 710 if( exp != null && exp.isStmt ) { |
660 StmtString stmt = new StmtString(); | 711 StmtString stmt = new StmtString(); |
967 return parser.success(exp1); | 1018 return parser.success(exp1); |
968 } | 1019 } |
969 | 1020 |
970 private ExpString SingleExpr(In in) throws ParseException { | 1021 private ExpString SingleExpr(In in) throws ParseException { |
971 parser.begin(); | 1022 parser.begin(); |
972 ExpString es = FunctionExpr(in); | 1023 ExpString exp = FunctionExpr(in); |
973 if( es != null ) | |
974 return parser.success(es); | |
975 es = VarExp(in); | |
976 if( es != null ) | |
977 return parser.success(es); | |
978 Expressions exp = VarArgs(in); | |
979 if( exp != null ) | 1024 if( exp != null ) |
980 return parser.success(new ExpString(exp)); | 1025 return parser.success(exp); |
1026 exp = VarExp(in); | |
1027 if( exp != null ) | |
1028 return parser.success(exp); | |
1029 exp = VarArgs(in); | |
1030 if( exp != null ) | |
1031 return parser.success(exp); | |
981 return parser.failure(null); | 1032 return parser.failure(null); |
982 } | 1033 } |
983 | 1034 |
984 private ExpString FunctionExpr(In in) throws ParseException { | 1035 private ExpString FunctionExpr(In in) throws ParseException { |
985 if( !Keyword("function",in) ) | 1036 if( !Keyword("function",in) ) |
991 int start = parser.begin(); | 1042 int start = parser.begin(); |
992 RequiredMatch('('); | 1043 RequiredMatch('('); |
993 In inParens = in.parens(); | 1044 In inParens = in.parens(); |
994 Spaces(inParens); | 1045 Spaces(inParens); |
995 frame = new Frame(frame); | 1046 frame = new Frame(frame); |
1047 StmtString stmt = new StmtString(); | |
996 List<String> names = NameList(in); | 1048 List<String> names = NameList(in); |
997 if( names != null ) { | 1049 if( names != null ) { |
998 addSymbols(names); | 1050 addSymbols(names,stmt); |
1051 List<Var> vars = new ArrayList<Var>(); | |
1052 for( String name : names ) { | |
1053 vars.add(nameVar(name)); | |
1054 } | |
1055 ExpString args = new ExpString(false,false); | |
1056 args.list.add( "args" ); | |
1057 stmt.list.addAll( makeSetStmt(vars,args).list ); | |
999 if( parser.match(',') ) { | 1058 if( parser.match(',') ) { |
1000 Spaces(inParens); | 1059 Spaces(inParens); |
1001 if( !parser.match("...") ) | 1060 if( !parser.match("...") ) |
1002 throw parser.exception(); | 1061 throw parser.exception(); |
1003 Spaces(inParens); | 1062 Spaces(inParens); |
1004 frame.isVarArg = true; | 1063 frame.isVarArg = true; |
1064 stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args," + vars.size() + ");\n" ); | |
1005 } | 1065 } |
1006 } else if( parser.match("...") ) { | 1066 } else if( parser.match("...") ) { |
1007 Spaces(inParens); | 1067 Spaces(inParens); |
1008 frame.isVarArg = true; | 1068 frame.isVarArg = true; |
1069 stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" ); | |
1009 } | 1070 } |
1010 RequiredMatch(')'); | 1071 RequiredMatch(')'); |
1011 Spaces(in); | 1072 Spaces(in); |
1012 StmtString block = RequiredBlock(); | 1073 StmtString block = RequiredBlock(); |
1074 stmt.list.addAll( block.list ); | |
1075 stmt.hasReturn = block.hasReturn; | |
1013 RequiredKeyword("end",in); | 1076 RequiredKeyword("end",in); |
1014 ExpString fnDef = newFnExpStr(start,block); | 1077 ExpString fnDef = newFnExpStr(start,stmt); |
1015 frame = frame.parent; | 1078 frame = frame.parent; |
1016 return parser.success(fnDef); | 1079 return parser.success(fnDef); |
1017 } | 1080 } |
1018 | 1081 |
1019 private VarArgs VarArgs(In in) throws ParseException { | 1082 private ExpString VarArgs(In in) throws ParseException { |
1020 parser.begin(); | 1083 parser.begin(); |
1021 if( !frame.isVarArg || !parser.match("...") ) | 1084 if( !frame.isVarArg || !parser.match("...") ) |
1022 return parser.failure(null); | 1085 return parser.failure(null); |
1023 Spaces(in); | 1086 Spaces(in); |
1024 return parser.success( new VarArgs() ); | 1087 ExpString exp = new ExpString(false,false); |
1088 exp.list.add("varArgs"); | |
1089 return parser.success(exp); | |
1025 } | 1090 } |
1026 | 1091 |
1027 private ExpString TableExpr(In in) throws ParseException { | 1092 private ExpString TableExpr(In in) throws ParseException { |
1028 parser.begin(); | 1093 parser.begin(); |
1029 if( !parser.match('{') ) | 1094 if( !parser.match('{') ) |
1140 // public Settable settable() throws ParseException; | 1205 // public Settable settable() throws ParseException; |
1141 public boolean isSettable(); | 1206 public boolean isSettable(); |
1142 public StmtString set(ExpString val) throws ParseException; | 1207 public StmtString set(ExpString val) throws ParseException; |
1143 } | 1208 } |
1144 | 1209 |
1145 private Expr env() { | 1210 private ExpString env() { |
1146 int index = stackIndex(_ENV); | 1211 Sym sym = getSym("_ENV"); |
1147 if( index != -1 ) | 1212 if( sym != null ) |
1148 return new GetLocalVar(index); | 1213 return sym.exp(); |
1149 index = upValueIndex(_ENV); | |
1150 if( index != -1 ) | |
1151 return new GetUpVar(index); | |
1152 return null; | 1214 return null; |
1153 } | 1215 } |
1154 | 1216 |
1155 private Var nameVar(final String name) { | 1217 private Var nameVar(final String name) { |
1156 return new Var() { | 1218 return new Var() { |
1157 | 1219 |
1158 public ExpString exp() throws ParseException { | 1220 public ExpString exp() throws ParseException { |
1159 int index = stackIndex(name); | 1221 Sym sym = getSym(name); |
1160 if( index != -1 ) | 1222 if( sym != null ) |
1161 return new ExpString(new GetLocalVar(index)); | 1223 return sym.exp(); |
1162 index = upValueIndex(name); | 1224 ExpString envExpr = env(); |
1163 if( index != -1 ) | |
1164 return new ExpString(new GetUpVar(index)); | |
1165 Expr envExpr = env(); | |
1166 if( envExpr != null ) | 1225 if( envExpr != null ) |
1167 return indexExpStr( new ExpString(envExpr), constExpStr(name) ); | 1226 return indexExpStr( envExpr, constExpStr(name) ); |
1168 parser.failure(null); | 1227 parser.failure(null); |
1169 throw parser.exception("name '"+name+"' not defined"); | 1228 throw parser.exception("name '"+name+"' not defined"); |
1170 } | 1229 } |
1171 | 1230 |
1172 public boolean isSettable() { | 1231 public boolean isSettable() { |
1173 return true; | 1232 return true; |
1174 } | 1233 } |
1175 | 1234 /* |
1176 private Settable settable() throws ParseException { | 1235 private Settable settable() throws ParseException { |
1177 int index = stackIndex(name); | 1236 int index = stackIndex(name); |
1178 if( index != -1 ) | 1237 if( index != -1 ) |
1179 return new SetLocalVar(index); | 1238 return new SetLocalVar(index); |
1180 index = upValueIndex(name); | 1239 index = upValueIndex(name); |
1184 if( envExpr != null ) | 1243 if( envExpr != null ) |
1185 return new SetTableEntry( envExpr, new ConstExpr(name) ); | 1244 return new SetTableEntry( envExpr, new ConstExpr(name) ); |
1186 parser.failure(null); | 1245 parser.failure(null); |
1187 throw parser.exception("name '"+name+"' not defined"); | 1246 throw parser.exception("name '"+name+"' not defined"); |
1188 } | 1247 } |
1189 | 1248 */ |
1190 public StmtString set(ExpString val) throws ParseException { | 1249 public StmtString set(ExpString val) throws ParseException { |
1191 StmtString stmt = new StmtString(); | 1250 Sym sym = getSym(name); |
1192 stmt.list.add( settableToString(settable()) + ".set(luan," ); | 1251 if( sym != null ) { |
1193 stmt.list.addAll( val.expr().list ); | 1252 StmtString stmt = new StmtString(); |
1194 stmt.list.add( ");\n" ); | 1253 stmt.list.addAll( sym.exp().list ); |
1195 return stmt; | 1254 stmt.list.add( " = " ); |
1255 stmt.list.addAll( val.expr().list ); | |
1256 stmt.list.add( ";\n" ); | |
1257 return stmt; | |
1258 } | |
1259 ExpString envExpr = env(); | |
1260 if( envExpr != null ) | |
1261 return indexVar( envExpr, constExpStr(name) ).set(val); | |
1262 throw new RuntimeException(); | |
1196 } | 1263 } |
1197 }; | 1264 }; |
1198 } | 1265 } |
1199 | 1266 |
1200 private Var exprVar(final ExpString expr) { | 1267 private Var exprVar(final ExpString expr) { |
1697 | 1764 |
1698 private class ExpString { | 1765 private class ExpString { |
1699 final List list = new ArrayList(); | 1766 final List list = new ArrayList(); |
1700 final boolean isExpr; | 1767 final boolean isExpr; |
1701 final boolean isStmt; | 1768 final boolean isStmt; |
1702 | 1769 /* |
1703 ExpString(Expressions exp) { | 1770 ExpString(Expressions exp) { |
1704 if( exp==null ) throw new NullPointerException(); | 1771 if( exp==null ) throw new NullPointerException(); |
1705 int i = LuanImpl.addObj(exp); | 1772 int i = LuanImpl.addObj(exp); |
1706 list.add( "((Expressions)LuanImpl.getObj(" + i + ")).eval(luan)" ); | 1773 list.add( "((Expressions)LuanImpl.getObj(" + i + ")).eval(luan)" ); |
1707 isExpr = exp instanceof Expr; | 1774 isExpr = exp instanceof Expr; |
1708 isStmt = exp instanceof StmtExp; | 1775 isStmt = exp instanceof StmtExp; |
1709 } | 1776 } |
1710 | 1777 */ |
1711 ExpString(boolean isExpr,boolean isStmt) { | 1778 ExpString(boolean isExpr,boolean isStmt) { |
1712 this.isExpr = isExpr; | 1779 this.isExpr = isExpr; |
1713 this.isStmt = isStmt; | 1780 this.isStmt = isStmt; |
1714 } | 1781 } |
1715 | 1782 |
1768 sb.append( o.toString() ); | 1835 sb.append( o.toString() ); |
1769 } | 1836 } |
1770 return sb.toString(); | 1837 return sb.toString(); |
1771 } | 1838 } |
1772 | 1839 |
1773 private static Class toFnClass(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) { | 1840 private Class toFnClass(StmtString stmt,List<UpSym> upValueSymbols) { |
1774 String code = concat(stmt.list); | 1841 String code = concat(stmt.list); |
1775 //System.out.println("code:\n"+code); | 1842 //System.out.println("code:\n"+code); |
1776 | 1843 |
1777 int i = LuanImpl.addObj(upValueGetters); | |
1778 String className = "EXP" + ++classCounter; | 1844 String className = "EXP" + ++classCounter; |
1779 String classCode = "" | 1845 String classCode = "" |
1780 +"package luan.impl;\n" | 1846 +"package luan.impl;\n" |
1781 +"import luan.Luan;\n" | 1847 +"import luan.Luan;\n" |
1782 +"import luan.LuanFunction;\n" | 1848 +"import luan.LuanFunction;\n" |
1849 +"import luan.LuanState;\n" | |
1783 +"import luan.LuanException;\n" | 1850 +"import luan.LuanException;\n" |
1784 +"import luan.modules.PackageLuan;\n" | 1851 +"import luan.modules.PackageLuan;\n" |
1785 +"\n" | 1852 +"\n" |
1786 +"public class " + className +" extends Closure {\n" | 1853 +"public class " + className +" extends Closure {\n" |
1787 +" public "+className+"(LuanStateImpl luan) throws LuanException {\n" | 1854 +" public "+className+"(LuanState luan) throws LuanException {\n" |
1788 +" super(luan,"+stackSize+","+numArgs+","+isVarArg+",(UpValue.Getter[])LuanImpl.getObj("+i+"));\n" | 1855 +" super("+upValueSymbols.size()+");\n" |
1856 + init(upValueSymbols) | |
1789 +" }\n" | 1857 +" }\n" |
1790 +"\n" | 1858 +"\n" |
1791 +" @Override public Object run(LuanStateImpl luan) throws LuanException {\n" | 1859 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n" |
1792 +" Object t;\n" | 1860 +" Object t;\n" |
1793 +" " + code | 1861 +" " + code |
1794 +" }\n" | 1862 +" }\n" |
1795 +"}\n" | 1863 +"}\n" |
1796 ; | 1864 ; |
1797 try { | 1865 try { |
1798 //System.out.println(classCode); | 1866 System.out.println(parser.sourceName); |
1799 return LuanJavaCompiler.compile("luan.impl."+className,"code",classCode); | 1867 System.out.println(classCode); |
1868 return LuanJavaCompiler.compile("luan.impl."+className,parser.sourceName,classCode); | |
1800 } catch(ClassNotFoundException e) { | 1869 } catch(ClassNotFoundException e) { |
1801 throw new RuntimeException(e); | 1870 throw new RuntimeException(e); |
1802 } | 1871 } |
1803 } | 1872 } |
1804 | 1873 |
1805 private ExpString toFnExpStr(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) { | 1874 private ExpString toFnExpStr(StmtString stmt,List<UpSym> upValueSymbols) { |
1806 int i = LuanImpl.addObj(upValueGetters); | |
1807 ExpString exp = new ExpString(true,false); | 1875 ExpString exp = new ExpString(true,false); |
1808 exp.list.add( "" | 1876 exp.list.add( "" |
1809 +"\n" | 1877 +"\n" |
1810 +"new Closure(luan,"+stackSize+","+numArgs+","+isVarArg+",(UpValue.Getter[])LuanImpl.getObj("+i+")) {\n" | 1878 +"new Closure("+upValueSymbols.size()+") {\n" |
1811 +" @Override public Object run(LuanStateImpl luan) throws LuanException {\n" | 1879 +"{\n" |
1880 + init(upValueSymbols) | |
1881 +"}\n" | |
1882 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n" | |
1812 +" Object t;\n" | 1883 +" Object t;\n" |
1813 +" " | 1884 +" " |
1814 ); | 1885 ); |
1815 exp.list.addAll( stmt.list ); | 1886 exp.list.addAll( stmt.list ); |
1816 exp.list.add( "" | 1887 exp.list.add( "" |
1818 +"}\n" | 1889 +"}\n" |
1819 ); | 1890 ); |
1820 return exp; | 1891 return exp; |
1821 } | 1892 } |
1822 | 1893 |
1823 | 1894 private static String init(List<UpSym> upValueSymbols) { |
1895 StringBuilder sb = new StringBuilder(); | |
1896 for( UpSym upSym : upValueSymbols ) { | |
1897 sb.append( upSym.init() ); | |
1898 } | |
1899 return sb.toString(); | |
1900 } | |
1901 | |
1902 /* | |
1824 private static String settableToString(Settable settable) { | 1903 private static String settableToString(Settable settable) { |
1825 if( settable==null ) throw new NullPointerException(); | 1904 if( settable==null ) throw new NullPointerException(); |
1826 int i = LuanImpl.addObj(settable); | 1905 int i = LuanImpl.addObj(settable); |
1827 return"((Settable)LuanImpl.getObj(" + i + "))"; | 1906 return"((Settable)LuanImpl.getObj(" + i + "))"; |
1828 } | 1907 } |
1829 | 1908 */ |
1830 } | 1909 } |