Пример #1
0
        public void EmitExtract(IBlockContext context, List <IBlockVariable> targetVariables)
        {
            IBlockVariable target = targetVariables[0];

            Type generatedType = resultType.GeneratedType(context.ModuleContext);

            context.IL.Emit(OpCodes.Dup);
            context.IL.Emit(OpCodes.Ldfld, generatedType.GetField("success"));
            if (target == null)
            {
                context.IL.Emit(OpCodes.Ldc_I4_0);
                context.IL.Emit(OpCodes.Ceq);
                context.IL.Emit(OpCodes.Pop);
            }
            else
            {
                LabelRef onOk = context.IL.DefineLabel(true);
                LabelRef end  = context.IL.DefineLabel(true);

                context.IL.Emit(OpCodes.Brtrue_S, onOk);
                context.IL.Emit(OpCodes.Ldfld, generatedType.GetField("error"));
                target.EmitStore(context);
                context.IL.Emit(OpCodes.Ldc_I4_1);
                context.IL.Emit(OpCodes.Br_S, end);

                context.IL.MarkLabel(onOk);
                context.IL.Emit(OpCodes.Pop);
                context.IL.Emit(OpCodes.Ldc_I4_0);

                context.IL.MarkLabel(end);
            }
        }
Пример #2
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);
        }
Пример #3
0
        public void EmitExtract(IBlockContext context, List <IBlockVariable> targetVariables)
        {
            IBlockVariable target = targetVariables[0];

            Type generatedType = optionType.GeneratedType(context.ModuleContext);

            context.IL.Emit(OpCodes.Dup);
            context.IL.Emit(OpCodes.Ldfld, generatedType.GetField("defined"));

            if (target == null)
            {
                context.IL.Emit(OpCodes.Pop);
            }
            else
            {
                LabelRef onUndefined = context.IL.DefineLabel(true);
                LabelRef end         = context.IL.DefineLabel(true);

                context.IL.Emit(OpCodes.Brfalse_S, onUndefined);
                context.IL.Emit(OpCodes.Ldfld, generatedType.GetField("value"));
                target.EmitStore(context);
                context.IL.Emit(OpCodes.Ldc_I4_1);
                context.IL.Emit(OpCodes.Br_S, end);

                context.IL.MarkLabel(onUndefined);
                context.IL.Emit(OpCodes.Pop);
                context.IL.Emit(OpCodes.Ldc_I4_0);

                context.IL.MarkLabel(end);
            }
        }
Пример #4
0
        public void EmitAssign(IBlockContext context, IBlockVariable variable, Node target)
        {
            using ITempBlockVariable tempRight = context.MakeTempVariable(sourceType);
            tempRight.EmitStore(context);
            context.IL.Emit(OpCodes.Pop); // Left side is just the variable we are about to override

            variable.EmitLoadPtr(context);
            EmitAssignToPtr(context, tempRight);
        }
Пример #5
0
        public override void EmitInitialize(IBlockContext context, IBlockVariable variable)
        {
            if (runtimeType.IsValueType)
            {
                return;
            }

            context.IL.EmitNew(OpCodes.Newobj, constructor, 0, 1);
            variable.EmitStore(context);
        }
Пример #6
0
 public void EmitAssign(IBlockContext context, IBlockVariable variable, Expression expression,
                        bool dropResult)
 {
     expression.EmitCode(context, false);
     context.IL.Emit(OpCodes.Conv_R8);
     if (!dropResult)
     {
         context.IL.Emit(OpCodes.Dup);
     }
     variable.EmitStore(context);
 }
Пример #7
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);
            }
        }
Пример #8
0
        /// <summary>
        /// Variant of Emit when the result of the expression should be directly stored to a local variable.
        /// </summary>
        public virtual void EmitStore(IBlockContext context, IBlockVariable variable, bool dropResult)
        {
            EmitCode(context, false);

            if (context.HasErrors)
            {
                return;
            }

            if (!dropResult)
            {
                context.IL.Emit(OpCodes.Dup);
            }

            variable.EmitStore(context);
        }
Пример #9
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);
            }
        }
Пример #10
0
        private void EmitAssign(IBlockContext context, IBlockVariable blockVariable, TO2Type valueType,
                                bool dropResult)
        {
            if (!blockVariable.Type.IsAssignableFrom(context.ModuleContext, valueType))
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.IncompatibleTypes,
                                     $"Variable '{name}' is of type {blockVariable.Type} but is assigned to {valueType}",
                                     Start,
                                     End
                                     ));
            }

            if (context.HasErrors)
            {
                return;
            }

            blockVariable.Type.AssignFrom(context.ModuleContext, valueType)
            .EmitAssign(context, blockVariable, expression, dropResult);
        }
Пример #11
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();
        }
Пример #12
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);
            }
        }
Пример #13
0
        private ILCount EstimateLoop(IBlockContext context, IForInSource source)
        {
            IBlockContext prepContext = context.CloneCountingContext();

            sourceExpression.EmitCode(prepContext, false);
            source.EmitInitialize(prepContext);

            IBlockContext countingContext = prepContext.CloneCountingContext()
                                            .CreateLoopContext(context.IL.DefineLabel(false), context.IL.DefineLabel(false));
            IBlockVariable loopVariable = countingContext.DeclaredVariable(variableName, true, source.ElementType);
            LabelRef       loop         = countingContext.IL.DefineLabel(false);

            source.EmitNext(countingContext);
            loopVariable.EmitStore(countingContext);
            loopExpression.EmitCode(countingContext, true);
            source.EmitCheckDone(countingContext, loop);

            return(new ILCount {
                opCodes = countingContext.IL.ILSize,
                stack = countingContext.IL.StackCount
            });
        }
Пример #14
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            RealizedType sourceType = sourceExpression.ResultType(context).UnderlyingType(context.ModuleContext);
            IForInSource source     = sourceType.ForInSource(context.ModuleContext, variableType);

            if (source == null)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.InvalidType,
                        $"{sourceType} cannot be use as for ... in source",
                        Start,
                        End
                        )
                    );
            }
            if (context.FindVariable(variableName) != null)
            {
                context.AddError(new StructuralError(
                                     StructuralError.ErrorType.DuplicateVariableName,
                                     $"Variable '{variableName}' already declared in this scope",
                                     Start,
                                     End
                                     ));
            }
            if (source != null && variableType != null &&
                !variableType.IsAssignableFrom(context.ModuleContext, source.ElementType))
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.InvalidType,
                        $"{sourceType} has elements of type {source.ElementType}, expected {variableType}",
                        Start,
                        End
                        )
                    );
            }

            if (context.HasErrors)
            {
                return;
            }

            using ITempLocalRef loopCounter = context.IL.TempLocal(typeof(int));
            ILCount  loopSize = EstimateLoop(context, source);
            LabelRef start    = context.IL.DefineLabel(loopSize.opCodes < 110);
            LabelRef end      = context.IL.DefineLabel(loopSize.opCodes < 110);
            LabelRef loop     = context.IL.DefineLabel(loopSize.opCodes < 100);

            IBlockContext  loopContext  = context.CreateLoopContext(start, end);
            IBlockVariable loopVariable = loopContext.DeclaredVariable(variableName, true, source !.ElementType);

            sourceExpression.EmitCode(context, false);

            if (context.HasErrors)
            {
                return;
            }

            source.EmitInitialize(loopContext);
            loopContext.IL.Emit(start.isShort ? OpCodes.Br_S : OpCodes.Br, start);

            loopContext.IL.MarkLabel(loop);

            // Timeout check
            LabelRef skipCheck = context.IL.DefineLabel(true);

            loopCounter.EmitLoad(loopContext);
            loopContext.IL.Emit(OpCodes.Ldc_I4_1);
            loopContext.IL.Emit(OpCodes.Add);
            loopContext.IL.Emit(OpCodes.Dup);
            loopCounter.EmitStore(loopContext);
            loopContext.IL.Emit(OpCodes.Ldc_I4, 10000);
            loopContext.IL.Emit(OpCodes.Cgt);
            loopContext.IL.Emit(OpCodes.Brfalse, skipCheck);
            loopContext.IL.Emit(OpCodes.Ldc_I4_0);
            loopCounter.EmitStore(loopContext);
            context.IL.EmitCall(OpCodes.Call, typeof(Runtime.ContextHolder).GetMethod("CheckTimeout"), 0);
            loopContext.IL.MarkLabel(skipCheck);

            source.EmitNext(loopContext);
            loopVariable.EmitStore(loopContext);
            loopExpression.EmitCode(loopContext, true);
            loopContext.IL.MarkLabel(start);
            source.EmitCheckDone(loopContext, loop);
            loopContext.IL.MarkLabel(end);
            if (!dropResult)
            {
                context.IL.Emit(OpCodes.Ldnull);
            }
        }
Пример #15
0
 public void EmitAssign(IBlockContext context, IBlockVariable variable, Node target)
 {
     EmitCode(context, target);
     variable.Type.AssignFrom(context.ModuleContext, ResultType).EmitConvert(context);
     variable.EmitStore(context);
 }
Пример #16
0
 public virtual void EmitInitialize(IBlockContext context, IBlockVariable variable)
 {
 }
Пример #17
0
 protected abstract void EmitAssignToPtr(IBlockContext context, IBlockVariable tempSource);
Пример #18
0
 public void EmitAssign(IBlockContext context, IBlockVariable variable, Expression expression,
                        bool dropResult) => expression.EmitStore(context, variable, dropResult);
Пример #19
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);
            }
        }
Пример #20
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);
            }
        }