diff --git a/compiler/NubLang.CLI/Program.cs b/compiler/NubLang.CLI/Program.cs index a0e4474..9e835f7 100644 --- a/compiler/NubLang.CLI/Program.cs +++ b/compiler/NubLang.CLI/Program.cs @@ -2,14 +2,13 @@ using NubLang.Ast; using NubLang.Diagnostics; using NubLang.Generation; -using NubLang.Modules; using NubLang.Syntax; var diagnostics = new List(); var syntaxTrees = new List(); -var nubFiles = args.Where(x => Path.GetExtension(x) == ".nub"); -var objectFiles = args.Where(x => Path.GetExtension(x) is ".o" or ".a"); +var nubFiles = args.Where(x => Path.GetExtension(x) == ".nub").ToArray(); +var objectFileArgs = args.Where(x => Path.GetExtension(x) is ".o" or ".a").ToArray(); foreach (var file in nubFiles) { @@ -24,16 +23,15 @@ foreach (var file in nubFiles) syntaxTrees.Add(syntaxTree); } -var moduleRepository = new ModuleRepository(syntaxTrees); +var modules = Module.Collect(syntaxTrees); +var compilationUnits = new List(); -var definitions = new List(); - -foreach (var syntaxTree in syntaxTrees) +for (var i = 0; i < nubFiles.Length; i++) { - var typeChecker = new TypeChecker(syntaxTree, moduleRepository); - typeChecker.Check(); + var typeChecker = new TypeChecker(syntaxTrees[i], modules); + var compilationUnit = typeChecker.Check(); - definitions.AddRange(typeChecker.Definitions); + compilationUnits.Add(compilationUnit); diagnostics.AddRange(typeChecker.Diagnostics); } @@ -47,36 +45,57 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro return 1; } +var cPaths = new List(); + Directory.CreateDirectory(".build"); -var generator = new Generator(definitions); -var c = generator.Emit(); -var cFilePath = Path.Combine(".build", "out.c"); - -File.WriteAllText(cFilePath, c); - -using var compileProcess = Process.Start("gcc", [ - "-ffreestanding", "-nostartfiles", "-std=c23", - "-g", "-lm", - "-c", "-o", Path.Combine(".build", "out.o"), - cFilePath, -]); - -compileProcess.WaitForExit(); - -if (compileProcess.ExitCode != 0) +for (var i = 0; i < nubFiles.Length; i++) { - Console.Error.WriteLine($"gcc failed with exit code {compileProcess.ExitCode}"); - return 1; + var file = nubFiles[i]; + var compilationUnit = compilationUnits[i]; + + var generator = new Generator(compilationUnit); + var directory = Path.GetDirectoryName(file); + if (!string.IsNullOrWhiteSpace(directory)) + { + Directory.CreateDirectory(Path.Combine(".build", directory)); + } + + var path = Path.Combine(".build", Path.ChangeExtension(file, "c")); + File.WriteAllText(path, generator.Emit()); + cPaths.Add(path); } -if (moduleRepository.Modules().TryGetValue("main", out var mainModule)) +var objectPaths = new List(); + +foreach (var cPath in cPaths) +{ + var objectPath = Path.ChangeExtension(cPath, "o"); + using var compileProcess = Process.Start("gcc", [ + "-ffreestanding", "-nostartfiles", "-std=c23", + "-g", "-lm", + "-c", "-o", objectPath, + cPath, + ]); + + compileProcess.WaitForExit(); + + if (compileProcess.ExitCode != 0) + { + Console.Error.WriteLine($"gcc failed with exit code {compileProcess.ExitCode}"); + return 1; + } + + objectPaths.Add(objectPath); +} + +if (modules.TryGetValue("main", out var mainModule)) { var mainFunction = mainModule .Functions(true) - .FirstOrDefault(x => x.ExternSymbol == "main"); + .FirstOrDefault(x => x.Prototype.ExternSymbol == "main"); - if (mainFunction is { ExternSymbol: not null }) + if (mainFunction is { Prototype.ExternSymbol: not null }) { var runtime = $""" .intel_syntax noprefix @@ -85,7 +104,7 @@ if (moduleRepository.Modules().TryGetValue("main", out var mainModule)) .globl _start _start: mov rdi, rsp # Pass stack pointer to main (length + cstring pointers) - call {mainFunction.ExternSymbol} + call {mainFunction.Prototype.ExternSymbol} mov rdi, rax # Move return value into rdi mov rax, 60 # syscall: exit syscall @@ -111,9 +130,9 @@ if (moduleRepository.Modules().TryGetValue("main", out var mainModule)) "-ffreestanding", "-nostartfiles", "-std=c23", "-g", "-lm", "-o", Path.Combine(".build", "out"), - Path.Combine(".build", "out.o"), + ..objectPaths, Path.Combine(".build", "runtime.o"), - ..objectFiles + ..objectFileArgs ])); if (linkProcess == null) return 1; diff --git a/compiler/NubLang/Ast/CompilationUnit.cs b/compiler/NubLang/Ast/CompilationUnit.cs new file mode 100644 index 0000000..f2115c1 --- /dev/null +++ b/compiler/NubLang/Ast/CompilationUnit.cs @@ -0,0 +1,15 @@ +namespace NubLang.Ast; + +public sealed class CompilationUnit +{ + public CompilationUnit(List functions, List importedStructTypes, List importedFunctions) + { + Functions = functions; + ImportedStructTypes = importedStructTypes; + ImportedFunctions = importedFunctions; + } + + public List Functions { get; } + public List ImportedStructTypes { get; } + public List ImportedFunctions { get; } +} \ No newline at end of file diff --git a/compiler/NubLang/Ast/Node.cs b/compiler/NubLang/Ast/Node.cs index 7ea2009..04c63fe 100644 --- a/compiler/NubLang/Ast/Node.cs +++ b/compiler/NubLang/Ast/Node.cs @@ -10,15 +10,9 @@ public abstract record DefinitionNode(List Tokens, string Module, string public record FuncParameterNode(List Tokens, string Name, NubType Type) : Node(Tokens); -public record FuncSignatureNode(List Tokens, List Parameters, NubType ReturnType) : Node(Tokens); +public record FuncPrototypeNode(List Tokens, string Module, string Name, string? ExternSymbol, List Parameters, NubType ReturnType) : Node(Tokens); -public record FuncNode(List Tokens, string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Tokens, Module, Name); - -public record StructFieldNode(List Tokens, string Name, NubType Type, ExpressionNode? Value) : Node(Tokens); - -public record StructFuncNode(List Tokens, string Name, FuncSignatureNode Signature, BlockNode Body) : Node(Tokens); - -public record StructNode(List Tokens, string Module, string Name, List Fields, List Functions) : DefinitionNode(Tokens, Module, Name); +public record FuncNode(List Tokens, FuncPrototypeNode Prototype, BlockNode? Body) : DefinitionNode(Tokens, Prototype.Module, Prototype.Name); #endregion @@ -32,8 +26,6 @@ public record BlockNode(List Tokens, List Statements) : St public record StatementFuncCallNode(List Tokens, FuncCallNode FuncCall) : StatementNode(Tokens); -public record StatementStructFuncCallNode(List Tokens, StructFuncCallNode StructFuncCall) : StatementNode(Tokens); - public record ReturnNode(List Tokens, ExpressionNode? Value) : TerminalStatementNode(Tokens); public record AssignmentNode(List Tokens, LValueExpressionNode Target, ExpressionNode Value) : StatementNode(Tokens); @@ -108,8 +100,6 @@ public record UnaryExpressionNode(List Tokens, NubType Type, UnaryOperato public record FuncCallNode(List Tokens, NubType Type, ExpressionNode Expression, List Parameters) : RValueExpressionNode(Tokens, Type); -public record StructFuncCallNode(List Tokens, NubType Type, string Module, string StructName, string FuncName, ExpressionNode StructExpression, List Parameters) : RValueExpressionNode(Tokens, Type); - public record LValueIdentifierNode(List Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type); public record RValueIdentifierNode(List Tokens, NubType Type, string Name) : RValueExpressionNode(Tokens, Type); diff --git a/compiler/NubLang/Ast/NubType.cs b/compiler/NubLang/Ast/NubType.cs index 65d4ff4..6e33635 100644 --- a/compiler/NubLang/Ast/NubType.cs +++ b/compiler/NubLang/Ast/NubType.cs @@ -100,7 +100,7 @@ public class NubFuncType(List parameters, NubType returnType) : NubType } } -public class NubStructType(string module, string name, List fields, List functions) : NubType +public class NubStructType(string module, string name, List fields) : NubType { public override bool IsValueType => true; public override bool IsScalar => false; @@ -108,9 +108,8 @@ public class NubStructType(string module, string name, List public string Module { get; } = module; public string Name { get; } = name; public List Fields { get; set; } = fields; - public List Functions { get; set; } = functions; - public override string ToString() => $"{Module}.{Name}"; + public override string ToString() => $"{Module}::{Name}"; public override bool Equals(NubType? other) => other is NubStructType structType && Name == structType.Name && Module == structType.Module; public override int GetHashCode() => HashCode.Combine(typeof(NubStructType), Module, Name); } diff --git a/compiler/NubLang/Ast/TypeChecker.cs b/compiler/NubLang/Ast/TypeChecker.cs index a977fdb..62e236e 100644 --- a/compiler/NubLang/Ast/TypeChecker.cs +++ b/compiler/NubLang/Ast/TypeChecker.cs @@ -1,6 +1,5 @@ using System.Diagnostics; using NubLang.Diagnostics; -using NubLang.Modules; using NubLang.Syntax; namespace NubLang.Ast; @@ -8,64 +7,69 @@ namespace NubLang.Ast; public sealed class TypeChecker { private readonly SyntaxTree _syntaxTree; - private readonly Dictionary _visibleModules; + private readonly Dictionary _importedModules; private readonly Stack _scopes = []; private readonly Stack _funcReturnTypes = []; private readonly Dictionary<(string Module, string Name), NubType> _typeCache = new(); private readonly HashSet<(string Module, string Name)> _resolvingTypes = []; - private readonly HashSet _checkedTemplateStructs = []; private Scope CurrentScope => _scopes.Peek(); - public TypeChecker(SyntaxTree syntaxTree, ModuleRepository moduleRepository) + public List Diagnostics { get; } = []; + + public TypeChecker(SyntaxTree syntaxTree, Dictionary modules) { _syntaxTree = syntaxTree; - _visibleModules = moduleRepository - .Modules() - .Where(x => syntaxTree.Metadata.Imports.Contains(x.Key) || _syntaxTree.Metadata.ModuleName == x.Key) + _importedModules = modules + .Where(x => syntaxTree.Imports.Contains(x.Key) || _syntaxTree.ModuleName == x.Key) .ToDictionary(); } - public List Definitions { get; } = []; - public List Diagnostics { get; } = []; - - public void Check() + public CompilationUnit Check() { _scopes.Clear(); _funcReturnTypes.Clear(); _typeCache.Clear(); _resolvingTypes.Clear(); - _checkedTemplateStructs.Clear(); - Diagnostics.Clear(); - Definitions.Clear(); - - using (BeginRootScope(_syntaxTree.Metadata.ModuleName)) + using (BeginRootScope(_syntaxTree.ModuleName)) { - foreach (var definition in _syntaxTree.Definitions) + var functions = new List(); + + foreach (var funcSyntax in _syntaxTree.Definitions.OfType()) { try { - switch (definition) - { - case FuncSyntax funcSyntax: - Definitions.Add(CheckFuncDefinition(funcSyntax)); - break; - case StructSyntax structSyntax: - Definitions.Add(CheckStructDefinition(structSyntax)); - break; - case StructTemplateSyntax: - break; - default: - throw new ArgumentOutOfRangeException(); - } + functions.Add(CheckFuncDefinition(funcSyntax)); } catch (TypeCheckerException e) { Diagnostics.Add(e.Diagnostic); } } + + var importedStructTypes = new List(); + var importedFunctions = new List(); + + foreach (var (name, module) in _importedModules) + { + foreach (var structSyntax in module.Structs(false)) + { + var fields = structSyntax.Fields + .Select(f => new NubStructFieldType(f.Name, ResolveType(f.Type), f.Value != null)) + .ToList(); + + importedStructTypes.Add(new NubStructType(name, structSyntax.Name, fields)); + } + + foreach (var funcSyntax in module.Functions(false)) + { + importedFunctions.Add(CheckFuncPrototype(funcSyntax.Prototype)); + } + } + + return new CompilationUnit(functions, importedStructTypes, importedFunctions); } } @@ -77,7 +81,7 @@ public sealed class TypeChecker } else { - _scopes.Push(new Scope(_syntaxTree.Metadata.ModuleName)); + _scopes.Push(new Scope(_syntaxTree.ModuleName)); } return new ScopeDisposer(this); @@ -101,74 +105,25 @@ public sealed class TypeChecker } } - private StructNode CheckStructDefinition(StructSyntax node) - { - var fieldTypes = node.Fields - .Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.Value != null)) - .ToList(); - - var fieldFunctions = node.Functions - .Select(x => - { - var parameters = x.Signature.Parameters.Select(y => ResolveType(y.Type)).ToList(); - var returnType = ResolveType(x.Signature.ReturnType); - return new NubStructFuncType(x.Name, parameters, returnType); - }) - .ToList(); - - var structType = new NubStructType(CurrentScope.Module, node.Name, fieldTypes, fieldFunctions); - - CurrentScope.DeclareVariable(new Variable("this", structType, VariableKind.RValue)); - - var fields = node.Fields.Select(CheckStructField).ToList(); - var functions = node.Functions.Select(CheckStructFunc).ToList(); - - return new StructNode(node.Tokens, CurrentScope.Module, node.Name, fields, functions); - } - - private StructFuncNode CheckStructFunc(StructFuncSyntax function) - { - foreach (var parameter in function.Signature.Parameters) - { - CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type), VariableKind.RValue)); - } - - _funcReturnTypes.Push(ResolveType(function.Signature.ReturnType)); - var body = CheckBlock(function.Body); - _funcReturnTypes.Pop(); - return new StructFuncNode(function.Tokens, function.Name, CheckFuncSignature(function.Signature), body); - } - - private StructFieldNode CheckStructField(StructFieldSyntax field) - { - ExpressionNode? value = null; - if (field.Value != null) - { - value = CheckExpression(field.Value, ResolveType(field.Type)); - } - - return new StructFieldNode(field.Tokens, field.Name, ResolveType(field.Type), value); - } - private FuncNode CheckFuncDefinition(FuncSyntax node) { - foreach (var parameter in node.Signature.Parameters) + foreach (var parameter in node.Prototype.Parameters) { CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type), VariableKind.RValue)); } - var signature = CheckFuncSignature(node.Signature); + var prototype = CheckFuncPrototype(node.Prototype); BlockNode? body = null; if (node.Body != null) { - _funcReturnTypes.Push(signature.ReturnType); + _funcReturnTypes.Push(prototype.ReturnType); body = CheckBlock(node.Body); if (!AlwaysReturns(body)) { - if (signature.ReturnType is NubVoidType) + if (prototype.ReturnType is NubVoidType) { body.Statements.Add(new ReturnNode(node.Tokens.Skip(node.Tokens.Count - 1).ToList(), null)); } @@ -184,7 +139,7 @@ public sealed class TypeChecker _funcReturnTypes.Pop(); } - return new FuncNode(node.Tokens, CurrentScope.Module, node.Name, node.ExternSymbol, signature, body); + return new FuncNode(node.Tokens, prototype, body); } private AssignmentNode CheckAssignment(AssignmentSyntax statement) @@ -231,7 +186,6 @@ public sealed class TypeChecker return expression switch { FuncCallNode funcCall => new StatementFuncCallNode(statement.Tokens, funcCall), - StructFuncCallNode structFuncCall => new StatementStructFuncCallNode(statement.Tokens, structFuncCall), _ => throw new TypeCheckerException(Diagnostic.Error("Expressions statements can only be function calls").At(statement).Build()) }; } @@ -269,7 +223,7 @@ public sealed class TypeChecker return new WhileNode(statement.Tokens, condition, body); } - private FuncSignatureNode CheckFuncSignature(FuncSignatureSyntax statement) + private FuncPrototypeNode CheckFuncPrototype(FuncPrototypeSyntax statement) { var parameters = new List(); foreach (var parameter in statement.Parameters) @@ -277,7 +231,7 @@ public sealed class TypeChecker parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.Name, ResolveType(parameter.Type))); } - return new FuncSignatureNode(statement.Tokens, parameters, ResolveType(statement.ReturnType)); + return new FuncPrototypeNode(statement.Tokens, CurrentScope.Module, statement.Name, statement.ExternSymbol, parameters, ResolveType(statement.ReturnType)); } private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null) @@ -290,7 +244,6 @@ public sealed class TypeChecker BinaryExpressionSyntax expression => CheckBinaryExpression(expression, expectedType), UnaryExpressionSyntax expression => CheckUnaryExpression(expression, expectedType), DereferenceSyntax expression => CheckDereference(expression), - MemberFuncCallSyntax expression => CheckMemberFuncCall(expression), FuncCallSyntax expression => CheckFuncCall(expression), LocalIdentifierSyntax expression => CheckLocalIdentifier(expression), ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression), @@ -608,56 +561,6 @@ public sealed class TypeChecker return new FuncCallNode(expression.Tokens, funcType.ReturnType, accessor, parameters); } - private StructFuncCallNode CheckMemberFuncCall(MemberFuncCallSyntax expression) - { - // todo(nub31): When adding interfaces, also support other types than structs - var target = CheckExpression(expression.Target); - if (target.Type is NubStructType structType) - { - var function = structType.Functions.FirstOrDefault(x => x.Name == expression.Name); - if (function == null) - { - throw new TypeCheckerException(Diagnostic - .Error($"Function {expression.Name} not found on struct {structType}") - .At(expression) - .Build()); - } - - if (expression.Parameters.Count != function.Parameters.Count) - { - throw new TypeCheckerException(Diagnostic - .Error($"Function {function.Name} expects {function.Parameters.Count} parameters but got {expression.Parameters.Count}") - .At(expression.Parameters.LastOrDefault(expression)) - .Build()); - } - - var parameters = new List(); - for (var i = 0; i < expression.Parameters.Count; i++) - { - var parameter = expression.Parameters[i]; - var expectedType = function.Parameters[i]; - - var parameterExpression = CheckExpression(parameter, expectedType); - if (parameterExpression.Type != expectedType) - { - throw new TypeCheckerException(Diagnostic - .Error($"Parameter {i + 1} does not match the type {expectedType} for function {function}") - .At(parameter) - .Build()); - } - - parameters.Add(parameterExpression); - } - - return new StructFuncCallNode(expression.Tokens, function.ReturnType, structType.Module, structType.Name, expression.Name, target, parameters); - } - - throw new TypeCheckerException(Diagnostic - .Error($"No function {expression.Name} exists on type {target.Type}") - .At(expression) - .Build()); - } - private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression) { var scopeIdent = CurrentScope.LookupVariable(expression.Name); @@ -671,14 +574,14 @@ public sealed class TypeChecker }; } - var module = _visibleModules[CurrentScope.Module]; + var module = _importedModules[CurrentScope.Module]; var function = module.Functions(true).FirstOrDefault(x => x.Name == expression.Name); if (function != null) { - var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList(); - var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType)); - return new FuncIdentifierNode(expression.Tokens, type, CurrentScope.Module, expression.Name, function.ExternSymbol); + var parameters = function.Prototype.Parameters.Select(x => ResolveType(x.Type)).ToList(); + var type = new NubFuncType(parameters, ResolveType(function.Prototype.ReturnType)); + return new FuncIdentifierNode(expression.Tokens, type, CurrentScope.Module, expression.Name, function.Prototype.ExternSymbol); } throw new TypeCheckerException(Diagnostic.Error($"Symbol {expression.Name} not found").At(expression).Build()); @@ -686,7 +589,7 @@ public sealed class TypeChecker private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression) { - if (!_visibleModules.TryGetValue(expression.Module, out var module)) + if (!_importedModules.TryGetValue(expression.Module, out var module)) { throw new TypeCheckerException(Diagnostic .Error($"Module {expression.Module} not found") @@ -700,9 +603,9 @@ public sealed class TypeChecker var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name); if (function != null) { - var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList(); - var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType)); - return new FuncIdentifierNode(expression.Tokens, type, expression.Module, expression.Name, function.ExternSymbol); + var parameters = function.Prototype.Parameters.Select(x => ResolveType(x.Type)).ToList(); + var type = new NubFuncType(parameters, ResolveType(function.Prototype.ReturnType)); + return new FuncIdentifierNode(expression.Tokens, type, expression.Module, expression.Name, function.Prototype.ExternSymbol); } throw new TypeCheckerException(Diagnostic @@ -824,8 +727,6 @@ public sealed class TypeChecker .Error($"Struct {structType.Name} does not have a field named {initializer.Key}") .At(initializer.Value) .Build()); - - continue; } initializers.Add(initializer.Key, CheckExpression(initializer.Value, typeField.Type)); @@ -849,34 +750,12 @@ public sealed class TypeChecker private BlockNode CheckBlock(BlockSyntax node) { - var statements = new List(); - - var reachable = true; - var warnedUnreachable = false; - using (BeginScope()) { + var statements = new List(); foreach (var statement in node.Statements) { - var checkedStatement = CheckStatement(statement); - - if (reachable) - { - if (checkedStatement is TerminalStatementNode) - { - reachable = false; - } - - statements.Add(checkedStatement); - } - else - { - if (!warnedUnreachable) - { - Diagnostics.Add(Diagnostic.Warning("Statement is unreachable").At(statement).Build()); - warnedUnreachable = true; - } - } + statements.Add(CheckStatement(statement)); } return new BlockNode(node.Tokens, statements); @@ -937,27 +816,11 @@ public sealed class TypeChecker PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType)), StringTypeSyntax => new NubStringType(), CustomTypeSyntax c => ResolveCustomType(c), - StructTemplateTypeSyntax t => ResolveStructTemplateType(t), - SubstitutionTypeSyntax s => ResolveTypeSubstitution(s), VoidTypeSyntax => new NubVoidType(), _ => throw new NotSupportedException($"Unknown type syntax: {type}") }; } - private NubType ResolveTypeSubstitution(SubstitutionTypeSyntax substitution) - { - var type = CurrentScope.LookupTypeSubstitution(substitution.Name); - if (type == null) - { - throw new TypeCheckerException(Diagnostic - .Error($"Template argument {substitution.Name} does not exist") - .At(substitution) - .Build()); - } - - return type; - } - private NubType ResolveCustomType(CustomTypeSyntax customType) { var key = (customType.Module, customType.Name); @@ -969,14 +832,14 @@ public sealed class TypeChecker if (!_resolvingTypes.Add(key)) { - var placeholder = new NubStructType(customType.Module, customType.Name, [], []); + var placeholder = new NubStructType(customType.Module, customType.Name, []); _typeCache[key] = placeholder; return placeholder; } try { - if (!_visibleModules.TryGetValue(customType.Module, out var module)) + if (!_importedModules.TryGetValue(customType.Module, out var module)) { throw new TypeCheckerException(Diagnostic .Error($"Module {customType.Module} not found") @@ -990,7 +853,7 @@ public sealed class TypeChecker var structDef = module.Structs(includePrivate).FirstOrDefault(x => x.Name == customType.Name); if (structDef != null) { - var result = new NubStructType(customType.Module, structDef.Name, [], []); + var result = new NubStructType(customType.Module, structDef.Name, []); _typeCache[key] = result; var fields = structDef.Fields @@ -998,19 +861,6 @@ public sealed class TypeChecker .ToList(); result.Fields.AddRange(fields); - - var functions = structDef.Functions - .Select(x => - { - var parameters = x.Signature.Parameters - .Select(y => ResolveType(y.Type)) - .ToList(); - - return new NubStructFuncType(x.Name, parameters, ResolveType(x.Signature.ReturnType)); - }) - .ToList(); - - result.Functions.AddRange(functions); return result; } @@ -1024,71 +874,6 @@ public sealed class TypeChecker _resolvingTypes.Remove(key); } } - - private NubStructType ResolveStructTemplateType(StructTemplateTypeSyntax structTemplate) - { - if (!_visibleModules.TryGetValue(structTemplate.Module, out var module)) - { - throw new TypeCheckerException(Diagnostic - .Error($"Module {structTemplate.Module} not found") - .WithHelp($"import \"{structTemplate.Module}\"") - .At(structTemplate) - .Build()); - } - - var includePrivate = structTemplate.Module == CurrentScope.Module; - - var templateDef = module - .StructTemplates(includePrivate) - .FirstOrDefault(x => x.Name == structTemplate.Name); - - if (templateDef == null) - { - throw new TypeCheckerException(Diagnostic - .Error($"Template type {structTemplate.Name} not found in module {structTemplate.Module}") - .At(structTemplate) - .Build()); - } - - var templateParameterTypes = structTemplate.TemplateParameters.Select(ResolveType).ToList(); - var mangledName = $"{structTemplate.Name}.{NameMangler.Mangle(templateParameterTypes)}"; - - using (BeginRootScope(structTemplate.Module)) - { - for (var i = 0; i < templateParameterTypes.Count; i++) - { - var parameterName = templateDef.TemplateArguments[i]; - var parameterType = templateParameterTypes[i]; - CurrentScope.DeclareTypeSubstitution(parameterName, parameterType); - } - - var fieldTypes = templateDef.Fields - .Select(x => new NubStructFieldType(x.Name, ResolveType(x.Type), x.Value != null)) - .ToList(); - - var fieldFunctions = templateDef.Functions - .Select(x => - { - var parameters = x.Signature.Parameters.Select(y => ResolveType(y.Type)).ToList(); - var returnType = ResolveType(x.Signature.ReturnType); - return new NubStructFuncType(x.Name, parameters, returnType); - }) - .ToList(); - - var structType = new NubStructType(structTemplate.Module, mangledName, fieldTypes, fieldFunctions); - - if (!_checkedTemplateStructs.Contains($"{structTemplate.Module}.{mangledName}")) - { - CurrentScope.DeclareVariable(new Variable("this", structType, VariableKind.RValue)); - var fields = templateDef.Fields.Select(CheckStructField).ToList(); - var functions = templateDef.Functions.Select(CheckStructFunc).ToList(); - Definitions.Add(new StructNode(templateDef.Tokens, structTemplate.Module, mangledName, fields, functions)); - _checkedTemplateStructs.Add($"{structTemplate.Module}.{mangledName}"); - } - - return structType; - } - } } public enum VariableKind diff --git a/compiler/NubLang/Generation/Generator.cs b/compiler/NubLang/Generation/Generator.cs index 6838ff7..309b7d1 100644 --- a/compiler/NubLang/Generation/Generator.cs +++ b/compiler/NubLang/Generation/Generator.cs @@ -1,4 +1,3 @@ -using System.Text; using NubLang.Ast; using NubLang.Syntax; @@ -6,17 +5,14 @@ namespace NubLang.Generation; public class Generator { - private readonly List _definitions; + private readonly CompilationUnit _compilationUnit; private readonly IndentedTextWriter _writer; private readonly Stack> _deferStack = []; - private readonly Stack<(string Name, NubFuncType FuncType)> _funcDefs = []; - private readonly List _structTypes = []; private int _tmpIndex; - private int _funcDefIndex; - public Generator(List definitions) + public Generator(CompilationUnit compilationUnit) { - _definitions = definitions; + _compilationUnit = compilationUnit; _writer = new IndentedTextWriter(); } @@ -26,54 +22,6 @@ public class Generator return $"_t{++_tmpIndex}"; } - private string MapType(NubType nubType) - { - return nubType switch - { - NubArrayType arrayType => MapType(arrayType.ElementType), - NubConstArrayType arrayType => MapType(arrayType.ElementType), - NubBoolType => "bool", - NubCStringType => "char", - NubFloatType floatType => floatType.Width switch - { - 32 => "f32", - 64 => "f64", - _ => throw new ArgumentOutOfRangeException() - }, - NubFuncType funcType => MapFuncType(funcType), - NubIntType intType => (intType.Signed, intType.Width) switch - { - (false, 8) => "u8", - (false, 16) => "u16", - (false, 32) => "u32", - (false, 64) => "u64", - (true, 8) => "i8", - (true, 16) => "i16", - (true, 32) => "i32", - (true, 64) => "i64", - _ => throw new ArgumentOutOfRangeException() - }, - NubPointerType pointerType => MapType(pointerType.BaseType), - NubStringType => throw new NotImplementedException(), - NubStructType structType => MapStructType(structType), - NubVoidType => "void", - _ => throw new ArgumentOutOfRangeException(nameof(nubType)) - }; - } - - private string MapStructType(NubStructType structType) - { - _structTypes.Add(structType); - return StructName(structType.Module, structType.Name); - } - - private string MapFuncType(NubFuncType funcType) - { - var name = $"_func_type_def{++_funcDefIndex}"; - _funcDefs.Push((name, funcType)); - return name; - } - private string MapNameWithType(NubType nubType, string name) { var prefix = ""; @@ -81,7 +29,7 @@ public class Generator switch (nubType) { - case NubCStringType or NubPointerType: + case NubCStringType or NubPointerType or NubFuncType: prefix = "*"; break; case NubArrayType: @@ -92,7 +40,42 @@ public class Generator break; } - return $"{MapType(nubType)} {prefix}{name}{postfix}"; + return $"{MapBaseType(nubType)} {prefix}{name}{postfix}"; + + string MapBaseType(NubType type) + { + return type switch + { + NubArrayType arrayType => MapBaseType(arrayType.ElementType), + NubConstArrayType arrayType => MapBaseType(arrayType.ElementType), + NubBoolType => "bool", + NubCStringType => "char", + NubFloatType floatType => floatType.Width switch + { + 32 => "f32", + 64 => "f64", + _ => throw new ArgumentOutOfRangeException() + }, + NubFuncType funcType => "void", + NubIntType intType => (intType.Signed, intType.Width) switch + { + (false, 8) => "u8", + (false, 16) => "u16", + (false, 32) => "u32", + (false, 64) => "u64", + (true, 8) => "i8", + (true, 16) => "i16", + (true, 32) => "i32", + (true, 64) => "i64", + _ => throw new ArgumentOutOfRangeException() + }, + NubPointerType pointerType => MapBaseType(pointerType.BaseType), + NubStringType => throw new NotImplementedException(), + NubStructType structType => StructName(structType.Module, structType.Name), + NubVoidType => "void", + _ => throw new ArgumentOutOfRangeException(nameof(type)) + }; + } } private static string FuncName(string module, string name, string? externSymbol) @@ -105,139 +88,101 @@ public class Generator return $"{module}_{name}"; } - private static string StructFuncName(string module, string name, string function) - { - return $"{module}_{name}_{function}"; - } - public string Emit() { - const string header = """ - typedef __builtin_va_list va_list; - - #define va_start(ap, last) __builtin_va_start(ap, last) - #define va_arg(ap, type) __builtin_va_arg(ap, type) - #define va_end(ap) __builtin_va_end(ap) - #define va_copy(dest, src) __builtin_va_copy(dest, src) - - #define NULL ((void*)0) - - typedef unsigned long size_t; - typedef unsigned long uintptr_t; - - #define offsetof(type, member) __builtin_offsetof(type, member) - - typedef unsigned char u8; - typedef signed char i8; - typedef unsigned short u16; - typedef signed short i16; - typedef unsigned int u32; - typedef signed int i32; - typedef unsigned long long u64; - typedef signed long long i64; - - typedef float f32; - typedef double f64; - - #define I8_C(x) x - #define U8_C(x) x##U - - #define I16_C(x) x - #define U16_C(x) x##U - - #define I32_C(x) x - #define U32_C(x) x##U - - #define I64_C(x) x##LL - #define U64_C(x) x##ULL - """; - - _writer.WriteLine(); - - var appendNewLine = false; - - foreach (var funcNode in _definitions.OfType()) + // note(nub31): Struct definitions + foreach (var structType in _compilationUnit.ImportedStructTypes) { - EmitLine(funcNode.Tokens.FirstOrDefault()); - appendNewLine = true; - var parameters = funcNode.Signature.Parameters.Count != 0 - ? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name))) - : "void"; + _writer.WriteLine("typedef struct"); + _writer.WriteLine("{"); + using (_writer.Indent()) + { + foreach (var field in structType.Fields) + { + _writer.WriteLine($"{MapNameWithType(field.Type, field.Name)};"); + } + } - var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol); - _writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters});"); - } - - if (appendNewLine) - { + _writer.WriteLine($"}} {StructName(structType.Module, structType.Name)};"); _writer.WriteLine(); } - foreach (var structNode in _definitions.OfType()) + // note(nub31): Forward declarations + foreach (var prototype in _compilationUnit.ImportedFunctions) { - foreach (var structFuncNode in structNode.Functions) - { - EmitLine(structFuncNode.Tokens.FirstOrDefault()); - var parameters = structFuncNode.Signature.Parameters.Count != 0 - ? string.Join(", ", structFuncNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name))) - : "void"; + EmitLine(prototype.Tokens.FirstOrDefault()); + var parameters = prototype.Parameters.Count != 0 + ? string.Join(", ", prototype.Parameters.Select(x => MapNameWithType(x.Type, x.Name))) + : "void"; - var name = StructFuncName(structNode.Module, structNode.Name, structFuncNode.Name); - _writer.WriteLine($"{MapNameWithType(structFuncNode.Signature.ReturnType, name)}({parameters})"); - EmitBlock(structFuncNode.Body); - _writer.WriteLine(); - } + var name = FuncName(prototype.Module, prototype.Name, prototype.ExternSymbol); + _writer.WriteLine($"{MapNameWithType(prototype.ReturnType, name)}({parameters});"); } - foreach (var funcNode in _definitions.OfType()) + _writer.WriteLine(); + + // note(nub31): Normal functions + foreach (var funcNode in _compilationUnit.Functions) { if (funcNode.Body == null) continue; EmitLine(funcNode.Tokens.FirstOrDefault()); - var parameters = funcNode.Signature.Parameters.Count != 0 - ? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name))) + var parameters = funcNode.Prototype.Parameters.Count != 0 + ? string.Join(", ", funcNode.Prototype.Parameters.Select(x => MapNameWithType(x.Type, x.Name))) : "void"; - if (funcNode.ExternSymbol == null) + if (funcNode.Prototype.ExternSymbol == null) { _writer.Write("static "); } - var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol); - _writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters})"); + var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol); + _writer.WriteLine($"{MapNameWithType(funcNode.Prototype.ReturnType, name)}({parameters})"); EmitBlock(funcNode.Body); _writer.WriteLine(); } - List typedefs = []; + return $""" + typedef __builtin_va_list va_list; - while (_funcDefs.TryPop(out var funcTypeDef)) - { - var returnType = MapType(funcTypeDef.FuncType.ReturnType); - var paramList = string.Join(", ", funcTypeDef.FuncType.Parameters.Select((type, i) => MapNameWithType(type, $"arg{i}"))); - if (funcTypeDef.FuncType.Parameters.Count == 0) - { - paramList = "void"; - } + #define va_start(ap, last) __builtin_va_start(ap, last) + #define va_arg(ap, type) __builtin_va_arg(ap, type) + #define va_end(ap) __builtin_va_end(ap) + #define va_copy(dest, src) __builtin_va_copy(dest, src) - typedefs.Add($"typedef {returnType} (*{funcTypeDef.Name})({paramList});"); - } + #define NULL ((void*)0) - var structDefSb = new StringBuilder(); - foreach (var structType in _structTypes) - { - structDefSb.AppendLine("typedef struct"); - structDefSb.AppendLine("{"); - foreach (var field in structType.Fields) - { - structDefSb.AppendLine($" {MapNameWithType(field.Type, field.Name)};"); - } + typedef unsigned long size_t; + typedef unsigned long uintptr_t; - structDefSb.AppendLine($"}} {StructName(structType.Module, structType.Name)};"); - structDefSb.AppendLine(); - } + #define offsetof(type, member) __builtin_offsetof(type, member) - return header + structDefSb + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer; + typedef unsigned char u8; + typedef signed char i8; + typedef unsigned short u16; + typedef signed short i16; + typedef unsigned int u32; + typedef signed int i32; + typedef unsigned long long u64; + typedef signed long long i64; + + typedef float f32; + typedef double f64; + + #define I8_C(x) x + #define U8_C(x) x##U + + #define I16_C(x) x + #define U16_C(x) x##U + + #define I32_C(x) x + #define U32_C(x) x##U + + #define I64_C(x) x##LL + #define U64_C(x) x##ULL + + {_writer} + """; } private void EmitStatement(StatementNode statementNode) @@ -269,9 +214,6 @@ public class Generator case StatementFuncCallNode statementFuncCallNode: EmitStatementFuncCall(statementFuncCallNode); break; - case StatementStructFuncCallNode statementStructFuncCallNode: - EmitStatementStructFuncCall(statementStructFuncCallNode); - break; case VariableDeclarationNode variableDeclarationNode: EmitVariableDeclaration(variableDeclarationNode); break; @@ -316,7 +258,7 @@ public class Generator private void EmitIf(IfNode ifNode, bool elseIf = false) { var condition = EmitExpression(ifNode.Condition); - _writer.WriteLine($"{(elseIf ? "else" : "")} if ({condition})"); + _writer.WriteLine($"{(elseIf ? "else " : "")}if ({condition})"); EmitBlock(ifNode.Body); ifNode.Else?.Match ( @@ -373,12 +315,6 @@ public class Generator _writer.WriteLine($"{funcCall};"); } - private void EmitStatementStructFuncCall(StatementStructFuncCallNode statementStructFuncCallNode) - { - var structFuncCall = EmitStructFuncCall(statementStructFuncCallNode.StructFuncCall); - _writer.WriteLine($"{structFuncCall};"); - } - private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode) { if (variableDeclarationNode.Assignment != null) @@ -423,7 +359,6 @@ public class Generator SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode), StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode), StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode), - StructFuncCallNode structFuncCallNode => EmitStructFuncCall(structFuncCallNode), StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode), UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode), UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode), @@ -606,12 +541,7 @@ public class Generator private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode) { - if (sizeBuiltinNode.TargetType is NubConstArrayType constArrayType) - { - return $"sizeof({MapType(constArrayType.ElementType)}) * {constArrayType.Size}"; - } - - return $"sizeof({MapType(sizeBuiltinNode.TargetType)})"; + throw new NotImplementedException(); } private string EmitStringLiteral(StringLiteralNode stringLiteralNode) @@ -625,14 +555,6 @@ public class Generator return $"{structExpr}.{structFieldAccessNode.Field}"; } - private string EmitStructFuncCall(StructFuncCallNode structFuncCallNode) - { - var thisParameter = EmitExpression(structFuncCallNode.StructExpression); - var name = StructFuncName(structFuncCallNode.Module, structFuncCallNode.StructName, structFuncCallNode.FuncName); - var parameterNames = structFuncCallNode.Parameters.Select(EmitExpression).ToList(); - return $"{name}({thisParameter}, {string.Join(", ", parameterNames)})"; - } - private string EmitStructInitializer(StructInitializerNode structInitializerNode) { var initValues = new List(); diff --git a/compiler/NubLang/Modules/Module.cs b/compiler/NubLang/Modules/Module.cs deleted file mode 100644 index 33d1b5a..0000000 --- a/compiler/NubLang/Modules/Module.cs +++ /dev/null @@ -1,37 +0,0 @@ -using NubLang.Syntax; - -namespace NubLang.Modules; - -public class Module -{ - private readonly List _definitions = []; - - public void Register(DefinitionSyntax definition) - { - _definitions.Add(definition); - } - - public List Structs(bool includePrivate) - { - return _definitions - .OfType() - .Where(x => x.Exported || includePrivate) - .ToList(); - } - - public List StructTemplates(bool includePrivate) - { - return _definitions - .OfType() - .Where(x => x.Exported || includePrivate) - .ToList(); - } - - public List Functions(bool includePrivate) - { - return _definitions - .OfType() - .Where(x => x.Exported || includePrivate) - .ToList(); - } -} \ No newline at end of file diff --git a/compiler/NubLang/Modules/ModuleRepository.cs b/compiler/NubLang/Modules/ModuleRepository.cs deleted file mode 100644 index 5b2a300..0000000 --- a/compiler/NubLang/Modules/ModuleRepository.cs +++ /dev/null @@ -1,41 +0,0 @@ -using NubLang.Syntax; - -namespace NubLang.Modules; - -public class ModuleRepository -{ - private readonly Dictionary _modules = new(); - - public ModuleRepository(List syntaxTrees) - { - foreach (var syntaxTree in syntaxTrees) - { - var module = GetOrCreate(syntaxTree.Metadata.ModuleName); - ProcessSyntaxTree(module, syntaxTree); - } - } - - private static void ProcessSyntaxTree(Module module, SyntaxTree syntaxTree) - { - foreach (var definition in syntaxTree.Definitions) - { - module.Register(definition); - } - } - - public Dictionary Modules() - { - return _modules; - } - - private Module GetOrCreate(string name) - { - if (!_modules.TryGetValue(name, out var module)) - { - module = new Module(); - _modules[name] = module; - } - - return module; - } -} \ No newline at end of file diff --git a/compiler/NubLang/Syntax/Module.cs b/compiler/NubLang/Syntax/Module.cs new file mode 100644 index 0000000..38188c5 --- /dev/null +++ b/compiler/NubLang/Syntax/Module.cs @@ -0,0 +1,39 @@ +namespace NubLang.Syntax; + +public sealed class Module +{ + public static Dictionary Collect(List syntaxTrees) + { + var modules = new Dictionary(); + foreach (var syntaxTree in syntaxTrees) + { + if (!modules.TryGetValue(syntaxTree.ModuleName, out var module)) + { + module = new Module(); + modules.Add(syntaxTree.ModuleName, module); + } + + module._definitions.AddRange(syntaxTree.Definitions); + } + + return modules; + } + + private readonly List _definitions = []; + + public List Structs(bool includePrivate) + { + return _definitions + .OfType() + .Where(x => x.Exported || includePrivate) + .ToList(); + } + + public List Functions(bool includePrivate) + { + return _definitions + .OfType() + .Where(x => x.Exported || includePrivate) + .ToList(); + } +} \ No newline at end of file diff --git a/compiler/NubLang/Syntax/Parser.cs b/compiler/NubLang/Syntax/Parser.cs index f94a033..bdc373d 100644 --- a/compiler/NubLang/Syntax/Parser.cs +++ b/compiler/NubLang/Syntax/Parser.cs @@ -5,7 +5,6 @@ namespace NubLang.Syntax; public sealed class Parser { - private readonly HashSet _templateArguments = []; private List _tokens = []; private int _tokenIndex; private string _moduleName = string.Empty; @@ -21,16 +20,7 @@ public sealed class Parser _tokens = tokens; _tokenIndex = 0; _moduleName = string.Empty; - _templateArguments.Clear(); - var metadata = ParseMetadata(); - var definitions = ParseDefinitions(); - - return new SyntaxTree(definitions, metadata); - } - - private SyntaxTreeMetadata ParseMetadata() - { var imports = new List(); try @@ -57,11 +47,6 @@ public sealed class Parser } } - return new SyntaxTreeMetadata(_moduleName, imports); - } - - private List ParseDefinitions() - { var definitions = new List(); while (HasToken) @@ -80,7 +65,7 @@ public sealed class Parser } var keyword = ExpectSymbol(); - var definition = keyword.Symbol switch + DefinitionSyntax definition = keyword.Symbol switch { Symbol.Func => ParseFunc(startIndex, exported, null), Symbol.Struct => ParseStruct(startIndex, exported), @@ -108,12 +93,22 @@ public sealed class Parser } } - return definitions; + return new SyntaxTree(definitions, _moduleName, imports); } - private FuncSignatureSyntax ParseFuncSignature() + private FuncParameterSyntax ParseFuncParameter() { var startIndex = _tokenIndex; + var name = ExpectIdentifier(); + ExpectSymbol(Symbol.Colon); + var type = ParseType(); + + return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type); + } + + private FuncSyntax ParseFunc(int startIndex, bool exported, string? externSymbol) + { + var name = ExpectIdentifier(); List parameters = []; ExpectSymbol(Symbol.OpenParen); @@ -131,23 +126,7 @@ public sealed class Parser var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax([]); - return new FuncSignatureSyntax(GetTokens(startIndex), parameters, returnType); - } - - private FuncParameterSyntax ParseFuncParameter() - { - var startIndex = _tokenIndex; - var name = ExpectIdentifier(); - ExpectSymbol(Symbol.Colon); - var type = ParseType(); - - return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type); - } - - private FuncSyntax ParseFunc(int startIndex, bool exported, string? externSymbol) - { - var name = ExpectIdentifier(); - var signature = ParseFuncSignature(); + var prototype = new FuncPrototypeSyntax(GetTokens(startIndex), name.Value, exported, externSymbol, parameters, returnType); BlockSyntax? body = null; var bodyStartIndex = _tokenIndex; @@ -156,64 +135,36 @@ public sealed class Parser body = ParseBlock(bodyStartIndex); } - return new FuncSyntax(GetTokens(startIndex), name.Value, exported, externSymbol, signature, body); + return new FuncSyntax(GetTokens(startIndex), prototype, body); } - private DefinitionSyntax ParseStruct(int startIndex, bool exported) + private StructSyntax ParseStruct(int startIndex, bool exported) { var name = ExpectIdentifier(); - if (TryExpectSymbol(Symbol.LessThan)) - { - while (!TryExpectSymbol(Symbol.GreaterThan)) - { - _templateArguments.Add(ExpectIdentifier().Value); - TryExpectSymbol(Symbol.Comma); - } - } - ExpectSymbol(Symbol.OpenBrace); List fields = []; - List funcs = []; while (!TryExpectSymbol(Symbol.CloseBrace)) { var memberStartIndex = _tokenIndex; - if (TryExpectSymbol(Symbol.Func)) + var fieldName = ExpectIdentifier().Value; + ExpectSymbol(Symbol.Colon); + var fieldType = ParseType(); + + ExpressionSyntax? fieldValue = null; + + if (TryExpectSymbol(Symbol.Assign)) { - var funcName = ExpectIdentifier().Value; - var funcSignature = ParseFuncSignature(); - var funcBody = ParseBlock(); - - funcs.Add(new StructFuncSyntax(GetTokens(memberStartIndex), funcName, funcSignature, funcBody)); + fieldValue = ParseExpression(); } - else - { - var fieldName = ExpectIdentifier().Value; - ExpectSymbol(Symbol.Colon); - var fieldType = ParseType(); - ExpressionSyntax? fieldValue = null; - - if (TryExpectSymbol(Symbol.Assign)) - { - fieldValue = ParseExpression(); - } - - fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldName, fieldType, fieldValue)); - } + fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldName, fieldType, fieldValue)); } - if (_templateArguments.Count > 0) - { - var templateArguments = _templateArguments.ToList(); - _templateArguments.Clear(); - return new StructTemplateSyntax(GetTokens(startIndex), templateArguments, name.Value, exported, fields, funcs); - } - - return new StructSyntax(GetTokens(startIndex), name.Value, exported, fields, funcs); + return new StructSyntax(GetTokens(startIndex), name.Value, exported, fields); } private StatementSyntax ParseStatement() @@ -543,24 +494,6 @@ public sealed class Parser if (TryExpectSymbol(Symbol.Period)) { var member = ExpectIdentifier().Value; - if (TryExpectSymbol(Symbol.OpenParen)) - { - var parameters = new List(); - - while (!TryExpectSymbol(Symbol.CloseParen)) - { - parameters.Add(ParseExpression()); - if (!TryExpectSymbol(Symbol.Comma)) - { - ExpectSymbol(Symbol.CloseParen); - break; - } - } - - expr = new MemberFuncCallSyntax(GetTokens(startIndex), member, expr, parameters); - continue; - } - expr = new MemberAccessSyntax(GetTokens(startIndex), expr, member); continue; } @@ -672,11 +605,6 @@ public sealed class Parser var startIndex = _tokenIndex; if (TryExpectIdentifier(out var name)) { - if (_templateArguments.Contains(name.Value)) - { - return new SubstitutionTypeSyntax(GetTokens(startIndex), name.Value); - } - if (name.Value[0] == 'u' && int.TryParse(name.Value[1..], out var size)) { if (size is not 8 and not 16 and not 32 and not 64) @@ -740,21 +668,6 @@ public sealed class Parser name = customTypeName; } - var templateParameters = new List(); - if (TryExpectSymbol(Symbol.LessThan)) - { - while (!TryExpectSymbol(Symbol.GreaterThan)) - { - templateParameters.Add(ParseType()); - TryExpectSymbol(Symbol.Comma); - } - } - - if (templateParameters.Count > 0) - { - return new StructTemplateTypeSyntax(GetTokens(startIndex), templateParameters, module, name.Value); - } - return new CustomTypeSyntax(GetTokens(startIndex), module, name.Value); } } @@ -946,9 +859,7 @@ public sealed class Parser } } -public record SyntaxTreeMetadata(string ModuleName, List Imports); - -public record SyntaxTree(List Definitions, SyntaxTreeMetadata Metadata); +public record SyntaxTree(List Definitions, string ModuleName, List Imports); public class ParseException : Exception { diff --git a/compiler/NubLang/Syntax/Syntax.cs b/compiler/NubLang/Syntax/Syntax.cs index 33d5e95..c532b9c 100644 --- a/compiler/NubLang/Syntax/Syntax.cs +++ b/compiler/NubLang/Syntax/Syntax.cs @@ -8,17 +8,13 @@ public abstract record DefinitionSyntax(List Tokens, string Name, bool Ex public record FuncParameterSyntax(List Tokens, string Name, TypeSyntax Type) : SyntaxNode(Tokens); -public record FuncSignatureSyntax(List Tokens, List Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens); +public record FuncPrototypeSyntax(List Tokens, string Name, bool Exported, string? ExternSymbol, List Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens); -public record FuncSyntax(List Tokens, string Name, bool Exported, string? ExternSymbol, FuncSignatureSyntax Signature, BlockSyntax? Body) : DefinitionSyntax(Tokens, Name, Exported); +public record FuncSyntax(List Tokens, FuncPrototypeSyntax Prototype, BlockSyntax? Body) : DefinitionSyntax(Tokens, Prototype.Name, Prototype.Exported); public record StructFieldSyntax(List Tokens, string Name, TypeSyntax Type, ExpressionSyntax? Value) : SyntaxNode(Tokens); -public record StructFuncSyntax(List Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens); - -public record StructSyntax(List Tokens, string Name, bool Exported, List Fields, List Functions) : DefinitionSyntax(Tokens, Name, Exported); - -public record StructTemplateSyntax(List Tokens, List TemplateArguments, string Name, bool Exported, List Fields, List Functions) : DefinitionSyntax(Tokens, Name, Exported); +public record StructSyntax(List Tokens, string Name, bool Exported, List Fields) : DefinitionSyntax(Tokens, Name, Exported); public enum UnaryOperatorSyntax { @@ -86,8 +82,6 @@ public record UnaryExpressionSyntax(List Tokens, UnaryOperatorSyntax Oper public record FuncCallSyntax(List Tokens, ExpressionSyntax Expression, List Parameters) : ExpressionSyntax(Tokens); -public record MemberFuncCallSyntax(List Tokens, string Name, ExpressionSyntax Target, List Parameters) : ExpressionSyntax(Tokens); - public record LocalIdentifierSyntax(List Tokens, string Name) : ExpressionSyntax(Tokens); public record ModuleIdentifierSyntax(List Tokens, string Module, string Name) : ExpressionSyntax(Tokens); @@ -146,8 +140,4 @@ public record ConstArrayTypeSyntax(List Tokens, TypeSyntax BaseType, int public record CustomTypeSyntax(List Tokens, string Module, string Name) : TypeSyntax(Tokens); -public record StructTemplateTypeSyntax(List Tokens, List TemplateParameters, string Module, string Name) : TypeSyntax(Tokens); - -public record SubstitutionTypeSyntax(List Tokens, string Name) : TypeSyntax(Tokens); - #endregion \ No newline at end of file diff --git a/examples/raylib/main.nub b/examples/raylib/main.nub index 1117396..782e6a4 100644 --- a/examples/raylib/main.nub +++ b/examples/raylib/main.nub @@ -5,7 +5,10 @@ module "main" extern "main" func main(args: []cstring): i64 { raylib::SetConfigFlags(4 | 64) + raylib::InitWindow(1600, 900, "Hi from nub-lang") + defer raylib::CloseWindow() + raylib::SetTargetFPS(240) let width: i32 = 150 @@ -20,26 +23,20 @@ extern "main" func main(args: []cstring): i64 let bgColor: raylib::Color = { r = 0 g = 0 b = 0 a = 255 } let color: raylib::Color = { r = 255 g = 255 b = 255 a = 255 } - while !raylib::WindowShouldClose() - { - if x <= 0 - { + while !raylib::WindowShouldClose() { + if x <= 0 { direction.x = 1 - } - else if x + width >= raylib::GetScreenWidth() - { + } else if x + width >= raylib::GetScreenWidth() { direction.x = -1 } - else if y <= 0 - { + + if y <= 0 { direction.y = 1 - } - else if y + height >= raylib::GetScreenHeight() - { + } else if y + height >= raylib::GetScreenHeight() { direction.y = -1 } - x = x + @floatToInt(i32, direction.x * speed * raylib::GetFrameTime()) + x = x + @floatToInt(i32, direction.x * speed * raylib::GetFrameTime()) y = y + @floatToInt(i32, direction.y * speed * raylib::GetFrameTime()) raylib::BeginDrawing()