more expression types

This commit is contained in:
Mid 2025-09-05 21:14:28 +03:00
parent 6b2b8944eb
commit a29b250f30
2 changed files with 142 additions and 6 deletions

11
lexer.c
View File

@ -99,6 +99,9 @@ vec_Token ltokenize(const char *buf, size_t len) {
} else if(buf[0] == '}') { } else if(buf[0] == '}') {
vec_Token_push(&tokens, (Token) {.type = TOK_SQUIGGLY_R}); vec_Token_push(&tokens, (Token) {.type = TOK_SQUIGGLY_R});
buf++, len--; buf++, len--;
} else if(buf[0] == '#') {
vec_Token_push(&tokens, (Token) {.type = TOK_SHARP});
buf++, len--;
} else if(len > 1 && buf[0] == '~' && buf[1] == '=') { } else if(len > 1 && buf[0] == '~' && buf[1] == '=') {
vec_Token_push(&tokens, (Token) {.type = TOK_NOT_EQUAL}); vec_Token_push(&tokens, (Token) {.type = TOK_NOT_EQUAL});
buf++, len--; 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}); vec_Token_push(&tokens, (Token) {.text = strndup(buf, idlen), .type = TOK_NUMBER});
buf += idlen, len -= idlen; 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] == '\"') { } else if(buf[0] == '\'' || buf[0] == '\"') {
bool single = buf[0] == '\''; bool single = buf[0] == '\'';

137
parse.c
View File

@ -92,9 +92,12 @@ typedef enum ExprKind {
EX_EQ, EX_EQ,
EX_NEQ, EX_NEQ,
EX_TBL_LIT, EX_TBL_LIT,
EX_FUNC_LIT,
EX_DOT,
EX_INDEX, EX_INDEX,
EX_CALL, EX_CALL,
EX_STR, EX_STR,
EX_LENGTH,
} ExprKind; } ExprKind;
typedef struct Expr { typedef struct Expr {
ExprKind kind; ExprKind kind;
@ -414,7 +417,11 @@ Expr *desc_subexp(Parser *P, int priority) {
} else if(priority == 3) { } else if(priority == 3) {
Expr *e = NULL; 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 = new_expr(0);
e->kind = EX_BOOL; e->kind = EX_BOOL;
e->b = true; e->b = true;
@ -449,6 +456,25 @@ Expr *desc_subexp(Parser *P, int priority) {
e = new_expr(0); e = new_expr(0);
e->kind = EX_STR; e->kind = EX_STR;
e->name = 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)) { } else if(maybe(P, TOK_SQUIGGLY_L)) {
e = new_expr(0); e = new_expr(0);
e->kind = EX_TBL_LIT; e->kind = EX_TBL_LIT;
@ -471,7 +497,7 @@ Expr *desc_subexp(Parser *P, int priority) {
} }
if(e) { 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) { if(peek(P, -1).type == TOK_PAREN_L) {
Expr *call = new_expr(sizeof(Expr*) + sizeof(Expr*) * 32); Expr *call = new_expr(sizeof(Expr*) + sizeof(Expr*) * 32);
call->kind = EX_CALL; call->kind = EX_CALL;
@ -493,11 +519,20 @@ Expr *desc_subexp(Parser *P, int priority) {
e = call; e = call;
} else if(peek(P, -1).type == TOK_DOT) { } else if(peek(P, -1).type == TOK_DOT) {
Expr *dot = new_expr(0); Expr *dot = new_expr(0);
dot->kind = EX_INDEX; dot->kind = EX_DOT;
dot->A = e; dot->A = e;
dot->B_tok = expect(P, TOK_NAME); dot->B_tok = expect(P, TOK_NAME);
e = dot; 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++) { for(size_t i = 1; i < expr->sub_count; i++) {
int av = find_vreg(P); int av = find_vreg(P);
emit_expr(P, av, expr->subs[i++]); emit_expr(P, av, expr->subs[i]);
args[(*arg_count)++] = av; args[(*arg_count)++] = av;
alloc_vreg(P, 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)}); 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) { } else if(expr->kind == EX_TBL_LIT) {
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETTABLE, .a = assigned_vreg, .bc = 16}); 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; P->i = expr->table_first_token;
expect(P, TOK_SQUIGGLY_L); expect(P, TOK_SQUIGGLY_L);
alloc_vreg(P, assigned_vreg);
if(!maybe(P, TOK_SQUIGGLY_R)) { if(!maybe(P, TOK_SQUIGGLY_R)) {
while(1) { 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; P->i = old_idx;
} else if(expr->kind == EX_INDEX) { } else if(expr->kind == EX_DOT) {
Token field = expr->B_tok; Token field = expr->B_tok;
emit_expr(P, assigned_vreg, expr->A); 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}); vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_GETFIELD, .a = assigned_vreg, .b = assigned_vreg, .c = keyv});
free_vreg(P, assigned_vreg); 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 { } 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); 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; 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; goto err;
} }
@ -841,6 +953,19 @@ bool parse_assignment(Parser *P) {
emit_expr(P, lhsv, lhs[i]->A); emit_expr(P, lhsv, lhs[i]->A);
alloc_vreg(P, lhsv); 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; Token field = lhs[i]->B_tok;
size_t abyss_idx = abyss_insert(P, NULL, sizeof(uint16_t) + strlen(field.text)); size_t abyss_idx = abyss_insert(P, NULL, sizeof(uint16_t) + strlen(field.text));