示例#1
0
        public FieldInfo AddVTablePointer(CompilerContext context, int offset)
        {
            TypeDefinition ptrType = null;
            context.TryFindTypeByName("^", out ptrType);
            FieldInfo field = new FieldInfo
            {
                Name = VTablePointerFieldName,
                IsPublic = true,
                Offset = offset,
                Type = context.GetArrayType(ptrType, 0)
            };

            this.fields.Add(field);
            return field;
        }
示例#2
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;
        }