From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id WKODF9AR7mbbHgEA62LTzQ:P1 (envelope-from ) for ; Sat, 21 Sep 2024 02:22:40 +0200 Received: from aspmx1.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1.migadu.com with LMTPS id WKODF9AR7mbbHgEA62LTzQ (envelope-from ) for ; Sat, 21 Sep 2024 02:22:40 +0200 X-Envelope-To: patches@johnnyrichard.com Authentication-Results: aspmx1.migadu.com; none Received: from mail-a.sr.ht (mail-a.sr.ht [46.23.81.152]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 50E938508A for ; Sat, 21 Sep 2024 02:22:40 +0200 (CEST) DKIM-Signature: a=rsa-sha256; bh=XW2np1izIWZkcpYGiJ2yw59HkrMhjj05rUD3EZk9A9w=; c=simple/simple; d=lists.sr.ht; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Unsubscribe:List-Subscribe:List-Archive:List-Post:List-ID; q=dns/txt; s=20240113; t=1726878159; v=1; b=K9dTF8H1xKw/FB4GyVLwhzJoNRtTIiyGOZFKsabmAK0bUqpavV3WDWibsofvso7yR8sMEGw5 y6mjelUgG8NBo3NhMMm6g1h4Nne7WhjWSnEieYLnOi7xPc1RrJfHs+NFX+T36xFp3TJXKFxsZij p77/tqT7BE2pdr3pBD78yihbDd58m/JRqmmYHXzUSvsascM0HjYwBU6OFxqxnZAFn7N3IFWhyLy OYmZ1qU89FPm3xytxf9obG31Epdr2imSonCTeaA3rO4ZjOl0BN8a4ByN4Sclgn/wcYRJ+DPxY6W /HaHihpzAnzevqq+7mZ9ZAcKJE0zKQrSw+/kJAmhYu8DA== Received: from lists.sr.ht (unknown [46.23.81.154]) by mail-a.sr.ht (Postfix) with ESMTPSA id DEA40202CA for ; Sat, 21 Sep 2024 00:22:39 +0000 (UTC) Received: from out-188.mta1.migadu.com (out-188.mta1.migadu.com [95.215.58.188]) by mail-a.sr.ht (Postfix) with ESMTPS id 222302026D for <~johnnyrichard/olang-devel@lists.sr.ht>; Sat, 21 Sep 2024 00:22:39 +0000 (UTC) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=johnnyrichard.com; s=key1; t=1726878159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=++/GvDfljb7JS0C4GO+3jq1UM8AAs9BKl9AhlcmW0Ao=; b=PV6HR0tSf39aqiY3mj9fvBKdooO+jz43vrTK26pvGAbypD8FtiQt8t9XULPlLwanuHE195 g9uwEcBanHk+UrbBr1Bq4f3UEUdfx6z6dbiXQlJWvAFr2JtPIWzLQlLWDqYTd7kFzK5bxK TuDyCwAspYIXN+2ZcQurWaF1rD4zwFagy/BPv29XUEbTgGND+mzeBvmSTHAU0Cr+3sfFcW DZc8dduaI2faQir2kYUCrVbgCsI5zGzuM2MhyzicdeldwExWkbayRgdjx8N4x1mj9Qrry/ vYSMSOlozWHUbxkjiRbJ7CzVnyaTGpWstguYyzInTZmeWIF+BGVaIWlvaPE7hg== From: Johnny Richard To: ~johnnyrichard/olang-devel@lists.sr.ht Cc: Johnny Richard Subject: [PATCH olang v1 2/3] checker: create checker and populate scope on ast nodes Date: Sat, 21 Sep 2024 02:20:39 +0200 Message-ID: <20240921002250.902558-3-johnny@johnnyrichard.com> In-Reply-To: <20240921002250.902558-1-johnny@johnnyrichard.com> References: <20240921002250.902558-1-johnny@johnnyrichard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Sourcehut-Patchset-Status: UNKNOWN List-Unsubscribe: List-Subscribe: List-Archive: Archived-At: List-Post: List-ID: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel.lists.sr.ht> Sender: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel@lists.sr.ht> X-Migadu-Flow: FLOW_IN X-Migadu-Country: NL X-Migadu-Queue-Id: 50E938508A X-Migadu-Scanner: mx11.migadu.com X-Spam-Score: -4.00 X-Migadu-Spam-Score: -4.00 X-TUID: 0gJYP7aB+roI The checker will check semantic analysis in the future, now we want to focus on create the scope (symbol table) and attach to a couple of ast nodes. We want the scope to be accessible from the ast nodes to easily resolve scope on the next compiler pipeline steps. Signed-off-by: Johnny Richard --- src/ast.h | 4 ++ src/checker.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/checker.h | 34 ++++++++++++++ src/main.c | 4 ++ 4 files changed, 167 insertions(+) create mode 100644 src/checker.c create mode 100644 src/checker.h diff --git a/src/ast.h b/src/ast.h index 94ee6b4..7d065c6 100644 --- a/src/ast.h +++ b/src/ast.h @@ -21,6 +21,7 @@ #include "arena.h" #include "list.h" +#include "scope.h" #include "string_view.h" typedef struct ast_node ast_node_t; @@ -66,6 +67,7 @@ typedef struct ast_var_definition string_view_t identifier; type_t type; ast_node_t *value; + scope_t *scope; } ast_var_definition_t; typedef enum @@ -85,6 +87,7 @@ typedef struct ast_literal typedef struct ast_ref { string_view_t identifier; + scope_t *scope; } ast_ref_t; typedef enum ast_binary_op_kind @@ -118,6 +121,7 @@ typedef struct ast_binary_op typedef struct ast_return_stmt { + // FIXME: rename to a meaningful name like expr ast_node_t *data; } ast_return_stmt_t; diff --git a/src/checker.c b/src/checker.c new file mode 100644 index 0000000..5925158 --- /dev/null +++ b/src/checker.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2024 olang maintainers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "checker.h" +#include "scope.h" +#include +#include +#include + +static void +populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast); + +checker_t * +checker_new(arena_t *arena) +{ + assert(arena); + + checker_t *checker = (checker_t *)arena_alloc(arena, sizeof(checker_t)); + if (checker == NULL) { + fprintf(stderr, "[FATAL] Out of memory: checker_new: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + checker->arena = arena; + return checker; +} + +void +checker_check(checker_t *checker, ast_node_t *ast) +{ + assert(checker); + assert(ast); + + scope_t *scope = scope_new(checker->arena); + populate_scope(checker, scope, ast); + + // TODO: traverse the ast tree to verify semantics +} + +static void +populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast) +{ + switch (ast->kind) { + case AST_NODE_PROGRAM: { + populate_scope(checker, scope, ast->as_program.fn); + return; + } + + case AST_NODE_FN_DEF: { + // FIXME: insert function symbol to scope + populate_scope(checker, scope, ast->as_fn_def.block); + return; + } + + case AST_NODE_IF_STMT: { + populate_scope(checker, scope, ast->as_if_stmt.cond); + populate_scope(checker, scope, ast->as_if_stmt.then); + + if (ast->as_if_stmt._else) { + populate_scope(checker, scope, ast->as_if_stmt._else); + } + + return; + } + + case AST_NODE_BINARY_OP: { + ast_binary_op_t bin_op = ast->as_bin_op; + + populate_scope(checker, scope, bin_op.lhs); + populate_scope(checker, scope, bin_op.rhs); + return; + } + + case AST_NODE_RETURN_STMT: { + ast_return_stmt_t return_stmt = ast->as_return_stmt; + + populate_scope(checker, scope, return_stmt.data); + return; + } + + case AST_NODE_BLOCK: { + ast_block_t block = ast->as_block; + scope = scope_push(scope); + + list_item_t *item = list_head(block.nodes); + + while (item != NULL) { + populate_scope(checker, scope, (ast_node_t *)item->value); + item = list_next(item); + } + + return; + } + + case AST_NODE_VAR_DEF: { + string_view_t id = ast->as_var_def.identifier; + symbol_t *symbol = symbol_new(checker->arena, id); + + scope_insert(scope, symbol); + ast->as_var_def.scope = scope; + return; + } + + case AST_NODE_REF: { + ast->as_ref.scope = scope; + return; + } + + case AST_NODE_LITERAL: + case AST_NODE_UNKNOWN: + return; + } +} diff --git a/src/checker.h b/src/checker.h new file mode 100644 index 0000000..681f405 --- /dev/null +++ b/src/checker.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 olang maintainers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef CHECKER_H +#define CHECKER_H + +#include "arena.h" +#include "ast.h" + +typedef struct checker +{ + arena_t *arena; +} checker_t; + +checker_t * +checker_new(arena_t *arena); + +void +checker_check(checker_t *checker, ast_node_t *ast); + +#endif /* CHECKER_H */ diff --git a/src/main.c b/src/main.c index 030f34c..810bf2d 100644 --- a/src/main.c +++ b/src/main.c @@ -22,6 +22,7 @@ #include #include "arena.h" +#include "checker.h" #include "cli.h" #include "codegen_linux_aarch64.h" #include "codegen_linux_x86_64.h" @@ -136,6 +137,9 @@ handle_codegen_linux(cli_opts_t *opts) ast_node_t *ast = parser_parse_program(&parser); + checker_t *checker = checker_new(&arena); + checker_check(checker, ast); + char asm_file[opts->output_bin.size + 3]; sprintf(asm_file, "" SV_FMT ".s", SV_ARG(opts->output_bin)); -- 2.46.0