diff --git a/compiler/Generator.cs b/compiler/Generator.cs index 96e4145..fc45187 100644 --- a/compiler/Generator.cs +++ b/compiler/Generator.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.Diagnostics; +using System.Text; namespace Compiler; @@ -45,7 +46,7 @@ public class Generator { if (info is Module.TypeInfoStruct s) { - writer.WriteLine($"struct {Name.Create(module.Name, name, NubTypeStruct.Get(module.Name, name))};"); + writer.WriteLine($"struct {NameMangler.Mangle(module.Name, name, NubTypeStruct.Get(module.Name, name))};"); } } } @@ -64,7 +65,7 @@ public class Generator writer.Write("__attribute__((__packed__)) "); } - writer.WriteLine(Name.Create(module.Name, name, NubTypeStruct.Get(module.Name, name))); + writer.WriteLine(NameMangler.Mangle(module.Name, name, NubTypeStruct.Get(module.Name, name))); writer.WriteLine("{"); using (writer.Indent()) { @@ -86,14 +87,14 @@ public class Generator { if (info.Type is NubTypeFunc fn) { - if (!functions.Any(x => x.GetMangledName() == Name.Create(module.Name, name, info.Type))) + if (info.External) writer.Write("extern "); - writer.WriteLine($"{CType(fn.ReturnType, Name.Create(module.Name, name, info.Type))}({string.Join(", ", fn.Parameters.Select(p => CType(p)))});"); + writer.WriteLine($"{CType(fn.ReturnType, info.MangledName)}({string.Join(", ", fn.Parameters.Select(p => CType(p)))});"); } else { - writer.WriteLine($"{CType(info.Type, Name.Create(module.Name, name, info.Type))};"); + writer.WriteLine($"{CType(info.Type, info.MangledName)};"); } } } @@ -102,12 +103,13 @@ public class Generator if (!compileLib) { - var main = functions.First(x => x.Module == "main" && x.Name.Ident == "main"); + if (!moduleGraph.TryResolveIdentifier("main", "main", true, out var info)) + throw new UnreachableException("func main::main() is not defined. This should have been caught earlier"); writer.WriteLine($$""" int main(int argc, char *argv[]) { - return {{main.GetMangledName()}}(); + return {{info.MangledName}}(); } """); } @@ -116,8 +118,11 @@ public class Generator foreach (var function in functions) { + if (!moduleGraph.TryResolveIdentifier(function.Module, function.Name.Ident, true, out var info)) + throw new UnreachableException($"Module graph does not have info about the function {function.Module}::{function.Name.Ident}. This should have been caught earlier"); + var parameters = function.Parameters.Select(x => CType(x.Type, x.Name.Ident)); - writer.WriteLine($"{CType(function.ReturnType, function.GetMangledName())}({string.Join(", ", parameters)})"); + writer.WriteLine($"{CType(function.ReturnType, info.MangledName)}({string.Join(", ", parameters)})"); writer.WriteLine("{"); using (writer.Indent()) { @@ -249,7 +254,7 @@ public class Generator TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression), TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression), TypedNodeExpressionLocalIdent expression => expression.Value.Ident, - TypedNodeExpressionModuleIdent expression => Name.Create(expression.Module.Ident, expression.Value.Ident, expression.Type), + TypedNodeExpressionModuleIdent expression => EmitExpressionModuleIdent(expression), TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression), _ => throw new ArgumentOutOfRangeException(nameof(node), node, null) }; @@ -304,9 +309,8 @@ public class Generator } var initializerStrings = initializerValues.Select(x => $".{x.Key} = {x.Value}"); - var structType = (NubTypeStruct)expression.Type; - return $"(struct {Name.Create(structType.Module, structType.Name, structType)}){{ {string.Join(", ", initializerStrings)} }}"; + return $"({CType(expression.Type)}){{ {string.Join(", ", initializerStrings)} }}"; } private string EmitExpressionMemberAccess(TypedNodeExpressionMemberAccess expression) @@ -315,6 +319,14 @@ public class Generator return $"{target}.{expression.Name.Ident}"; } + private string EmitExpressionModuleIdent(TypedNodeExpressionModuleIdent expression) + { + if (!moduleGraph.TryResolveIdentifier(expression.Module.Ident, expression.Value.Ident, true, out var info)) + throw new UnreachableException($"Module graph does not have info about identifier {expression.Module.Ident}::{expression.Value.Ident}. This should have been caught earlier"); + + return info.MangledName; + } + private string EmitExpressionFuncCall(TypedNodeExpressionFuncCall expression) { var name = EmitExpression(expression.Target); @@ -328,7 +340,7 @@ public class Generator { NubTypeVoid => "void" + (varName != null ? $" {varName}" : ""), NubTypeBool => "bool" + (varName != null ? $" {varName}" : ""), - NubTypeStruct type => $"struct {Name.Create(type.Module, type.Name, type)}" + (varName != null ? $" {varName}" : ""), + NubTypeStruct type => $"struct {NameMangler.Mangle(type.Module, type.Name, type)}" + (varName != null ? $" {varName}" : ""), NubTypeSInt type => $"int{type.Width}_t" + (varName != null ? $" {varName}" : ""), NubTypeUInt type => $"uint{type.Width}_t" + (varName != null ? $" {varName}" : ""), NubTypePointer type => CType(type.To) + (varName != null ? $" *{varName}" : "*"), diff --git a/compiler/ModuleGraph.cs b/compiler/ModuleGraph.cs index e2af09b..860f135 100644 --- a/compiler/ModuleGraph.cs +++ b/compiler/ModuleGraph.cs @@ -19,6 +19,34 @@ public class ModuleGraph return modules.Values.ToList(); } + public bool TryResolveIdentifier(string moduleName, string identifierName, bool searchPrivate, [NotNullWhen(true)] out Module.IdentifierInfo? info) + { + if (!TryResolveModule(moduleName, out var module)) + { + info = null; + return false; + } + + if (!module.TryResolveIdentifier(identifierName, searchPrivate, out info)) + return false; + + return true; + } + + public bool TryResolveType(string moduleName, string typeName, bool searchPrivate, [NotNullWhen(true)] out Module.TypeInfo? info) + { + if (!TryResolveModule(moduleName, out var module)) + { + info = null; + return false; + } + + if (!module.TryResolveType(typeName, searchPrivate, out info)) + return false; + + return true; + } + public bool TryResolveModule(string moduleName, [NotNullWhen(true)] out Module? module) { module = modules.GetValueOrDefault(moduleName); @@ -69,7 +97,7 @@ public class ModuleGraph foreach (var (name, identifier) in manifestModule.Identifiers) { - module.AddIdentifier(name, new Module.IdentifierInfo(identifier.Exported, identifier.Type)); + module.AddIdentifier(name, new Module.IdentifierInfo(identifier.Exported, identifier.Type, identifier.MangledName, true)); } } } @@ -110,14 +138,14 @@ public class ModuleGraph var parameters = funcDef.Parameters.Select(x => ResolveType(x.Type, module.Name)).ToList(); var returnType = ResolveType(funcDef.ReturnType, module.Name); var funcType = NubTypeFunc.Get(parameters, returnType); - var info = new Module.IdentifierInfo(funcDef.Exported, funcType); + var info = new Module.IdentifierInfo(funcDef.Exported, funcType, NameMangler.Mangle(module.Name, funcDef.Name.Ident, funcType), false); module.AddIdentifier(funcDef.Name.Ident, info); } foreach (var globalVariable in ast.Definitions.OfType()) { var type = ResolveType(globalVariable.Type, module.Name); - var info = new Module.IdentifierInfo(globalVariable.Exported, type); + var info = new Module.IdentifierInfo(globalVariable.Exported, type, NameMangler.Mangle(module.Name, globalVariable.Name.Ident, type), false); module.AddIdentifier(globalVariable.Name.Ident, info); } } @@ -233,19 +261,19 @@ public class Module(string name) identifiers.Add(name, info); } - public class IdentifierInfo(bool exported, NubType type) + public class IdentifierInfo(bool exported, NubType type, string mangledName, bool external) { public bool Exported { get; } = exported; public NubType Type { get; } = type; + public string MangledName { get; } = mangledName; + public bool External { get; } = external; } - public abstract class TypeInfo(bool exported) { public bool Exported { get; } = exported; } - public class TypeInfoStruct(bool exported, bool packed) : TypeInfo(exported) { private IReadOnlyList? fields; diff --git a/compiler/NubLib.cs b/compiler/NubLib.cs index 66d4600..ed7e4dd 100644 --- a/compiler/NubLib.cs +++ b/compiler/NubLib.cs @@ -71,7 +71,7 @@ public record Manifest(Dictionary Modules) foreach (var module in moduleGraph.GetModules()) { var types = module.GetTypes().ToDictionary(x => x.Key, x => ConvertType(x.Value)); - var identifiers = module.GetIdentifiers().ToDictionary(x => x.Key, x => new Module.IdentifierInfo(x.Value.Exported, x.Value.Type)); + var identifiers = module.GetIdentifiers().ToDictionary(x => x.Key, x => new Module.IdentifierInfo(x.Value.Exported, x.Value.Type, x.Value.MangledName)); modules[module.Name] = new Module(types, identifiers); } @@ -90,7 +90,7 @@ public record Manifest(Dictionary Modules) public record Module(Dictionary Types, Dictionary Identifiers) { - public record IdentifierInfo(bool Exported, NubType Type); + public record IdentifierInfo(bool Exported, NubType Type, string MangledName); [JsonDerivedType(typeof(TypeInfoStruct), "struct")] public abstract record TypeInfo(bool Exported); diff --git a/compiler/NubType.cs b/compiler/NubType.cs index f50ab4b..89dbc1a 100644 --- a/compiler/NubType.cs +++ b/compiler/NubType.cs @@ -150,8 +150,6 @@ public class NubTypeFunc : NubType public IReadOnlyList Parameters { get; } public NubType ReturnType { get; } - public string MangledName(string name, string module) => Name.Create(name, module, this); - private NubTypeFunc(List parameters, NubType returnType) { Parameters = parameters; @@ -434,9 +432,9 @@ public static class Hashing } } -public static class Name +public static class NameMangler { - public static string Create(string module, string name, NubType type) + public static string Mangle(string module, string name, NubType type) { var canonical = TypeEncoder.Encode(type); var hash = Hashing.Fnv1a64(canonical); diff --git a/compiler/TypeChecker.cs b/compiler/TypeChecker.cs index 0a8a563..a2ed02a 100644 --- a/compiler/TypeChecker.cs +++ b/compiler/TypeChecker.cs @@ -494,11 +494,6 @@ public class TypedNodeDefinitionFunc(List tokens, string module, TokenIde return NubTypeFunc.Get(Parameters.Select(x => x.Type).ToList(), ReturnType); } - public string GetMangledName() - { - return Compiler.Name.Create(Module, Name.Ident, GetNubType()); - } - public class Param(List tokens, TokenIdent name, NubType type) : TypedNode(tokens) { public TokenIdent Name { get; } = name;