public inbox for ~johnnyrichard/olang-devel@lists.sr.ht
 help / color / mirror / code / Atom feed
* [PATCH olang v1 0/6] Remove symbol lookups from codegen
@ 2024-10-24 12:38 Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 1/6] ast: create the ast_id_t and apply it to var_def and ref Carlos Maniero
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Carlos Maniero @ 2024-10-24 12:38 UTC (permalink / raw)
  To: ~johnnyrichard/olang-devel; +Cc: Carlos Maniero

Until now, the codegen was responsible to make the symbol resolution
because we didn't have a semantics layer.

Now with the semantics, the symbols are already resolved and saved on
the AST. To avoid redundancy and code duplication, a new struct was
added to represent identifiers.

Carlos Maniero (6):
  ast: create the ast_id_t and apply it to var_def and ref
  semantics: resolve variable symbols
  semantics: refactor: use the ast_id_t into the fn_call node
  semantics: refactor: use the ast_id_t into the fn_def.params
  type: refactor: rename type.id to type.name
  ast: remove dead code from var_assign ast node

 src/ast.c              |   8 +-
 src/ast.h              |  26 +++----
 src/codegen_x86_64.c   |  47 ++++--------
 src/pretty_print_ast.c |  17 +++--
 src/type.c             |   8 +-
 src/type.h             |  25 ++++---
 src/type_checker.c     | 161 ++++++++++++++++++++++++++++++++++++-----
 7 files changed, 201 insertions(+), 91 deletions(-)


base-commit: f87fb371a0105a458be07bd3f269bb45da913d16
-- 
2.46.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH olang v1 1/6] ast: create the ast_id_t and apply it to var_def and ref
  2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
@ 2024-10-24 12:38 ` Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 2/6] semantics: resolve variable symbols Carlos Maniero
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Carlos Maniero @ 2024-10-24 12:38 UTC (permalink / raw)
  To: ~johnnyrichard/olang-devel; +Cc: Carlos Maniero

The ast_id_t is a base structure that will be used for symbol
resolution. Instead of having the id string_view and the scope in all
nodes that need to be added to or resolved in the symbol table, these
fields were added into a single struct, this will help to remove the
redundancy into the semantics level which will lock to a common
structure for all nodes.

Signed-off-by: Carlos Maniero <carlos@maniero.me>
---
 src/ast.c              |  4 ++--
 src/ast.h              | 12 ++++++++----
 src/codegen_x86_64.c   | 12 ++++++------
 src/pretty_print_ast.c |  4 ++--
 src/type_checker.c     | 19 ++++++++++++-------
 5 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/src/ast.c b/src/ast.c
index b96a463..d4f6e87 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -106,7 +106,7 @@ ast_new_node_var_def(arena_t *arena,
     node_var_def->loc = loc;
     ast_var_definition_t *var_def = &node_var_def->as_var_def;
 
-    var_def->id = id;
+    var_def->id.name = id;
     var_def->type = type;
     var_def->value = value;
 
@@ -174,7 +174,7 @@ ast_new_node_ref(arena_t *arena, token_loc_t loc, string_view_t id)
 
     node_ref->kind = AST_NODE_REF;
     node_ref->loc = loc;
-    node_ref->as_ref.id = id;
+    node_ref->as_ref.id.name = id;
 
     return node_ref;
 }
diff --git a/src/ast.h b/src/ast.h
index 7c5e9af..c55ecf1 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -68,6 +68,12 @@ typedef struct ast_block
     list_t *nodes;
 } ast_block_t;
 
+typedef struct ast_id
+{
+    string_view_t name;
+    scope_t *scope;
+} ast_id_t;
+
 typedef struct ast_translation_unit
 {
     AST_NODE_HEAD;
@@ -102,10 +108,9 @@ typedef struct ast_fn_call
 typedef struct ast_var_definition
 {
     AST_NODE_HEAD;
-    string_view_t id;
+    ast_id_t id;
     type_t *type;
     ast_node_t *value;
-    scope_t *scope;
 } ast_var_definition_t;
 
 typedef enum
@@ -126,8 +131,7 @@ typedef struct ast_literal
 typedef struct ast_ref
 {
     AST_NODE_HEAD;
-    string_view_t id;
-    scope_t *scope;
+    ast_id_t id;
 } ast_ref_t;
 
 typedef enum ast_binary_op_kind
diff --git a/src/codegen_x86_64.c b/src/codegen_x86_64.c
index 9006250..c7122be 100644
--- a/src/codegen_x86_64.c
+++ b/src/codegen_x86_64.c
@@ -143,7 +143,7 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
         case AST_NODE_REF: {
             ast_ref_t ref = expr_node->as_ref;
 
-            symbol_t *symbol = scope_lookup(ref.scope, ref.id);
+            symbol_t *symbol = scope_lookup(ref.id.scope, ref.id.name);
             assert(symbol);
 
             size_t offset = codegen_x86_64_get_stack_offset(codegen, symbol);
@@ -597,9 +597,9 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
                     switch (bin_op.lhs->kind) {
                         case AST_NODE_REF: {
                             ast_ref_t ref = bin_op.lhs->as_ref;
-                            scope_t *scope = ref.scope;
+                            scope_t *scope = ref.id.scope;
 
-                            symbol_t *symbol = scope_lookup(scope, ref.id);
+                            symbol_t *symbol = scope_lookup(scope, ref.id.name);
                             assert(symbol);
 
                             size_t offset = codegen_x86_64_get_stack_offset(
@@ -668,7 +668,7 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
 
                     ast_ref_t ref = unary_op.operand->as_ref;
 
-                    symbol_t *symbol = scope_lookup(ref.scope, ref.id);
+                    symbol_t *symbol = scope_lookup(ref.id.scope, ref.id.name);
                     assert(symbol);
 
                     size_t offset =
@@ -722,9 +722,9 @@ codegen_x86_64_emit_block(codegen_x86_64_t *codegen, ast_block_t *block)
 
             case AST_NODE_VAR_DEF: {
                 ast_var_definition_t var_def = node->as_var_def;
-                scope_t *scope = var_def.scope;
+                scope_t *scope = var_def.id.scope;
 
-                symbol_t *symbol = scope_lookup(scope, var_def.id);
+                symbol_t *symbol = scope_lookup(scope, var_def.id.name);
                 assert(symbol);
 
                 size_t type_size = type_to_bytes(symbol->type);
diff --git a/src/pretty_print_ast.c b/src/pretty_print_ast.c
index bc5d119..fdc6b65 100644
--- a/src/pretty_print_ast.c
+++ b/src/pretty_print_ast.c
@@ -288,7 +288,7 @@ ast_node_to_pretty_print_node(ast_node_t *ast, arena_t *arena)
             char name[256];
             sprintf(name,
                     "Var_Definition <name:" SV_FMT "> <kind:" SV_FMT ">",
-                    SV_ARG(var.id),
+                    SV_ARG(var.id.name),
                     SV_ARG(var.type->id));
             node->name =
                 (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1));
@@ -305,7 +305,7 @@ ast_node_to_pretty_print_node(ast_node_t *ast, arena_t *arena)
             ast_ref_t ref = ast->as_ref;
 
             char name[256];
-            sprintf(name, "Reference <name:" SV_FMT ">", SV_ARG(ref.id));
+            sprintf(name, "Reference <name:" SV_FMT ">", SV_ARG(ref.id.name));
             node->name =
                 (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1));
             strcpy(node->name, name);
diff --git a/src/type_checker.c b/src/type_checker.c
index 235d711..a2ffdd6 100644
--- a/src/type_checker.c
+++ b/src/type_checker.c
@@ -102,6 +102,15 @@ checker_check(checker_t *checker, ast_node_t *ast)
     // TODO: traverse the ast tree to verify semantics
 }
 
+static void
+register_id(checker_t *checker, scope_t *scope, ast_id_t *id, type_t *type)
+{
+    id->scope = scope;
+    symbol_t *symbol = symbol_new(checker->arena, id->name, type);
+
+    scope_insert(scope, symbol);
+}
+
 static void
 populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast)
 {
@@ -215,22 +224,18 @@ populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast)
         }
 
         case AST_NODE_VAR_DEF: {
-            string_view_t id = ast->as_var_def.id;
 
             type_resolve(ast->as_var_def.type);
 
-            symbol_t *symbol =
-                symbol_new(checker->arena, id, ast->as_var_def.type);
-
-            scope_insert(scope, symbol);
-            ast->as_var_def.scope = scope;
+            register_id(
+                checker, scope, &ast->as_var_def.id, ast->as_var_def.type);
 
             populate_scope(checker, scope, ast->as_var_def.value);
             return;
         }
 
         case AST_NODE_REF: {
-            ast->as_ref.scope = scope;
+            ast->as_ref.id.scope = scope;
             return;
         }
 
-- 
2.46.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH olang v1 2/6] semantics: resolve variable symbols
  2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 1/6] ast: create the ast_id_t and apply it to var_def and ref Carlos Maniero
@ 2024-10-24 12:38 ` Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 3/6] semantics: refactor: use the ast_id_t into the fn_call node Carlos Maniero
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Carlos Maniero @ 2024-10-24 12:38 UTC (permalink / raw)
  To: ~johnnyrichard/olang-devel; +Cc: Carlos Maniero

This is a first step for semantics check. It introduces the symbol to
ast_id_t. It still does not check if types match neither print helpful
errors.

Why to add the symbol into the ast_id_t?
----------------------------------------

The semantics is required to resolve the symbol in order to perform type
checking and to check if the reference can be resolved. So, checking if
the symbol exists and throw the found symbol away is a computational
waste.

Additionally, adding the symbol to the id removes complexity from
codegen, once symbol_lookups will be no longer required.

Why to create the resolve_symbols function?
-------------------------------------------

If you look at the resolve_symbols and the populate_scope you should
wonder "why there are two functions that traverse the entire ast?". The
main reason is that olang allows reference before definition. So if
something such as a function call refer to a function before it is
defined the checker will fail. Meaning that it is required to first to
populate the scope and make the symbols' registration for the entire AST
and afterwards check for symbols.

Signed-off-by: Carlos Maniero <carlos@maniero.me>
---
 src/ast.h            |   1 +
 src/codegen_x86_64.c |  30 ++++-------
 src/type_checker.c   | 123 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 132 insertions(+), 22 deletions(-)

diff --git a/src/ast.h b/src/ast.h
index c55ecf1..2181849 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -72,6 +72,7 @@ typedef struct ast_id
 {
     string_view_t name;
     scope_t *scope;
+    symbol_t *symbol;
 } ast_id_t;
 
 typedef struct ast_translation_unit
diff --git a/src/codegen_x86_64.c b/src/codegen_x86_64.c
index c7122be..1758902 100644
--- a/src/codegen_x86_64.c
+++ b/src/codegen_x86_64.c
@@ -143,12 +143,10 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
         case AST_NODE_REF: {
             ast_ref_t ref = expr_node->as_ref;
 
-            symbol_t *symbol = scope_lookup(ref.id.scope, ref.id.name);
-            assert(symbol);
-
-            size_t offset = codegen_x86_64_get_stack_offset(codegen, symbol);
+            size_t offset =
+                codegen_x86_64_get_stack_offset(codegen, ref.id.symbol);
 
-            size_t bytes = type_to_bytes(symbol->type);
+            size_t bytes = type_to_bytes(ref.id.symbol->type);
 
             fprintf(codegen->out,
                     "    mov -%ld(%%rbp), %s\n",
@@ -597,17 +595,14 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
                     switch (bin_op.lhs->kind) {
                         case AST_NODE_REF: {
                             ast_ref_t ref = bin_op.lhs->as_ref;
-                            scope_t *scope = ref.id.scope;
-
-                            symbol_t *symbol = scope_lookup(scope, ref.id.name);
-                            assert(symbol);
 
                             size_t offset = codegen_x86_64_get_stack_offset(
-                                codegen, symbol);
+                                codegen, ref.id.symbol);
 
                             codegen_x86_64_emit_expression(codegen, bin_op.rhs);
 
-                            size_t type_size = type_to_bytes(symbol->type);
+                            size_t type_size =
+                                type_to_bytes(ref.id.symbol->type);
                             fprintf(codegen->out,
                                     "    mov %s, -%ld(%%rbp)\n",
                                     get_reg_for(REG_ACCUMULATOR, type_size),
@@ -668,11 +663,8 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
 
                     ast_ref_t ref = unary_op.operand->as_ref;
 
-                    symbol_t *symbol = scope_lookup(ref.id.scope, ref.id.name);
-                    assert(symbol);
-
                     size_t offset =
-                        codegen_x86_64_get_stack_offset(codegen, symbol);
+                        codegen_x86_64_get_stack_offset(codegen, ref.id.symbol);
 
                     fprintf(
                         codegen->out, "    lea -%ld(%%rbp), %%rax\n", offset);
@@ -722,16 +714,12 @@ codegen_x86_64_emit_block(codegen_x86_64_t *codegen, ast_block_t *block)
 
             case AST_NODE_VAR_DEF: {
                 ast_var_definition_t var_def = node->as_var_def;
-                scope_t *scope = var_def.id.scope;
-
-                symbol_t *symbol = scope_lookup(scope, var_def.id.name);
-                assert(symbol);
 
-                size_t type_size = type_to_bytes(symbol->type);
+                size_t type_size = type_to_bytes(var_def.id.symbol->type);
                 codegen->base_offset += type_size;
 
                 codegen_x86_64_put_stack_offset(
-                    codegen, symbol, codegen->base_offset);
+                    codegen, var_def.id.symbol, codegen->base_offset);
 
                 if (var_def.value) {
                     codegen_x86_64_emit_expression(codegen, var_def.value);
diff --git a/src/type_checker.c b/src/type_checker.c
index a2ffdd6..daccecf 100644
--- a/src/type_checker.c
+++ b/src/type_checker.c
@@ -23,6 +23,9 @@
 static void
 populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast);
 
+static void
+resolve_symbols(checker_t *checker, ast_node_t *ast);
+
 checker_t *
 checker_new(arena_t *arena)
 {
@@ -98,6 +101,7 @@ checker_check(checker_t *checker, ast_node_t *ast)
 
     scope_t *scope = scope_new(checker->arena);
     populate_scope(checker, scope, ast);
+    resolve_symbols(checker, ast);
 
     // TODO: traverse the ast tree to verify semantics
 }
@@ -105,12 +109,27 @@ checker_check(checker_t *checker, ast_node_t *ast)
 static void
 register_id(checker_t *checker, scope_t *scope, ast_id_t *id, type_t *type)
 {
-    id->scope = scope;
     symbol_t *symbol = symbol_new(checker->arena, id->name, type);
 
+    id->scope = scope;
+    id->symbol = symbol;
+
     scope_insert(scope, symbol);
 }
 
+static void
+resolve_id(checker_t *checker, ast_id_t *id)
+{
+    assert(checker);
+
+    symbol_t *symbol = scope_lookup(id->scope, id->name);
+
+    // FIXME: assert types and print a friendly error message
+    assert(symbol);
+
+    id->symbol = symbol;
+}
+
 static void
 populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast)
 {
@@ -244,3 +263,105 @@ populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast)
             return;
     }
 }
+
+static void
+resolve_symbols(checker_t *checker, ast_node_t *ast)
+{
+    assert(checker);
+
+    switch (ast->kind) {
+        case AST_NODE_TRANSLATION_UNIT: {
+            list_item_t *item = list_head(ast->as_translation_unit.decls);
+
+            while (item != NULL) {
+                resolve_symbols(checker, (ast_node_t *)item->value);
+                item = list_next(item);
+            }
+            return;
+        }
+
+        case AST_NODE_FN_DEF: {
+            if (ast->as_fn_def.block != NULL) {
+                resolve_symbols(checker, ast->as_fn_def.block);
+            }
+            return;
+        }
+
+        case AST_NODE_FN_CALL: {
+            list_item_t *item = list_head(ast->as_fn_call.args);
+
+            while (item != NULL) {
+                resolve_symbols(checker, (ast_node_t *)item->value);
+                item = list_next(item);
+            }
+
+            return;
+        }
+
+        case AST_NODE_IF_STMT: {
+            resolve_symbols(checker, ast->as_if_stmt.cond);
+            resolve_symbols(checker, ast->as_if_stmt.then);
+
+            if (ast->as_if_stmt._else) {
+                resolve_symbols(checker, ast->as_if_stmt._else);
+            }
+
+            return;
+        }
+
+        case AST_NODE_WHILE_STMT: {
+            resolve_symbols(checker, ast->as_while_stmt.cond);
+            resolve_symbols(checker, ast->as_while_stmt.then);
+
+            return;
+        }
+
+        case AST_NODE_BINARY_OP: {
+            ast_binary_op_t bin_op = ast->as_bin_op;
+
+            resolve_symbols(checker, bin_op.lhs);
+            resolve_symbols(checker, bin_op.rhs);
+            return;
+        }
+
+        case AST_NODE_UNARY_OP: {
+            ast_unary_op_t unary_op = ast->as_unary_op;
+
+            resolve_symbols(checker, unary_op.operand);
+            return;
+        }
+
+        case AST_NODE_RETURN_STMT: {
+            ast_return_stmt_t return_stmt = ast->as_return_stmt;
+
+            resolve_symbols(checker, return_stmt.value);
+            return;
+        }
+
+        case AST_NODE_BLOCK: {
+            ast_block_t block = ast->as_block;
+
+            list_item_t *item = list_head(block.nodes);
+
+            while (item != NULL) {
+                resolve_symbols(checker, (ast_node_t *)item->value);
+                item = list_next(item);
+            }
+
+            return;
+        }
+
+        case AST_NODE_VAR_DEF: {
+            resolve_symbols(checker, ast->as_var_def.value);
+            return;
+        }
+
+        case AST_NODE_REF: {
+            resolve_id(checker, &ast->as_ref.id);
+            return;
+        }
+        case AST_NODE_LITERAL:
+        case AST_NODE_UNKNOWN:
+            return;
+    }
+}
-- 
2.46.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH olang v1 3/6] semantics: refactor: use the ast_id_t into the fn_call node
  2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 1/6] ast: create the ast_id_t and apply it to var_def and ref Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 2/6] semantics: resolve variable symbols Carlos Maniero
@ 2024-10-24 12:38 ` Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 4/6] semantics: refactor: use the ast_id_t into the fn_def.params Carlos Maniero
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Carlos Maniero @ 2024-10-24 12:38 UTC (permalink / raw)
  To: ~johnnyrichard/olang-devel; +Cc: Carlos Maniero

Signed-off-by: Carlos Maniero <carlos@maniero.me>
---
 src/ast.c              | 2 +-
 src/ast.h              | 3 +--
 src/codegen_x86_64.c   | 8 +++-----
 src/pretty_print_ast.c | 5 +++--
 src/type_checker.c     | 3 ++-
 5 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/src/ast.c b/src/ast.c
index d4f6e87..e0722d8 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -85,7 +85,7 @@ ast_new_node_fn_call(arena_t *arena,
     node_fn_call->loc = loc;
     ast_fn_call_t *fn_call = &node_fn_call->as_fn_call;
 
-    fn_call->id = id;
+    fn_call->id.name = id;
     fn_call->args = args;
 
     return node_fn_call;
diff --git a/src/ast.h b/src/ast.h
index 2181849..048d725 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -101,9 +101,8 @@ typedef struct ast_fn_definition
 typedef struct ast_fn_call
 {
     AST_NODE_HEAD;
-    string_view_t id;
+    ast_id_t id;
     list_t *args;
-    scope_t *scope;
 } ast_fn_call_t;
 
 typedef struct ast_var_definition
diff --git a/src/codegen_x86_64.c b/src/codegen_x86_64.c
index 1758902..936a77b 100644
--- a/src/codegen_x86_64.c
+++ b/src/codegen_x86_64.c
@@ -157,9 +157,6 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
         case AST_NODE_FN_CALL: {
             ast_fn_call_t fn_call = expr_node->as_fn_call;
 
-            symbol_t *symbol = scope_lookup(fn_call.scope, fn_call.id);
-            assert(symbol);
-
             size_t i = 0;
             for (list_item_t *item = list_head(fn_call.args); item != NULL;
                  item = list_next(item)) {
@@ -182,9 +179,10 @@ codegen_x86_64_emit_expression(codegen_x86_64_t *codegen, ast_node_t *expr_node)
                         get_reg_for(x86_call_args[i - 1], 8));
             }
 
-            fprintf(codegen->out, "    call " SV_FMT "\n", SV_ARG(fn_call.id));
+            fprintf(
+                codegen->out, "    call " SV_FMT "\n", SV_ARG(fn_call.id.name));
 
-            return type_to_bytes(symbol->type);
+            return type_to_bytes(fn_call.id.symbol->type);
         }
         case AST_NODE_BINARY_OP: {
             ast_binary_op_t bin_op = expr_node->as_bin_op;
diff --git a/src/pretty_print_ast.c b/src/pretty_print_ast.c
index fdc6b65..f65c253 100644
--- a/src/pretty_print_ast.c
+++ b/src/pretty_print_ast.c
@@ -183,8 +183,9 @@ ast_node_to_pretty_print_node(ast_node_t *ast, arena_t *arena)
             ast_fn_call_t fn_call = ast->as_fn_call;
 
             char name[256];
-            sprintf(
-                name, "Function_Call <name:" SV_FMT ">", SV_ARG(fn_call.id));
+            sprintf(name,
+                    "Function_Call <name:" SV_FMT ">",
+                    SV_ARG(fn_call.id.name));
             node->name =
                 (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1));
             strcpy(node->name, name);
diff --git a/src/type_checker.c b/src/type_checker.c
index daccecf..9481539 100644
--- a/src/type_checker.c
+++ b/src/type_checker.c
@@ -176,7 +176,7 @@ populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast)
         }
 
         case AST_NODE_FN_CALL: {
-            ast->as_fn_call.scope = scope;
+            ast->as_fn_call.id.scope = scope;
 
             list_item_t *item = list_head(ast->as_fn_call.args);
 
@@ -288,6 +288,7 @@ resolve_symbols(checker_t *checker, ast_node_t *ast)
         }
 
         case AST_NODE_FN_CALL: {
+            resolve_id(checker, &ast->as_fn_call.id);
             list_item_t *item = list_head(ast->as_fn_call.args);
 
             while (item != NULL) {
-- 
2.46.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH olang v1 4/6] semantics: refactor: use the ast_id_t into the fn_def.params
  2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
                   ` (2 preceding siblings ...)
  2024-10-24 12:38 ` [PATCH olang v1 3/6] semantics: refactor: use the ast_id_t into the fn_call node Carlos Maniero
@ 2024-10-24 12:38 ` Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 5/6] type: refactor: rename type.id to type.name Carlos Maniero
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Carlos Maniero @ 2024-10-24 12:38 UTC (permalink / raw)
  To: ~johnnyrichard/olang-devel; +Cc: Carlos Maniero

With this refactor the codegen no longer perform symbol_lookups by
receiving the symbols fully resolved at the semantics level.

Signed-off-by: Carlos Maniero <carlos@maniero.me>
---
 src/ast.c              | 2 +-
 src/ast.h              | 2 +-
 src/codegen_x86_64.c   | 9 ++++-----
 src/pretty_print_ast.c | 2 +-
 src/type_checker.c     | 4 +---
 5 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/src/ast.c b/src/ast.c
index e0722d8..6d83bd3 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -253,7 +253,7 @@ ast_new_fn_param(arena_t *arena, string_view_t id, type_t *type)
         (ast_fn_param_t *)arena_alloc(arena, sizeof(ast_fn_param_t));
     assert(fn_param);
 
-    fn_param->id = id;
+    fn_param->id.name = id;
     fn_param->type = type;
 
     return fn_param;
diff --git a/src/ast.h b/src/ast.h
index 048d725..8cf072a 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -83,7 +83,7 @@ typedef struct ast_translation_unit
 
 typedef struct ast_fn_param
 {
-    string_view_t id;
+    ast_id_t id;
     type_t *type;
 } ast_fn_param_t;
 
diff --git a/src/codegen_x86_64.c b/src/codegen_x86_64.c
index 936a77b..57c201b 100644
--- a/src/codegen_x86_64.c
+++ b/src/codegen_x86_64.c
@@ -894,19 +894,18 @@ codegen_x86_64_emit_function(codegen_x86_64_t *codegen,
 
         ast_fn_param_t *param = item->value;
 
-        symbol_t *symbol = scope_lookup(fn_def->scope, param->id);
-        assert(symbol);
-
         // FIXME: add offset according to the param size
         codegen->base_offset += 8;
         size_t offset = codegen->base_offset;
 
-        codegen_x86_64_put_stack_offset(codegen, symbol, codegen->base_offset);
+        codegen_x86_64_put_stack_offset(
+            codegen, param->id.symbol, codegen->base_offset);
 
         fprintf(codegen->out,
                 "    mov %s, -%ld(%%rbp)\n",
                 // FIXME: Type may not be an as_primitive
-                get_reg_for(x86_call_args[i], symbol->type->as_primitive.size),
+                get_reg_for(x86_call_args[i],
+                            param->id.symbol->type->as_primitive.size),
                 offset);
 
         ++i;
diff --git a/src/pretty_print_ast.c b/src/pretty_print_ast.c
index f65c253..6ae8358 100644
--- a/src/pretty_print_ast.c
+++ b/src/pretty_print_ast.c
@@ -120,7 +120,7 @@ pretty_print_new_fn_param(ast_fn_param_t *param, arena_t *arena)
     char name[256];
     sprintf(name,
             "Param_Definition <name:" SV_FMT "> <type:" SV_FMT ">",
-            SV_ARG(param->id),
+            SV_ARG(param->id.name),
             SV_ARG(param->type->id));
     node->name = (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1));
     strcpy(node->name, name);
diff --git a/src/type_checker.c b/src/type_checker.c
index 9481539..5864f79 100644
--- a/src/type_checker.c
+++ b/src/type_checker.c
@@ -162,9 +162,7 @@ populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast)
                 ast_fn_param_t *param = (ast_fn_param_t *)item->value;
 
                 type_resolve(param->type);
-                symbol_t *symbol =
-                    symbol_new(checker->arena, param->id, param->type);
-                scope_insert(fn_def->scope, symbol);
+                register_id(checker, scope, &param->id, param->type);
 
                 item = list_next(item);
             }
-- 
2.46.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH olang v1 5/6] type: refactor: rename type.id to type.name
  2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
                   ` (3 preceding siblings ...)
  2024-10-24 12:38 ` [PATCH olang v1 4/6] semantics: refactor: use the ast_id_t into the fn_def.params Carlos Maniero
@ 2024-10-24 12:38 ` Carlos Maniero
  2024-10-24 12:38 ` [PATCH olang v1 6/6] ast: remove dead code from var_assign ast node Carlos Maniero
  2024-10-31  3:16 ` [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
  6 siblings, 0 replies; 9+ messages in thread
From: Carlos Maniero @ 2024-10-24 12:38 UTC (permalink / raw)
  To: ~johnnyrichard/olang-devel; +Cc: Carlos Maniero

Now that there is a struct called ast_id_t the type.id may be
interpreted as an ast_id, to avoid confusion, it was renamed to name
which also is more meaningful since the id is not actually the type id
(as per TOKEN_ID) but the full type string representation. ie: "u8***".

Signed-off-by: Carlos Maniero <carlos@maniero.me>
---
 src/pretty_print_ast.c |  6 +++---
 src/type.c             |  8 ++++----
 src/type.h             | 25 ++++++++++++++-----------
 src/type_checker.c     | 14 +++++++-------
 4 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/src/pretty_print_ast.c b/src/pretty_print_ast.c
index 6ae8358..b9359ae 100644
--- a/src/pretty_print_ast.c
+++ b/src/pretty_print_ast.c
@@ -121,7 +121,7 @@ pretty_print_new_fn_param(ast_fn_param_t *param, arena_t *arena)
     sprintf(name,
             "Param_Definition <name:" SV_FMT "> <type:" SV_FMT ">",
             SV_ARG(param->id.name),
-            SV_ARG(param->type->id));
+            SV_ARG(param->type->name));
     node->name = (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1));
     strcpy(node->name, name);
     return node;
@@ -158,7 +158,7 @@ ast_node_to_pretty_print_node(ast_node_t *ast, arena_t *arena)
                     "Function_Definition <name:" SV_FMT "> <return:" SV_FMT
                     ">%s",
                     SV_ARG(fn_def.id),
-                    SV_ARG(fn_def.return_type->id),
+                    SV_ARG(fn_def.return_type->name),
                     fn_def._extern ? " <extern>" : "");
             node->name =
                 (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1));
@@ -290,7 +290,7 @@ ast_node_to_pretty_print_node(ast_node_t *ast, arena_t *arena)
             sprintf(name,
                     "Var_Definition <name:" SV_FMT "> <kind:" SV_FMT ">",
                     SV_ARG(var.id.name),
-                    SV_ARG(var.type->id));
+                    SV_ARG(var.type->name));
             node->name =
                 (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1));
             strcpy(node->name, name);
diff --git a/src/type.c b/src/type.c
index 4a8d6f4..b146fb7 100644
--- a/src/type.c
+++ b/src/type.c
@@ -18,24 +18,24 @@
 #include "assert.h"
 
 type_t *
-type_new_unknown(arena_t *arena, string_view_t id)
+type_new_unknown(arena_t *arena, string_view_t name)
 {
     type_t *type = arena_alloc(arena, sizeof(type_t));
     assert(type);
 
     type->kind = TYPE_UNKNOWN;
-    type->id = id;
+    type->name = name;
     return type;
 }
 
 type_t *
-type_new_ptr(arena_t *arena, string_view_t id, type_t *ref_type)
+type_new_ptr(arena_t *arena, string_view_t name, type_t *ref_type)
 {
     type_t *type = arena_alloc(arena, sizeof(type_t));
     assert(type);
 
     type->kind = TYPE_PTR;
-    type->id = id;
+    type->name = name;
     type->as_ptr.type = ref_type;
     return type;
 }
diff --git a/src/type.h b/src/type.h
index d930a88..e5f2481 100644
--- a/src/type.h
+++ b/src/type.h
@@ -19,6 +19,16 @@
 #include "arena.h"
 #include "string_view.h"
 
+#define TYPE_BASE                                                              \
+    {                                                                          \
+        type_kind_t kind;                                                      \
+        string_view_t name;                                                    \
+    }
+
+#define TYPE_HEAD                                                              \
+    type_kind_t base_kind;                                                     \
+    string_view_t name
+
 typedef union type type_t;
 
 typedef enum
@@ -38,32 +48,25 @@ typedef enum
 
 typedef struct type_primitive
 {
-    type_kind_t _type_kind;
-    string_view_t id;
+    TYPE_HEAD;
     type_primitive_kind_t kind;
     short size;
 } type_primitive_t;
 
 typedef struct type_unknown
 {
-    type_kind_t _type_kind;
-    string_view_t id;
+    TYPE_HEAD;
 } type_unknown_t;
 
 typedef struct type_ptr
 {
-    type_kind_t _type_kind;
-    string_view_t id;
+    TYPE_HEAD;
     type_t *type;
 } type_ptr_t;
 
 typedef union type
 {
-    struct
-    {
-        type_kind_t kind;
-        string_view_t id;
-    };
+    struct TYPE_BASE;
     type_unknown_t as_unknown;
     type_primitive_t as_primitive;
     type_ptr_t as_ptr;
diff --git a/src/type_checker.c b/src/type_checker.c
index 5864f79..f3911d8 100644
--- a/src/type_checker.c
+++ b/src/type_checker.c
@@ -43,29 +43,29 @@ checker_new(arena_t *arena)
 }
 
 static type_t
-type_from_id(string_view_t id)
+type_from_id(string_view_t name)
 {
     type_t type = { 0 };
-    type.id = id;
-    if (string_view_eq_to_cstr(id, "u8")) {
+    type.name = name;
+    if (string_view_eq_to_cstr(name, "u8")) {
         type.kind = TYPE_PRIMITIVE;
         type.as_primitive.size = 1;
         type.as_primitive.kind = TYPE_U8;
         return type;
     }
-    if (string_view_eq_to_cstr(id, "u16")) {
+    if (string_view_eq_to_cstr(name, "u16")) {
         type.kind = TYPE_PRIMITIVE;
         type.as_primitive.size = 2;
         type.as_primitive.kind = TYPE_U16;
         return type;
     }
-    if (string_view_eq_to_cstr(id, "u32")) {
+    if (string_view_eq_to_cstr(name, "u32")) {
         type.kind = TYPE_PRIMITIVE;
         type.as_primitive.size = 4;
         type.as_primitive.kind = TYPE_U32;
         return type;
     }
-    if (string_view_eq_to_cstr(id, "u64")) {
+    if (string_view_eq_to_cstr(name, "u64")) {
         type.kind = TYPE_PRIMITIVE;
         type.as_primitive.size = 8;
         type.as_primitive.kind = TYPE_U64;
@@ -84,7 +84,7 @@ type_resolve(type_t *type)
 {
     switch (type->kind) {
         case TYPE_UNKNOWN:
-            *type = type_from_id(type->as_unknown.id);
+            *type = type_from_id(type->as_unknown.name);
             break;
         case TYPE_PTR:
             type_resolve(type->as_ptr.type);
-- 
2.46.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH olang v1 6/6] ast: remove dead code from var_assign ast node
  2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
                   ` (4 preceding siblings ...)
  2024-10-24 12:38 ` [PATCH olang v1 5/6] type: refactor: rename type.id to type.name Carlos Maniero
@ 2024-10-24 12:38 ` Carlos Maniero
  2024-10-24 12:39   ` [olang/patches/.build.yml] build success builds.sr.ht
  2024-10-31  3:16 ` [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
  6 siblings, 1 reply; 9+ messages in thread
From: Carlos Maniero @ 2024-10-24 12:38 UTC (permalink / raw)
  To: ~johnnyrichard/olang-devel; +Cc: Carlos Maniero

Previously, the var_assign was a ast_node but it was replaced to be an
binop. The previous struct was not removed tho.

Signed-off-by: Carlos Maniero <carlos@maniero.me>
---
 src/ast.h | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/src/ast.h b/src/ast.h
index 8cf072a..4ba0848 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -182,13 +182,6 @@ typedef struct ast_unary_op
     ast_node_t *operand;
 } ast_unary_op_t;
 
-typedef struct ast_var_assign_stmt
-{
-    AST_NODE_HEAD;
-    ast_node_t *ref;
-    ast_node_t *value;
-} ast_var_assign_stmt_t;
-
 typedef struct ast_return_stmt
 {
     AST_NODE_HEAD;
@@ -222,7 +215,6 @@ typedef union ast_node
     ast_literal_t as_literal;
     ast_ref_t as_ref;
     ast_block_t as_block;
-    ast_var_assign_stmt_t as_var_assign_stmt;
     ast_return_stmt_t as_return_stmt;
     ast_if_stmt_t as_if_stmt;
     ast_while_stmt_t as_while_stmt;
-- 
2.46.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [olang/patches/.build.yml] build success
  2024-10-24 12:38 ` [PATCH olang v1 6/6] ast: remove dead code from var_assign ast node Carlos Maniero
@ 2024-10-24 12:39   ` builds.sr.ht
  0 siblings, 0 replies; 9+ messages in thread
From: builds.sr.ht @ 2024-10-24 12:39 UTC (permalink / raw)
  To: Carlos Maniero; +Cc: ~johnnyrichard/olang-devel

olang/patches/.build.yml: SUCCESS in 31s

[Remove symbol lookups from codegen][0] from [Carlos Maniero][1]

[0]: https://lists.sr.ht/~johnnyrichard/olang-devel/patches/55616
[1]: mailto:carlos@maniero.me

✓ #1355878 SUCCESS olang/patches/.build.yml https://builds.sr.ht/~johnnyrichard/job/1355878

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH olang v1 0/6] Remove symbol lookups from codegen
  2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
                   ` (5 preceding siblings ...)
  2024-10-24 12:38 ` [PATCH olang v1 6/6] ast: remove dead code from var_assign ast node Carlos Maniero
@ 2024-10-31  3:16 ` Carlos Maniero
  6 siblings, 0 replies; 9+ messages in thread
From: Carlos Maniero @ 2024-10-31  3:16 UTC (permalink / raw)
  To: Carlos Maniero, ~johnnyrichard/olang-devel

Superseded by:
Message-ID: <20241031031302.136553-1-carlos@maniero.me>                                                                                                       

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-10-31  3:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-24 12:38 [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero
2024-10-24 12:38 ` [PATCH olang v1 1/6] ast: create the ast_id_t and apply it to var_def and ref Carlos Maniero
2024-10-24 12:38 ` [PATCH olang v1 2/6] semantics: resolve variable symbols Carlos Maniero
2024-10-24 12:38 ` [PATCH olang v1 3/6] semantics: refactor: use the ast_id_t into the fn_call node Carlos Maniero
2024-10-24 12:38 ` [PATCH olang v1 4/6] semantics: refactor: use the ast_id_t into the fn_def.params Carlos Maniero
2024-10-24 12:38 ` [PATCH olang v1 5/6] type: refactor: rename type.id to type.name Carlos Maniero
2024-10-24 12:38 ` [PATCH olang v1 6/6] ast: remove dead code from var_assign ast node Carlos Maniero
2024-10-24 12:39   ` [olang/patches/.build.yml] build success builds.sr.ht
2024-10-31  3:16 ` [PATCH olang v1 0/6] Remove symbol lookups from codegen Carlos Maniero

Code repositories for project(s) associated with this public inbox

	https://git.johnnyrichard.com/olang.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox