internal override void FinishBind(TotemNameBinder binder) { if (_freeVars != null && _freeVars.Count > 0) { ReadOnlyCollectionBuilder<TotemVariable> closureVariables = new ReadOnlyCollectionBuilder<TotemVariable>(); _closureType = MutableTuple.MakeTupleType(_freeVars.Select(v => typeof(ClosureCell)).ToArray()); _localClosureTuple = Expression.Parameter(_closureType, "$closure"); for (var i = 0; i < _freeVars.Count; i++) { var variable = _freeVars[i]; _variableMapping[variable] = new ClosureExpression(variable, Expression.Property(_localClosureTuple, String.Format("Item{0:D3}", i)), null); closureVariables.Add(variable); } _closureVariables = closureVariables.ToReadOnlyCollection(); } if (_scopeVars != null) foreach (var local in _scopeVars) { if (local.Kind == VariableKind.Parameter) // handled in subclass continue; // scope variables, defined in this scope Debug.Assert(local.Kind == VariableKind.Local); Debug.Assert(local.Scope == this); if (local.AccessedInNestedScope) { // Closure variable _variableMapping[local] = new ClosureExpression(local, Expression.Parameter(typeof(ClosureCell), local.Name), null); } else { // Not used in nested function-scopes _variableMapping[local] = Expression.Parameter(typeof(object), local.Name); } } }
internal virtual void FinishBind(TotemNameBinder binder) { if (_freeVars != null) foreach (var variable in _freeVars) { // Free variables, defined in outer scopes. // Note that this scope is only a lexical scope (like a loop // or BlockStatement), thus we don't need to query a local // closure-tuple, we simply ask the parent scope for the // binding. _variableMapping[variable] = Parent._variableMapping[variable]; } if (_scopeVars != null) foreach (var local in _scopeVars) { // scope variables, defined in this scope Debug.Assert(local.Kind == VariableKind.Local); Debug.Assert(local.Scope == this); if (local.AccessedInNestedScope) { // Closure variable _variableMapping[local] = new ClosureExpression(local, Expression.Parameter(typeof(ClosureCell), local.Name), null); } else { // Not used in nested function-scopes _variableMapping[local] = Expression.Parameter(typeof(object), local.Name); } } }
internal virtual void FinishBind(TotemNameBinder binder) { List<ClosureInfo> closureVariables = null; if (FreeVariables != null && FreeVariables.Count > 0) { _localParentTuple = Ast.Parameter(Parent.GetClosureTupleType(), "$tuple"); foreach (var variable in _freeVars) { var parentClosure = Parent._closureVariables; Debug.Assert(parentClosure != null); for (int i = 0; i < parentClosure.Length; i++) { if (parentClosure[i].Variable == variable) { _variableMapping[variable] = new ClosureExpression(variable, Ast.Property(_localParentTuple, String.Format("Item{0:D3}", i)), null); break; } } Debug.Assert(_variableMapping.ContainsKey(variable)); if (closureVariables == null) { closureVariables = new List<ClosureInfo>(); } closureVariables.Add(new ClosureInfo(variable, true)); } } if (Variables != null) { foreach (TotemVariable variable in Variables.Values) { if (!HasClosureVariable(closureVariables, variable) && !variable.IsGlobal && (variable.AccessedInNestedScope || ExposesLocalVariable(variable))) { if (closureVariables == null) { closureVariables = new List<ClosureInfo>(); } closureVariables.Add(new ClosureInfo(variable, true)); } if (variable.Kind == VariableKind.Local) { Debug.Assert(variable.Scope == this); if (variable.AccessedInNestedScope || ExposesLocalVariable(variable)) { _variableMapping[variable] = new ClosureExpression(variable, Ast.Parameter(typeof(ClosureCell), variable.Name), null); } else { _variableMapping[variable] = Ast.Parameter(typeof(object), variable.Name); } } } } if (closureVariables != null) { _closureVariables = closureVariables.ToArray(); } }