From 2c76277a68e217aa87b9356c03ddac7261f1d38b Mon Sep 17 00:00:00 2001 From: samsonium Date: Sun, 11 Oct 2026 19:11:49 +0300 Subject: [PATCH] wip: working on variables --- .gdbinit | 1 + exl/variables.fzs | 12 ++++ include/common/fzl_opcodes.h | 6 ++ include/compiler/fzl_parser.h | 7 +++ src/compiler/fzl_debug.c | 104 +++++++++++++++++++--------------- src/compiler/fzl_parser.c | 84 ++++++++++++++++++++------- src/compiler/fzl_reader.c | 27 +++++++-- src/compiler/fzl_walker.c | 46 ++++++++++++++- 8 files changed, 215 insertions(+), 72 deletions(-) create mode 100644 exl/variables.fzs diff --git a/.gdbinit b/.gdbinit index c0863a3..b48dd6a 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1,4 +1,5 @@ skip peek skip consume skip next +skip is diff --git a/exl/variables.fzs b/exl/variables.fzs new file mode 100644 index 0000000..95c091f --- /dev/null +++ b/exl/variables.fzs @@ -0,0 +1,12 @@ +uint work_it = 21 * 2 ^ 2 +int make_it = 10 + +u64 do_it +do_it = 15 + +printline(work_it) +printline(make_it + do_it) + +char make_us +string floyd = "hello, Pink Floyd!" + diff --git a/include/common/fzl_opcodes.h b/include/common/fzl_opcodes.h index cd1c0e2..4bc136b 100644 --- a/include/common/fzl_opcodes.h +++ b/include/common/fzl_opcodes.h @@ -8,6 +8,12 @@ typedef enum FZL_OPCODE_CALL_BUILTIN = 0xF00002, // Call builtin function FZL_OPCODE_PUSHNUM = 0xF00003, // Push number into stack + FZL_OPCODE_MK_ENVTABLE = 0xF10001, // Allocate new environment table + FZL_OPCODE_RM_ENVTABLE = 0xF10002, // Free environment table + FZL_OPCODE_STORE = 0xF10003, // Push variable to environment table + FZL_OPCODE_LOOKUP_ENV = 0xF10004, // Lookup name in environment table + FZL_OPCODE_WRITE = 0xF10005, // Wirte into variable + FZL_OPCODE_ADD = 0xA00001, // Sum two numbers in arg strack FZL_OPCODE_SUB = 0xA00002, // Subract two numbers in arg stack FZL_OPCODE_MUL = 0xA00003, // Multiply two numbers in arg stack diff --git a/include/compiler/fzl_parser.h b/include/compiler/fzl_parser.h index a0064e2..b8bee88 100644 --- a/include/compiler/fzl_parser.h +++ b/include/compiler/fzl_parser.h @@ -65,6 +65,13 @@ typedef struct fzl_node { struct fzl_node *operand; } unary_op; + + // Variables declaration and initializing + struct + { + fzl_token_t *type; + struct fzl_node *identifier; + } var; }; } fzl_node_t; diff --git a/src/compiler/fzl_debug.c b/src/compiler/fzl_debug.c index 3e40d63..5df5833 100644 --- a/src/compiler/fzl_debug.c +++ b/src/compiler/fzl_debug.c @@ -32,56 +32,70 @@ void print_node(fzl_node_t *node, int level) switch (node->type) { - case FZL_NODETYPE_CALL: - if (node->call.args_count > 0) - { - printf("%s Call fn '%s' with args:\n", levelbuf, - (char *)node->token->value); - for (size_t i = 0; i < node->call.args_count; i++) - print_node(node->call.args[i], level + 1); - } - else - printf("%s Call fn '%s' w/o args\n", levelbuf, - (char *)node->token->value); - break; - - case FZL_NODETYPE_LITERAL: - printf("%s Literal '%s'\n", levelbuf, (char *)node->token->value); - break; - - case FZL_NODETYPE_BLOCK: - printf("%s Block: ", levelbuf); - - if (node->list.entry_count < 1) - { - printf("\n"); + case FZL_NODETYPE_DECLARATION: + printf("%s Declare variable with type %d:\n", levelbuf, + node->var.type->type); + print_node(node->var.identifier, level + 1); break; - } - printf("\n"); - for (size_t i = 0; i < node->list.entry_count; i++) - print_node(node->list.entries[i], level + 1); + case FZL_NODETYPE_ASSIGN: + printf("%s Assign:\n", levelbuf); + printf("-%s Target:\n", levelbuf); + print_node(node->binary_op.left, level + 2); + printf("-%s Source:\n", levelbuf); + print_node(node->binary_op.right, level + 2); + break; - break; - case FZL_NODETYPE_ADD: - case FZL_NODETYPE_SUB: - case FZL_NODETYPE_MUL: - case FZL_NODETYPE_DIV: - case FZL_NODETYPE_POW: - case FZL_NODETYPE_MOD: - printf("%s Binary op (%d)\n", levelbuf, node->type); - printf("-%s LEFT:\n", levelbuf); - print_node(node->binary_op.left, level + 2); - printf("-%s RIGHT:\n", levelbuf); - print_node(node->binary_op.right, level + 2); - break; + case FZL_NODETYPE_CALL: + if (node->call.args_count > 0) + { + printf("%s Call fn '%s' with args:\n", levelbuf, + (char *)node->token->value); + for (size_t i = 0; i < node->call.args_count; i++) + print_node(node->call.args[i], level + 1); + } + else + printf("%s Call fn '%s' w/o args\n", levelbuf, + (char *)node->token->value); + break; - case FZL_NODETYPE_IDENTIFIER: - printf("%s Identifier ('%s')\n", levelbuf, (char *)node->token->value); - break; + case FZL_NODETYPE_LITERAL: + printf("%s Literal '%s'\n", levelbuf, (char *)node->token->value); + break; - default: - printf("%s Secure node\n", levelbuf); + case FZL_NODETYPE_BLOCK: + printf("%s Block: ", levelbuf); + + if (node->list.entry_count < 1) + { + printf("\n"); + break; + } + + printf("\n"); + for (size_t i = 0; i < node->list.entry_count; i++) + print_node(node->list.entries[i], level + 1); + + break; + case FZL_NODETYPE_ADD: + case FZL_NODETYPE_SUB: + case FZL_NODETYPE_MUL: + case FZL_NODETYPE_DIV: + case FZL_NODETYPE_POW: + case FZL_NODETYPE_MOD: + printf("%s Binary op (%d)\n", levelbuf, node->type); + printf("-%s LEFT:\n", levelbuf); + print_node(node->binary_op.left, level + 2); + printf("-%s RIGHT:\n", levelbuf); + print_node(node->binary_op.right, level + 2); + break; + + case FZL_NODETYPE_IDENTIFIER: + printf("%s Identifier ('%s')\n", levelbuf, (char *)node->token->value); + break; + + default: + printf("%s Secure node\n", levelbuf); } } diff --git a/src/compiler/fzl_parser.c b/src/compiler/fzl_parser.c index c311aa3..d814953 100644 --- a/src/compiler/fzl_parser.c +++ b/src/compiler/fzl_parser.c @@ -4,6 +4,7 @@ #include #include #include +#include char plast_err[256]; @@ -93,21 +94,21 @@ static fzl_nodetype_t math_op_to_type(fzl_toktype_t type) { switch (type) { - case FZL_TOKTYPE_PLUS: - return FZL_NODETYPE_ADD; - case FZL_TOKTYPE_MINUS: - return FZL_NODETYPE_SUB; - case FZL_TOKTYPE_STAR: - return FZL_NODETYPE_MUL; - case FZL_TOKTYPE_SLASH: - return FZL_NODETYPE_DIV; - case FZL_TOKTYPE_CARET: - return FZL_NODETYPE_POW; - case FZL_TOKTYPE_PERCENT: - return FZL_NODETYPE_MOD; + case FZL_TOKTYPE_PLUS: + return FZL_NODETYPE_ADD; + case FZL_TOKTYPE_MINUS: + return FZL_NODETYPE_SUB; + case FZL_TOKTYPE_STAR: + return FZL_NODETYPE_MUL; + case FZL_TOKTYPE_SLASH: + return FZL_NODETYPE_DIV; + case FZL_TOKTYPE_CARET: + return FZL_NODETYPE_POW; + case FZL_TOKTYPE_PERCENT: + return FZL_NODETYPE_MOD; - default: - return 0; + default: + return 0; } } @@ -115,13 +116,13 @@ static fzl_nodetype_t unary_op_to_type(fzl_toktype_t type) { switch (type) { - case FZL_TOKTYPE_PLUS: - return FZL_NODETYPE_UNARY_PLUS; - case FZL_TOKTYPE_MINUS: - return FZL_NODETYPE_UNARY_MINUS; + case FZL_TOKTYPE_PLUS: + return FZL_NODETYPE_UNARY_PLUS; + case FZL_TOKTYPE_MINUS: + return FZL_NODETYPE_UNARY_MINUS; - default: - return 0; + default: + return 0; } } @@ -380,6 +381,49 @@ fzl_node_t *parse_expression(fzl_parser_t *parser) // Statement parsing fzl_node_t *parse_statement(fzl_parser_t *parser) { + if (is(parser, FZL_TOKTYPE_TYPE) || is(parser, FZL_TOKTYPE_NAME)) + { + fzl_token_t *type = peek(parser); + if (type->type == FZL_TOKTYPE_TYPE) + consume(parser); + + if (type->type == FZL_TOKTYPE_TYPE || next(parser)->type == FZL_TOKTYPE_EQ) + { + + fzl_node_t *identifier = parse_primary(parser); + if (!identifier || identifier->type != FZL_NODETYPE_IDENTIFIER) + { + snprintf(plast_err, sizeof(plast_err), "expected identifier at %ld:%ld", + type->ln, type->cn); + return NULL; + } + + fzl_node_t *left = fzl_mknode(FZL_NODETYPE_DECLARATION, type); + left->var.type = type; + left->var.identifier = identifier; + + if (!is(parser, FZL_TOKTYPE_EQ)) + return left; + + fzl_node_t *right; + while (is(parser, FZL_TOKTYPE_EQ)) + { + fzl_token_t *asn = consume(parser); + right = parse_expression(parser); + if (!right) + return NULL; + + fzl_node_t *node = fzl_mknode(FZL_NODETYPE_ASSIGN, asn); + node->binary_op.left = left; + node->binary_op.right = right; + + left = node; + } + + return left; + } + } + return parse_expression(parser); } diff --git a/src/compiler/fzl_reader.c b/src/compiler/fzl_reader.c index c7e4889..9c28c97 100644 --- a/src/compiler/fzl_reader.c +++ b/src/compiler/fzl_reader.c @@ -59,16 +59,30 @@ fzl_token_t *parse_name(fzl_reader_t *reader) lpos++; size++; } while ((reader->source[lpos] >= 'A' && reader->source[lpos] <= 'Z') || - (reader->source[lpos] >= 'a' && reader->source[lpos] <= 'z')); + (reader->source[lpos] >= 'a' && reader->source[lpos] <= 'z') || + (reader->source[lpos] >= '0' && reader->source[lpos] <= '9') || + (reader->source[lpos] == '_')); - char *value = malloc(size); + char *value = malloc(size + 1); memcpy(value, reader->source + reader->position, size); + value[size] = '\0'; size_t start = reader->position; move(reader, size); - fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_NAME, reader->line_n, - start - reader->line_start, value, size); + fzl_token_t *tok; + size_t line = reader->line_n; + size_t pos = start - reader->line_start; + + if (strcmp(value, "str") == 0 || strcmp(value, "char") == 0 || + strcmp(value, "uint") == 0 || strcmp(value, "int") == 0 || + strcmp(value, "i8") == 0 || strcmp(value, "i16") == 0 || + strcmp(value, "i32") == 0 || strcmp(value, "i64") == 0 || + strcmp(value, "u8") == 0 || strcmp(value, "u16") == 0 || + strcmp(value, "u32") == 0 || strcmp(value, "u64") == 0) + tok = fzl_mktoken(FZL_TOKTYPE_TYPE, line, pos, value, size); + else + tok = fzl_mktoken(FZL_TOKTYPE_NAME, line, pos, value, size); free(value); return tok; @@ -198,7 +212,10 @@ int fzl_read(fzl_reader_t *reader) token = add_single(reader, FZL_TOKTYPE_CARET); else if (curr == '%') token = add_single(reader, FZL_TOKTYPE_PERCENT); - else if (curr >= 'A' && curr <= 'Z' || curr >= 'a' && curr <= 'z') + else if (curr == '=') + token = add_single(reader, FZL_TOKTYPE_EQ); + else if (curr >= 'A' && curr <= 'Z' || curr >= 'a' && curr <= 'z' || + curr == '_') token = parse_name(reader); else if (curr >= '0' && curr <= '9') token = parse_number(reader); diff --git a/src/compiler/fzl_walker.c b/src/compiler/fzl_walker.c index 2ba4717..fb79258 100644 --- a/src/compiler/fzl_walker.c +++ b/src/compiler/fzl_walker.c @@ -1,6 +1,6 @@ -#include "common/fzl_types.h" #include #include +#include #include #include #include @@ -94,15 +94,28 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node) if (!walker || !node) return (fzl_walk_res_t){.error = true, .error_msg = "walker is null"}; + push_op(walker, FZL_OPCODE_MK_ENVTABLE); + fzl_walk_res_t current_res; while (node != NULL) { switch (node->type) { case FZL_NODETYPE_UNARY_PLUS: - case FZL_NODETYPE_IDENTIFIER: break; + case FZL_NODETYPE_IDENTIFIER: + { + size_t n = add_const( + walker, (fzl_const_t){.type = FZL_CONSTTYPE_STRING, + .as.string.chars = node->token->value, + .as.string.length = node->token->value_sz}); + + push_op(walker, FZL_OPCODE_LOADCONST); + push_word(walker, n); + current_res = (fzl_walk_res_t){.type = FZL_TYPE_STRING, .error = false}; + } + case FZL_NODETYPE_BLOCK: if (node->list.entry_count > 0) for (size_t i = 0; i < node->list.entry_count; i++) @@ -248,6 +261,35 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node) push_op(walker, FZL_OPCODE_NEG); current_res = (fzl_walk_res_t){.type = res.type, .error = false}; } + + case FZL_NODETYPE_DECLARATION: + { + fzl_walk_res_t rres = walk(walker, node->var.identifier); + if (rres.error) + return rres; + + push_op(walker, FZL_OPCODE_STORE); + + // NOTE: ignoring type field for now + + current_res = (fzl_walk_res_t){.type = FZL_TYPE_NULL, .error = false}; + } + + case FZL_NODETYPE_ASSIGN: + { + fzl_walk_res_t lres = walk(walker, node->binary_op.left); + if (lres.error) + return lres; + + push_op(walker, FZL_OPCODE_LOOKUP_ENV); + + fzl_walk_res_t rres = walk(walker, node->binary_op.right); + if (rres.error) + return rres; + + push_op(walker, FZL_OPCODE_WRITE); + current_res = (fzl_walk_res_t){.type = rres.type, .error = false}; + } } node = node->next;