public EvaluationCallback Create(Node node) { foreach (Node n in EnumerateNodes(node)) { if (n.Token.AsOperator == Operator.Assignment) return NestedFunctionBuild(node); if (n.Token.Data is Tokenizing.CustomFunctionData) return NestedFunctionBuild(node); } return SingleFunctionBuild(node); }
Node ParseNode(List<Token> tokens, ref Int32 tokenindex) { if (tokens == null) throw new ArgumentNullException("tokens"); if (tokenindex < 0 || tokenindex >= tokens.Count) throw new ArgumentOutOfRangeException("tokenindex"); Node lhs = ParseEndNode(tokens, ref tokenindex); if (lhs == null) return null; for (Token token = GetToken(tokens, tokenindex); token != null; token = GetToken(tokens, tokenindex)) { if ((token.Data is Tokenizing.BinaryOperatorData) == false) break; if (lhs.Token.Data is Tokenizing.RangeData && lhs.PrecedenceOverride == false) return null; Node operatornode = new Node(token); ++tokenindex; Operator @operator = (token.Data as Tokenizing.BinaryOperatorData).Operator; if (@operator == Operator.Equals || @operator == Operator.NotEquals) { Node range = ParseRangeNode(tokens, ref tokenindex); if (range != null) { range.Children[0] = lhs; range.Arguments[0] = @operator; lhs = range; continue; } } Node rhs = ParseNode(tokens, ref tokenindex); if (rhs == null) return null; if(SwitchOrder(operatornode, rhs) == true) { lhs = BreakTree(lhs, operatornode, rhs); } else { operatornode.Children.Add(lhs); operatornode.Children.Add(rhs); lhs = operatornode; } } return lhs; }
public EvaluationCallback Create(Node node) { DynamicMethod method = new DynamicMethod(String.Empty, typeof(Number), new Type[] { typeof(Object) }, typeof(Compiler), true); CompilerState compilerstate = new CompilerState(); compilerstate.Generator = method.GetILGenerator(); compilerstate.FunctionState = compilerstate.Generator.DeclareLocal(typeof(Object)); compilerstate.ErrorLabel = compilerstate.Generator.DefineLabel(); compilerstate.ErrorVariable = compilerstate.Generator.DeclareLocal(typeof(Boolean)); compilerstate.Generator.Emit(OpCodes.Ldarg, 0); StoreLocalVariable(compilerstate, compilerstate.FunctionState); LocalVariableInfo result = Emit(compilerstate, node); if (result.LocalType == typeof(Int32)) { LoadLocalVariable(compilerstate, result); compilerstate.Generator.Emit(OpCodes.Newobj, typeof(Number).GetConstructor(new Type[] { typeof(Int32) })); } else if (result.LocalType == typeof(Single)) { LoadLocalVariable(compilerstate, result); compilerstate.Generator.Emit(OpCodes.Newobj, typeof(Number).GetConstructor(new Type[] { typeof(Single) })); } else { throw new Exception(); } compilerstate.Generator.Emit(OpCodes.Ret); compilerstate.Generator.MarkLabel(compilerstate.ErrorLabel); LoadLocalVariable(compilerstate, compilerstate.Generator.DeclareLocal(typeof(Number))); compilerstate.Generator.Emit(OpCodes.Ret); EvaluationCallback callback = (EvaluationCallback)method.CreateDelegate(typeof(EvaluationCallback)); return callback; }
LocalVariableInfo EmitAssignmentOperator(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); Evaluation.Tokenizing.OperatorData data = node.Token.Data as Evaluation.Tokenizing.OperatorData; if (data == null || data.Operator != Operator.Assignment) throw new Exception(); if (node.Children.Count != 2) throw new Exception(); Evaluation.Tokenizing.CustomFunctionData vardata = node.Children[0].Token.Data as Evaluation.Tokenizing.CustomFunctionData; if (vardata == null) throw new Exception(); if (node.Children[0].Children.Count != 1) throw new Exception(); LocalVariableInfo index = Emit(state, node.Children[0].Children[0]); LocalVariableInfo value = Emit(state, node.Children[1]); List<LocalVariableInfo> args = new List<LocalVariableInfo>() { state.FunctionState, index, value }; if (vardata.Type == typeof(Triggers.Var)) { return EmitMethod(state, typeof(SpecialFunctions).GetMethod("Assignment_Var"), args); } if (vardata.Type == typeof(Triggers.FVar)) { return EmitMethod(state, typeof(SpecialFunctions).GetMethod("Assignment_FVar"), args); } if (vardata.Type == typeof(Triggers.SysVar)) { return EmitMethod(state, typeof(SpecialFunctions).GetMethod("Assignment_SysVar"), args); } if (vardata.Type == typeof(Triggers.SysFVar)) { return EmitMethod(state, typeof(SpecialFunctions).GetMethod("Assignment_SysFVar"), args); } throw new Exception(); }
LocalVariableInfo EmitOperator(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); Evaluation.Tokenizing.OperatorData data = node.Token.Data as Evaluation.Tokenizing.OperatorData; if (data == null) throw new Exception(); if (node.Children.Count == 1) return EmitUnaryOperator(state, node); if (node.Children.Count != 2) throw new Exception(); if (data.Operator == Operator.Assignment) return EmitAssignmentOperator(state, node); LocalVariableInfo lhs = Emit(state, node.Children[0]); LocalVariableInfo rhs = Emit(state, node.Children[1]); switch (data.Operator) { case Operator.Plus: return EmitArithmeticOperator(state, OpCodes.Add, lhs, rhs); case Operator.Minus: return EmitArithmeticOperator(state, OpCodes.Sub, lhs, rhs); case Operator.Divide: return EmitArithmeticOperator(state, OpCodes.Div, lhs, rhs); case Operator.Multiply: return EmitArithmeticOperator(state, OpCodes.Mul, lhs, rhs); case Operator.Modulus: return EmitArithmeticOperator(state, OpCodes.Rem, lhs, rhs); case Operator.Equals: case Operator.NotEquals: case Operator.Greater: case Operator.GreaterEquals: case Operator.Lesser: case Operator.LesserEquals: return EmitComparsionOperator(state, data.Operator, lhs, rhs); case Operator.LogicalAnd: case Operator.LogicalOr: case Operator.LogicalXor: return EmitLogicalOperator(state, data.Operator, lhs, rhs); case Operator.Exponent: return EmitMethod(state, typeof(Math).GetMethod("Pow"), new List<LocalVariableInfo>() { lhs, rhs }); default: throw new Exception(); } }
LocalVariableInfo EmitFunction(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); Evaluation.Tokenizing.CustomFunctionData data = node.Token.Data as Evaluation.Tokenizing.CustomFunctionData; if (data == null) throw new Exception(); if (data.Type == typeof(Triggers.Const) || data.Type == typeof(Triggers.GetHitVar)) { return EmitSpecialFunction(state, data.Type, (String)node.Arguments[0]); } List<LocalVariableInfo> functionargs = EmitDescendants(state, node); MethodInfo method = FindCorrectMethod(data.Type, functionargs); ParameterInfo[] parameters = method.GetParameters(); LoadLocalVariable(state, state.FunctionState); state.Generator.Emit(OpCodes.Ldloca, state.ErrorVariable.LocalIndex); for (Int32 i = 0; i != functionargs.Count; ++i) { LocalVariableInfo arg = functionargs[i]; ParameterInfo parameter = parameters[i + 2]; LoadLocalVariable(state, arg); //if (parameter.ParameterType == typeof(Int32) && arg.LocalType == typeof(Single)) state.Generator.Emit(OpCodes.Conv_I4); //if (parameter.ParameterType == typeof(Single) && arg.LocalType == typeof(Int32)) state.Generator.Emit(OpCodes.Conv_R4); } state.Generator.Emit(OpCodes.Call, method); Type returntype = method.ReturnType; if (returntype == typeof(Boolean)) returntype = typeof(Int32); LocalVariableInfo result = state.Generator.DeclareLocal(returntype); StoreLocalVariable(state, result); LoadLocalVariable(state, state.ErrorVariable); state.Generator.Emit(OpCodes.Brtrue, state.ErrorLabel); return result; }
LocalVariableInfo EmitStateRedirection(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); Evaluation.Tokenizing.StateRedirectionData data = node.Token.Data as Evaluation.Tokenizing.StateRedirectionData; if (data == null) throw new Exception(); if (node.Children.Count < 1) throw new Exception(); List<LocalVariableInfo> functionargs = EmitRedirectionDescendants(state, node); MethodInfo method = FindCorrectRedirectionMethod(data.Type, functionargs); ParameterInfo[] parameters = method.GetParameters(); LoadLocalVariable(state, state.FunctionState); state.Generator.Emit(OpCodes.Ldloca, state.ErrorVariable.LocalIndex); for (Int32 i = 0; i != functionargs.Count; ++i) { LocalVariableInfo arg = functionargs[i]; ParameterInfo parameter = parameters[i + 2]; LoadLocalVariable(state, arg); //if (parameter.ParameterType == typeof(Int32) && arg.LocalType == typeof(Single)) state.Generator.Emit(OpCodes.Conv_I4); //if (parameter.ParameterType == typeof(Single) && arg.LocalType == typeof(Int32)) state.Generator.Emit(OpCodes.Conv_R4); } state.Generator.Emit(OpCodes.Call, method); LocalVariableInfo oldstate = state.FunctionState; state.FunctionState = state.Generator.DeclareLocal(typeof(Object)); StoreLocalVariable(state, state.FunctionState); LoadLocalVariable(state, state.ErrorVariable); state.Generator.Emit(OpCodes.Brtrue, state.ErrorLabel); LocalVariableInfo returnvalue = Emit(state, node.Children[node.Children.Count - 1]); state.FunctionState = oldstate; return returnvalue; }
void SingleFunctionBuild(ILGenerator generator, Node node) { if (node.Token.Data is Evaluation.Tokenizing.NumberData) { Number number = (node.Token.Data as Evaluation.Tokenizing.NumberData).GetNumber(node.Token.ToString()); switch (number.NumberType) { case NumberType.Int: generator.Emit(OpCodes.Ldc_I4, number.IntValue); generator.Emit(OpCodes.Newobj, typeof(Number).GetConstructor(new Type[] { typeof(Int32) })); break; case NumberType.Float: generator.Emit(OpCodes.Ldc_R4, number.FloatValue); generator.Emit(OpCodes.Newobj, typeof(Number).GetConstructor(new Type[] { typeof(Single) })); break; default: generator.Emit(OpCodes.Ldloc, generator.DeclareLocal(typeof(Number)).LocalIndex); break; } } else if (node.Token.Data is Evaluation.Tokenizing.OperatorData) { foreach (Node childnode in node.Children) SingleFunctionBuild(generator, childnode); if (node.Children.Count == 1 && node.Token.AsOperator == Operator.Minus) { generator.Emit(OpCodes.Call, typeof(Number).GetMethod("Negate", BindingFlags.Static | BindingFlags.Public)); } else { String methodname = (node.Token.Data as Evaluation.Tokenizing.OperatorData).Name; generator.Emit(OpCodes.Call, typeof(Number).GetMethod(methodname, BindingFlags.Static | BindingFlags.Public)); } } else if (node.Token.Data is Evaluation.Tokenizing.RangeData) { SingleFunctionSubBuild(generator, node); generator.Emit(OpCodes.Call, typeof(Number).GetMethod("Range", BindingFlags.Static | BindingFlags.Public)); } else if (node.Token.Data is Evaluation.Tokenizing.CustomFunctionData) { SingleFunctionSubBuild(generator, node); generator.Emit(OpCodes.Call, (node.Token.Data as Evaluation.Tokenizing.CustomFunctionData).Type.GetMethod("Evaluate", BindingFlags.Static | BindingFlags.Public)); } else { } }
List<LocalVariableInfo> EmitRedirectionDescendants(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); List<LocalVariableInfo> output = new List<LocalVariableInfo>(); for (Int32 i = 0; i < node.Children.Count - 1; ++i) output.Add(Emit(state, node.Children[i])); foreach (Object arg in node.Arguments) { if (arg is String) { LocalVariableInfo local = state.Generator.DeclareLocal(typeof(String)); state.Generator.Emit(OpCodes.Ldstr, (String)arg); StoreLocalVariable(state, local); output.Add(local); } else if (arg.GetType().IsEnum == true) { LocalVariableInfo local = state.Generator.DeclareLocal(arg.GetType()); state.Generator.Emit(OpCodes.Ldc_I4, (Int32)arg); StoreLocalVariable(state, local); output.Add(local); } else { throw new Exception(); } } return output; }
LocalVariableInfo EmitNumber(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); Evaluation.Tokenizing.NumberData data = node.Token.Data as Evaluation.Tokenizing.NumberData; if (data == null) throw new Exception(); Number number = data.GetNumber(node.Token.ToString()); if (number.NumberType == NumberType.Int) { LocalVariableInfo local = state.Generator.DeclareLocal(typeof(Int32)); state.Generator.Emit(OpCodes.Ldc_I4, number.IntValue); StoreLocalVariable(state, local); return local; } if (number.NumberType == NumberType.Float) { LocalVariableInfo local = state.Generator.DeclareLocal(typeof(Single)); state.Generator.Emit(OpCodes.Ldc_R4, number.FloatValue); StoreLocalVariable(state, local); return local; } throw new Exception(); }
static Node BreakTree(Node lhs, Node operatornode, Node rhs) { if (lhs == null) throw new ArgumentNullException("lhs"); if (operatornode == null) throw new ArgumentNullException("operatornode"); if (rhs == null) throw new ArgumentNullException("rhs"); operatornode.Children.Add(lhs); Node newbase = rhs; while (newbase.Children.Count != 0 && newbase.Children[0].Children.Count != 0 && newbase.Children[0].PrecedenceOverride == false && SwitchOrder(operatornode, newbase.Children[0]) == true) { newbase = newbase.Children[0]; } operatornode.Children.Add(newbase.Children[0]); newbase.Children[0] = operatornode; return rhs; }
Node ParseRangeNode(List<Token> tokens, ref Int32 tokenindex) { if (tokens == null) throw new ArgumentNullException("tokens"); if (tokenindex < 0 || tokenindex >= tokens.Count) throw new ArgumentOutOfRangeException("tokenindex"); Int32 savedindex = tokenindex; Token token_pre = GetToken(tokens, tokenindex); if (token_pre == null || (token_pre.AsSymbol != Symbol.LeftBracket && token_pre.AsSymbol != Symbol.LeftParen)) goto EndOfMethod; ++tokenindex; Node node_left = ParseNode(tokens, ref tokenindex); if (node_left == null) goto EndOfMethod; Token token_comma = GetToken(tokens, tokenindex); if (token_comma == null || token_comma.AsSymbol != Symbol.Comma) goto EndOfMethod; ++tokenindex; Node node_right = ParseNode(tokens, ref tokenindex); if (node_right == null) goto EndOfMethod; Token token_post = GetToken(tokens, tokenindex); if (token_post == null || (token_post.AsSymbol != Symbol.RightBracket && token_post.AsSymbol != Symbol.RightParen)) goto EndOfMethod; ++tokenindex; Node rangenode = new Node(new Token(String.Empty, new Tokenizing.RangeData())); rangenode.Children.Add(null); rangenode.Children.Add(node_left); rangenode.Children.Add(node_right); rangenode.Arguments.Add(null); rangenode.Arguments.Add(token_pre.AsSymbol); rangenode.Arguments.Add(token_post.AsSymbol); return rangenode; EndOfMethod: tokenindex = savedindex; return null; }
Node ParseEndNode(List<Token> tokens, ref Int32 tokenindex) { if (tokens == null) throw new ArgumentNullException("tokens"); if (tokenindex < 0 || tokenindex >= tokens.Count) throw new ArgumentOutOfRangeException("tokenindex"); Token token = GetToken(tokens, tokenindex); if (token == null) return null; if (token.Data is Tokenizing.NumberData) { ++tokenindex; Node node = new Node(token); return node; } if (token.Data is Tokenizing.UnaryOperatorData) { ++tokenindex; Node node = new Node(token); Node child = ParseEndNode(tokens, ref tokenindex); if (child == null) return null; node.Children.Add(child); return node; } if (token.AsOperator == Operator.Minus || token.AsOperator == Operator.Plus) { ++tokenindex; Node node = new Node(token); Node child = ParseEndNode(tokens, ref tokenindex); if (child == null) return null; node.Children.Add(child); return node; } if (token.AsSymbol == Symbol.LeftParen) { Int32 savedindex = tokenindex; ++tokenindex; Node node = ParseNode(tokens, ref tokenindex); if (node != null) { Token endtoken = GetToken(tokens, tokenindex); if (endtoken != null && endtoken.AsSymbol == Symbol.RightParen) { ++tokenindex; node.PrecedenceOverride = true; return node; } } tokenindex = savedindex; } if (token.Data is Tokenizing.CustomFunctionData) { Tokenizing.CustomFunctionData data = token.Data as Tokenizing.CustomFunctionData; Node node = new Node(token); ++tokenindex; ParseState state = new ParseState(m_system, m_fullnodebuild, m_endnodebuild, m_rangenodebuild, node, tokens, tokenindex); Node parsednode = data.Parse(state); if (parsednode != null) { tokenindex = state.TokenIndex; return parsednode; } else { tokenindex = state.InitialTokenIndex - 1; return null; } } if (token.Data is Tokenizing.StateRedirectionData) { Tokenizing.StateRedirectionData data = token.Data as Tokenizing.StateRedirectionData; Node node = new Node(token); ++tokenindex; ParseState state = new ParseState(m_system, m_fullnodebuild, m_endnodebuild, m_rangenodebuild, node, tokens, tokenindex); Node parsednode = data.Parse(state); if (parsednode != null) { tokenindex = state.TokenIndex; return parsednode; } else { tokenindex = state.InitialTokenIndex - 1; return null; } } return null; }
static Node() { s_emptynode = new Node(new Token("", new Tokenizing.IntData())); s_zeronode = new Node(new Token("0", new Tokenizing.IntData())); s_negativeonenode = new Node(new Token("-1", new Tokenizing.IntData())); }
static IEnumerable<Node> EnumerateNodes(Node basenode) { foreach (Node node in basenode.Children) { foreach (Node child in EnumerateNodes(node)) yield return child; } yield return basenode; }
void SingleFunctionSubBuild(ILGenerator generator, Node node) { foreach (Node childnode in node.Children) { SingleFunctionBuild(generator, childnode); } foreach (Object arg in node.Arguments) { if (arg is String) { generator.Emit(OpCodes.Ldstr, (String)arg); } else if (arg.GetType().IsEnum == true) { generator.Emit(OpCodes.Ldc_I4, (Int32)arg); } else { } } }
static Boolean SwitchOrder(Node lhs, Node rhs) { if (lhs == null) throw new ArgumentNullException("lhs"); if (rhs == null) throw new ArgumentNullException("rhs"); if (rhs.PrecedenceOverride == true) return false; Tokenizing.BinaryOperatorData lhsdata = lhs.Token.Data as Tokenizing.BinaryOperatorData; Tokenizing.BinaryOperatorData rhsdata = rhs.Token.Data as Tokenizing.BinaryOperatorData; if (lhsdata == null || rhsdata == null) return false; return lhsdata.Precedence >= rhsdata.Precedence; }
LocalVariableInfo EmitUnaryOperator(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); Evaluation.Tokenizing.OperatorData data = node.Token.Data as Evaluation.Tokenizing.OperatorData; if (data == null) throw new Exception(); if (node.Children.Count != 1) throw new Exception(); if (data.Operator == Operator.Minus) { LocalVariableInfo value = Emit(state, node.Children[0]); LocalVariableInfo result = state.Generator.DeclareLocal(value.LocalType); LoadLocalVariable(state, value); state.Generator.Emit(OpCodes.Neg); StoreLocalVariable(state, result); return result; } if (data.Operator == Operator.LogicalNot) { LocalVariableInfo value = Emit(state, node.Children[0]); LoadLocalVariable(state, value); LocalVariableInfo result = state.Generator.DeclareLocal(typeof(Int32)); Label l1 = state.Generator.DefineLabel(); Label l2 = state.Generator.DefineLabel(); state.Generator.Emit(OpCodes.Brtrue, l1); state.Generator.Emit(OpCodes.Ldc_I4_1); state.Generator.Emit(OpCodes.Br, l2); state.Generator.MarkLabel(l1); state.Generator.Emit(OpCodes.Ldc_I4_0); state.Generator.MarkLabel(l2); StoreLocalVariable(state, result); return result; } throw new Exception(); }
EvaluationCallback NestedFunctionBuild(Node node) { if (node.Token.Data is Evaluation.Tokenizing.NumberData) { Number number = (node.Token.Data as Evaluation.Tokenizing.NumberData).GetNumber(node.Token.ToString()); return GetNumberCallback(number); } if (node.Token.Data is Evaluation.Tokenizing.RangeData) { Object[] args = new Object[node.Children.Count + node.Arguments.Count]; for (Int32 i = 0; i != node.Children.Count; ++i) args[i] = NestedFunctionBuild(node.Children[i]); for (Int32 i = 0; i != node.Arguments.Count; ++i) args[i + node.Children.Count] = node.Arguments[i]; Constructor constructor = GetRangeConstructor(); IFunction function = (IFunction)constructor(args); return function.Evaluate; } if (node.Token.AsOperator == Operator.Assignment) { Object[] args = new Object[node.Children.Count + node.Arguments.Count]; for (Int32 i = 0; i != node.Children.Count; ++i) args[i] = NestedFunctionBuild(node.Children[i]); for (Int32 i = 0; i != node.Arguments.Count; ++i) args[i + node.Children.Count] = node.Arguments[i]; Constructor constructor = GetCustomFunctionConstructor("_Assignment", typeof(Evaluation.Triggers._Assignment), args); IFunction function = (IFunction)constructor(args); return function.Evaluate; } if (node.Token.AsOperator != Operator.None) { Constructor constructor = GetOperatorTypeConstructor(node.Token.Data as OperatorData); EvaluationCallback[] childcallbacks; if (node.Token.AsOperator == Operator.Minus && node.Children.Count == 1) { childcallbacks = new EvaluationCallback[2] { GetNumberCallback(new Number(0)), NestedFunctionBuild(node.Children[0]) }; } else { childcallbacks = new EvaluationCallback[node.Children.Count]; for (Int32 i = 0; i != node.Children.Count; ++i) childcallbacks[i] = NestedFunctionBuild(node.Children[i]); } IFunction function = (IFunction)constructor(childcallbacks); return function.Evaluate; } if (node.Token.Data is Evaluation.Tokenizing.CustomFunctionData) { Object[] args = new Object[node.Children.Count + node.Arguments.Count]; for (Int32 i = 0; i != node.Children.Count; ++i) args[i] = NestedFunctionBuild(node.Children[i]); for (Int32 i = 0; i != node.Arguments.Count; ++i) args[i + node.Children.Count] = node.Arguments[i]; CustomFunctionData data = node.Token.Data as CustomFunctionData; Constructor constructor = GetCustomFunctionConstructor(data.Name, data.Type, args); IFunction function = (IFunction)constructor(args); return function.Evaluate; } return null; }
List<LocalVariableInfo> EmitDescendants(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); List<LocalVariableInfo> output = new List<LocalVariableInfo>(); foreach (Node child in node.Children) output.Add(Emit(state, child)); foreach (Object arg in node.Arguments) { if (arg is String) { LocalVariableInfo local = state.Generator.DeclareLocal(typeof(String)); state.Generator.Emit(OpCodes.Ldstr, (String)arg); StoreLocalVariable(state, local); output.Add(local); } else if (arg.GetType().IsEnum == true) { LocalVariableInfo local = state.Generator.DeclareLocal(arg.GetType()); state.Generator.Emit(OpCodes.Ldc_I4, (Int32)arg); StoreLocalVariable(state, local); output.Add(local); } else if (arg is Combat.HitType[]) { LocalVariableInfo local = state.Generator.DeclareLocal(arg.GetType()); Combat.HitType[] hitypes = (Combat.HitType[])arg; state.Generator.Emit(OpCodes.Ldc_I4, hitypes.Length); state.Generator.Emit(OpCodes.Newarr, typeof(Combat.HitType)); StoreLocalVariable(state, local); for (Int32 i = 0; i != hitypes.Length; ++i) { LoadLocalVariable(state, local); state.Generator.Emit(OpCodes.Ldc_I4, i); state.Generator.Emit(OpCodes.Ldc_I4, (Int32)hitypes[i].Class); state.Generator.Emit(OpCodes.Ldc_I4, (Int32)hitypes[i].Power); state.Generator.Emit(OpCodes.Newobj, typeof(Combat.HitType).GetConstructor(new Type[] { typeof(AttackClass), typeof(AttackPower) })); state.Generator.Emit(OpCodes.Stelem, typeof(Combat.HitType)); } output.Add(local); } else { throw new Exception(); } } return output; }
LocalVariableInfo EmitRange(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); Evaluation.Tokenizing.RangeData data = node.Token.Data as Evaluation.Tokenizing.RangeData; if (data == null) throw new Exception(); if (node.Children.Count != 3) throw new Exception(); if (node.Arguments.Count != 3) throw new Exception(); List<LocalVariableInfo> args = EmitDescendants(state, node); Type[] argtypes = new Type[args.Count]; for (Int32 i = 0; i != args.Count; ++i) argtypes[i] = args[i].LocalType; MethodInfo method = typeof(SpecialFunctions).GetMethod("Range", argtypes); return EmitMethod(state, method, args); }
LocalVariableInfo Emit(CompilerState state, Node node) { if (state == null) throw new Exception(); if (node == null) throw new Exception(); if (node.Token.Data is Evaluation.Tokenizing.NumberData) { return EmitNumber(state, node); } if (node.Token.Data is Evaluation.Tokenizing.OperatorData) { return EmitOperator(state, node); } if (node.Token.Data is Evaluation.Tokenizing.StateRedirectionData) { return EmitStateRedirection(state, node); } if (node.Token.Data is Evaluation.Tokenizing.CustomFunctionData) { return EmitFunction(state, node); } if (node.Token.Data is Evaluation.Tokenizing.RangeData) { return EmitRange(state, node); } throw new Exception(); }
EvaluationCallback SingleFunctionBuild(Node node) { DynamicMethod method = new DynamicMethod(String.Empty, typeof(Number), new Type[] { typeof(Object) }, typeof(TreeCompiler)); ILGenerator generator = method.GetILGenerator(); foreach (Node n in EnumerateNodes(node)) { if (n.Token.Data is Evaluation.Tokenizing.CustomFunctionData) generator.Emit(OpCodes.Ldarg, 0); } SingleFunctionBuild(generator, node); generator.Emit(OpCodes.Ret); EvaluationCallback callback = (EvaluationCallback)method.CreateDelegate(typeof(EvaluationCallback)); return callback; }