예제 #1
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);
            }
        }
예제 #2
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);
            }
        }
예제 #3
0
        public override void EmitInitialize(IBlockContext context, IBlockVariable variable)
        {
            if (runtimeType.IsValueType)
            {
                return;
            }

            context.IL.EmitNew(OpCodes.Newobj, constructor, 0, 1);
            variable.EmitStore(context);
        }
예제 #4
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);
 }
예제 #5
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);
        }
예제 #6
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
            });
        }
예제 #7
0
 public void EmitAssign(IBlockContext context, IBlockVariable variable, Node target)
 {
     EmitCode(context, target);
     variable.Type.AssignFrom(context.ModuleContext, ResultType).EmitConvert(context);
     variable.EmitStore(context);
 }
예제 #8
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);
            }
        }