From ab9bd6fd059ee3e78a7fc3bb4b3ec3d904debe20 Mon Sep 17 00:00:00 2001 From: nub31 Date: Mon, 9 Feb 2026 20:49:09 +0100 Subject: [PATCH] ... --- compiler/Generator.cs | 50 +++---- compiler/ModuleGraph.cs | 178 +++++++++++++++++++++++ compiler/{TypeResolver.cs => NubType.cs} | 78 ---------- compiler/Parser.cs | 34 +++-- compiler/Program.cs | 44 +++--- compiler/Tokenizer.cs | 6 - compiler/TypeChecker.cs | 65 ++++++--- compiler/test.nub | 12 +- compiler/test2.nub | 9 ++ 9 files changed, 300 insertions(+), 176 deletions(-) create mode 100644 compiler/ModuleGraph.cs rename compiler/{TypeResolver.cs => NubType.cs} (59%) create mode 100644 compiler/test2.nub diff --git a/compiler/Generator.cs b/compiler/Generator.cs index b747579..a3e22fc 100644 --- a/compiler/Generator.cs +++ b/compiler/Generator.cs @@ -2,11 +2,11 @@ namespace Compiler; -public sealed class Generator(List functions) +public sealed class Generator(List functions, ModuleGraph moduleGraph) { - public static string Emit(List functions) + public static string Emit(List functions, ModuleGraph moduleGraph) { - return new Generator(functions).Emit(); + return new Generator(functions, moduleGraph).Emit(); } private readonly IndentedTextWriter writer = new(); @@ -28,27 +28,26 @@ public sealed class Generator(List functions) """); - // for (var i = 0; i < ast.StructTypes.Count; i++) - // { - // var structType = ast.StructTypes[i]; - // structTypeNames[structType] = $"s{i}"; - // } - // - // foreach (var structType in ast.StructTypes) - // { - // var name = structTypeNames[structType]; - // writer.WriteLine($"struct {name}"); - // writer.WriteLine("{"); - // using (writer.Indent()) - // { - // foreach (var field in structType.Fields) - // { - // writer.WriteLine($"{CType(field.Type, field.Name)};"); - // } - // } - // - // writer.WriteLine("};"); - // } + foreach (var (i, structType) in moduleGraph.GetStructTypes().Index()) + structTypeNames[structType] = $"s{i}"; + + foreach (var typeName in structTypeNames) + writer.WriteLine($"struct {typeName.Value};"); + + writer.WriteLine(); + + foreach (var typeName in structTypeNames) + { + writer.WriteLine($"struct {typeName.Value}"); + writer.WriteLine("{"); + using (writer.Indent()) + { + foreach (var field in typeName.Key.Fields) + writer.WriteLine($"{CType(field.Type, field.Name)};"); + } + + writer.WriteLine("};"); + } writer.WriteLine(); @@ -199,7 +198,8 @@ public sealed class Generator(List functions) TypedNodeExpressionStringLiteral expression => $"(struct string){{ \"{expression.Value.Value}\", {expression.Value.Value.Length} }}", TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression), TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression), - TypedNodeExpressionIdent expression => expression.Value.Ident, + TypedNodeExpressionLocalIdent expression => expression.Value.Ident, + TypedNodeExpressionModuleIdent expression => expression.Value.Ident, _ => throw new ArgumentOutOfRangeException(nameof(node), node, null) }; } diff --git a/compiler/ModuleGraph.cs b/compiler/ModuleGraph.cs new file mode 100644 index 0000000..7b62513 --- /dev/null +++ b/compiler/ModuleGraph.cs @@ -0,0 +1,178 @@ +namespace Compiler; + +public class ModuleGraph(Dictionary modules) +{ + public static Builder Create() => new(); + + public NubTypeStruct ResolveStruct(string moduleName, string name) + { + var module = modules.GetValueOrDefault(moduleName); + if (module == null) + throw new CompileException(Diagnostic.Error($"Module '{moduleName}' not found").Build()); + + var structType = module.ResolveStruct(name); + if (structType == null) + throw new CompileException(Diagnostic.Error($"Struct '{moduleName}::{name}' not found").Build()); + + return structType; + } + + public NubType ResolveIdentifier(string moduleName, string name) + { + var module = modules.GetValueOrDefault(moduleName); + if (module == null) + throw new CompileException(Diagnostic.Error($"Module '{moduleName}' not found").Build()); + + var identType = module.ResolveIdentifier(name); + if (identType == null) + throw new CompileException(Diagnostic.Error($"Function '{moduleName}::{name}' not found").Build()); + + return identType; + } + + public List GetStructTypes() + { + return modules.SelectMany(x => x.Value.GetStructTypes()).ToList(); + } + + public sealed class Module + { + private readonly Dictionary structTypes = new(); + private readonly Dictionary identifierTypes = new(); + + public List GetStructTypes() + { + return structTypes.Values.ToList(); + } + + public List GetIdentifiers() + { + return identifierTypes.Values.ToList(); + } + + public NubTypeStruct? ResolveStruct(string name) + { + return structTypes.GetValueOrDefault(name); + } + + public NubType? ResolveIdentifier(string name) + { + return identifierTypes.GetValueOrDefault(name); + } + + public void AddStruct(string name, NubTypeStruct structType) + { + structTypes.Add(name, structType); + } + + public void AddIdentifier(string name, NubType identifier) + { + identifierTypes.Add(name, identifier); + } + } + + public class Builder + { + private readonly List asts = []; + + public void AddAst(Ast ast) + { + asts.Add(ast); + } + + public ModuleGraph Build(out List diagnostics) + { + diagnostics = []; + + var modules = new Dictionary(); + + // First pass: Register modules + foreach (var ast in asts) + { + var moduleDefinitions = ast.Definitions.OfType().ToList(); + var currentModule = moduleDefinitions[0].Name.Ident; + + if (!modules.ContainsKey(currentModule)) + modules.Add(currentModule, new Module()); + } + + // Second pass: Register struct types without fields + foreach (var ast in asts) + { + var moduleDefinitions = ast.Definitions.OfType().ToList(); + var currentModule = moduleDefinitions[0].Name.Ident; + + if (!modules.TryGetValue(currentModule, out var module)) + { + module = new Module(); + modules[currentModule] = module; + } + + foreach (var structDef in ast.Definitions.OfType()) + { + module.AddStruct(structDef.Name.Ident, new NubTypeStruct()); + } + } + + // Third pass: Resolve struct fields + foreach (var ast in asts) + { + var moduleDefinitions = ast.Definitions.OfType().ToList(); + var module = modules[moduleDefinitions[0].Name.Ident]; + + foreach (var structDef in ast.Definitions.OfType()) + { + var structType = module.ResolveStruct(structDef.Name.Ident); + var fields = structDef.Fields.Select(f => new NubTypeStruct.Field(f.Name.Ident, Resolve(f.Type))).ToList(); + structType.ResolveFields(fields); + } + } + + // Fourth pass: Register identifiers + foreach (var ast in asts) + { + var moduleDefinitions = ast.Definitions.OfType().ToList(); + var module = modules[moduleDefinitions[0].Name.Ident]; + + foreach (var funcDef in ast.Definitions.OfType()) + { + var parameters = funcDef.Parameters.Select(x => Resolve(x.Type)).ToList(); + var returnType = Resolve(funcDef.ReturnType); + var funcType = new NubTypeFunc(parameters, returnType); + module.AddIdentifier(funcDef.Name.Ident, funcType); + } + } + + return new ModuleGraph(modules); + + NubType Resolve(NodeType node) + { + return node switch + { + NodeTypeBool type => new NubTypeBool(), + NodeTypeCustom type => ResolveStruct(type), + NodeTypeFunc type => new NubTypeFunc(type.Parameters.Select(Resolve).ToList(), Resolve(type.ReturnType)), + NodeTypePointer type => new NubTypePointer(Resolve(type.To)), + NodeTypeSInt type => new NubTypeSInt(type.Width), + NodeTypeUInt type => new NubTypeUInt(type.Width), + NodeTypeString type => new NubTypeString(), + NodeTypeVoid type => new NubTypeVoid(), + _ => throw new ArgumentOutOfRangeException(nameof(node)) + }; + } + + NubTypeStruct ResolveStruct(NodeTypeCustom type) + { + var module = modules.GetValueOrDefault(type.Module.Ident); + if (module == null) + throw new CompileException(Diagnostic.Error($"Unknown module: {type.Module.Ident}").Build()); + + var structType = module.ResolveStruct(type.Name.Ident); + if (structType == null) + throw new CompileException(Diagnostic.Error($"Unknown custom type: {type.Module.Ident}::{type.Name.Ident}").Build()); + + return structType; + } + } + } +} \ No newline at end of file diff --git a/compiler/TypeResolver.cs b/compiler/NubType.cs similarity index 59% rename from compiler/TypeResolver.cs rename to compiler/NubType.cs index f153d8b..42a9fce 100644 --- a/compiler/TypeResolver.cs +++ b/compiler/NubType.cs @@ -1,83 +1,5 @@ namespace Compiler; -public sealed class TypeResolver(string fileName) -{ - private readonly Dictionary<(string Module, string Name), NubTypeStruct> structTypes = []; - - public NubTypeStruct? GetNamedStruct(string module, string name) => structTypes.GetValueOrDefault((module, name)); - - public static TypeResolver Create(string fileName, Ast ast, out List diagnostics) - { - diagnostics = []; - var resolver = new TypeResolver(fileName); - - var moduleDefinitions = ast.Definitions.OfType().ToList(); - - if (moduleDefinitions.Count == 0) - diagnostics.Add(Diagnostic.Error($"'{fileName}' is not part of a module").At(fileName, 1, 1, 1).Build()); - - foreach (var moduleDefinition in moduleDefinitions.Skip(1)) - diagnostics.Add(Diagnostic.Warning("Duplicate module definition").At(fileName, moduleDefinition).Build()); - - if (moduleDefinitions.Count >= 1) - { - var currentModule = moduleDefinitions[0].Name.Ident; - - foreach (var structDef in ast.Definitions.OfType()) - { - if (resolver.structTypes.ContainsKey((currentModule, structDef.Name.Ident))) - { - diagnostics.Add(Diagnostic.Error($"Duplicate struct: {structDef.Name.Ident}").At(fileName, structDef.Name).Build()); - continue; - } - - resolver.structTypes.Add((currentModule, structDef.Name.Ident), new NubTypeStruct()); - } - - foreach (var structDef in ast.Definitions.OfType()) - { - var structType = resolver.structTypes[(currentModule, structDef.Name.Ident)]; - - try - { - structType.ResolveFields(structDef.Fields.Select(f => new NubTypeStruct.Field(f.Name.Ident, resolver.Resolve(f.Type))).ToList()); - } - catch (CompileException e) - { - diagnostics.Add(e.Diagnostic); - } - } - } - - return resolver; - } - - public NubType Resolve(NodeType node) - { - return node switch - { - NodeTypeBool type => new NubTypeBool(), - NodeTypeCustom type => ResolveStruct(type), - NodeTypeFunc type => new NubTypeFunc(type.Parameters.Select(Resolve).ToList(), Resolve(type.ReturnType)), - NodeTypePointer type => new NubTypePointer(Resolve(type.To)), - NodeTypeSInt type => new NubTypeSInt(type.Width), - NodeTypeUInt type => new NubTypeUInt(type.Width), - NodeTypeString type => new NubTypeString(), - NodeTypeVoid type => new NubTypeVoid(), - _ => throw new ArgumentOutOfRangeException(nameof(node)) - }; - } - - private NubTypeStruct ResolveStruct(NodeTypeCustom type) - { - var structType = structTypes.GetValueOrDefault((type.Module.Ident, type.Name.Ident)); - if (structType == null) - throw new CompileException(Diagnostic.Error($"Unknown custom type: {type.Module.Ident}::{type.Name.Ident}").At(fileName, type).Build()); - - return structType; - } -} - public abstract class NubType : IEquatable { public abstract override string ToString(); diff --git a/compiler/Parser.cs b/compiler/Parser.cs index d13c225..037e342 100644 --- a/compiler/Parser.cs +++ b/compiler/Parser.cs @@ -28,7 +28,7 @@ public sealed class Parser(string fileName, List tokens) diagnostics.Add(e.Diagnostic); } - return new Ast(definitions); + return new Ast(definitions, fileName); } private NodeDefinition ParseDefinition() @@ -82,12 +82,6 @@ public sealed class Parser(string fileName, List tokens) return new NodeDefinitionModule(TokensFrom(startIndex), name); } - if (TryExpectKeyword(Keyword.Import)) - { - var name = ExpectIdent(); - return new NodeDefinitionImport(TokensFrom(startIndex), name); - } - throw new CompileException(Diagnostic.Error("Not a valid definition").At(fileName, Peek()).Build()); } @@ -244,7 +238,15 @@ public sealed class Parser(string fileName, List tokens) } else if (TryExpectIdent(out var ident)) { - expr = new NodeExpressionIdent(TokensFrom(startIndex), ident); + if (TryExpectSymbol(Symbol.ColonColon)) + { + var name = ExpectIdent(); + expr = new NodeExpressionModuleIdent(TokensFrom(startIndex), ident, name); + } + else + { + expr = new NodeExpressionLocalIdent(TokensFrom(startIndex), ident); + } } else if (TryExpectKeyword(Keyword.Struct)) { @@ -532,8 +534,9 @@ public sealed class Parser(string fileName, List tokens) } } -public sealed class Ast(List definitions) +public sealed class Ast(List definitions, string fileName) { + public string FileName = fileName; public readonly List Definitions = definitions; } @@ -549,11 +552,6 @@ public sealed class NodeDefinitionModule(List tokens, TokenIdent name) : public readonly TokenIdent Name = name; } -public sealed class NodeDefinitionImport(List tokens, TokenIdent name) : NodeDefinition(tokens) -{ - public readonly TokenIdent Name = name; -} - public sealed class NodeDefinitionFunc(List tokens, TokenIdent name, List parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens) { public readonly TokenIdent Name = name; @@ -660,11 +658,17 @@ public sealed class NodeExpressionMemberAccess(List tokens, NodeExpressio public readonly TokenIdent Name = name; } -public sealed class NodeExpressionIdent(List tokens, TokenIdent value) : NodeExpression(tokens) +public sealed class NodeExpressionLocalIdent(List tokens, TokenIdent value) : NodeExpression(tokens) { public readonly TokenIdent Value = value; } +public sealed class NodeExpressionModuleIdent(List tokens, TokenIdent module, TokenIdent value) : NodeExpression(tokens) +{ + public readonly TokenIdent Module = module; + public readonly TokenIdent Value = value; +} + public sealed class NodeExpressionBinary(List tokens, NodeExpression left, NodeExpressionBinary.Op operation, NodeExpression right) : NodeExpression(tokens) { public readonly NodeExpression Left = left; diff --git a/compiler/Program.cs b/compiler/Program.cs index f5c3f4a..a7c3008 100644 --- a/compiler/Program.cs +++ b/compiler/Program.cs @@ -1,6 +1,9 @@ using System.Diagnostics; using Compiler; +var moduleGraphBuilder = ModuleGraph.Create(); +var asts = new List(); + foreach (var fileName in args) { var file = File.ReadAllText(fileName); @@ -21,19 +24,25 @@ foreach (var fileName in args) if (parserDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) return 1; - var typeResolver = TypeResolver.Create(fileName, ast, out var typeResolverDiagnostics); + moduleGraphBuilder.AddAst(ast); + asts.Add(ast); +} - foreach (var diagnostic in typeResolverDiagnostics) - DiagnosticFormatter.Print(diagnostic, Console.Error); +var moduleGraph = moduleGraphBuilder.Build(out var moduleGraphDiagnostics); - if (typeResolverDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) - return 1; +foreach (var diagnostic in moduleGraphDiagnostics) + DiagnosticFormatter.Print(diagnostic, Console.Error); - var functions = new List(); +if (moduleGraphDiagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) + return 1; - foreach (var function in ast.Definitions.OfType()) +var functions = new List(); + +foreach (var ast in asts) +{ + foreach (var func in ast.Definitions.OfType()) { - var typedFunction = TypeChecker.CheckFunction(fileName, function, typeResolver, out var typeCheckerDiagnostics); + var typedFunction = TypeChecker.CheckFunction(ast.FileName, func, moduleGraph, out var typeCheckerDiagnostics); foreach (var diagnostic in typeCheckerDiagnostics) DiagnosticFormatter.Print(diagnostic, Console.Error); @@ -43,16 +52,15 @@ foreach (var fileName in args) functions.Add(typedFunction); } - - var output = Generator.Emit(functions); - - Directory.Delete(".build", recursive: true); - Directory.CreateDirectory(".build"); - - var outFilePath = Path.Combine(".build", Path.ChangeExtension(fileName, "c")); - File.WriteAllText(outFilePath, output); - - Process.Start("gcc", ["-Og", "-g", "-c", "-o", Path.ChangeExtension(outFilePath, "o"), outFilePath]); } +var output = Generator.Emit(functions, moduleGraph); + +Directory.Delete(".build", recursive: true); +Directory.CreateDirectory(".build"); + +File.WriteAllText(".build/out.c", output); + +Process.Start("gcc", ["-Og", "-g", "-o", ".build/out", ".build/out.c"]); + return 0; \ No newline at end of file diff --git a/compiler/Tokenizer.cs b/compiler/Tokenizer.cs index 218e4ad..a8db0cd 100644 --- a/compiler/Tokenizer.cs +++ b/compiler/Tokenizer.cs @@ -347,8 +347,6 @@ public sealed class Tokenizer(string fileName, string contents) "while" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.While), "return" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Return), "module" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Module), - "import" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Import), - "export" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Export), "true" => new TokenBoolLiteral(line, startColumn, column - startColumn, true), "false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false), _ => new TokenIdent(line, startColumn, column - startColumn, value) @@ -482,8 +480,6 @@ public enum Keyword While, Return, Module, - Import, - Export, } public sealed class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length) @@ -546,8 +542,6 @@ public static class TokenExtensions Keyword.While => "while", Keyword.Return => "return", Keyword.Module => "module", - Keyword.Import => "import", - Keyword.Export => "export", _ => throw new ArgumentOutOfRangeException(nameof(symbol), symbol, null) }; } diff --git a/compiler/TypeChecker.cs b/compiler/TypeChecker.cs index 42e6bd5..0cf774f 100644 --- a/compiler/TypeChecker.cs +++ b/compiler/TypeChecker.cs @@ -1,13 +1,13 @@ namespace Compiler; -public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, TypeResolver typeResolver) +public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, ModuleGraph moduleGraph) { - public static TypedNodeDefinitionFunc? CheckFunction(string fileName, NodeDefinitionFunc function, TypeResolver typeResolver, out List diagnostics) + public static TypedNodeDefinitionFunc? CheckFunction(string fileName, NodeDefinitionFunc function, ModuleGraph moduleGraph, out List diagnostics) { - return new TypeChecker(fileName, function, typeResolver).CheckFunction(out diagnostics); + return new TypeChecker(fileName, function, moduleGraph).CheckFunction(out diagnostics); } - private Scope scope = new(null); + private readonly Scope scope = new(null); private TypedNodeDefinitionFunc? CheckFunction(out List diagnostics) { @@ -42,7 +42,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty try { - returnType = typeResolver.Resolve(function.ReturnType); + returnType = ResolveType(function.ReturnType); } catch (CompileException e) { @@ -57,7 +57,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty private TypedNodeDefinitionFunc.Param CheckDefinitionFuncParameter(NodeDefinitionFunc.Param node) { - return new TypedNodeDefinitionFunc.Param(node.Tokens, node.Name, typeResolver.Resolve(node.Type)); + return new TypedNodeDefinitionFunc.Param(node.Tokens, node.Name, ResolveType(node.Type)); } private TypedNodeStatement CheckStatement(NodeStatement node) @@ -102,7 +102,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty private TypedNodeStatementVariableDeclaration CheckStatementVariableDeclaration(NodeStatementVariableDeclaration statement) { - var type = typeResolver.Resolve(statement.Type); + var type = ResolveType(statement.Type); var value = CheckExpression(statement.Value); if (type != value.Type) @@ -125,7 +125,8 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty NodeExpressionBinary expression => CheckExpressionBinary(expression), NodeExpressionUnary expression => CheckExpressionUnary(expression), NodeExpressionBoolLiteral expression => CheckExpressionBoolLiteral(expression), - NodeExpressionIdent expression => CheckExpressionIdent(expression), + NodeExpressionLocalIdent expression => CheckExpressionIdent(expression), + NodeExpressionModuleIdent expression => CheckExpressionModuleIdent(expression), NodeExpressionIntLiteral expression => CheckExpressionIntLiteral(expression), NodeExpressionMemberAccess expression => CheckExpressionMemberAccess(expression), NodeExpressionStringLiteral expression => CheckExpressionStringLiteral(expression), @@ -272,13 +273,19 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty return new TypedNodeExpressionBoolLiteral(expression.Tokens, new NubTypeBool(), expression.Value); } - private TypedNodeExpressionIdent CheckExpressionIdent(NodeExpressionIdent expression) + private TypedNodeExpressionLocalIdent CheckExpressionIdent(NodeExpressionLocalIdent expression) { var type = scope.GetIdentifierType(expression.Value.Ident); if (type == null) throw new CompileException(Diagnostic.Error($"Identifier '{expression.Value.Ident}' is not declared").At(fileName, expression.Value).Build()); - return new TypedNodeExpressionIdent(expression.Tokens, type, expression.Value); + return new TypedNodeExpressionLocalIdent(expression.Tokens, type, expression.Value); + } + + private TypedNodeExpressionModuleIdent CheckExpressionModuleIdent(NodeExpressionModuleIdent expression) + { + var identifierType = moduleGraph.ResolveIdentifier(expression.Module.Ident, expression.Value.Ident); + return new TypedNodeExpressionModuleIdent(expression.Tokens, identifierType, expression.Module, expression.Value); } private TypedNodeExpressionIntLiteral CheckExpressionIntLiteral(NodeExpressionIntLiteral expression) @@ -306,7 +313,7 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty private TypedNodeExpressionStructLiteral CheckExpressionStructLiteral(NodeExpressionStructLiteral expression) { - var type = typeResolver.GetNamedStruct(expression.Module.Ident, expression.Name.Ident); + var type = moduleGraph.ResolveStruct(expression.Module.Ident, expression.Name.Ident); if (type == null) throw new CompileException(Diagnostic.Error($"Undeclared struct '{expression.Module.Ident}::{expression.Name.Ident}'").At(fileName, expression.Name).Build()); @@ -327,6 +334,22 @@ public sealed class TypeChecker(string fileName, NodeDefinitionFunc function, Ty return new TypedNodeExpressionStructLiteral(expression.Tokens, type, initializers); } + private NubType ResolveType(NodeType node) + { + return node switch + { + NodeTypeBool type => new NubTypeBool(), + NodeTypeCustom type => moduleGraph.ResolveStruct(type.Module.Ident, type.Name.Ident), + NodeTypeFunc type => new NubTypeFunc(type.Parameters.Select(ResolveType).ToList(), ResolveType(type.ReturnType)), + NodeTypePointer type => new NubTypePointer(ResolveType(type.To)), + NodeTypeSInt type => new NubTypeSInt(type.Width), + NodeTypeUInt type => new NubTypeUInt(type.Width), + NodeTypeString type => new NubTypeString(), + NodeTypeVoid type => new NubTypeVoid(), + _ => throw new ArgumentOutOfRangeException(nameof(node)) + }; + } + private class Scope(Scope? parent) { private readonly Dictionary identifiers = new(); @@ -366,18 +389,6 @@ public sealed class TypedNodeDefinitionFunc(List tokens, TokenIdent name, } } -public sealed class TypedNodeDefinitionStruct(List tokens, TokenIdent name, List fields) : TypedNodeDefinition(tokens) -{ - public readonly TokenIdent Name = name; - public readonly List Fields = fields; - - public sealed class Field(List tokens, TokenIdent name, NubType type) : TypedNode(tokens) - { - public readonly TokenIdent Name = name; - public readonly NubType Type = type; - } -} - public abstract class TypedNodeStatement(List tokens) : TypedNode(tokens); public sealed class TypedNodeStatementBlock(List tokens, List statements) : TypedNodeStatement(tokens) @@ -459,11 +470,17 @@ public sealed class TypedNodeExpressionMemberAccess(List tokens, NubType public readonly TokenIdent Name = name; } -public sealed class TypedNodeExpressionIdent(List tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type) +public sealed class TypedNodeExpressionLocalIdent(List tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type) { public readonly TokenIdent Value = value; } +public sealed class TypedNodeExpressionModuleIdent(List tokens, NubType type, TokenIdent module, TokenIdent value) : TypedNodeExpression(tokens, type) +{ + public readonly TokenIdent Module = module; + public readonly TokenIdent Value = value; +} + public sealed class TypedNodeExpressionBinary(List tokens, NubType type, TypedNodeExpression left, TypedNodeExpressionBinary.Op operation, TypedNodeExpression right) : TypedNodeExpression(tokens, type) { public readonly TypedNodeExpression Left = left; diff --git a/compiler/test.nub b/compiler/test.nub index 39d6975..fc2b13c 100644 --- a/compiler/test.nub +++ b/compiler/test.nub @@ -1,10 +1,5 @@ module main -struct person { - age: i32 - name: string -} - func main(): i32 { let x: i32 = 23 x = 24 @@ -25,11 +20,8 @@ func main(): i32 { x = i } - let me: main::person = struct main::person { age = 21 name = "Oliver" } + let me: test::person = struct test::person { age = 21 name = "Oliver" } - do_something(me.name) + test::do_something(me.name) return x -} - -func do_something(text: string): void { } \ No newline at end of file diff --git a/compiler/test2.nub b/compiler/test2.nub new file mode 100644 index 0000000..467364e --- /dev/null +++ b/compiler/test2.nub @@ -0,0 +1,9 @@ +module test + +struct person { + age: i32 + name: string +} + +func do_something(name: string): void { +} \ No newline at end of file