コード例 #1
0
ファイル: Program.cs プロジェクト: strunberg/TEA
        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;
            }
        }
コード例 #2
0
ファイル: CodeGenerator.cs プロジェクト: strunberg/TEA
        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;
        }