コード例 #1
0
        protected override void EmitAssignToPtr(IBlockContext context, IBlockVariable tempSource)
        {
            foreach (var kv in targetType.fields)
            {
                IFieldAccessFactory sourceFieldFactory = sourceType.FindField(context.ModuleContext, kv.Key);
                if (sourceFieldFactory == null)
                {
                    continue;
                }

                IFieldAccessEmitter sourceField = sourceFieldFactory.Create(context.ModuleContext);
                context.IL.Emit(OpCodes.Dup);
                if (sourceField.RequiresPtr)
                {
                    tempSource.EmitLoadPtr(context);
                }
                else
                {
                    tempSource.EmitLoad(context);
                }
                sourceField.EmitLoad(context);
                targetType.ItemTypes[kv.Key].AssignFrom(context.ModuleContext, sourceType.ItemTypes[kv.Key])
                .EmitConvert(context);
                context.IL.Emit(OpCodes.Stfld, kv.Value);
            }

            context.IL.Emit(OpCodes.Pop);
        }
コード例 #2
0
        // ---------------- IAssignEmitter -----------------
        public void EmitAssign(IBlockContext context, IBlockVariable variable, Expression expression, bool dropResult)
        {
            using ITempBlockVariable valueTemp = context.MakeTempVariable(sourceType);
            expression.EmitStore(context, valueTemp, true);

            variable.EmitLoadPtr(context);
            EmitAssignToPtr(context, valueTemp);
            if (!dropResult)
            {
                variable.EmitLoad(context);
            }
        }
コード例 #3
0
        public override void EmitStore(IBlockContext context, IBlockVariable variable, bool dropResult)
        {
            if (!BuiltinType.Int.IsAssignableFrom(context.ModuleContext, from.ResultType(context)))
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.IncompatibleTypes,
                                     "Range can only be created from int values",
                                     from.Start,
                                     from.End
                                     ));
            }
            if (!BuiltinType.Int.IsAssignableFrom(context.ModuleContext, to.ResultType(context)))
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.IncompatibleTypes,
                                     "Range can only be created from int values",
                                     to.Start,
                                     to.End
                                     ));
            }

            if (context.HasErrors)
            {
                return;
            }

            variable.EmitLoadPtr(context);
            context.IL.Emit(OpCodes.Dup);
            from.EmitCode(context, false);
            context.IL.Emit(OpCodes.Stfld, typeof(Range).GetField("from"));
            to.EmitCode(context, false);
            if (inclusive)
            {
                context.IL.Emit(OpCodes.Ldc_I4_1);
                context.IL.Emit(OpCodes.Conv_I8);
                context.IL.Emit(OpCodes.Add);
            }

            context.IL.Emit(OpCodes.Stfld, typeof(Range).GetField("to"));

            if (!dropResult)
            {
                variable.EmitLoad(context);
            }
        }
コード例 #4
0
        public void EmitConstructor(IBlockContext context)
        {
            foreach (StructField field in fields.Where(e => e.IsRight).Select(e => e.Right))
            {
                TO2Type initializerType = field.initializer.ResultType(context);
                if (!field.type.IsAssignableFrom(context.ModuleContext, initializerType))
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.IncompatibleTypes,
                                         $"Expected item {field.name} of {name} to be a {field.type}, found {initializerType}",
                                         Start,
                                         End
                                         ));
                }
            }

            if (context.HasErrors)
            {
                return;
            }

            Type           type     = typeDelegate.GeneratedType(context.ModuleContext);
            IBlockVariable variable =
                context.DeclaredVariable("instance", false, typeDelegate.UnderlyingType(context.ModuleContext));

            variable.EmitLoad(context);

            foreach (StructField field in fields.Where(e => e.IsRight).Select(e => e.Right))
            {
                context.IL.Emit(OpCodes.Dup);
                field.initializer.EmitCode(context, false);
                field.type.AssignFrom(context.ModuleContext, field.initializer.ResultType(context))
                .EmitConvert(context);
                context.IL.Emit(OpCodes.Stfld, type.GetField(field.name));
            }

            context.IL.EmitReturn(type);

            typeDelegate.CreateStructType();
        }
コード例 #5
0
        public void EmitAssign(IBlockContext context, IBlockVariable variable, Expression expression, bool dropResult)
        {
            Type generatedType = optionType.GeneratedType(context.ModuleContext);

            using ITempBlockVariable valueTemp =
                      context.MakeTempVariable(optionType.elementType.UnderlyingType(context.ModuleContext));
            optionType.elementType.AssignFrom(context.ModuleContext, otherType)
            .EmitAssign(context, valueTemp, expression, true);

            variable.EmitLoadPtr(context);
            context.IL.Emit(OpCodes.Dup);
            context.IL.Emit(OpCodes.Initobj, generatedType, 1, 0);
            context.IL.Emit(OpCodes.Dup);
            context.IL.Emit(OpCodes.Ldc_I4_1);
            context.IL.Emit(OpCodes.Stfld, generatedType.GetField("defined"));
            valueTemp.EmitLoad(context);
            context.IL.Emit(OpCodes.Stfld, generatedType.GetField("value"));
            if (!dropResult)
            {
                variable.EmitLoad(context);
            }
        }
コード例 #6
0
        public override void EmitStore(IBlockContext context, IBlockVariable variable, bool dropResult)
        {
            TupleType tupleType = variable.Type as TupleType;

            if (tupleType == null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.InvalidType,
                                     $"{variable.Type} is not a tuple",
                                     Start,
                                     End
                                     ));
                return;
            }
            else
            {
                if (items.Count != tupleType.itemTypes.Count)
                {
                    context.AddError(new StructuralError(
                                         StructuralError.ErrorType.InvalidType,
                                         $"Expected tuple of {tupleType.itemTypes.Count} items, found {items.Count} items",
                                         Start,
                                         End
                                         ));
                }

                for (int i = 0; i < items.Count; i++)
                {
                    TO2Type valueType = items[i].ResultType(context);
                    if (!tupleType.itemTypes[i].IsAssignableFrom(context.ModuleContext, valueType))
                    {
                        context.AddError(new StructuralError(
                                             StructuralError.ErrorType.InvalidType,
                                             $"Expected item {i} of {tupleType} to be a {tupleType.itemTypes[i]}, found {valueType}",
                                             Start,
                                             End
                                             ));
                    }
                }
            }

            if (context.HasErrors)
            {
                return;
            }

            foreach (Expression item in items)
            {
                item.Prepare(context);
            }

            Type type = tupleType.GeneratedType(context.ModuleContext);

            variable.EmitLoadPtr(context);
            // Note: Potentially overoptimized: Since all fields will be set, initialization should not be necessary
            //            context.IL.Emit(OpCodes.Dup);
            //            context.IL.Emit(OpCodes.Initobj, type, 1, 0);

            for (int i = 0; i < items.Count; i++)
            {
                if (i > 0 && i % 7 == 0)
                {
                    context.IL.Emit(OpCodes.Ldflda, type.GetField("Rest"));
                    type = type.GetGenericArguments()[7];
                    //                    context.IL.Emit(OpCodes.Dup);
                    //                    context.IL.Emit(OpCodes.Initobj, type, 1, 0);
                }

                if (i < items.Count - 1)
                {
                    context.IL.Emit(OpCodes.Dup);
                }
                items[i].EmitCode(context, false);
                tupleType.itemTypes[i].AssignFrom(context.ModuleContext, items[i].ResultType(context))
                .EmitConvert(context);
                context.IL.Emit(OpCodes.Stfld, type.GetField($"Item{i % 7 + 1}"));
            }

            if (context.HasErrors)
            {
                return;
            }

            if (!dropResult)
            {
                variable.EmitLoad(context);
            }
        }
コード例 #7
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            IBlockVariable blockVariable = context.FindVariable(name);

            if (blockVariable == null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchVariable,
                                     $"No local variable '{name}'",
                                     Start,
                                     End
                                     ));
            }
            else if (blockVariable.IsConst)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.NoSuchVariable,
                                     $"Local variable '{name}' is read-only (const)",
                                     Start,
                                     End
                                     ));
            }

            if (context.HasErrors)
            {
                return;
            }

            TO2Type valueType = expression.ResultType(context);

            if (context.HasErrors)
            {
                return;
            }

            if (op == Operator.Assign)
            {
                EmitAssign(context, blockVariable, valueType, dropResult);
                return;
            }

            IOperatorEmitter operatorEmitter = blockVariable !.Type.AllowedSuffixOperators(context.ModuleContext)
                                               .GetMatching(context.ModuleContext, op, valueType);

            if (operatorEmitter == null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.IncompatibleTypes,
                                     $"Cannot {op} a {blockVariable.Type} with a {valueType}",
                                     Start,
                                     End
                                     ));
                return;
            }

            expression.Prepare(context);

            blockVariable.EmitLoad(context);
            expression.EmitCode(context, false);

            if (context.HasErrors)
            {
                return;
            }

            operatorEmitter.OtherType.AssignFrom(context.ModuleContext, valueType).EmitConvert(context);
            operatorEmitter.EmitAssign(context, blockVariable, this);

            if (!dropResult)
            {
                blockVariable.EmitLoad(context);
            }
        }