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