From 6e403a98843ff6b2284a444981e1326c640a2867 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sat, 20 Sep 2025 19:19:40 +0200 Subject: [PATCH] ... --- .../NubLang/Generation/QBE/QBEGenerator.cs | 16 +---- compiler/NubLang/Modules/Module.cs | 4 +- compiler/NubLang/TypeChecking/TypeChecker.cs | 30 +++++--- example/src/main.nub | 72 +++++++++---------- 4 files changed, 59 insertions(+), 63 deletions(-) diff --git a/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/compiler/NubLang/Generation/QBE/QBEGenerator.cs index ad8fe5c..87c964f 100644 --- a/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -467,7 +467,7 @@ public class QBEGenerator private void EmitBlock(BlockNode block, Scope? scope = null) { - scope ??= Scope.SubScope(); + scope ??= new Scope(); _scopes.Push(scope); foreach (var statement in block.Statements) @@ -1295,12 +1295,6 @@ public class QBEGenerator return new NubStructType(definition.Module, definition.Name, fieldTypes, functionTypes); } - private NubFuncType TypeOfFunc(FuncSignatureNode signature) - { - var parameters = signature.Parameters.Select(x => x.Type).ToList(); - return new NubFuncType(parameters, signature.ReturnType); - } - private string TmpName() { return $"%.t{++_tmpIndex}"; @@ -1342,16 +1336,10 @@ public class QBEGenerator } } -// todo(nub31): Parent is not used when getting variables and deferred statements -public class Scope(Scope? parent = null) +public class Scope { public readonly Stack DeferredStatements = []; public readonly Stack Variables = []; - - public Scope SubScope() - { - return new Scope(this); - } } public record Variable(string Name, NubType Type); diff --git a/compiler/NubLang/Modules/Module.cs b/compiler/NubLang/Modules/Module.cs index ff28711..c1cbb96 100644 --- a/compiler/NubLang/Modules/Module.cs +++ b/compiler/NubLang/Modules/Module.cs @@ -38,6 +38,4 @@ public record ModuleStruct(bool Exported, string Name, List F public record ModuleFunctionParameter(string Name, TypeSyntax Type); -public record ModuleFunction(bool Exported, string Name, string? ExternSymbol, List Parameters, TypeSyntax ReturnType); - -public record ModuleTemplateStruct(bool Exported, string? Name); \ No newline at end of file +public record ModuleFunction(bool Exported, string Name, string? ExternSymbol, List Parameters, TypeSyntax ReturnType); \ No newline at end of file diff --git a/compiler/NubLang/TypeChecking/TypeChecker.cs b/compiler/NubLang/TypeChecking/TypeChecker.cs index e4cb05d..3f02fb4 100644 --- a/compiler/NubLang/TypeChecking/TypeChecker.cs +++ b/compiler/NubLang/TypeChecking/TypeChecker.cs @@ -70,19 +70,18 @@ public sealed class TypeChecker } } - private Scope BeginScope(bool root) + private void BeginScope(bool root) { var scope = root ? _globalScope.SubScope() : _scopes.Peek().SubScope(); _scopes.Push(scope); - return scope; } - private Scope EndScope() + private void EndScope() { - return _scopes.Pop(); + _scopes.Pop(); } private StructNode CheckStructDefinition(StructSyntax node) @@ -841,13 +840,24 @@ public sealed class TypeChecker private bool AlwaysReturns(StatementNode statement) { - return statement switch + switch (statement) { - ReturnNode => true, - BlockNode block => block.Statements.Count != 0 && AlwaysReturns(block.Statements.Last()), - IfNode ifNode => AlwaysReturns(ifNode.Body) && ifNode.Else.TryGetValue(out var elseStatement) ? elseStatement.Match(AlwaysReturns, AlwaysReturns) : true, - _ => false - }; + case ReturnNode: + return true; + case BlockNode block: + return block.Statements.Count != 0 && AlwaysReturns(block.Statements.Last()); + case IfNode ifNode: + { + if (!AlwaysReturns(ifNode.Body)) + { + return false; + } + + return !ifNode.Else.TryGetValue(out var elseStatement) || elseStatement.Match(AlwaysReturns, AlwaysReturns); + } + default: + return false; + } } private NubType ResolveType(TypeSyntax type) diff --git a/example/src/main.nub b/example/src/main.nub index 12ded5a..024d0a9 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -11,49 +11,49 @@ struct Human extern "main" func main(args: []cstring): i64 { - // let x: ref = {} + let x: ref = {} - // test(x) + test(x) return 0 } -// func test(x: ref) -// { +func test(x: ref) +{ -// } +} -// struct ref -// { -// value: ^T -// count: ^u64 +struct ref +{ + value: ^T + count: ^u64 -// @oncreate -// func on_create() -// { -// puts("on_create") -// this.value = @interpret(^T, malloc(@size(T))) -// this.count = @interpret(^u64, malloc(@size(u64))) -// this.count^ = 1 -// } + @oncreate + func on_create() + { + puts("on_create") + this.value = @interpret(^T, malloc(@size(T))) + this.count = @interpret(^u64, malloc(@size(u64))) + this.count^ = 1 + } -// @oncopy -// func on_copy() -// { -// puts("on_copy") -// this.count^ = this.count^ + 1 -// } + @oncopy + func on_copy() + { + puts("on_copy") + this.count^ = this.count^ + 1 + } -// @ondestroy -// func on_destroy() -// { -// puts("on_destroy") -// this.count^ = this.count^ - 1 -// if this.count^ <= 0 -// { -// puts("free") -// free(@interpret(^void, this.value)) -// free(@interpret(^void, this.count)) -// } -// } -// } \ No newline at end of file + @ondestroy + func on_destroy() + { + puts("on_destroy") + this.count^ = this.count^ - 1 + if this.count^ <= 0 + { + puts("free") + free(@interpret(^void, this.value)) + free(@interpret(^void, this.count)) + } + } +} \ No newline at end of file