public static (ImmutableArray <Diagnostic> diagnostics, Compilation?compilation) Create( string[] references, params SyntaxTree[] syntaxTrees ) { var bag = new DiagnosticBag(); var assemblies = ImmutableArray.CreateBuilder <AssemblyDefinition>(); foreach (var reference in references) { try { var asm = AssemblyDefinition.ReadAssembly(reference); assemblies.Add(asm); } catch (BadImageFormatException) { bag.ReportInvalidReference(reference); } } if (bag.Any()) { return(bag.ToImmutableArray(), null); } return(ImmutableArray <Diagnostic> .Empty, Create(assemblies.ToImmutable(), syntaxTrees)); }
public ImmutableArray <Diagnostic> Emit(BoundProgram program, string outputPath) { if (_diagnostics.Any()) { return(_diagnostics.ToImmutableArray()); } var objectType = _knownTypes[TypeSymbol.Any]; _typeDefinition = new TypeDefinition("", "Program", TypeAttributes.Abstract | TypeAttributes.Sealed, objectType); _assemblyDefinition.MainModule.Types.Add(_typeDefinition); foreach (var functionWithBody in program.Functions) { EmitFunctionDeclaration(functionWithBody.Key); } foreach (var functionWithBody in program.Functions) { EmitFunctionBody(functionWithBody.Key, functionWithBody.Value); } if (program.MainFunction != null) { _assemblyDefinition.EntryPoint = _methods[program.MainFunction]; } _assemblyDefinition.Write(outputPath); return(_diagnostics.ToImmutableArray()); }
public static ImmutableArray <Diagnostic> Emit(BoundProgram program, string moduleName, string[] references, string outputPath) { if (program.Diagnostics.Any()) { return(program.Diagnostics); } var assemblies = new List <AssemblyDefinition>(); var result = new DiagnosticBag(); foreach (var reference in references) { try { var assembly = AssemblyDefinition.ReadAssembly(reference); assemblies.Add(assembly); } catch (BadImageFormatException) { result.ReportInvalidReference(reference); } } var builtInTypes = new List <(TypeSymbol type, string MetadataName)>() { (TypeSymbol.Any, "System.Object"), (TypeSymbol.Bool, "System.Boolean"), (TypeSymbol.Int, "System.Int32"), (TypeSymbol.String, "System.String"), (TypeSymbol.Void, "System.Void"), }; var assemblyName = new AssemblyNameDefinition(moduleName, new Version(1, 0)); var assemblyDefinition = AssemblyDefinition.CreateAssembly(assemblyName, moduleName, ModuleKind.Console); var knownTypes = new Dictionary <TypeSymbol, TypeReference>(); foreach (var(typeSymbol, metadataName) in builtInTypes) { var typeReference = ResolveType(typeSymbol.Name, metadataName); knownTypes.Add(typeSymbol, typeReference); } TypeReference ResolveType(string minskName, string metadataName) { var foundTypes = assemblies.SelectMany(a => a.Modules) .SelectMany(m => m.Types) .Where(t => t.FullName == metadataName) .ToArray(); if (foundTypes.Length == 1) { var typeReference = assemblyDefinition.MainModule.ImportReference(foundTypes[0]); return(typeReference); } else if (foundTypes.Length == 0) { result.ReportRequiredTypeNotFound(minskName, metadataName); } else { result.ReportRequiredTypeAmbiguous(minskName, metadataName, foundTypes); } return(null); } MethodReference ResolveMethod(string typeName, string methodName, string[] parameterTypeNames) { var foundTypes = assemblies.SelectMany(a => a.Modules) .SelectMany(m => m.Types) .Where(t => t.FullName == typeName) .ToArray(); if (foundTypes.Length == 1) { var foundType = foundTypes[0]; var methods = foundType.Methods.Where(m => m.Name == methodName); foreach (var method in methods) { if (method.Parameters.Count != parameterTypeNames.Length) { continue; } var allParametersMatch = true; for (var i = 0; i < parameterTypeNames.Length; i++) { if (method.Parameters[i].ParameterType.FullName != parameterTypeNames[i]) { allParametersMatch = false; break; } } if (!allParametersMatch) { continue; } return(assemblyDefinition.MainModule.ImportReference(method)); } result.ReportRequiredMethodNotFound(typeName, methodName, parameterTypeNames); return(null); } else if (foundTypes.Length == 0) { result.ReportRequiredTypeNotFound(null, typeName); } else { result.ReportRequiredTypeAmbiguous(null, typeName, foundTypes); } return(null); } var consoleWriteLineReference = ResolveMethod("System.Console", "WriteLine", new [] { "System.String" }); if (result.Any()) { return(result.ToImmutableArray()); } var objectType = knownTypes[TypeSymbol.Any]; var typeDefinition = new TypeDefinition("", "Program", TypeAttributes.Abstract | TypeAttributes.Sealed, objectType); assemblyDefinition.MainModule.Types.Add(typeDefinition); var voidType = knownTypes[TypeSymbol.Void]; var mainMethod = new MethodDefinition("Main", MethodAttributes.Static | MethodAttributes.Private, voidType); typeDefinition.Methods.Add(mainMethod); var ilProcessor = mainMethod.Body.GetILProcessor(); ilProcessor.Emit(OpCodes.Ldstr, "Hello world from Minsk!"); ilProcessor.Emit(OpCodes.Call, consoleWriteLineReference); ilProcessor.Emit(OpCodes.Ret); assemblyDefinition.EntryPoint = mainMethod; assemblyDefinition.Write(outputPath); return(result.ToImmutableArray()); }