Example #1
0
        public bool CreateModule(CompilerContext context, ProgramUnit programUnit, out Module module)
        {
            bool failed = false;
            module = new Module();
            foreach (MethodDefinition methodDef in programUnit.Methods)
            {
                MethodInfo methodInfo = null;
                TypeDefinition type = null;
                List<TypeDefinition> parameterTypes = new List<TypeDefinition>();
                foreach (var paramDecl in methodDef.Parameters)
                {
                    TypeDefinition paramType = null;
                    if (!this.TryResolveTypeReference(context, paramDecl.Type, out paramType))
                    {
                        return false;
                    }

                    foreach (string paramName in paramDecl.ParameterNames)
                    {
                        parameterTypes.Add(paramType);
                    }
                }

                if (!context.TryFindMethodAndType(
                    methodDef.MethodNameReference,
                    parameterTypes,
                    out type,
                    out methodInfo))
                {
                    string message = string.Format(
                        Properties.Resources.CodeGenerator_UndeclaredMethod,
                        methodDef.MethodNameReference);
                    this.log.Write(new Message(
                        methodDef.Start.Path,
                        methodDef.Start.Line,
                        methodDef.Start.Column,
                        Severity.Error,
                        message));
                    failed = true;
                    continue;
                }

                MethodImpl methodImpl = new MethodImpl(module);
                methodImpl.Method = methodInfo;
                if (this.TryImplementMethod(methodImpl, context, methodDef, type))
                {
                    module.CodeSegment.Add(methodImpl);
                }
                else
                {
                    failed = true;
                }
            }

            return !failed;
        }
Example #2
0
        public bool TryParse(
            TokenReader reader, 
            out ProgramUnit result)
        {
            result = null;
            Token tok = reader.Peek();
            ProgramUnit programUnit = new ProgramUnit(tok);
            if (tok.Is(Keyword.Namespace))
            {
                reader.Read();
                string namespaceDecl = null;
                if (!this.ParseFullNameDeclaration(reader, out namespaceDecl))
                {
                    return false;
                }

                if (!this.Expect(reader, Keyword.SemiColon))
                {
                    return false;
                }

                programUnit.Namespace = namespaceDecl;
            }

            tok = reader.Peek();
            if (tok.Is(Keyword.Uses))
            {
                reader.Read();
                string usesRef = null;
                if (!this.ParseFullNameDeclaration(reader, out usesRef))
                {
                    return false;
                }

                programUnit.AddUses(usesRef);
                tok = reader.Peek();
                while (tok.Is(Keyword.Comma))
                {
                    reader.Read();
                    if (!this.ParseFullNameDeclaration(reader, out usesRef))
                    {
                        return false;
                    }

                    programUnit.AddUses(usesRef);
                    tok = reader.Peek();
                }

                if (!this.Expect(reader, Keyword.SemiColon))
                {
                    return false;
                }
            }

            tok = reader.Peek();
            if (tok.Is(Keyword.Type))
            {
                if (!this.ParseTypeBlock(reader, programUnit))
                {
                    return false;
                }
            }

            tok = reader.Peek();
            if (tok.Is(Keyword.Var))
            {
                VarBlock globalVars = null;
                if (!this.ParseVarBlock(reader, true, out globalVars))
                {
                    return false;
                }

                programUnit.Variables = globalVars;
            }

            tok = reader.Peek();
            while (
                tok.Is(Keyword.Function) ||
                tok.Is(Keyword.Procedure) ||
                tok.Is(Keyword.Constructor) ||
                tok.Is(Keyword.Destructor))
            {
                MethodDefinition methodDef = null;
                if (!this.ParseMethodDefinition(reader, out methodDef))
                {
                    return false;
                }

                programUnit.AddMethod(methodDef);
                if (!this.Expect(reader, Keyword.SemiColon))
                {
                    return false;
                }

                tok = reader.Peek();
            }

            bool passed = ExpectEndOfFile(reader);
            if (passed)
            {
                result = programUnit;
            }

            return passed;
        }
Example #3
0
        private bool ParseTypeBlock(TokenReader reader, ProgramUnit program)
        {
            if (!this.Expect(reader, Keyword.Type))
            {
                return false;
            }

            IdentifierToken typeName = reader.Peek() as IdentifierToken;
            while (typeName != null)
            {
                reader.Read();
                TypeDeclaration type = null;

                if (!this.Expect(reader, Keyword.Equals))
                {
                    return false;
                }

                Token tok = reader.Peek();
                if (tok.Is(Keyword.LeftParen))
                {
                    if (!this.ParseEnumDeclaration(typeName, reader, out type))
                    {
                        return false;
                    }
                }
                else if (tok.Is(Keyword.Class) || tok.Is(Keyword.Static) || tok.Is(Keyword.Public))
                {
                    if (!this.ParseClassDeclaration(typeName, reader, out type))
                    {
                        return false;
                    }
                }
                else
                {
                }

                program.AddType(type);
                if (!this.Expect(reader, Keyword.SemiColon))
                {
                    return false;
                }

                typeName = reader.Peek() as IdentifierToken;
            }

            return true;
        }
Example #4
0
        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;
        }