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