Example #1
0
        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;
        }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <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;
        }
Example #4
0
 /// <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;
 }
Example #5
0
 /// <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;
 }
Example #6
0
        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);
        }
Example #7
0
 /// <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);
 }
Example #8
0
        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);
        }
Example #9
0
        /// <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;
                }
            }
        }
Example #10
0
        /// <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);
        }
Example #11
0
        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);
            }
        }
Example #12
0
        /// <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);
        }
Example #13
0
        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);
            }
        }
Example #14
0
        /// <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);
        }
Example #15
0
        /// <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);
        }
Example #16
0
        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);
        }