public static void DeclareFunctions(DeclaredKontrolModule declaredModule) { ModuleContext moduleContext = declaredModule.moduleContext; foreach (ConstDeclaration constant in declaredModule.to2Module.constants) { FieldInfo runtimeField = moduleContext.typeBuilder.DefineField($"const_{constant.name}", constant.type.GeneratedType(moduleContext), constant.isPublic ? FieldAttributes.Public | FieldAttributes.Static : FieldAttributes.Private | FieldAttributes.Static); DeclaredKontrolConstant declaredConstant = new DeclaredKontrolConstant(declaredModule, constant, runtimeField); if (moduleContext.mappedConstants.ContainsKey(declaredConstant.Name)) { throw new CompilationErrorException(new List <StructuralError> { new StructuralError( StructuralError.ErrorType.DuplicateConstantName, $"Module {declaredModule.Name} already defines a constant {declaredConstant.Name}", constant.Start, constant.End ) }); } moduleContext.mappedConstants.Add(declaredConstant.Name, declaredConstant); declaredModule.declaredConstants.Add(declaredConstant.Name, declaredConstant); } foreach (FunctionDeclaration function in declaredModule.to2Module.functions) { IBlockContext methodContext = moduleContext.CreateMethodContext(function.modifier, function.isAsync, function.name, function.declaredReturn, function.parameters); DeclaredKontrolFunction declaredFunction = new DeclaredKontrolFunction(declaredModule, methodContext, function); if (moduleContext.mappedFunctions.ContainsKey(declaredFunction.Name)) { throw new CompilationErrorException(new List <StructuralError> { new StructuralError( StructuralError.ErrorType.DuplicateFunctionName, $"Module {declaredModule.Name} already defines a function {declaredFunction.Name}", function.Start, function.End ) }); } moduleContext.mappedFunctions.Add(declaredFunction.Name, declaredFunction); declaredModule.declaredFunctions.Add(declaredFunction); if (function.modifier == FunctionModifier.Public) { declaredModule.publicFunctions.Add(declaredFunction.Name, declaredFunction); } } foreach (StructDeclaration to2Struct in declaredModule.to2Module.structs) { IBlockContext methodContext = moduleContext.CreateMethodContext( to2Struct.exported ? FunctionModifier.Public : FunctionModifier.Private, false, to2Struct.name, to2Struct.typeDelegate, to2Struct.constructorParameters); DeclaredKontrolStructConstructor declaredConstructor = new DeclaredKontrolStructConstructor(declaredModule, methodContext, to2Struct); moduleContext.mappedFunctions.Add(declaredConstructor.Name, declaredConstructor); declaredModule.declaredStructConstructors.Add(declaredConstructor); if (to2Struct.exported) { declaredModule.publicFunctions.Add(declaredConstructor.Name, declaredConstructor); } } }
public static CompiledKontrolModule CompileModule(DeclaredKontrolModule declaredModule) { ModuleContext moduleContext = declaredModule.moduleContext; List <StructuralError> errors = new List <StructuralError>(); List <CompiledKontrolConstant> compiledConstants = new List <CompiledKontrolConstant>(); SyncBlockContext constructorContext = new SyncBlockContext(moduleContext); foreach (DeclaredKontrolConstant constant in declaredModule.declaredConstants.Values) { TO2Type expressionType = constant.to2Constant.expression.ResultType(constructorContext); if (!constant.Type.IsAssignableFrom(constructorContext.ModuleContext, expressionType)) { errors.Add(new StructuralError( StructuralError.ErrorType.InvalidType, $"Constant {constant.Name} can not be initialized with type {expressionType}", constant.to2Constant.Start, constant.to2Constant.End )); continue; } constant.to2Constant.expression.EmitCode(constructorContext, false); constant.Type.AssignFrom(constructorContext.ModuleContext, expressionType) .EmitConvert(constructorContext); if (constructorContext.HasErrors) { errors.AddRange(constructorContext.AllErrors); } else { constructorContext.IL.Emit(OpCodes.Stsfld, constant.runtimeField); } if (constant.IsPublic) { compiledConstants.Add(new CompiledKontrolConstant(constant.Name, constant.Description, constant.Type, constant.runtimeField)); } } foreach (DeclaredKontrolFunction function in declaredModule.declaredFunctions) { IBlockContext methodContext = function.methodContext; function.to2Function.EmitCode(methodContext); errors.AddRange(methodContext.AllErrors); } if (errors.Any()) { throw new CompilationErrorException(errors); } Type runtimeType = moduleContext.CreateType(); List <CompiledKontrolFunction> compiledFunctions = new List <CompiledKontrolFunction>(); List <CompiledKontrolFunction> testFunctions = new List <CompiledKontrolFunction>(); foreach (DeclaredKontrolFunction function in declaredModule.declaredFunctions) { if (function.to2Function.modifier == FunctionModifier.Private) { continue; } MethodBuilder methodBuilder = function.methodContext.MethodBuilder; MethodInfo methodInfo = runtimeType.GetMethod(methodBuilder.Name, methodBuilder.GetParameters().Select(p => p.ParameterType).ToArray()); CompiledKontrolFunction compiledFunction = new CompiledKontrolFunction(function.Name, function.Description, function.IsAsync, function.Parameters, function.ReturnType, methodInfo); if (function.to2Function.modifier == FunctionModifier.Test) { testFunctions.Add(compiledFunction); } else { compiledFunctions.Add(compiledFunction); } } return(new CompiledKontrolModule(declaredModule.Name, declaredModule.Description, moduleContext.exportedTypes.Select(t => (t.alias, t.type.UnderlyingType(moduleContext))), compiledConstants, compiledFunctions, testFunctions)); }