From a29b250f3083ec9f47d4ab53209cbaf183a9e0ad Mon Sep 17 00:00:00 2001 From: Mid <> Date: Fri, 5 Sep 2025 21:14:28 +0300 Subject: [PATCH] more expression types --- lexer.c | 11 +++++ parse.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 142 insertions(+), 6 deletions(-) diff --git a/lexer.c b/lexer.c index c8695e8..ef5032b 100644 --- a/lexer.c +++ b/lexer.c @@ -99,6 +99,9 @@ vec_Token ltokenize(const char *buf, size_t len) { } else if(buf[0] == '}') { vec_Token_push(&tokens, (Token) {.type = TOK_SQUIGGLY_R}); buf++, len--; + } else if(buf[0] == '#') { + vec_Token_push(&tokens, (Token) {.type = TOK_SHARP}); + buf++, len--; } else if(len > 1 && buf[0] == '~' && buf[1] == '=') { vec_Token_push(&tokens, (Token) {.type = TOK_NOT_EQUAL}); buf++, len--; @@ -116,6 +119,14 @@ vec_Token ltokenize(const char *buf, size_t len) { vec_Token_push(&tokens, (Token) {.text = strndup(buf, idlen), .type = TOK_NUMBER}); buf += idlen, len -= idlen; + } else if(buf[0] == '-' && (len == 1 || buf[1] != '-')) { + vec_Token_push(&tokens, (Token) {.type = TOK_MINUS}); + buf++, len--; + } else if(len >= 2 && buf[0] == '-' && buf[1] == '-') { + while(*buf != '\n') { + buf++, len--; + } + row++; } else if(buf[0] == '\'' || buf[0] == '\"') { bool single = buf[0] == '\''; diff --git a/parse.c b/parse.c index 6a040e3..8b83f36 100644 --- a/parse.c +++ b/parse.c @@ -92,9 +92,12 @@ typedef enum ExprKind { EX_EQ, EX_NEQ, EX_TBL_LIT, + EX_FUNC_LIT, + EX_DOT, EX_INDEX, EX_CALL, EX_STR, + EX_LENGTH, } ExprKind; typedef struct Expr { ExprKind kind; @@ -414,7 +417,11 @@ Expr *desc_subexp(Parser *P, int priority) { } else if(priority == 3) { Expr *e = NULL; - if(maybe(P, TOK_TRUE)) { + if(maybe(P, TOK_SHARP)) { + e = new_expr(0); + e->kind = EX_LENGTH; + e->A = desc_subexp(P, priority); + } else if(maybe(P, TOK_TRUE)) { e = new_expr(0); e->kind = EX_BOOL; e->b = true; @@ -449,6 +456,25 @@ Expr *desc_subexp(Parser *P, int priority) { e = new_expr(0); e->kind = EX_STR; e->name = str; + } else if(maybe(P, TOK_FUNCTION)) { + e = new_expr(0); + e->kind = EX_FUNC_LIT; + e->table_first_token = P->i - 1; + + size_t depth = 1; + while(1) { + Token t = get(P); + if(t.type == TOK_THEN || t.type == TOK_DO) { + depth++; + } else if(t.type == TOK_END) { + depth--; + if(depth == 0) { + break; + } + } + } + + e->table_last_token = P->i - 1; } else if(maybe(P, TOK_SQUIGGLY_L)) { e = new_expr(0); e->kind = EX_TBL_LIT; @@ -471,7 +497,7 @@ Expr *desc_subexp(Parser *P, int priority) { } if(e) { - while(maybe(P, TOK_PAREN_L) || maybe(P, TOK_DOT)) { + while(maybe(P, TOK_PAREN_L) || maybe(P, TOK_DOT) || maybe(P, TOK_SQUAREN_L)) { if(peek(P, -1).type == TOK_PAREN_L) { Expr *call = new_expr(sizeof(Expr*) + sizeof(Expr*) * 32); call->kind = EX_CALL; @@ -493,11 +519,20 @@ Expr *desc_subexp(Parser *P, int priority) { e = call; } else if(peek(P, -1).type == TOK_DOT) { Expr *dot = new_expr(0); - dot->kind = EX_INDEX; + dot->kind = EX_DOT; dot->A = e; dot->B_tok = expect(P, TOK_NAME); e = dot; + } else if(peek(P, -1).type == TOK_SQUAREN_L) { + Expr *index = new_expr(0); + index->kind = EX_INDEX; + index->A = e; + index->B = desc_exp(P); + + expect(P, TOK_SQUAREN_R); + + e = index; } } @@ -654,7 +689,7 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) { for(size_t i = 1; i < expr->sub_count; i++) { int av = find_vreg(P); - emit_expr(P, av, expr->subs[i++]); + emit_expr(P, av, expr->subs[i]); args[(*arg_count)++] = av; alloc_vreg(P, av); } @@ -667,6 +702,66 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) { } vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_CALL, .a = vreg, .bc = abyss_insert(P, buf, 2 + *arg_count)}); + } else if(expr->kind == EX_FUNC_LIT) { + size_t old_idx = P->i; + + P->i = expr->table_first_token; + + expect(P, TOK_FUNCTION); + + expect(P, TOK_PAREN_L); + + Chunk old_chunk = P->current_chunk; + P->current_chunk = (Chunk) {}; + + Scope *new_scope = calloc(1, sizeof(*new_scope)); + new_scope->parent = P->scope; + P->scope = new_scope; + + size_t arg_count = 0; + if(!maybe(P, TOK_PAREN_R)) { + while(1) { + expect(P, TOK_NAME); + + P->i--; + + ScopeItem *si = calloc(1, sizeof(*si)); + si->name = expect(P, TOK_NAME); + si->vreg = arg_count++; + scope_set_direct(P->scope, si); + + if(maybe(P, TOK_PAREN_R)) { + break; + } else { + expect(P, TOK_COMMA); + } + } + } + + parse_chunk(P); + if(P->current_chunk.instrs.data[P->current_chunk.instrs.size - 1].opcode != L_RET) { + vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_RET, .argb = {0}}); + } + + expect(P, TOK_END); + + assert(P->unit_functions.size > 0); + + LFunc lf = {}; + lf.unit = P->unit_functions.data[0].unit; + lf.is_native = false; + lf.lua_instrs = P->current_chunk.instrs.data; + lf.env = P->environment; + vec_LFunc_push(&P->unit_functions, lf); + + size_t function_idx = P->unit_functions.size - 1; + + P->current_chunk = old_chunk; + scope_kill(P); + + P->i = old_idx; + + vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETFUNC, .a = assigned_vreg, .bc = function_idx}); } else if(expr->kind == EX_TBL_LIT) { vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETTABLE, .a = assigned_vreg, .bc = 16}); @@ -674,6 +769,8 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) { P->i = expr->table_first_token; expect(P, TOK_SQUIGGLY_L); + + alloc_vreg(P, assigned_vreg); if(!maybe(P, TOK_SQUIGGLY_R)) { while(1) { @@ -709,9 +806,11 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) { } } } + + free_vreg(P, assigned_vreg); P->i = old_idx; - } else if(expr->kind == EX_INDEX) { + } else if(expr->kind == EX_DOT) { Token field = expr->B_tok; emit_expr(P, assigned_vreg, expr->A); @@ -728,6 +827,19 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) { vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_GETFIELD, .a = assigned_vreg, .b = assigned_vreg, .c = keyv}); free_vreg(P, assigned_vreg); + } else if(expr->kind == EX_INDEX) { + emit_expr(P, assigned_vreg, expr->A); + + alloc_vreg(P, assigned_vreg); + int keyv = find_vreg(P); + emit_expr(P, keyv, expr->B); + free_vreg(P, assigned_vreg); + + vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_GETFIELD, .a = assigned_vreg, .b = assigned_vreg, .c = keyv}); + } else if(expr->kind == EX_LENGTH) { + emit_expr(P, assigned_vreg, expr->A); + + vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_LEN, .a = assigned_vreg, .b = assigned_vreg, .c = 0}); } else { assert(expr->kind == EX_ADD || expr->kind == EX_SUB || expr->kind == EX_MUL || expr->kind == EX_DIV || expr->kind == EX_IDIV || expr->kind == EX_MOD || expr->kind == EX_POW || expr->kind == EX_BAND || expr->kind == EX_BOR || expr->kind == EX_BXOR || expr->kind == EX_AND || expr->kind == EX_OR || expr->kind == EX_EQ || expr->kind == EX_NEQ); @@ -796,7 +908,7 @@ bool parse_assignment(Parser *P) { goto err; } - if(lhs[lhsi - 1]->kind != EX_LOCAL && lhs[lhsi - 1]->kind != EX_GLOBAL && lhs[lhsi - 1]->kind != EX_INDEX) { + if(lhs[lhsi - 1]->kind != EX_LOCAL && lhs[lhsi - 1]->kind != EX_GLOBAL && lhs[lhsi - 1]->kind != EX_DOT && lhs[lhsi - 1]->kind != EX_INDEX) { goto err; } @@ -841,6 +953,19 @@ bool parse_assignment(Parser *P) { emit_expr(P, lhsv, lhs[i]->A); alloc_vreg(P, lhsv); + int keyv = find_vreg(P); + assert(keyv != -1); + emit_expr(P, keyv, lhs[i]->B); + + vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETFIELD, .a = lhsv, .b = keyv, .c = rhsv[i]}); + + free_vreg(P, lhsv); + } else if(lhs[i]->kind == EX_DOT) { + int lhsv = find_vreg(P); + assert(lhsv != -1); + emit_expr(P, lhsv, lhs[i]->A); + alloc_vreg(P, lhsv); + Token field = lhs[i]->B_tok; size_t abyss_idx = abyss_insert(P, NULL, sizeof(uint16_t) + strlen(field.text));