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 }