public static InlineFunctionExpression InlineFunction(AnonymousFunctionExpr e) { if (!CanInline(e)) throw new Exception("Cannot inline function!"); ReturnStatement rs = e.Body[0] as ReturnStatement; InlineFunctionExpression ife = new InlineFunctionExpression(); foreach (Variable v in e.Arguments) ife.Arguments.Add(v); ife.IsVararg = e.IsVararg; foreach (Expression expr in rs.Arguments) ife.Expressions.Add(expr); ife.Scope = e.Scope; rs.Scope = e.Scope; return ife; }
Expression ParseSimpleExpr(Scope scope) { if (reader.Is(TokenType.Number)) return new NumberExpr { Value = reader.Get().Data }; else if (reader.Is(TokenType.DoubleQuoteString) || reader.Is(TokenType.SingleQuoteString) || reader.Is(TokenType.LongString)) { StringExpr s = new StringExpr { Value = reader.Peek().Data, StringType = reader.Peek().Type }; reader.Get(); return s; } else if (reader.ConsumeKeyword("nil")) return new NilExpr(); else if (reader.IsKeyword("false") || reader.IsKeyword("true")) return new BoolExpr { Value = reader.Get().Data == "true" }; else if (reader.ConsumeSymbol("...")) return new VarargExpr(); else if (reader.ConsumeSymbol('{')) { TableConstructorExpr v = new TableConstructorExpr(); while (true) { if (reader.IsSymbol('[')) { // key reader.Get(); // eat '[' Expression key = ParseExpr(scope); if (!reader.ConsumeSymbol(']')) { error("']' expected"); break; } if (!reader.ConsumeSymbol('=')) { error("'=' Expected"); break; } Expression value = ParseExpr(scope); v.EntryList.Add(new TableConstructorKeyExpr { Key = key, Value = value, }); } else if (reader.Is(TokenType.Ident)) { // value or key Token lookahead = reader.Peek(1); if (lookahead.Type == TokenType.Symbol && lookahead.Data == "=") { // we are a key Token key = reader.Get(); if (!reader.ConsumeSymbol('=')) error("'=' Expected"); Expression value = ParseExpr(scope); v.EntryList.Add(new TableConstructorStringKeyExpr { Key = key.Data, Value = value, }); } else { // we are a value Expression val = ParseExpr(scope); v.EntryList.Add(new TableConstructorValueExpr { Value = val }); } } #if !VANILLA_LUA else if (reader.ConsumeKeyword("function")) { if (reader.Peek().Type != TokenType.Ident) error("function name expected"); string name = reader.Get().Data; FunctionStatement fs = ParseFunctionArgsAndBody(scope); fs.IsLocal = false; fs.Name = new StringExpr(name); v.EntryList.Add(new TableConstructorNamedFunctionExpr { Value = fs }); } #endif else if (reader.ConsumeSymbol('}')) break; else { //value Expression value = ParseExpr(scope); v.EntryList.Add(new TableConstructorValueExpr { Value = value }); } if (reader.ConsumeSymbol(';') || reader.ConsumeSymbol(',')) { // I could have used just an empty statement (';') here, instead of { } // but that leaves a warning, which clutters up the output // other than that, all is good } else if (reader.ConsumeSymbol('}')) break; else { error("'}' or table entry Expected"); break; } } return v; } else if (reader.ConsumeKeyword("function")) { AnonymousFunctionExpr func = ParseExprFunctionArgsAndBody(scope); //func.IsLocal = true; return func; } #if !VANILLA_LUA else if (reader.ConsumeSymbol('|')) { // inline function... |<arg list>| -> <expr>, <expr> InlineFunctionExpression func = new InlineFunctionExpression(); func.Scope = new Scope(scope); // arg list List<Variable> arglist = new List<Variable>(); bool isVarArg = false; while (reader.ConsumeSymbol('|') == false) { if (reader.Is(TokenType.Ident)) { Variable arg = new Variable(); arg.Name = reader.Get().Data; func.Scope.AddLocal(arg); arglist.Add(arg); if (!reader.ConsumeSymbol(',')) { if (reader.ConsumeSymbol('|')) { break; } else { error("'|' expected"); break; } } } else if (reader.ConsumeSymbol("...")) { isVarArg = true; if (!reader.ConsumeSymbol('|')) error("'...' must be the last argument of a function"); break; } else { error("Argument name or '...' expected"); break; } } if (!reader.ConsumeSymbol("->")) error("'->' expected"); // body List<Expression> body = new List<Expression> { ParseExpr(func.Scope) }; while (reader.ConsumeSymbol(',')) body.Add(ParseExpr(func.Scope)); // end //nodeFunc.AstType = AstType.Function; func.Arguments = arglist; func.Expressions = body; func.IsVararg = isVarArg; return func; } #endif else return ParseSuffixedExpr(scope); }