private static LuaType ParseFirstType(Scope scope, LuaLexer code) { string sType = FetchToken(LuaToken.Identifier, code).Value; LuaType luaType = LuaType.GetCachedType(sType); if (luaType == null) { ConstantExpression expr = scope.LookupExpression(sType, false) as ConstantExpression; if (expr != null && expr.Type == typeof(LuaType)) return (LuaType)expr.Value; else return LuaType.GetType(LuaType.Clr.GetIndex(sType, false, null)); } else return luaType; }
private static void ParseExpressionStatement(Scope scope, LuaLexer code, bool lLocal) { List<ParameterExpression> registerLocals = null; List<PrefixMemberInfo> prefixes = new List<PrefixMemberInfo>(); // parse the assgiee list (var0, var1, var2, ...) while (true) { if (lLocal) // parse local variables { Token tVar; Type typeVar; ParseIdentifierAndType(scope, code, out tVar, out typeVar); ParameterExpression exprVar = scope.LookupExpression(tVar.Value, true) as ParameterExpression; if (exprVar == null) { exprVar = Expression.Variable(typeVar, tVar.Value); if (registerLocals == null) registerLocals = new List<ParameterExpression>(); registerLocals.Add(exprVar); } else if (exprVar.Type != typeVar) throw ParseError(tVar, Properties.Resources.rsParseTypeRedef); prefixes.Add(new PrefixMemberInfo(tVar, exprVar, null, null, null)); } else // parse a assignee { // parse as a prefix prefixes.Add(ParsePrefix(scope, code)); } // is there another prefix if (code.Current.Typ == LuaToken.Comma) code.Next(); else break; } // Optional assign if (code.Current.Typ == LuaToken.Assign) { code.Next(); // parse all expressions IEnumerator<Expression> expr = ParseExpressionList(scope, code).GetEnumerator(); expr.MoveNext(); if (prefixes.Count == 1) // one expression, one variable? { scope.AddExpression( prefixes[0].GenerateSet(scope, expr.Current != null ? expr.Current : Expression.Constant(null, typeof(object))) ); } else if (expr.Current == null) // No expression, assign null { for (int i = 0; i < prefixes.Count; i++) scope.AddExpression(prefixes[i].GenerateSet(scope, Expression.Constant(null, typeof(object)))); } else // assign on an unknown number of expressions { #region -- unknown number -- List<ParameterExpression> assignTempVars = new List<ParameterExpression>(); List<Expression> assignExprs = new List<Expression>(); int iExpressionVarOffset; // Safe the prefixes in variables for (int k = 0; k < prefixes.Count; k++) { var p = prefixes[k]; if (p.Member != null || prefixes[k].Indices != null) { p.Instance = ParseExpressionStatementExchangeToTempVar(assignTempVars, assignExprs, p.Instance); if (p.Indices != null) { for (int l = 0; l < p.Indices.Length; l++) p.Indices[l] = ParseExpressionStatementExchangeToTempVar(assignTempVars, assignExprs, p.Indices[l]); } } } // collect the results of the expressions iExpressionVarOffset = assignTempVars.Count; do { ParseExpressionStatementExchangeToTempVar(assignTempVars, assignExprs, expr.Current); } while (expr.MoveNext()); // Assign the Result to the prefixes int i = 0; int j = 0; ParameterExpression lastVariable = null; while (i < prefixes.Count) { if (i < assignTempVars.Count - iExpressionVarOffset) // are the variables { if (i == assignTempVars.Count - iExpressionVarOffset - 1 && assignTempVars[i + iExpressionVarOffset].Type == typeof(LuaResult)) // check if the last expression is a LuaResult { lastVariable = assignTempVars[i + iExpressionVarOffset]; assignExprs.Add(prefixes[i].GenerateSet(scope, GetResultExpression(scope.Runtime, code.Current, lastVariable, j++))); } else { assignExprs.Add(prefixes[i].GenerateSet(scope, assignTempVars[i + iExpressionVarOffset])); } } else if (lastVariable != null) // we enroll the last expression { assignExprs.Add(prefixes[i].GenerateSet(scope, GetResultExpression(scope.Runtime, code.Current, lastVariable, j++))); } else // no variable left { assignExprs.Add(prefixes[i].GenerateSet(scope, Expression.Default(typeof(object)))); } i++; } // add the block scope.AddExpression(Expression.Block(assignTempVars, assignExprs)); #endregion } // Führe die restlichen Expressions aus while (expr.MoveNext()) scope.AddExpression(expr.Current); } else if (!lLocal) { for (int i = 0; i < prefixes.Count; i++) { if (prefixes[i].Arguments == null) // do not execute getMember throw ParseError(prefixes[i].Position, Properties.Resources.rsParseAssignmentExpected); scope.AddExpression(prefixes[i].GenerateGet(scope, InvokeResult.None)); } } // register the variables if (registerLocals != null) { for (int i = 0; i < registerLocals.Count; i++) scope.RegisterVariable(registerLocals[i]); } }
private static Expression ParseFunctionAddChain(Scope scope, Token tStart, Expression assignee, string sMember) { if (assignee == null) { Expression expr = scope.LookupExpression(sMember); if (expr == null) assignee = ParseFunctionAddChain(scope, tStart, scope.LookupExpression(csEnv), sMember); else assignee = expr; } else assignee = MemberGetExpression(scope, tStart, assignee, sMember); return assignee; }
private static PrefixMemberInfo ParsePrefix(Scope scope, LuaLexer code) { // prefix ::= Identifier suffix_opt | '(' exp ')' suffix | literal | tablector Token tStart = code.Current; PrefixMemberInfo info; switch (tStart.Typ) { case LuaToken.BracketOpen: // Parse eine Expression { code.Next(); var expr = ConvertObjectExpression(scope.Runtime, tStart, ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug)); FetchToken(LuaToken.BracketClose, code); info = new PrefixMemberInfo(tStart, expr, null, null, null); } break; case LuaToken.DotDotDot: case LuaToken.Identifier: case LuaToken.KwForEach: var t = code.Current; if (t.Value == csClr) // clr is a special package, that always exists { code.Next(); info = new PrefixMemberInfo(tStart, Expression.Property(null, Lua.TypeClrPropertyInfo), null, null, null); } else { string sMemberName; if (t.Typ == LuaToken.DotDotDot) sMemberName = csArgList; else if (t.Typ == LuaToken.KwCast) sMemberName = "cast"; else if (t.Typ == LuaToken.KwForEach) sMemberName = "foreach"; else sMemberName = t.Value; var p = scope.LookupExpression(sMemberName); if (t.Typ == LuaToken.DotDotDot && p == null) throw ParseError(t, Properties.Resources.rsParseNoArgList); code.Next(); if (p == null) // No local variable found info = new PrefixMemberInfo(tStart, scope.LookupExpression(csEnv), t.Value, null, null); else info = new PrefixMemberInfo(tStart, p, null, null, null); } break; case LuaToken.KwCast: info = new PrefixMemberInfo(tStart, ParsePrefixCast(scope, code), null, null, null); break; case LuaToken.String: // Literal String info = new PrefixMemberInfo(tStart, Expression.Constant(FetchToken(LuaToken.String, code).Value, typeof(string)), null, null, null); break; case LuaToken.Number: // Literal Zahl info = new PrefixMemberInfo(tStart, ParseNumber(scope.Runtime, FetchToken(LuaToken.Number, code)), null, null, null); break; case LuaToken.KwTrue: // Literal TRUE code.Next(); info = new PrefixMemberInfo(tStart, Expression.Constant(true, typeof(bool)), null, null, null); break; case LuaToken.KwFalse: // Literal FALSE code.Next(); info = new PrefixMemberInfo(tStart, Expression.Constant(false, typeof(bool)), null, null, null); break; case LuaToken.KwNil: // Literal NIL code.Next(); info = new PrefixMemberInfo(tStart, Expression.Constant(null, typeof(object)), null, null, null); break; case LuaToken.BracketCurlyOpen: // tablector info = new PrefixMemberInfo(tStart, ParseTableConstructor(scope, code), null, null, null); break; case LuaToken.KwFunction: // Function definition code.Next(); info = new PrefixMemberInfo(tStart, ParseLamdaDefinition(scope, code, "lambda", false, null), null, null, null); break; default: throw ParseError(code.Current, Properties.Resources.rsParseUnexpectedTokenPrefix); } return ParseSuffix(scope, code, info); }
private static void ParseFunction(Scope scope, LuaLexer code, bool lLocal) { FetchToken(LuaToken.KwFunction, code); if (lLocal) // Local function, only one identifier is allowed { var t = FetchToken(LuaToken.Identifier, code); ParameterExpression funcVar = null; Expression exprFunction = ParseLamdaDefinition(scope, code, t.Value, false, typeDelegate => funcVar = scope.RegisterVariable(typeDelegate, t.Value) ); scope.AddExpression(Expression.Assign(funcVar, exprFunction)); } else // Function that is assigned to a table. A chain of identifiers is allowed. { Expression assignee = null; Token tCurrent = FetchToken(LuaToken.Identifier, code); string sMember = tCurrent.Value; // Collect the chain of members while (code.Current.Typ == LuaToken.Dot) { code.Next(); // Create the get-member for the current assignee assignee = ParseFunctionAddChain(scope, tCurrent, assignee, sMember); sMember = FetchToken(LuaToken.Identifier, code).Value; } // add a method to the table. methods get a hidden parameter and will bo marked bool lMethodMember; if (code.Current.Typ == LuaToken.Colon) { code.Next(); // add the last member to the assignee chain assignee = ParseFunctionAddChain(scope, tCurrent, assignee, sMember); // fetch the method name sMember = FetchToken(LuaToken.Identifier, code).Value; lMethodMember = true; } else { if (assignee == null) assignee = scope.LookupExpression(csEnv); // create a global function lMethodMember = false; } // generate lambda scope.AddExpression(MemberSetExpression(scope.Runtime, tCurrent, assignee, sMember, lMethodMember, ParseLamdaDefinition(scope, code, sMember, lMethodMember, null))); } }