commit 89c19100b77b3ab89675aeb9cfab834f1d464c0b
parent ba4d6709b055e7e7ffc6581809388ce97a77a58b
Author: citbl <citbl@citbl.org>
Date: Mon, 20 Oct 2025 22:08:29 +1000
handle assignments, check existence and matching type
Diffstat:
11 files changed, 92 insertions(+), 16 deletions(-)
diff --git a/.zed/debug.json b/.zed/debug.json
@@ -11,7 +11,7 @@
"cwd": "$ZED_WORKTREE_ROOT"
},
"program": "$ZED_WORKTREE_ROOT/oxc",
- "args": ["$ZED_WORKTREE_ROOT/ex9.ox"],
+ "args": ["$ZED_WORKTREE_ROOT/ex12.ox"],
"request": "launch",
"adapter": "CodeLLDB"
}
diff --git a/ex12.ox b/ex12.ox
@@ -0,0 +1,5 @@
+void main() {
+ string jake = "before change";
+ jake = "expected result";
+ print(jake);
+}
diff --git a/src/gen/gen.c b/src/gen/gen.c
@@ -260,7 +260,8 @@ handle_expr(Gen* gen, Node* node)
}
// case NODE_IDENT: {
// return NULL; // fixme
- // } break;
+ // break;
+ // }
default:
printf("handle_expr unhandled, %s\n", node_type_str(node->type));
}
@@ -289,6 +290,17 @@ ox_type_to_c_type(Gen* gen, Node* node)
}
static void
+add_symbol(Gen* gen, Symbol* sym)
+{
+ if (gen->scope->len == gen->scope->cap) {
+ gen->scope->cap *= 2;
+ gen->scope->symbols = (Symbol**)realloc(gen->scope->symbols, sizeof(Symbol*) * gen->scope->cap);
+ }
+
+ gen->scope->symbols[gen->scope->len++] = sym;
+}
+
+static void
build_statement(Gen* gen, Node* node)
{
switch (node->type) {
@@ -314,25 +326,42 @@ build_statement(Gen* gen, Node* node)
if (node->data.var_decl.init == NULL) { panic("could not instanciate gcc jit new local"); }
- printf("adding 1 symbol: %s\n", span_str(gen->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 }));
+ printf("adding 1 symbol: %s\n", var_name);
Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol));
sym->name = node->data.var_decl.name;
sym->decl = node;
sym->ctype = declared_type;
sym->d.lvalue = var_decl;
-
- if (gen->scope->len == gen->scope->cap) {
- gen->scope->cap *= 2;
- gen->scope->symbols = (Symbol**)realloc(gen->scope->symbols, sizeof(Symbol*) * gen->scope->cap);
+ add_symbol(gen, sym);
+ break;
+ }
+ case NODE_VAR_ASSIGN: {
+ gcc_jit_location* loc = loc_from_node(gen, node);
+ gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_assign.rhs);
+ // find the var_decl (d.lvalue) from the symbols table's symbol.
+ for (size_t i = 0; i < gen->scope->len; i++) {
+ Symbol* sym = gen->scope->symbols[i];
+ if (span_ident_same(sym->name, node->data.var_assign.lhs->data.ident.name, gen->src)) {
+ // we found the symbol we are assigning to
+ gcc_jit_lvalue* lvalue = sym->d.lvalue;
+
+ // check the type of lvalue matches the rvalue
+ gcc_jit_type* ltype = sym->ctype;
+ gcc_jit_type* rtype = gcc_jit_rvalue_get_type(rvalue);
+ if (rtype != ltype) {
+ panic_at(node, "right hand side of assigment doesn't match the type of the left hand side");
+ }
+ if (lvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, lvalue, rvalue);
+ }
}
-
- gen->scope->symbols[gen->scope->len++] = sym;
- } break;
+ break;
+ }
case NODE_EXPR_STATEMENT: {
gcc_jit_rvalue* rv = handle_expr(gen, node->data.expr_statement.expr);
if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv);
- } break;
+ break;
+ }
default:
printf("build_statement unhandled, %s\n", node_type_str(node->type));
break;
diff --git a/src/main.c b/src/main.c
@@ -56,7 +56,7 @@ main(int argc, char* argv[])
Ast ast;
parser_parse(&ast, &par);
- // ast_print(&ast);
+ ast_print(&ast);
printf("--- sem --- \n");
diff --git a/src/parser.h b/src/parser.h
@@ -61,3 +61,6 @@ Node* make_call_node(Node*, NodeVec);
const char* span_str(const char* src, Span s, char* stack_alloc_chptr);
const char* range_str(const char* src, size_t start, size_t end, char* stack_alloc_chptr);
+bool span_ident_same(Span a, Span b, const char* src);
+
+void error_fmt(char* buffer, const char* message, Node* node);
diff --git a/src/parser/parser.c b/src/parser/parser.c
@@ -52,7 +52,7 @@ expect(Parser* par, TokenType type)
Token tok = peek(par);
if (tok.type != type) {
const char* name = range_str(par->src, tok.start, tok.end, (char[IDENTSZ]) { 0 });
- panic("Expected %d got '%s' (%d) at %s:%zu:%zu", token_type_str(type), name, tok.type, par->filename, tok.line, tok.col);
+ panic("Expected %s, but got '%s' (%d) at %s:%zu:%zu", token_type_str(type), name, tok.type, par->filename, tok.line, tok.col);
assert(tok.type == type);
}
return consume(par);
@@ -182,7 +182,9 @@ parse_statement(Parser* par)
return parse_block(par);
}
- if (tok.type == TOKEN_IDENT && tok2.type == TOKEN_IDENT) return parse_decl_or_func_decl(par);
+ if (tok.type == TOKEN_IDENT && tok2.type == TOKEN_IDENT) { return parse_decl_or_func_decl(par); }
+
+ if (tok.type == TOKEN_IDENT && tok2.type == TOKEN_EQUAL) { return parse_assignment(par); }
switch (tok.type) {
case TOKEN_RETURN:
diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c
@@ -24,6 +24,14 @@ span_str(const char* src, Span s, char* stack_alloc_chptr)
return range_str(src, s.start, s.end, stack_alloc_chptr);
}
+bool
+span_ident_same(Span a, Span b, const char* src)
+{
+ const char* a_name = span_str(src, a, (char[IDENTSZ]) { 0 });
+ const char* b_name = span_str(src, b, (char[IDENTSZ]) { 0 });
+ return strcmp(a_name, b_name) == 0;
+}
+
// int span_to_str(const char* src, size_t start, size_t end, char* out_buf) {
// if (!src || !out_buf) return -1; /* Null pointer passed */
// if (start >= end) return -2; /* Empty or inverted span */
@@ -59,6 +67,12 @@ span_str(const char* src, Span s, char* stack_alloc_chptr)
// return s;
// }
+void
+error_fmt(char* buffer, const char* msg, Node* node)
+{
+ sprintf(buffer, "%s (%s L.%zu:%zu).", msg, node->filename, node->line, node->col);
+}
+
static void
print_node(const char* source, Node* node, int level)
{
diff --git a/src/parser/stmt.c b/src/parser/stmt.c
@@ -118,6 +118,9 @@ parse_assignment(Parser* par)
dereference
*p = 5;
*/
+ assign->filename = par->filename;
+ assign->line = ident.line;
+ assign->col = ident.col;
assign->data.var_assign.lhs->type = NODE_IDENT; // TODO handle other cases
assign->data.var_assign.lhs->scope = NULL;
assign->data.var_assign.lhs->data.ident.name = name;
diff --git a/src/types.h b/src/types.h
@@ -150,7 +150,7 @@ typedef struct Node {
struct Node* next;
struct Scope* scope;
const char* filename;
- int line, col;
+ size_t line, col;
/* NOTE we will eventually add spans for condition info, etc. to print out in errors */
diff --git a/src/utils.c b/src/utils.c
@@ -7,6 +7,23 @@
#include <string.h>
void
+panic_at(Node* node, const char* fmt, ...)
+{
+ va_list args;
+ int saved_errno;
+ saved_errno = errno;
+ va_start(args, fmt);
+ fprintf(stderr, "%s, [%zu:%zu] ", node->filename, node->line, node->col);
+ fprintf(stderr, "Error: ");
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ if (fmt[0] && fmt[strlen(fmt) - 1] == ':') fprintf(stderr, " %s", strerror(saved_errno));
+ fputc('\n', stderr);
+ exit(1);
+}
+
+void
panic(const char* fmt, ...)
{
va_list args;
diff --git a/src/utils.h b/src/utils.h
@@ -1,6 +1,9 @@
#pragma once
#include <stdlib.h>
+#include "types.h"
-void panic(const char* fmt, ...);
void softpanic(const char* fmt, ...);
+
+void panic(const char* fmt, ...);
+void panic_at(Node* node, const char* fmt, ...);