private DeclarationIL Build(IDeclaration declaration, ISymbolTree symbolTree) { if (declarationsIL.TryGetValue(declaration.Symbol, out var declarationIL)) { return(declarationIL); } switch (declaration) { default: throw ExhaustiveMatch.Failed(declaration); case IFunctionDeclaration function: { var il = ilFactory.CreateGraph(function); declarationIL = new FunctionIL(false, false, function.Symbol, BuildParameters(function.Parameters), il); break; } case IAssociatedFunctionDeclaration associatedFunction: { var il = ilFactory.CreateGraph(associatedFunction); declarationIL = new FunctionIL(false, true, associatedFunction.Symbol, BuildParameters(associatedFunction.Parameters), il); break; } case IConcreteMethodDeclaration method: { var il = ilFactory.CreateGraph(method); declarationIL = new MethodDeclarationIL(method.Symbol, BuildParameter(method.SelfParameter), BuildParameters(method.Parameters), il); break; } case IAbstractMethodDeclaration method: { declarationIL = new MethodDeclarationIL(method.Symbol, BuildParameter(method.SelfParameter), BuildParameters(method.Parameters), null); break; } case IConstructorDeclaration constructor: { var il = ilFactory.CreateGraph(constructor); var parameters = BuildConstructorParameters(constructor); var fieldInitializations = BuildFieldInitializations(constructor); declarationIL = new ConstructorIL(constructor.Symbol, parameters, fieldInitializations, il); break; } case IFieldDeclaration fieldDeclaration: declarationIL = new FieldIL(fieldDeclaration.Symbol); break; case IClassDeclaration classDeclaration: declarationIL = new ClassIL(classDeclaration.Symbol, BuildClassMembers(classDeclaration, symbolTree)); break; } declarationsIL.Add(declaration.Symbol, declarationIL); return(declarationIL); }
private void EmitType(ClassIL @class, Code code) { var typeName = nameMangler.MangleName(@class); // Struct Forward Declarations var selfType = $"{typeName}___Self"; var vtableType = $"{typeName}___VTable"; var types = code.TypeDeclarations; types.AppendLine($"typedef struct {selfType} {selfType};"); types.AppendLine($"typedef struct {vtableType} {vtableType};"); // Declare the full type because when it is used as a field, its // size will need to be known. However, order within struct // declarations is not defined. types.AppendLine($"typedef struct {typeName}"); types.BeginBlock(); types.AppendLine($"{vtableType} const* restrict _vtable;"); types.AppendLine($"{selfType}* restrict _self;"); types.EndBlockWith($"}} {typeName};"); var structs = code.StructDeclarations; structs.AppendLine($"struct {selfType}"); structs.BeginBlock(); foreach (var field in @class.Members.OfType <FieldIL>()) { var binding = field.Symbol.IsMutableBinding ? "var" : "let"; structs.AppendLine($"// {binding} {field.Symbol.Name}: {field.DataType}"); var fieldType = typeConverter.Convert(field.DataType.Known()); var fieldName = nameMangler.MangleName(field); structs.AppendLine($"{fieldType} {fieldName};"); } structs.EndBlockWithSemicolon(); structs.AppendLine($"struct {vtableType}"); structs.BeginBlock(); foreach (var method in @class.Members.OfType <MethodDeclarationIL>()) { var name = nameMangler.MangleMethodName(method); var parameters = Convert(method.Parameters.Prepend(method.SelfParameter)); var returnType = typeConverter.Convert(method.Symbol.ReturnDataType.Known()); structs.AppendLine($"{returnType} (*{name})({parameters});"); } structs.EndBlockWithSemicolon(); var globals = code.StructDeclarations; globals.AppendLine($"const {vtableType} {typeName}___vtable = ({vtableType})"); globals.BeginBlock(); foreach (var method in @class.Members.OfType <MethodDeclarationIL>()) { var fieldName = nameMangler.MangleMethodName(method); var functionName = nameMangler.MangleName(method); globals.AppendLine($".{fieldName} = {functionName},"); } globals.EndBlockWithSemicolon(); }
public string MangleName(ClassIL @class) { return(Mangle(@class.Symbol)); }