Beispiel #1
0
        public void EmitConvert(IBlockContext context)
        {
            using ITempBlockVariable valueTemp = context.MakeTempVariable(sourceType);
            valueTemp.EmitStore(context);

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

            using ITempLocalRef someResult = context.IL.TempLocal(generatedType);
            someResult.EmitLoadPtr(context);
            EmitAssignToPtr(context, valueTemp);
            someResult.EmitLoad(context);
        }
Beispiel #2
0
        // ---------------- IOperatorEmitter ----------------
        public void EmitCode(IBlockContext context, Node target)
        {
            using ITempBlockVariable tempRight = context.MakeTempVariable(sourceType);
            tempRight.EmitStore(context);

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

            using ITempLocalRef someResult = context.IL.TempLocal(generatedType);
            someResult.EmitStore(context);

            someResult.EmitLoadPtr(context);
            EmitAssignToPtr(context, tempRight);
            someResult.EmitLoad(context);
        }
Beispiel #3
0
        public void EmitConvert(IBlockContext context)
        {
            Type generatedType = optionType.GeneratedType(context.ModuleContext);

            using ITempLocalRef value =
                      context.IL.TempLocal(optionType.elementType.GeneratedType(context.ModuleContext));
            optionType.elementType.AssignFrom(context.ModuleContext, otherType).EmitConvert(context);
            value.EmitStore(context);
            using ITempLocalRef someResult = context.IL.TempLocal(generatedType);
            someResult.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"));
            value.EmitLoad(context);
            context.IL.Emit(OpCodes.Stfld, generatedType.GetField("value"));
            someResult.EmitLoad(context);
        }
 public TempVariable(RealizedType type, ITempLocalRef localRef)
 {
     Type          = type;
     this.localRef = localRef;
 }
Beispiel #5
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            if (condition.ResultType(context) != BuiltinType.Bool)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.InvalidType,
                        "Condition of while is not a boolean",
                        Start,
                        End
                        )
                    );
            }

            IBlockContext tmpContext =
                context.CreateLoopContext(context.IL.DefineLabel(false), context.IL.DefineLabel(false));
            Dictionary <string, TO2Type> scopeVariables = condition.GetScopeVariables(tmpContext);

            if (scopeVariables != null)
            {
                foreach (var(name, type) in scopeVariables)
                {
                    tmpContext.DeclaredVariable(name, true, type.UnderlyingType(context.ModuleContext));
                }
            }

            ILCount conditionCount = condition.GetILCount(tmpContext, false);
            ILCount loopCount      = loopExpression.GetILCount(tmpContext, true);

            if (loopCount.stack > 0)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.CoreGeneration,
                        "Body of the while expression leaves values on stack. This must not happen",
                        Start,
                        End
                        )
                    );
                return;
            }

            if (context.HasErrors)
            {
                return;
            }

            using ITempLocalRef loopCounter = context.IL.TempLocal(typeof(int));
            LabelRef      whileStart  = context.IL.DefineLabel(conditionCount.opCodes + loopCount.opCodes < 110);
            LabelRef      whileEnd    = context.IL.DefineLabel(conditionCount.opCodes + loopCount.opCodes < 110);
            LabelRef      whileLoop   = context.IL.DefineLabel(conditionCount.opCodes + loopCount.opCodes < 100);
            IBlockContext loopContext = context.CreateLoopContext(whileStart, whileEnd);

            if (scopeVariables != null)
            {
                foreach (var(name, type) in scopeVariables)
                {
                    if (loopContext.FindVariable(name) != null)
                    {
                        loopContext.AddError(new StructuralError(
                                                 StructuralError.ErrorType.DuplicateVariableName,
                                                 $"Variable '{name}' already declared in this scope",
                                                 Start,
                                                 End
                                                 ));
                        return;
                    }

                    loopContext.DeclaredVariable(name, true, type.UnderlyingType(context.ModuleContext));
                }
            }

            loopContext.IL.Emit(whileStart.isShort ? OpCodes.Br_S : OpCodes.Br, whileStart);
            context.IL.MarkLabel(whileLoop);

            // 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);

            loopExpression.EmitCode(loopContext, true);
            loopContext.IL.MarkLabel(whileStart);
            condition.EmitCode(loopContext, false);

            loopContext.IL.Emit(whileLoop.isShort ? OpCodes.Brtrue_S : OpCodes.Brtrue, whileLoop);

            loopContext.IL.MarkLabel(whileEnd);
            if (!dropResult)
            {
                context.IL.Emit(OpCodes.Ldnull);
            }
        }
Beispiel #6
0
        internal static AsyncClass Create(IBlockContext parent, string name, TO2Type declaredReturn,
                                          List <FunctionParameter> parameters, Expression expression)
        {
            Type returnType    = declaredReturn.GeneratedType(parent.ModuleContext);
            Type typeParameter = returnType == typeof(void) ? typeof(object) : returnType;

            ModuleContext asyncModuleContext = parent.ModuleContext.DefineSubContext($"AsyncFunction_{name}",
                                                                                     typeof(Future <>).MakeGenericType(typeParameter));

            List <ClonedFieldVariable> clonedParameters = new List <ClonedFieldVariable>();

            foreach (FunctionParameter parameter in parameters)
            {
                FieldBuilder field = asyncModuleContext.typeBuilder.DefineField(parameter.name,
                                                                                parameter.type.GeneratedType(parent.ModuleContext), FieldAttributes.Private);
                clonedParameters.Add(
                    new ClonedFieldVariable(parameter.type.UnderlyingType(parent.ModuleContext), field));
            }

            // ------------- PollValue -------------
            AsyncBlockContext asyncContext = new AsyncBlockContext(asyncModuleContext, FunctionModifier.Public,
                                                                   "PollValue", declaredReturn, typeof(FutureResult <>).MakeGenericType(typeParameter), clonedParameters);

            LabelRef applyState   = asyncContext.IL.DefineLabel(false);
            LabelRef initialState = asyncContext.IL.DefineLabel(false);

            asyncContext.IL.Emit(OpCodes.Br, applyState);
            asyncContext.IL.MarkLabel(initialState);

            expression.EmitCode(asyncContext, false);
            if (!asyncContext.HasErrors)
            {
                declaredReturn.AssignFrom(asyncContext.ModuleContext, expression.ResultType(asyncContext))
                .EmitConvert(asyncContext);
            }

            asyncContext.IL.EmitNew(OpCodes.Newobj,
                                    asyncContext.MethodBuilder.ReturnType.GetConstructor(new[] { typeParameter }));
            asyncContext.IL.EmitReturn(asyncContext.MethodBuilder.ReturnType);

            // Apply state
            asyncContext.IL.MarkLabel(applyState);
            asyncContext.IL.Emit(OpCodes.Ldarg_0);
            asyncContext.IL.Emit(OpCodes.Ldfld, asyncContext.stateField);
            asyncContext.IL.Emit(OpCodes.Switch,
                                 initialState.Yield().Concat(asyncContext.asyncResumes.Select(ar => ar.pollLabel)));
            asyncContext.IL.Emit(OpCodes.Ldarg_0);
            asyncContext.IL.Emit(OpCodes.Ldfld, asyncContext.stateField);
            asyncContext.IL.EmitNew(OpCodes.Newobj,
                                    typeof(InvalidAsyncStateException).GetConstructor(new[] { typeof(int) }), 1);
            asyncContext.IL.Emit(OpCodes.Throw);

            foreach (AsyncResume asyncResume in asyncContext.asyncResumes)
            {
                asyncResume.EmitPoll(asyncContext);
            }

            // Restore state
            asyncContext.IL.MarkLabel(asyncContext.resume);
            foreach (StateRef stateRef in asyncContext.stateRefs)
            {
                stateRef.EmitRestore(asyncContext);
            }
            asyncContext.IL.Emit(OpCodes.Ldarg_0);
            asyncContext.IL.Emit(OpCodes.Ldfld, asyncContext.stateField);
            asyncContext.IL.Emit(OpCodes.Switch,
                                 initialState.Yield().Concat(asyncContext.asyncResumes.Select(ar => ar.resumeLabel)));
            asyncContext.IL.Emit(OpCodes.Ldarg_0);
            asyncContext.IL.Emit(OpCodes.Ldfld, asyncContext.stateField);
            asyncContext.IL.EmitNew(OpCodes.Newobj,
                                    typeof(InvalidAsyncStateException).GetConstructor(new[] { typeof(int) }), 1);
            asyncContext.IL.Emit(OpCodes.Throw);

            // Store state
            asyncContext.IL.MarkLabel(asyncContext.storeState);
            foreach (StateRef stateRef in asyncContext.stateRefs)
            {
                stateRef.EmitStore(asyncContext);
            }

            asyncContext.IL.MarkLabel(asyncContext.notReady);
            using (ITempLocalRef notReady = asyncContext.IL.TempLocal(asyncContext.MethodBuilder.ReturnType)) {
                notReady.EmitLoadPtr(asyncContext);
                asyncContext.IL.Emit(OpCodes.Initobj, asyncContext.MethodBuilder.ReturnType, 1, 0);
                notReady.EmitLoad(asyncContext);
                asyncContext.IL.EmitReturn(asyncContext.MethodBuilder.ReturnType);
            }

            foreach (StructuralError error in asyncContext.AllErrors)
            {
                parent.AddError(error);
            }

            // ------------- Constructor -------------
            List <FieldInfo>   parameterFields    = clonedParameters.Select(c => c.valueField).ToList();
            ConstructorBuilder constructorBuilder = asyncModuleContext.typeBuilder.DefineConstructor(
                MethodAttributes.Public, CallingConventions.Standard,
                parameterFields.Select(f => f.FieldType).ToArray());
            IILEmitter constructorEmitter = new GeneratorILEmitter(constructorBuilder.GetILGenerator());

            int argIndex = 1;

            foreach (FieldInfo field in parameterFields)
            {
                constructorEmitter.Emit(OpCodes.Ldarg_0);
                MethodParameter.EmitLoadArg(constructorEmitter, argIndex++);
                constructorEmitter.Emit(OpCodes.Stfld, field);
            }

            constructorEmitter.Emit(OpCodes.Ldarg_0);
            constructorEmitter.Emit(OpCodes.Ldc_I4_0);
            constructorEmitter.Emit(OpCodes.Stfld, asyncContext.stateField);

            constructorEmitter.EmitReturn(typeof(void));

            return(new AsyncClass(asyncModuleContext.typeBuilder, constructorBuilder));
        }
Beispiel #7
0
        public override void EmitCode(IBlockContext context, bool dropResult)
        {
            if (condition.ResultType(context) != BuiltinType.Bool)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.InvalidType,
                        "Condition of if is not a boolean",
                        Start,
                        End
                        )
                    );
                return;
            }

            IBlockContext thenContext = context.CreateChildContext();
            Dictionary <string, TO2Type> scopeVariables = condition.GetScopeVariables(thenContext);

            if (scopeVariables != null)
            {
                foreach (var(name, type) in scopeVariables)
                {
                    if (thenContext.FindVariable(name) != null)
                    {
                        thenContext.AddError(new StructuralError(
                                                 StructuralError.ErrorType.DuplicateVariableName,
                                                 $"Variable '{name}' already declared in this scope",
                                                 Start,
                                                 End
                                                 ));
                        return;
                    }

                    thenContext.DeclaredVariable(name, true, type.UnderlyingType(context.ModuleContext));
                }
            }

            ILCount thenCount = thenExpression.GetILCount(thenContext, true);

            if (!context.HasErrors && thenCount.stack > 0)
            {
                context.AddError(
                    new StructuralError(
                        StructuralError.ErrorType.CoreGeneration,
                        "Then expression leaves values on stack. This must not happen",
                        Start,
                        End
                        )
                    );
                return;
            }

            condition.EmitCode(thenContext, false);

            if (context.HasErrors)
            {
                return;
            }

            TO2Type thenResultType = thenExpression.ResultType(thenContext);

            if (dropResult)
            {
                LabelRef skipThen = context.IL.DefineLabel(thenCount.opCodes < 124);

                thenContext.IL.Emit(skipThen.isShort ? OpCodes.Brfalse_S : OpCodes.Brfalse, skipThen);
                thenExpression.EmitCode(thenContext, true);
                thenContext.IL.MarkLabel(skipThen);
            }
            else
            {
                OptionType optionType    = new OptionType(thenResultType);
                Type       generatedType = optionType.GeneratedType(thenContext.ModuleContext);
                using ITempLocalRef tempResult = thenContext.IL.TempLocal(generatedType);
                LabelRef skipThen = thenContext.IL.DefineLabel(thenCount.opCodes < 114);

                thenContext.IL.Emit(skipThen.isShort ? OpCodes.Brfalse_S : OpCodes.Brfalse, skipThen);
                thenExpression.Prepare(thenContext);
                tempResult.EmitLoadPtr(context);
                thenContext.IL.Emit(OpCodes.Dup);
                thenContext.IL.Emit(OpCodes.Initobj, generatedType, 1, 0);
                thenContext.IL.Emit(OpCodes.Dup);
                thenContext.IL.Emit(OpCodes.Ldc_I4_1);
                thenContext.IL.Emit(OpCodes.Stfld, generatedType.GetField("defined"));
                thenExpression.EmitCode(thenContext, false);
                thenContext.IL.Emit(OpCodes.Stfld, generatedType.GetField("value"));
                LabelRef ifEnd = context.IL.DefineLabel(true);
                thenContext.IL.Emit(OpCodes.Br_S, ifEnd);

                thenContext.IL.MarkLabel(skipThen);

                tempResult.EmitLoadPtr(context);
                thenContext.IL.Emit(OpCodes.Initobj, generatedType, 1, 0);

                thenContext.IL.MarkLabel(ifEnd);

                tempResult.EmitLoad(thenContext);
            }
        }
Beispiel #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);
            }
        }