public static int Main(string[] args) { try { Arguments arguments = null; if (!Arguments.TryParse(args, out arguments)) { Console.Error.WriteLine(Properties.Resources.Usage); return 1; } MessageLog log = new MessageLog(); CompilerContext context = new CompilerContext(); context.AddIncludePaths(arguments.Includes); using (TokenReader reader = new TokenReader(arguments.InputFile, log)) { Parser parser = new Parser(log); ProgramUnit programUnit = null; // parsing pass. if (parser.TryParse(reader, out programUnit)) { // code generation pass. CodeGenerator codeGen = new CodeGenerator(log); if (codeGen.CreateTypes(context, programUnit)) { Module module = null; if (codeGen.CreateModule(context, programUnit, out module)) { using (AsmModuleWriter moduleWriter = new AsmModuleWriter(arguments.OutputListing)) { moduleWriter.Write(module); } } } } } foreach (Message message in log.Messages) { TextWriter target = message.Severity == Severity.Error ? Console.Error : Console.Out; target.WriteLine(message.ToString()); } return log.HasErrors ? 1 : 0; } catch (Exception ex) { Console.Error.WriteLine(ex.ToString()); return 1; } }
public bool CreateTypes(CompilerContext context, ProgramUnit programUnit) { bool failed = false; foreach (string uses in programUnit.Uses) { List<string> searchDirs = new List<string>(); searchDirs.Add(System.IO.Path.GetDirectoryName(programUnit.Start.Path)); searchDirs.AddRange(context.Includes); string headerPath = null; foreach (string dir in searchDirs) { string includePath = System.IO.Path.Combine( dir, uses + ".th"); if (System.IO.File.Exists(includePath)) { headerPath = includePath; break; } } if (headerPath != null && !context.AlreadyUsed(uses)) { context.AddAlreadyUsed(uses); ProgramUnit usedProgramUnit = null; using (TokenReader reader = new TokenReader(headerPath, this.log)) { Parser includeParser = new Parser(this.log); if (includeParser.TryParse(reader, out usedProgramUnit)) { if (!this.CreateTypes(context, usedProgramUnit)) { failed = true; } } else { failed = true; } } } } context.ClearUses(); foreach (string uses in programUnit.Uses) { context.AddUses(uses); } context.Namespace = programUnit.Namespace; foreach (TypeDeclaration typeDecl in programUnit.Types) { TypeDefinition typeDef = null; if (!context.TryDeclareType(typeDecl.Name, out typeDef)) { string message = string.Format( Properties.Resources.CodeGenerator_TypeAlreadyDeclared, typeDecl.Name); log.Write(new Message( typeDecl.Start.Path, typeDecl.Start.Line, typeDecl.Start.Column, Severity.Error, message)); failed = true; } ClassDeclaration classDecl = typeDecl as ClassDeclaration; if (classDecl != null) { typeDef.IsClass = true; typeDef.IsPublic = classDecl.IsPublic; typeDef.IsStaticClass = classDecl.IsStatic; if (classDecl.BaseType != null) { TypeDefinition baseType = null; if (!context.TryFindTypeByName(classDecl.BaseType, out baseType)) { string message = string.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.CodeGenerator_UndefinedType, classDecl.BaseType); this.log.Write(new Message( classDecl.Start.Path, classDecl.Start.Line, classDecl.Start.Column, Severity.Error, message)); failed = true; } else { if (!baseType.IsClass || baseType.IsStaticClass) { string message = string.Format( System.Globalization.CultureInfo.CurrentCulture, Properties.Resources.CodeGenerator_BaseTypeNotClass, baseType.FullName); this.log.Write(new Message( classDecl.Start.Path, classDecl.Start.Line, classDecl.Start.Column, Severity.Error, message)); failed = true; } else { typeDef.BaseClass = baseType; } } } bool hasVirtualMethods = false; foreach (MethodDeclaration meth in classDecl.PublicMethods) { MethodInfo methodInfo = null; if (!this.TryCreateMethod(context, typeDef, meth, out methodInfo)) { failed = true; continue; } methodInfo.IsPublic = true; typeDef.Methods.Add(methodInfo); if (methodInfo.IsVirtual) { hasVirtualMethods = true; } } foreach (MethodDeclaration meth in classDecl.ProtectedMethods) { MethodInfo methodInfo = null; if (!this.TryCreateMethod(context, typeDef, meth, out methodInfo)) { failed = true; continue; } methodInfo.IsProtected = true; typeDef.Methods.Add(methodInfo); if (methodInfo.IsVirtual) { hasVirtualMethods = true; } } foreach (MethodDeclaration meth in classDecl.PrivateMethods) { MethodInfo methodInfo = null; if (!this.TryCreateMethod(context, typeDef, meth, out methodInfo)) { failed = true; continue; } methodInfo.IsProtected = true; typeDef.Methods.Add(methodInfo); if (methodInfo.IsVirtual) { hasVirtualMethods = true; } } int size = 0; if (typeDef.BaseClass != null) { size = typeDef.BaseClass.Size; } if (hasVirtualMethods) { FieldInfo vtblPtr = typeDef.GetVTablePointer(); if (vtblPtr == null) { vtblPtr = typeDef.AddVTablePointer(context, size); size += vtblPtr.Type.Size; } } if (classDecl.Fields != null) { foreach (var field in classDecl.Fields.Variables) { TypeDefinition fieldType = null; if (!this.TryResolveTypeReference(context, field.Type, out fieldType)) { failed = true; continue; } foreach (string identifier in field.VariableNames) { FieldInfo fieldInfo = new FieldInfo(); fieldInfo.Name = identifier; fieldInfo.Type = fieldType; fieldInfo.IsStatic = classDecl.IsStatic; if (!fieldInfo.IsStatic) { fieldInfo.Offset = size; size += fieldType.Size; } typeDef.Fields.Add(fieldInfo); } } } typeDef.Size = size; } } return !failed; }