/// <summary> /// Resolves which function is being called where possible. /// </summary> internal override void ResolveVariables(OptimizationInfo optimizationInfo) { // Resolve condition: Condition.ResolveVariables(optimizationInfo); // Is the condition constant? StaticResult = Condition.Evaluate(); if (StaticResult == null) { // Resolve both: IfClause.ResolveVariables(optimizationInfo); if (ElseClause != null) { // Only resolve else. ElseClause.ResolveVariables(optimizationInfo); } } else { // Convert it to a bool: bool result = TypeConverter.ToBoolean(StaticResult); if (result) { // Only resolve if. IfClause.ResolveVariables(optimizationInfo); } else { if (ElseClause != null) { // Only resolve else. ElseClause.ResolveVariables(optimizationInfo); } } } }
/// <summary> /// Generates IL for a specific variant of the method. Arguments MUST include 'this' keyword. /// </summary> public UserDefinedFunction GenerateCode(ArgVariable[] arguments, OptimizationInfo optimizationInfo) { // Generate the abstract syntax tree if it hasn't already been generated. if (this.AbstractSyntaxTree == null) { Parse(optimizationInfo); Dependencies = optimizationInfo.NestedFunctions; } // Create the param types, which is the args (as they already include 'this'): int argCount = arguments == null?0 : arguments.Length; Type[] parameters = new Type[argCount]; for (int i = 0; i < argCount; i++) { // Transfer the type over: parameters[i] = arguments[i].Type; } string name = GetMethodName(); // Initialize global code-gen information. optimizationInfo.AbstractSyntaxTree = this.AbstractSyntaxTree; optimizationInfo.StrictMode = this.StrictMode; optimizationInfo.MethodOptimizationHints = this.MethodOptimizationHints; optimizationInfo.FunctionName = this.GetStackName(); optimizationInfo.Source = this.Source; ILGenerator generator; // Create the UDF now (must be before we generate the code as it would go recursive for recursive functions otherwise): UserDefinedFunction mtd = new UserDefinedFunction(name, arguments, this as FunctionMethodGenerator, StrictMode); // Add to created set: GeneratedMethods.Add(mtd); // Clear locals: if (InitialScope != null) { InitialScope.Reset(); } // Resolve variables now: AbstractSyntaxTree.ResolveVariables(optimizationInfo); // Low trust path. ReflectionEmitModuleInfo reflectionEmitInfo = this.Engine.ReflectionEmitInfo; var typeBuilder = reflectionEmitInfo.MainType; // Create the method builder now: var methodBuilder = typeBuilder.DefineMethod(name, System.Reflection.MethodAttributes.HideBySig | System.Reflection.MethodAttributes.Static | System.Reflection.MethodAttributes.Public, optimizationInfo.ReturnType, parameters); mtd.body = methodBuilder; // Generate the IL for the method. generator = new ReflectionEmitILGenerator(Engine, methodBuilder); if (ScriptEngine.EnableILAnalysis) { // Replace the generator with one that logs. generator = new LoggingILGenerator(generator); } // optimizationInfo.MarkSequencePoint(generator, new SourceCodeSpan(1, 1, 1, 1)); GenerateCode(arguments, generator, optimizationInfo); generator.Complete(); if (ScriptEngine.EnableILAnalysis) { // Store the disassembled IL so it can be retrieved for analysis purposes. mtd.DisassembledIL = generator.ToString(); string args = ""; if (arguments != null) { for (int i = 0; i < arguments.Length; i++) { if (i != 0) { args += ","; } args += parameters[i] + " " + arguments[i].Name.ToString(); } } Engine.Log("-IL " + GetMethodName() + "(" + args + ") : " + methodBuilder.ReturnType + "-"); Engine.Log(mtd.DisassembledIL); } return(mtd); }