private LocalName(LocalName other, int dist = 0) { Name = other.Name; Type = other.Type; IsImmutable = other.IsImmutable; IsRefArgument = other.IsRefArgument; IsClosured = other.IsClosured; ClosureFieldName = other.ClosureFieldName; IsConstant = other.IsConstant; ConstantValue = other.ConstantValue; LocalBuilder = other.LocalBuilder; ArgumentId = other.ArgumentId; ClosureDistance = dist; }
/// <summary> /// Registers closure entities and assigns IDs to variables. /// </summary> public void FinalizeScope(Context ctx) { foreach (var curr in Names.Values) { if (curr.IsConstant && curr.IsImmutable && ctx.Options.UnrollConstants) continue; if (curr.IsClosured) { // create a field in the closured class var name = string.Format(EntityNames.ClosureFieldNameTemplate, curr.Name); curr.ClosureFieldName = name; ClosureType.CreateField(name, curr.Type); } else { curr.LocalBuilder = ctx.CurrentILGenerator.DeclareLocal(curr.Type); } } // create a field for base scope in the current type if(OuterScope != null && ClosureType != null) ClosureType.CreateField(EntityNames.ParentScopeFieldName, OuterScope.ClosureType.TypeBuilder); // register a variable for closure instance in the scope if (ClosureType != null) ClosureVariable = DeclareInternalName(string.Format(EntityNames.ClosureInstanceVariableNameTemplate, ClosureTypeId), ctx, ClosureType.TypeBuilder, false); }
/// <summary> /// Declares a new name in the current scope. /// </summary> public LocalName DeclareName(string name, Type type, bool isConst, bool isRefArg = false) { if(find(name)) throw new LensCompilerException(string.Format(CompilerMessages.VariableDefined, name)); var n = new LocalName(name, type, isConst, isRefArg); Names[name] = n; return n; }
/// <summary> /// Declares a new temp variable that is instantly initialized. /// </summary> public LocalName DeclareInternalName(string name, Context ctx, Type type, bool isConst) { var lb = ctx.CurrentILGenerator.DeclareLocal(type); var ln = new LocalName(name, type, isConst) { LocalBuilder = lb }; Names[name] = ln; return ln; }
/// <summary> /// Declares a new variable with autogenerated name. /// This name cannot be closured. /// </summary> public LocalName DeclareImplicitName(Context ctx, Type type, bool isConst) { var lb = ctx.CurrentILGenerator.DeclareLocal(type); var name = string.Format(EntityNames.ImplicitVariableNameTemplate, lb.LocalIndex); var ln = new LocalName(name, type, isConst) { LocalBuilder = lb }; Names[name] = ln; return ln; }
public override void ProcessClosures(Context ctx) { base.ProcessClosures(ctx); var type = ExceptionType != null ? ctx.ResolveType(ExceptionType) : typeof(Exception); if (type != typeof(Exception) && !type.IsSubclassOf(typeof(Exception))) Error(CompilerMessages.CatchTypeNotException, type); if(!string.IsNullOrEmpty(ExceptionVariable)) m_ExceptionVariable = ctx.CurrentScope.DeclareName(ExceptionVariable, type, false); }
/// <summary> /// Saves the value from the stack to a local variable. /// </summary> public static void EmitSaveLocal(this ILGenerator gen, LocalName loc) { var varId = loc.LocalId.Value; gen.Emit(OpCodes.Stloc, (short)varId); }
public override void ProcessClosures(Context ctx) { if(IterableExpression != null) detectEnumerableType(ctx); else detectRangeType(ctx); m_Variable = ctx.CurrentScope.DeclareName(VariableName, m_VariableType, false); base.ProcessClosures(ctx); }
/// <summary> /// Loads the value of a local variable onto the stack. /// </summary> public static void EmitLoadLocal(this ILGenerator gen, LocalName loc, bool getPointer = false) { var varId = loc.LocalId.Value; if (getPointer) { if (varId < 255) gen.Emit(OpCodes.Ldloca_S, (byte)varId); else gen.Emit(OpCodes.Ldloca, (short)varId); } else { switch (varId) { case 0: gen.Emit(OpCodes.Ldloc_0); break; case 1: gen.Emit(OpCodes.Ldloc_1); break; case 2: gen.Emit(OpCodes.Ldloc_2); break; case 3: gen.Emit(OpCodes.Ldloc_3); break; default: gen.Emit(OpCodes.Ldloc, (short)varId); break; } } }
/// <summary> /// Assigns a closured variable that has been imported from outer scopes. /// </summary> private void assignClosuredRemote(Context ctx, LocalName name) { var gen = ctx.CurrentILGenerator; gen.EmitLoadArgument(0); var dist = name.ClosureDistance; var type = (Type)ctx.CurrentType.TypeBuilder; while (dist > 1) { var rootField = ctx.ResolveField(type, EntityNames.ParentScopeFieldName); gen.EmitLoadField(rootField.FieldInfo); type = rootField.FieldType; dist--; } Expr.Cast(Value, name.Type).Compile(ctx, true); var clsField = ctx.ResolveField(type, name.ClosureFieldName); gen.EmitSaveField(clsField.FieldInfo); }
private void assignLocal(Context ctx, LocalName name) { var gen = ctx.CurrentILGenerator; var castNode = Expr.Cast(Value, name.Type); if (!name.IsRefArgument) { castNode.Compile(ctx, true); if(name.ArgumentId.HasValue) gen.EmitSaveArgument(name.ArgumentId.Value); else gen.EmitSaveLocal(name); } else { gen.EmitLoadArgument(name.ArgumentId.Value); castNode.Compile(ctx, true); gen.EmitSaveObject(name.Type); } }
/// <summary> /// Assigns a closured variable that is declared in current scope. /// </summary> private void assignClosuredLocal(Context ctx, LocalName name) { var gen = ctx.CurrentILGenerator; gen.EmitLoadLocal(ctx.CurrentScope.ClosureVariable); Expr.Cast(Value, name.Type).Compile(ctx, true); var clsType = ctx.CurrentScope.ClosureType.TypeInfo; var clsField = ctx.ResolveField(clsType, name.ClosureFieldName); gen.EmitSaveField(clsField.FieldInfo); }
private void getLocal(Context ctx, LocalName name) { var gen = ctx.CurrentILGenerator; var ptr = PointerRequired || RefArgumentRequired; if (name.ArgumentId.HasValue) { gen.EmitLoadArgument(name.ArgumentId.Value, ptr); if(name.IsRefArgument && !ptr) gen.EmitLoadFromPointer(name.Type); } else { gen.EmitLoadLocal(name, ptr); } }
/// <summary> /// Gets a closured variable that has been imported from outer scopes. /// </summary> private void getClosuredRemote(Context ctx, LocalName name) { var gen = ctx.CurrentILGenerator; gen.EmitLoadArgument(0); var dist = name.ClosureDistance; var type = (Type)ctx.CurrentType.TypeBuilder; while (dist > 1) { var rootField = ctx.ResolveField(type, EntityNames.ParentScopeFieldName); gen.EmitLoadField(rootField.FieldInfo); type = rootField.FieldType; dist--; } var clsField = ctx.ResolveField(type, name.ClosureFieldName); gen.EmitLoadField(clsField.FieldInfo, PointerRequired || RefArgumentRequired); }
/// <summary> /// Gets a closured variable that has been declared in the current scope. /// </summary> private void getClosuredLocal(Context ctx, LocalName name) { var gen = ctx.CurrentILGenerator; gen.EmitLoadLocal(ctx.CurrentScope.ClosureVariable); var clsField = ctx.CurrentScope.ClosureType.ResolveField(name.ClosureFieldName); gen.EmitLoadField(clsField.FieldBuilder, PointerRequired || RefArgumentRequired); }
protected override Type resolveExpressionType(Context ctx, bool mustReturn = true) { var local = LocalName ?? ctx.CurrentScope.FindName(Identifier); if (local != null) { // only local constants are cached // because mutable variables could be closured later on if (local.IsConstant && local.IsImmutable && ctx.Options.UnrollConstants) m_LocalConstant = local; return local.Type; } try { var methods = ctx.MainType.ResolveMethodGroup(Identifier); if (methods.Length > 1) Error(CompilerMessages.FunctionInvocationAmbiguous, Identifier); m_Method = methods[0]; return FunctionalHelper.CreateFuncType(m_Method.ReturnType, m_Method.GetArgumentTypes(ctx)); } catch (KeyNotFoundException) { } try { m_Property = ctx.ResolveGlobalProperty(Identifier); return m_Property.PropertyType; } catch (KeyNotFoundException) { Error(CompilerMessages.IdentifierNotFound, Identifier); } return typeof (Unit); }