} // func GetDebugInfo #endregion #region -- Emit Helper ------------------------------------------------------------ private static Expression SafeExpression(Func<Expression> f, Token tStart) { try { return f(); } catch (LuaEmitException e) { throw ParseError(tStart, e.Message); } } // func SafeExpression
private static Expression ConcatOperationExpression(Lua runtime, Token tStart, Expression[] args) { if (Array.Exists(args, c => LuaEmit.IsDynamicType(c.Type))) // we have a dynamic type in the list -> to the concat on runtime { return SafeExpression(() => Expression.Call(Lua.ConcatStringMethodInfo, Expression.NewArrayInit(typeof(object), from e in args select ConvertObjectExpression(runtime, tStart, e, true))), tStart); } else { return SafeExpression(() => Expression.Call(Lua.StringConcatMethodInfo, Expression.NewArrayInit(typeof(string), from e in args select LuaEmit.Convert(runtime, e, e.Type, typeof(string), true))), tStart); } }
private static Expression ConvertObjectExpression(Lua runtime, Token tStart, Expression expr, bool lConvertToObject = false) { if (expr.Type == typeof(LuaResult)) return GetResultExpression(runtime, tStart, expr, 0); else if (expr.Type == typeof(object) && expr.NodeType == ExpressionType.Dynamic) { DynamicExpression exprDynamic = (DynamicExpression)expr; if (exprDynamic.Binder is InvokeBinder || exprDynamic.Binder is InvokeMemberBinder) return DynamicExpression.Dynamic(runtime.GetConvertBinder(typeof(object)), typeof(object), expr); else if (lConvertToObject) return Lua.EnsureType(expr, typeof(object)); else return expr; } else if (lConvertToObject) return Lua.EnsureType(expr, typeof(object)); else return expr; }
private static Expression WrapDebugInfo(bool lWrap, bool lAfter, Token tStart, Token tEnd, Expression expr) { if (lWrap) { if (lAfter) { if (expr.Type == typeof(void)) return Expression.Block(expr, GetDebugInfo(tStart, tEnd)); else { ParameterExpression r = Expression.Variable(expr.Type); return Expression.Block(r.Type, new ParameterExpression[] { r }, Expression.Assign(r, expr), GetDebugInfo(tStart, tEnd), r); } } else return Expression.Block(GetDebugInfo(tStart, tEnd), expr); } else return expr; } // func WrapDebugInfo
private static void ParseIdentifierAndType(Scope scope, LuaLexer code, out Token tName, out Type type) { // var ::= name ':' type tName = FetchToken(LuaToken.Identifier, code); if (code.Current.Typ == LuaToken.Colon) { code.Next(); type = ParseType(scope, code, true); } else type = typeof(object); }
private static Expression GetResultExpression(Lua runtime, Token tStart, Expression expr, int iIndex) { return SafeExpression(() => LuaEmit.GetResultExpression(expr, expr.Type, iIndex), tStart); }
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; }
public PrefixMemberInfo(Token position, Expression instance, string sMember, Expression[] indices, ArgumentsList arguments) { this.Position = position; this.Instance = instance; this.Member = sMember; this.Indices = indices; this.Arguments = arguments; }
private static Expression GetLuaResultExpression(Scope scope, Token tStart, Expression[] exprs) { Expression exprReturnValue; if (exprs.Length == 1) if (exprs[0].Type == typeof(LuaResult)) exprReturnValue = exprs[0]; else exprReturnValue = Expression.New(Lua.ResultConstructorInfoArg1, ConvertExpression(scope.Runtime, tStart, exprs[0], typeof(object))); else exprReturnValue = Expression.New(Lua.ResultConstructorInfoArgN, Expression.NewArrayInit(typeof(object), from c in exprs select Expression.Convert(c, typeof(object)) ) ); return exprReturnValue; }
public void AddNamedArgument(Token name, Expression expr) { if (callInfo.IsValueCreated) throw new InvalidOperationException("internal: no manipulation after CallInfo creation."); names.Add(name.Value); arguments.Add(expr); }
public void WrapArgument(int index, bool emitExpressionDebug, Token position) { arguments[index] = WrapDebugInfo(emitExpressionDebug, true, position, position, arguments[index]); }
private static Expression MemberGetExpression(Scope scope, Token tStart, Expression instance, string sMember) { return MemberGetSandbox(scope, SafeExpression(() => LuaEmit.GetMember(scope.Runtime, instance, instance.Type, sMember, false, true), tStart), instance, sMember); }
private static Expression MemberSetExpression(Lua runtime, Token tStart, Expression instance, string sMember, bool lMethodMember, Expression set) { // Assign the value to a member if (lMethodMember) { return Expression.Call( ConvertExpression(runtime, tStart, instance, typeof(LuaTable)), Lua.TableDefineMethodLightMethodInfo, Expression.Constant(sMember, typeof(string)), ConvertExpression(runtime, tStart, set, typeof(Delegate)) ); } else return SafeExpression(() => LuaEmit.SetMember(runtime, instance, instance.Type, sMember, false, set, set.Type, true), tStart); }
private static Expression InvokeMemberExpression(Scope scope, Token tStart, Expression instance, string sMember, InvokeResult result, Expression[] arguments) { if (LuaEmit.IsDynamicType(instance.Type)) { return EnsureInvokeResult(scope, tStart, DynamicExpression.Dynamic(scope.Runtime.GetInvokeMemberBinder(sMember, new CallInfo(arguments.Length)), typeof(object), new Expression[] { ConvertExpression(scope.Runtime, tStart, instance, typeof(object)) }.Concat( from c in arguments select Lua.EnsureType(c, typeof(object)) ).ToArray() ), result, instance, sMember ); } else { // look up the method MethodInfo method = LuaEmit.FindMethod( LuaType.GetType(instance.Type).GetInstanceMethods(sMember, false), arguments, getExpressionTypeFunction, true); if (method != null) return EnsureInvokeResult(scope, tStart, SafeExpression(() => InvokeMemberExpressionBind(method, scope.Runtime, instance, arguments), tStart), result, instance, sMember); else return InvokeMemberExpressionDynamic(scope, tStart, instance, sMember, result, arguments); } }
private static Expression InvokeMemberExpressionDynamic(Scope scope, Token tStart, Expression instance, string sMember, InvokeResult result, Expression[] arguments) { return EnsureInvokeResult(scope, tStart, DynamicExpression.Dynamic(scope.Runtime.GetInvokeMemberBinder(sMember, new CallInfo(arguments.Length)), typeof(object), new Expression[] { ConvertExpression(scope.Runtime, tStart, instance, typeof(object)) }.Concat(from a in arguments select Lua.EnsureType(a, typeof(object))).ToArray() ), result, instance, sMember ); }
private static Expression InvokeExpression(Scope scope, Token tStart, Expression instance, InvokeResult result, Expression[] arguments, bool lParse) { MethodInfo mi; ConstantExpression constInstance = instance as ConstantExpression; LuaType t; if (constInstance != null && (t = constInstance.Value as LuaType) != null && t.Type != null) // we have a type, bind the ctor { Type type = t.Type; TypeInfo typeInfo = type.GetTypeInfo(); ConstructorInfo ci = typeInfo.IsValueType && arguments.Length == 0 ? null : LuaEmit.FindMember(typeInfo.DeclaredConstructors.Where(c => c.IsPublic), arguments, getExpressionTypeFunction); if (ci == null && !typeInfo.IsValueType) throw ParseError(tStart, String.Format(Properties.Resources.rsMemberNotResolved, type.Name, "ctor")); return SafeExpression(() => LuaEmit.BindParameter(scope.Runtime, args => ci == null ? Expression.New(type) : Expression.New(ci, args), ci == null ? new ParameterInfo[0] : ci.GetParameters(), arguments, getExpressionFunction, getExpressionTypeFunction, true), tStart); } else if (LuaEmit.IsDynamicType(instance.Type)) { // fallback is a dynamic call return EnsureInvokeResult(scope, tStart, DynamicExpression.Dynamic(scope.Runtime.GetInvokeBinder(new CallInfo(arguments.Length)), typeof(object), new Expression[] { ConvertExpression(scope.Runtime, tStart, instance, typeof(object)) }.Concat( from c in arguments select Lua.EnsureType(c, typeof(object)) ) ), result, instance, null ); } else if (typeof(Delegate).GetTypeInfo().IsAssignableFrom(instance.Type.GetTypeInfo()) && // test if the type is assignable from delegate (mi = instance.Type.GetRuntimeMethods().Where(c => !c.IsStatic && c.IsPublic && c.Name == "Invoke").FirstOrDefault()) != null) // Search the Invoke method for the arguments { return EnsureInvokeResult(scope, tStart, SafeExpression(() => LuaEmit.BindParameter<Expression>( scope.Runtime, args => Expression.Invoke(instance, args), mi.GetParameters(), arguments, getExpressionFunction, getExpressionTypeFunction, true), tStart), result, instance, null ); } else throw ParseError(tStart, LuaEmitException.GetMessageText(LuaEmitException.InvokeNoDelegate, instance.Type.Name)); }
private static Expression IndexSetExpression(Lua runtime, Token tStart, Expression instance, Expression[] indexes, Expression set) { if (instance.Type == typeof(LuaTable)) { if (indexes.Length == 1) { var arg = indexes[0]; if (LuaTable.IsIndexKey(arg.Type)) // integer access { return Expression.Call(instance, Lua.TableSetValueKeyIntMethodInfo, ConvertExpression(runtime, tStart, arg, typeof(int)), ConvertObjectExpression(runtime, tStart, set, true), Expression.Constant(false) ); } else if (arg.Type == typeof(string)) // member access { return Expression.Call(instance, Lua.TableSetValueKeyStringMethodInfo, arg, ConvertObjectExpression(runtime, tStart, set, true), Expression.Constant(false), Expression.Constant(false) ); } else // key access { return Expression.Call(instance, Lua.TableSetValueKeyObjectMethodInfo, ConvertObjectExpression(runtime, tStart, arg, true), ConvertObjectExpression(runtime, tStart, set, true), Expression.Constant(false) ); } } else { return Expression.Call(instance, Lua.TableSetValueKeyListMethodInfo, Expression.NewArrayInit(typeof(object), from i in indexes select ConvertObjectExpression(runtime, tStart, i, true)), ConvertObjectExpression(runtime, tStart, set, true), Expression.Constant(false) ); } } else return SafeExpression(() => LuaEmit.SetIndex(runtime, instance, indexes, set, getExpressionFunction, getExpressionTypeFunction, true), tStart); }
private static Expression IndexGetExpression(Scope scope, Token tStart, Expression instance, Expression[] indexes) { if (instance.Type == typeof(LuaTable)) { if (indexes.Length == 1) { var arg = indexes[0]; if (LuaTable.IsIndexKey(arg.Type)) // integer access { return MemberGetSandbox( scope, Expression.Call(instance, Lua.TableGetValueKeyIntMethodInfo, ConvertExpression(scope.Runtime, tStart, arg, typeof(int)), Expression.Constant(false) ), instance, null ); } else if (arg.Type == typeof(string)) // member access { return MemberGetSandbox( scope, Expression.Call(instance, Lua.TableGetValueKeyStringMethodInfo, arg, Expression.Constant(false), Expression.Constant(false) ), instance, null ); } else // key access { return MemberGetSandbox( scope, Expression.Call(instance, Lua.TableGetValueKeyObjectMethodInfo, ConvertObjectExpression(scope.Runtime, tStart, arg, true), Expression.Constant(false) ), instance, null ); } } else { return MemberGetSandbox( scope, Expression.Call(instance, Lua.TableGetValueKeyListMethodInfo, Expression.NewArrayInit(typeof(object), from i in indexes select ConvertObjectExpression(scope.Runtime, tStart, i, true)), Expression.Constant(false) ), instance, null ); } } else if (instance.Type == typeof(LuaResult) && indexes.Length == 1) { return MemberGetSandbox( scope, Expression.MakeIndex( instance, Lua.ResultIndexPropertyInfo, new Expression[] { ConvertExpression(scope.Runtime, tStart, indexes[0], typeof(int)) } ), instance, null ); } else return MemberGetSandbox(scope, SafeExpression(() => LuaEmit.GetIndex(scope.Runtime, instance, indexes, getExpressionFunction, getExpressionTypeFunction, true), tStart), instance, null); }
private static Expression ParseNumber(Lua runtime, Token t) { string sNumber = t.Value; if (String.IsNullOrEmpty(sNumber)) return Expression.Constant(0, Lua.GetIntegerType(runtime.NumberType)); else { object v = Lua.RtParseNumber(sNumber, runtime.FloatType == LuaFloatType.Double, false); if (v != null) return Expression.Constant(v); else throw ParseError(t, String.Format(Properties.Resources.rsParseConvertNumberError, sNumber)); } }
private static Expression UnaryOperationExpression(Lua runtime, Token tStart, ExpressionType op, Expression expr) { if (op != ExpressionType.ArrayLength) expr = ConvertObjectExpression(runtime, tStart, expr); return SafeExpression(() => LuaEmit.UnaryOperationExpression(runtime, op, expr, expr.Type, true), tStart); }
private static Expression GenerateForLoop(LoopScope loopScope, Token tStart, ParameterExpression loopVar, Expression loopStart, Expression loopEnd, Expression loopStep) { const string csVar = "#var"; const string csEnd = "#end"; const string csStep = "#step"; ParameterExpression internLoopVar = Expression.Variable(loopVar.Type, csVar); ParameterExpression endVar = Expression.Variable(loopEnd.Type, csEnd); ParameterExpression stepVar = Expression.Variable(loopStep.Type, csStep); LabelTarget labelLoop = Expression.Label("#loop"); // Erzeuge CodeBlock loopScope.InsertExpression(0, Expression.Assign(loopVar, internLoopVar)); // Erzeuge den Schleifenblock return Expression.Block(new ParameterExpression[] { internLoopVar, endVar, stepVar }, Expression.Assign(internLoopVar, ConvertExpression(loopScope.Runtime, tStart, loopStart, internLoopVar.Type)), Expression.Assign(endVar, loopEnd), Expression.Assign(stepVar, loopStep), Expression.Label(labelLoop), Expression.IfThenElse( BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.OrElse, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.AndAlso, ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.GreaterThan, stepVar, Expression.Constant(0, typeof(int))), typeof(bool)), ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.LessThanOrEqual, internLoopVar, endVar), typeof(bool)) ), BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.AndAlso, ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.LessThanOrEqual, stepVar, Expression.Constant(0, typeof(int))), typeof(bool)), ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.GreaterThanOrEqual, internLoopVar, endVar), typeof(bool)) ) ), loopScope.ExpressionBlock, Expression.Goto(loopScope.BreakLabel) ), Expression.Label(loopScope.ContinueLabel), Expression.Assign(internLoopVar, ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.Add, internLoopVar, stepVar), internLoopVar.Type)), Expression.Goto(labelLoop), Expression.Label(loopScope.BreakLabel) ); }
private static Expression BinaryOperationExpression(Lua runtime, Token tStart, ExpressionType op, Expression expr1, Expression expr2) { expr1 = ConvertObjectExpression(runtime, tStart, expr1); expr2 = ConvertObjectExpression(runtime, tStart, expr2); return SafeExpression(() => LuaEmit.BinaryOperationExpression(runtime, op, expr1, expr1.Type, expr2, expr2.Type, true), tStart); }
public void AddPositionalArgument(Token position, Expression expr) { if (callInfo.IsValueCreated) throw new InvalidOperationException("internal: no manipulation after CallInfo creation."); if (names.Count > 0) throw ParseError(position, Properties.Resources.rsParseInvalidArgList); arguments.Add(expr); }
private static Expression EnsureInvokeResult(Scope scope, Token tStart, Expression expr, InvokeResult result, Expression instance, string sMember) { switch (result) { case InvokeResult.LuaResult: return ConvertExpression(scope.Runtime, tStart, expr, typeof(LuaResult)); case InvokeResult.Object: if (LuaEmit.IsDynamicType(expr.Type)) return MemberGetSandbox(scope,DynamicExpression.Dynamic(scope.Runtime.GetConvertBinder(typeof(object)), typeof(object), ConvertExpression(scope.Runtime, tStart, expr, typeof(object))), instance, sMember); else return MemberGetSandbox(scope, expr, instance, sMember); default: return MemberGetSandbox(scope, expr, instance, sMember); } }
private static Expression GenerateForLoop(LoopScope loopScope, Token tStart, List<ParameterExpression> loopVars, Expression[] explist) { const string csFunc = "#f"; const string csState = "#s"; const string csVar = "#var"; ParameterExpression varTmp = Expression.Variable(typeof(LuaResult), "#tmp"); ParameterExpression varFunc = Expression.Variable(explist.Length > 0 && typeof(Delegate).GetTypeInfo().IsAssignableFrom(explist[0].Type.GetTypeInfo()) ? explist[0].Type : typeof(object), csFunc); ParameterExpression varState = Expression.Variable(typeof(object), csState); ParameterExpression varVar = Expression.Variable(typeof(object), csVar); // local var1, ..., varn = tmp; for (int i = 0; i < loopVars.Count; i++) loopScope.InsertExpression(i, Expression.Assign(loopVars[i], ConvertExpression(loopScope.Runtime, tStart, GetResultExpression(loopScope.Runtime, tStart, varTmp, i), loopVars[i].Type))); return Expression.Block(new ParameterExpression[] { varTmp, varFunc, varState, varVar }, // fill the local loop variables initial // local #f, #s, #var = explist Expression.Assign(varTmp, GetLuaResultExpression(loopScope, tStart, explist)), Expression.Assign(varFunc, ConvertExpression(loopScope.Runtime, tStart, GetResultExpression(loopScope.Runtime, tStart, varTmp, 0), varFunc.Type)), Expression.Assign(varState, GetResultExpression(loopScope.Runtime, tStart, varTmp, 1)), Expression.Assign(varVar, GetResultExpression(loopScope.Runtime, tStart, varTmp, 2)), Expression.Label(loopScope.ContinueLabel), // local tmp = f(s, var) Expression.Assign(varTmp, InvokeExpression(loopScope, tStart, varFunc, InvokeResult.LuaResult, new ArgumentsList(varState, varVar), true) ), // var = tmp[0] Expression.Assign(varVar, GetResultExpression(loopScope.Runtime, tStart, varTmp, 0)), // if var == nil then goto break; Expression.IfThenElse(Expression.Equal(varVar, Expression.Constant(null, typeof(object))), Expression.Goto(loopScope.BreakLabel), loopScope.ExpressionBlock), // LoopBody Expression.Goto(loopScope.ContinueLabel), Expression.Label(loopScope.BreakLabel) ); }
private static Expression ConvertExpression(Lua runtime, Token tStart, Expression expr, Type toType) { return SafeExpression(() => LuaEmit.Convert(runtime, expr, expr.Type, toType, true), tStart); }
public void SetMember(Token tMember, bool lMethod) { Position = tMember; MethodMember = lMethod; Member = tMember.Value; }
} // func NextTokenWithSkipRules /// <summary>Reads the next token from the stream</summary> public void Next() { if (lookahead == null) // Erstinitialisierung der Lookaheads notwendig { current = NextTokenWithSkipRules(); lookahead = NextTokenWithSkipRules(); } else { current = lookahead; lookahead = NextTokenWithSkipRules(); } } // proc Next
private static LuaParseException ParseError(Token start, string sMessage) { return new LuaParseException(start.Start, sMessage, null); }
private static Expression GetDebugInfo(Token tStart, Token tEnd) { return Expression.DebugInfo(tStart.Start.Document, tStart.Start.Line, tStart.Start.Col, tEnd.End.Line, tEnd.End.Col); }