From 093a8003b65acaa8cf32e75e53beb2f1d13ff9b7 Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 26 Sep 2019 21:36:26 -0300 Subject: [PATCH] ast_printer: fix children printing - add scope ids for debug purposes - add children to parent on Scope.createChild - types: add validation of if's condition expr type - types: add scopes to ifs --- src/ast_printer.zig | 4 ++-- src/comp_ctx.zig | 24 +++++++++++++++++++----- src/types.zig | 33 ++++++++++++++++++--------------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/ast_printer.zig b/src/ast_printer.zig index ac42790..322ccb7 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -370,7 +370,7 @@ fn prettyType(typ: SymbolUnderlyingType) []const u8 { } pub fn printScope(scope: *Scope, ident: usize) void { - print(ident, "scope at addr {}\n", &scope); + print(ident, "scope '{}' at addr {}\n", scope.id, &scope); var it = scope.env.iterator(); while (it.next()) |kv| { @@ -378,7 +378,7 @@ pub fn printScope(scope: *Scope, ident: usize) void { } for (scope.children.toSlice()) |child| { - printScope(scope, ident + 1); + printScope(child, ident + 1); } } diff --git a/src/comp_ctx.zig b/src/comp_ctx.zig index e645dd9..3549762 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -39,8 +39,9 @@ pub const Scope = struct { children: ScopeList, allocator: *std.mem.Allocator, + id: ?[]const u8 = null, - pub fn create(allocator: *std.mem.Allocator, parent: ?*Scope) !*Scope { + pub fn create(allocator: *std.mem.Allocator, parent: ?*Scope, id: ?[]const u8) !*Scope { var scope = try allocator.create(Scope); scope.* = Scope{ @@ -48,12 +49,15 @@ pub const Scope = struct { .env = Environment.init(allocator), .children = ScopeList.init(allocator), .allocator = allocator, + .id = id, }; return scope; } - pub fn createChild(self: *@This()) !*Scope { - return try @This().create(self.allocator, self); + pub fn createChild(self: *@This(), id: ?[]const u8) !*Scope { + var child = try @This().create(self.allocator, self, id); + try self.children.append(child); + return child; } pub fn deinit(self: *const @This()) void { @@ -135,12 +139,14 @@ pub const CompilationContext = struct { } /// Create a new scope out of the current one and set it as the current. - pub fn bumpScope(self: *@This()) !void { + pub fn bumpScope(self: *@This(), scope_id: ?[]const u8) !void { if (self.current_scope == null) { @panic("can't bump scope from null"); } - var child = try self.current_scope.?.createChild(); + std.debug.warn("==scope bump== '{}'\n", scope_id); + + var child = try self.current_scope.?.createChild(scope_id); self.current_scope = child; } @@ -155,6 +161,14 @@ pub const CompilationContext = struct { @panic("can't dump scope from null"); } + const parent_id: ?[]const u8 = if (self.current_scope.?.parent == null) null else self.current_scope.?.parent.?.id; + + std.debug.warn( + "==scope dump== {} to {}\n", + self.current_scope.?.id, + parent_id, + ); + self.current_scope = self.current_scope.?.parent; } diff --git a/src/types.zig b/src/types.zig index dfe384b..ab61922 100644 --- a/src/types.zig +++ b/src/types.zig @@ -88,6 +88,14 @@ pub const TypeSolver = struct { } } + pub fn expectSymUnType(self: *@This(), symbol_type: comp.SymbolUnderlyingType, wanted_type: comp.SymbolUnderlyingTypeEnum) !void { + var actual_type = comp.SymbolUnderlyingTypeEnum(symbol_type); + if (actual_type != wanted_type) { + std.debug.warn("Expected {}, got {}\n", wanted_type, actual_type); + return CompileError.TypeError; + } + } + // TODO make return type optional and so, skip exprs that // fail to be fully resolved, instead of returning CompileError pub fn resolveExprType( @@ -235,17 +243,21 @@ pub const TypeSolver = struct { // If create two scopes for each branch of the if .If => |ifstmt| { - _ = try self.resolveExprType(ctx, ifstmt.condition); + var cond_type = try self.resolveExprType(ctx, ifstmt.condition); + try self.expectSymUnType(cond_type, .Bool); - // TODO assert condition's type is bool + try ctx.bumpScope("if_then"); - // TODO bump-dump scope for (ifstmt.then_branch.toSlice()) |then_stmt| { try self.stmtPass(ctx, then_stmt); } + ctx.dumpScope(); + if (ifstmt.else_branch) |else_branch| { - // TODO bump-dump scope + try ctx.bumpScope("if_else"); + defer ctx.dumpScope(); + for (else_branch.toSlice()) |else_stmt| { try self.stmtPass(ctx, else_stmt); } @@ -287,7 +299,7 @@ pub const TypeSolver = struct { self.setErrContext("function {}", decl.func_name.lexeme); var ret_type = self.resolveGlobalType(ctx, decl.return_type.lexeme); - std.debug.warn("resolved fn {} type: {}\n", decl.func_name.lexeme, ret_type); + std.debug.warn("start analysis of fn {} ret_type: {}\n", decl.func_name.lexeme, ret_type); var parameters = comp.TypeList.init(self.allocator); for (decl.params.toSlice()) |param| { @@ -298,7 +310,7 @@ pub const TypeSolver = struct { // for a function, we always create a new root scope for it // and force-set it into the current context - var scope = try comp.Scope.create(self.allocator, null); + var scope = try comp.Scope.create(self.allocator, null, "function"); errdefer scope.deinit(); // we must always start from a null current scope, @@ -314,15 +326,6 @@ pub const TypeSolver = struct { ctx.dumpScope(); std.debug.assert(ctx.current_scope == null); - // TODO scopes: down scope - - // TODO symbols and scope resolution, that's - // its own can of worms - var symbols = comp.SymbolTable.init(self.allocator); - - // TODO go through body, resolve statements, expressions - // and everything else - if (ret_type != null and parameters.len == decl.params.len) { try ctx.insertFn(decl, ret_type.?, parameters, scope); }