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; }
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; }