internal override Variable AddVariable(string name, Type type, Expression valueAtTopOfScope) { if (name == null) { throw new ArgumentNullException("name"); } // If variables cannot be declared in the scope, try the parent scope instead. if (this.CanDeclareVariables == false) { if (this.ParentScope == null) { throw new InvalidOperationException("Invalid scope chain."); } return(this.ParentScope.AddVariable(name, type, valueAtTopOfScope)); } Variable variable; this.variables.TryGetValue(name, out variable); DeclaredVariable dVariable; if (variable == null || !(variable is DeclaredVariable)) { // This is a local variable that has not been declared before (or is an arg being overwritten). dVariable = new DeclaredVariable() { Name = name, Scope = this }; variable = dVariable; this.variables[name] = dVariable; } else { dVariable = (DeclaredVariable)variable; } // Set the initial value, if one was provided. if (valueAtTopOfScope != null) { // Function expressions override literals. if ((valueAtTopOfScope is LiteralExpression && dVariable.ValueAtTopOfScope is FunctionExpression) == false) { dVariable.ValueAtTopOfScope = valueAtTopOfScope; } } variable.Type = type; return(variable); }
/// <summary>Called before recompiling a function with different args.</summary> public override void Reset() { foreach (KeyValuePair <string, Variable> kvp in variables) { DeclaredVariable dec = kvp.Value as DeclaredVariable; if (dec == null) { continue; } // Ensure store is cleared out: dec.Store = null; } }
/// <summary> /// Generates code that initializes the variable and function declarations. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> internal void GenerateDeclarations(ILGenerator generator, OptimizationInfo optimizationInfo) { // Parent root: Expression rootExpression = optimizationInfo.RootExpression; // Initialize the declared variables and functions. foreach (var variable in this.variables.Values) { DeclaredVariable dVariable = variable as DeclaredVariable; // When a scope is reused, i.e. with an eval(), do not reinitialize the variables. if (dVariable == null || dVariable.Initialized) { continue; } if (dVariable.ValueAtTopOfScope != null) { // Emit the initialization code. var name = new NameExpression(this, dVariable.Name); Type rType = dVariable.ValueAtTopOfScope.GetResultType(optimizationInfo); name.ApplyType(optimizationInfo, rType); name.GenerateSet(generator, optimizationInfo, false, rType, delegate(bool two) { optimizationInfo.RootExpression = dVariable.ValueAtTopOfScope; dVariable.ValueAtTopOfScope.GenerateCode(generator, optimizationInfo); if (two) { // Dupe it: generator.Duplicate(); } }, false); // Mark the variable as having been initialized. dVariable.Initialized = true; } } // Restore root: optimizationInfo.RootExpression = rootExpression; }