public DeclaredKontrolConstant(DeclaredKontrolModule module, ConstDeclaration to2Constant, FieldInfo runtimeField) { this.module = module; this.to2Constant = to2Constant; this.runtimeField = runtimeField; }
public DeclaredKontrolStructConstructor(DeclaredKontrolModule module, IBlockContext methodContext, StructDeclaration to2Struct) { this.module = module; Parameters = to2Struct.constructorParameters.Select(p => new RealizedParameter(methodContext, p)).ToList(); ReturnType = to2Struct.typeDelegate.UnderlyingType(methodContext.ModuleContext); this.methodContext = methodContext; this.to2Struct = to2Struct; }
public DeclaredKontrolFunction(DeclaredKontrolModule module, IBlockContext methodContext, FunctionDeclaration to2Function) { this.module = module; Parameters = to2Function.parameters.Select(p => new RealizedParameter(methodContext, p)).ToList(); ReturnType = to2Function.declaredReturn.UnderlyingType(methodContext.ModuleContext); this.methodContext = methodContext; this.to2Function = to2Function; }
public Context AddDirectory(string baseDir) { Context context = new Context(this); List <DeclaredKontrolModule> declaredModules = new List <DeclaredKontrolModule>(); foreach (string fileName in Directory.GetFiles(baseDir, "*.to2", SearchOption.AllDirectories)) { // First declare the existence of a module and its types TO2Module to2Module = TO2Parser.ParseModuleFile(baseDir, fileName.Remove(0, baseDir.Length + 1)); DeclaredKontrolModule module = ModuleGenerator.DeclareModule(context, to2Module); declaredModules.Add(module); context.registry.RegisterModule(module); } foreach (DeclaredKontrolModule declared in declaredModules) { // ... so that types can be imported by other modules ModuleGenerator.ImportTypes(declared); } foreach (DeclaredKontrolModule declared in declaredModules) { // ... so that function can be declared (potentially using imported types as arguments or return) ModuleGenerator.DeclareFunctions(declared); } foreach (DeclaredKontrolModule declared in declaredModules) { // ... so that other modules may import these functions ModuleGenerator.ImportFunctions(declared); } foreach (DeclaredKontrolModule declared in declaredModules) { // ... so that we should now be able to infer all types ModuleGenerator.VerifyFunctions(declared); } foreach (DeclaredKontrolModule declared in declaredModules) { ModuleGenerator.CompileStructs(declared); } foreach (DeclaredKontrolModule declared in declaredModules) { // ... and eventually emit the code and bake the modules CompiledKontrolModule compiled = ModuleGenerator.CompileModule(declared); context.registry.RegisterModule(compiled); } return(context); }
public static void ImportTypes(DeclaredKontrolModule declaredModule) { ModuleContext moduleContext = declaredModule.moduleContext; List <StructuralError> errors = declaredModule.to2Module.TryImportTypes(moduleContext); if (errors.Any()) { throw new CompilationErrorException(errors); } }
public Context AddFile(string baseDir, string file) { TO2Module to2Module = TO2Parser.ParseModuleFile(baseDir, file); Context context = new Context(this); DeclaredKontrolModule declaredKontrolModule = ModuleGenerator.DeclareModule(context, to2Module); ModuleGenerator.ImportTypes(declaredKontrolModule); ModuleGenerator.DeclareFunctions(declaredKontrolModule); ModuleGenerator.ImportFunctions(declaredKontrolModule); ModuleGenerator.VerifyFunctions(declaredKontrolModule); CompiledKontrolModule kontrolModule = ModuleGenerator.CompileModule(declaredKontrolModule); RegisterModule(kontrolModule); return(context); }
public static void CompileStructs(DeclaredKontrolModule declaredModule) { List <StructuralError> errors = new List <StructuralError>(); foreach (DeclaredKontrolStructConstructor structConstructor in declaredModule.declaredStructConstructors) { IBlockContext methodContext = structConstructor.methodContext; structConstructor.to2Struct.EmitConstructor(methodContext); errors.AddRange(methodContext.AllErrors); } if (errors.Any()) { throw new CompilationErrorException(errors); } }
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)); }