From: cassowarii Date: Mon, 29 Jun 2026 04:55:17 +0000 (-0700) Subject: fix minor parser bug, IR can do multi-assignment now X-Git-Url: https://git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=79d88ca461e53405d083e36401b692b3436cb4a4;p=sarabande.git fix minor parser bug, IR can do multi-assignment now --- diff --git a/Makefile b/Makefile index 9922968..a40b929 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,10 @@ build/a.out: $(OBJECTS) @mkdir -p $(dir $@) $(CC) $(CFLAGS) -I$(SRC) $(OBJECTS) $(LIBS) -o $@ +.PHONY: parsedebug +parsedebug: CFLAGS += -DPARSEDEBUG +parsedebug: build/a.out + $(OBJ)/%.o: $(SRC)/%.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) $(LIBS) -I$(SRC) -c $< -o $@ diff --git a/src/compile/ir.c b/src/compile/ir.c index 80e9b8e..9fca3ed 100644 --- a/src/compile/ir.c +++ b/src/compile/ir.c @@ -11,7 +11,7 @@ typedef struct varmapentry { sbIrVariable *var; } varmapentry; -static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast); +static void compile_ast_function(hIrChunk ck, sbAst seqast); static sbIrChunk *new_chunk(hIrProgram ir); static void chunk_deinitialize(hIrChunk ck); static void print_stmt(sbIrStmt *s); @@ -37,7 +37,7 @@ void sbIrProgram_deinitialize(hIrProgram ir) { void sbIrProgram_compile_ast(hIrProgram ir, sbAst ast) { sbIrChunk *ck = new_chunk(ir); - compile_ast_stmtseq(ck, ast); + compile_ast_function(ck, ast); } void sbIrProgram_print(hIrProgram ir) { @@ -198,9 +198,15 @@ static void put_return(hIrChunk ck) { } static void compile_ast_stmt(hIrChunk ck, sbAst stmtast); +static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast); static sbIrExpr *compile_ast_expr(hIrChunk ck, sbAst exprast); static sbIrVariable *compile_ast_var(hIrChunk ck, sbAst node); +static void compile_ast_function(hIrChunk ck, sbAst seqast) { + compile_ast_stmtseq(ck, seqast); + put_return(ck); +} + static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast) { usize varmapsize = ck->program->varmapping.size; @@ -212,7 +218,6 @@ static void compile_ast_stmtseq(hIrChunk ck, sbAst seqast) { } compile_ast_stmt(ck, considering->seq.left); - //put_return(ck); considering = considering->seq.right; } @@ -225,6 +230,7 @@ static void compile_ast_stmt(hIrChunk ck, sbAst node) { sbIrExpr *E1; sbIrLabel *L1, *L2; sbIrVariable *V1; + sbAst N1, N2; switch (node->type) { case AST_NODE_LET: /* @@ -239,23 +245,62 @@ static void compile_ast_stmt(hIrChunk ck, sbAst node) { * TODO: I need to add support for declaring multiple * variables in one line. */ - if (node->seq.left->type != AST_NODE_MULTIVAL) PANIC("expected multival on left side of let!"); - const char *vname = sbSymbol_name(node->seq.left->seq.left->symb); - V1 = create_var(ck, vname, strlen(vname)); - if (node->seq.right != NO_NODE) { + if (node->seq.right == NO_NODE) { + /* let ... */ + if (node->seq.left->type != AST_NODE_MULTIVAL) PANIC("expected multival on left side of let!"); + N1 = node->seq.left; /* things to bind to */ + while (N1 != NO_NODE) { + if (N1->seq.left->type != AST_NODE_NAME) { + fprintf(stderr, "Only variable names are permitted after 'let'!\n"); + break; + } + const char *vname = sbSymbol_name(N1->seq.left->symb); + V1 = create_var(ck, vname, strlen(vname)); + N1 = N1->seq.right; + } + } else { /* let ... = ... */ if (node->seq.right->type != AST_NODE_MULTIVAL) PANIC("expected multival on right side of let!"); - E1 = compile_ast_expr(ck, node->seq.right->seq.left); - put_assign(ck, V1, E1); + N1 = node->seq.left; /* things to bind to */ + N2 = node->seq.right; /* values to assign */ + while (N1 != NO_NODE && N2 != NO_NODE) { + if (N1->seq.left->type != AST_NODE_NAME) { + fprintf(stderr, "Only variable names are permitted on the left side of 'let'!\n"); + break; + } + const char *vname = sbSymbol_name(N1->seq.left->symb); + V1 = create_var(ck, vname, strlen(vname)); + E1 = compile_ast_expr(ck, N2->seq.left); + put_assign(ck, V1, E1); + N1 = N1->seq.right; + N2 = N2->seq.right; + } + if (N1 != NO_NODE) { + fprintf(stderr, "too many bindings on left side of assignment!"); + } else if (N2 != NO_NODE) { + fprintf(stderr, "too many values on right side of assignment!"); + } } break; case AST_NODE_ASSIGN: if (node->seq.left->type != AST_NODE_MULTIVAL) PANIC("expected multival on left side of assign!"); if (node->seq.right->type != AST_NODE_MULTIVAL) PANIC("expected multival on right side of assign!"); - V1 = compile_ast_var(ck, node->seq.left->seq.left); - E1 = compile_ast_expr(ck, node->seq.right->seq.left); - put_assign(ck, V1, E1); + N1 = node->seq.left; /* things to bind to */ + N2 = node->seq.right; /* values to assign */ + while (N1 != NO_NODE && N2 != NO_NODE) { + V1 = compile_ast_var(ck, N1->seq.left); + E1 = compile_ast_expr(ck, N2->seq.left); + put_assign(ck, V1, E1); + N1 = N1->seq.right; + N2 = N2->seq.right; + } + + if (N1 != NO_NODE) { + fprintf(stderr, "too many bindings on left side of assignment!"); + } else if (N2 != NO_NODE) { + fprintf(stderr, "too many values on right side of assignment!"); + } break; case AST_NODE_WHILE: diff --git a/src/parse/lexer.c b/src/parse/lexer.c index 56369c7..17acc38 100644 --- a/src/parse/lexer.c +++ b/src/parse/lexer.c @@ -399,9 +399,9 @@ static void compute_next_token(hLexer lx) { } if (begins_brace_terminated_state(token.type)) { - /* only start brace-terminated state if we are actually starting a new line, - * or if we are after an "else" (special case for else if) */ - if (lx->last_token_seen.type == ';' || lx->last_token_seen.type == T_rELSE) { + /* don't start brace-terminated state if we are directly after a '}' (otherwise it gets + * confused by things like repeat..until */ + if (lx->last_token_seen.type != '}') { brackets_stack_push(lx, 'B'); } } diff --git a/src/parse/parser.c b/src/parse/parser.c index 9e41f55..5d6780a 100644 --- a/src/parse/parser.c +++ b/src/parse/parser.c @@ -201,6 +201,11 @@ static sbLexToken next_token(hParser pr) { sbLexToken t = peek_ahead(pr, 0); +#ifdef PARSEDEBUG + fprint_token(stdout, t); + printf("\n"); +#endif + return t; }