diff --git a/src/compiler/fzl_parser.c b/src/compiler/fzl_parser.c index 5ce31bc..9bf96c5 100644 --- a/src/compiler/fzl_parser.c +++ b/src/compiler/fzl_parser.c @@ -9,6 +9,16 @@ char plast_err[256]; fzl_token_t *last_known_tok = NULL; +fzl_token_t null_tok = { + .type = FZL_TOKTYPE_TYPE, + .filename = "", + .ln = 0, + .cn = 0, + .store_value = true, + .value = "null", + .value_sz = 4, +}; + fzl_parser_t *fzl_mkparser(fzl_reader_ll_t *first) { if (!first) @@ -35,6 +45,7 @@ fzl_parser_t *fzl_mkparser(fzl_reader_ll_t *first) fzl_node_t *fzl_mknode(fzl_nodetype_t type, fzl_token_t *token) { fzl_node_t *node = malloc(sizeof(fzl_node_t)); + memset(node, 0, sizeof(fzl_node_t)); if (!node) return NULL; @@ -226,7 +237,7 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser) if (args_capacity <= args_count) { args_capacity *= 2; - args = realloc(args, args_capacity * sizeof(fzl_node_t)); + args = realloc(args, args_capacity * sizeof(fzl_node_t *)); } args[args_count] = arg; @@ -700,9 +711,19 @@ fzl_node_t *parse_class(fzl_parser_t *parser) } } - fzl_node_t **new_args = realloc(node->fn.args, ++node->fn.args_count); - memcpy(&new_args[1], new_args, - (node->fn.args_count - 1) * sizeof(fzl_node_t *)); + fzl_node_t **new_args = realloc(node->fn.args, (++node->fn.args_count) * + sizeof(fzl_node_t *)); + if (!new_args) + { + snprintf(plast_err, sizeof(plast_err), + "failed to reallocate method args list"); + free(fields); + return NULL; + } + + if (node->fn.args_count > 1) + memmove(&new_args[1], new_args, + (node->fn.args_count - 1) * sizeof(fzl_node_t *)); fzl_token_t *this_tok = fzl_mktoken(FZL_TOKTYPE_NAME, node->fn.name->ln, node->fn.name->cn, @@ -713,6 +734,7 @@ fzl_node_t *parse_class(fzl_parser_t *parser) this_dec->var.identifier = this_id; new_args[0] = this_dec; + node->fn.args = new_args; methods[mcount++] = node; } else @@ -814,8 +836,7 @@ fzl_node_t *parse_function(fzl_parser_t *parser) type = consume(parser); if (!type) - type = fzl_mktoken(FZL_TOKTYPE_TYPE, last_known_tok->ln, last_known_tok->cn, - "null", 4, last_known_tok->filename); + type = &null_tok; if (!is(parser, FZL_TOKTYPE_LBRACE)) { @@ -1051,80 +1072,105 @@ void fzl_freeast(fzl_node_t *root) while (root) { - if (root->type == FZL_NODETYPE_BLOCK) + switch (root->type) { - if (root->list.entries) - { - for (size_t i = 0; i < root->list.entry_count; i++) - if (root->list.entries[i]) - fzl_freeast(root->list.entries[i]); + case FZL_NODETYPE_IDENTIFIER: + case FZL_NODETYPE_LITERAL: + break; - free(root->list.entries); - } - } - else if (root->type == FZL_NODETYPE_CALL) - { - if (root->call.args_count) - { - for (size_t i = 0; i < root->call.args_count; i++) - if (root->call.args[i]) - fzl_freeast(root->call.args[i]); + case FZL_NODETYPE_BLOCK: + if (root->list.entries) + { + for (size_t i = 0; i < root->list.entry_count; i++) + if (root->list.entries[i]) + fzl_freeast(root->list.entries[i]); - free(root->call.args); - } - } - else if (root->type == FZL_NODETYPE_ADD || root->type == FZL_NODETYPE_SUB || - root->type == FZL_NODETYPE_MUL || root->type == FZL_NODETYPE_DIV || - root->type == FZL_NODETYPE_POW || root->type == FZL_NODETYPE_MOD) - { - if (root->binary_op.left) - fzl_freeast(root->binary_op.left); - if (root->binary_op.right) - fzl_freeast(root->binary_op.right); - } - else if (root->type == FZL_NODETYPE_UNARY_PLUS || - root->type == FZL_NODETYPE_UNARY_MINUS) - { - if (root->unary_op.operand) - fzl_freeast(root->unary_op.operand); - } - else if (root->type == FZL_NODETYPE_FUNCTION) - { - if (root->fn.args_count) - for (size_t i = 0; i < root->fn.args_count; i++) - fzl_freenode(root->fn.args[i]); - free(root->fn.args); - fzl_freenode(root->fn.body); - } - else if (root->type == FZL_NODETYPE_RETURN) - { - if (root->ret.value) - fzl_freenode(root->ret.value); - } - else if (root->type == FZL_NODETYPE_CLASS) - { - if (root->class.fields_count) - for (size_t i = 0; i < root->class.fields_count; i++) - fzl_freenode(root->class.fields[i]); - free(root->class.fields); + free(root->list.entries); + } + break; - if (root->class.methods_count) - for (size_t i = 0; i < root->class.methods_count; i++) - fzl_freenode(root->class.methods[i]); - free(root->class.methods); - } - else if (root->type == FZL_NODETYPE_CONSTRUCT) - { - fzl_freenode(root->construct.name); - } - else if (root->type == FZL_NODETYPE_FIELD) - { - fzl_freenode(root->memb.field); - fzl_freenode(root->memb.parent); + case FZL_NODETYPE_CALL: + if (root->call.args_count) + { + for (size_t i = 0; i < root->call.args_count; i++) + if (root->call.args[i]) + fzl_freeast(root->call.args[i]); + + free(root->call.args); + } + 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: + case FZL_NODETYPE_CONDITIONAL: + case FZL_NODETYPE_OR: + case FZL_NODETYPE_AND: + case FZL_NODETYPE_EQUAL: + case FZL_NODETYPE_NEQUAL: + case FZL_NODETYPE_LESS: + case FZL_NODETYPE_LESS_EQUAL: + case FZL_NODETYPE_GREATER: + case FZL_NODETYPE_GREATER_EQUAL: + case FZL_NODETYPE_ASSIGN: + if (root->binary_op.left) + fzl_freeast(root->binary_op.left); + if (root->binary_op.right) + fzl_freeast(root->binary_op.right); + break; + + case FZL_NODETYPE_UNARY_PLUS: + case FZL_NODETYPE_UNARY_MINUS: + case FZL_NODETYPE_NOT: + if (root->unary_op.operand) + fzl_freeast(root->unary_op.operand); + break; + + case FZL_NODETYPE_FUNCTION: + if (root->fn.args_count) + for (size_t i = 0; i < root->fn.args_count; i++) + fzl_freeast(root->fn.args[i]); + free(root->fn.args); + fzl_freeast(root->fn.body); + break; + + case FZL_NODETYPE_RETURN: + if (root->ret.value) + fzl_freeast(root->ret.value); + break; + + case FZL_NODETYPE_CLASS: + if (root->class.fields_count) + for (size_t i = 0; i < root->class.fields_count; i++) + fzl_freeast(root->class.fields[i]); + free(root->class.fields); + + if (root->class.methods_count) + for (size_t i = 0; i < root->class.methods_count; i++) + fzl_freeast(root->class.methods[i]); + free(root->class.methods); + break; + + case FZL_NODETYPE_CONSTRUCT: + fzl_freeast(root->construct.name); + break; + + case FZL_NODETYPE_FIELD: + fzl_freeast(root->memb.field); + fzl_freeast(root->memb.parent); + break; + + case FZL_NODETYPE_DECLARATION: + if (root->var.identifier) + fzl_freeast(root->var.identifier); + break; } fzl_node_t *next = root->next; - free(root); + fzl_freenode(root); root = next; } } diff --git a/src/compiler/fzl_reader.c b/src/compiler/fzl_reader.c index 9f5cc70..540d29c 100644 --- a/src/compiler/fzl_reader.c +++ b/src/compiler/fzl_reader.c @@ -204,31 +204,31 @@ fzl_token_t *parse_number(fzl_reader_t *reader) // Add single-char token fzl_token_t *add_single(fzl_reader_t *reader, fzl_toktype_t type) { - size_t p = move(reader, 1); fzl_file_loc l; - bool ok = fzl_linked_getpos(reader->linked, p, &l); + bool ok = fzl_linked_getpos(reader->linked, reader->position, &l); if (!ok) { snprintf(last_err, sizeof(last_err), "failed to locate line:col"); return NULL; } - return fzl_mktoken(type, l.line, l.col, NULL, 0, l.filename); + move(reader, 1); + return fzl_mktoken(type, l.line, l.col, "", 0, l.filename); } // Add double-char token fzl_token_t *add_double(fzl_reader_t *reader, fzl_toktype_t type) { - size_t p = move(reader, 2); fzl_file_loc l; - bool ok = fzl_linked_getpos(reader->linked, p, &l); + bool ok = fzl_linked_getpos(reader->linked, reader->position, &l); if (!ok) { snprintf(last_err, sizeof(last_err), "failed to locate line:col"); return NULL; } - return fzl_mktoken(type, l.line, l.col, NULL, 0, l.filename); + move(reader, 2); + return fzl_mktoken(type, l.line, l.col, "", 0, l.filename); } // Skip symbols until '\n' or EOF @@ -353,6 +353,7 @@ int fzl_read(fzl_reader_t *reader) } fzl_reader_ll_t *tok_node = malloc(sizeof(fzl_reader_ll_t)); + tok_node->next = NULL; tok_node->token = token; reader->last->next = tok_node; diff --git a/src/compiler/fzl_token.c b/src/compiler/fzl_token.c index 8ba49a7..dc62955 100644 --- a/src/compiler/fzl_token.c +++ b/src/compiler/fzl_token.c @@ -6,15 +6,20 @@ fzl_token_t *fzl_mktoken(const fzl_toktype_t type, size_t line, size_t col, void *value, size_t value_len, char *filename) { - char *valholder = malloc(value_len + 1); - memcpy(valholder, value, value_len); - valholder[value_len] = '\0'; + char *valholder = NULL; + + if (value && value_len > 0) + { + valholder = malloc(value_len + 1); + memcpy(valholder, value, value_len); + valholder[value_len] = '\0'; + } fzl_token_t *token = malloc(sizeof(fzl_token_t)); token->type = type; token->ln = line; token->cn = col; - token->store_value = value_len > 0; + token->store_value = (valholder != NULL); token->value = valholder; token->value_sz = value_len; token->filename = filename; diff --git a/src/compiler/fzl_walker.c b/src/compiler/fzl_walker.c index 0875399..d4442f9 100644 --- a/src/compiler/fzl_walker.c +++ b/src/compiler/fzl_walker.c @@ -246,6 +246,9 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node) strcpy((method_name + classname_len + 1), fn->fn.name->value); method_name[classname_len + fnname_len + 1] = 0; + if (fn->fn.name->value) + free(fn->fn.name->value); + fn->fn.name->value = method_name; fzl_walk_res_t fnres = walk(walker, fn); if (fnres.error) diff --git a/src/compiler/utils/fzl_linked.c b/src/compiler/utils/fzl_linked.c index feb2887..409455b 100644 --- a/src/compiler/utils/fzl_linked.c +++ b/src/compiler/utils/fzl_linked.c @@ -86,6 +86,7 @@ bool fzl_linked_add_files(fzl_linked_t *l, char **files, size_t files_count) } strcpy(l->source + current_start, source); + free(source); current_start += file_sz; } diff --git a/src/vm/fzl_vm.c b/src/vm/fzl_vm.c index 4dcce34..9cc73c3 100644 --- a/src/vm/fzl_vm.c +++ b/src/vm/fzl_vm.c @@ -42,6 +42,7 @@ fzl_vm_t *fzl_mkvm(const char *filepath) if (!fd) { snprintf(last_err, sizeof(last_err), "failed to open file '%s'", filepath); + free(vm); return NULL; } @@ -50,6 +51,8 @@ fzl_vm_t *fzl_mkvm(const char *filepath) if (memcmp(hdr, expect_hdr, 5) != 0) { snprintf(last_err, sizeof(last_err), "magic check error"); + fclose(fd); + free(vm); return NULL; } @@ -60,6 +63,8 @@ fzl_vm_t *fzl_mkvm(const char *filepath) if (ops_count < 1) { snprintf(last_err, sizeof(last_err), "there is nothing to do (0 ops)"); + fclose(fd); + free(vm); return NULL; } @@ -89,6 +94,9 @@ fzl_vm_t *fzl_mkvm(const char *filepath) } else { + fclose(fd); + free(vm->consts); + free(vm); snprintf(last_err, sizeof(last_err), "unknown const type at index %ld", i); return NULL; @@ -104,6 +112,7 @@ fzl_vm_t *fzl_mkvm(const char *filepath) fread(&op, sizeof(uint64_t), 1, fd); vm->ops[i] = op; } + fclose(fd); return vm; } @@ -732,6 +741,14 @@ int fzl_vm_run(fzl_vm_t *vm) } } + if (wrlvl <= -1) + { + snprintf(last_err, sizeof(last_err), + "runtime error - name '%s' not found in this scope", wrname); + print_err_data(vm); + return -1; + } + fzl_vm_env_wresult_t wresult = fzl_env_writevalue(vm->estack[wrlvl], (char *)wrname, value); if (wresult != FZL_VM_ENV_WRESULT_OK) @@ -825,7 +842,7 @@ int fzl_vm_run(fzl_vm_t *vm) else if (fn_id == FZL_BUILTIN_EXIT) { fzl_value_t arg = vm->dstack[--vm->dtop]; - exit(arg.as.i); + return arg.as.i; } else { diff --git a/src/vm/main.c b/src/vm/main.c index cb357c0..7551e1c 100644 --- a/src/vm/main.c +++ b/src/vm/main.c @@ -49,6 +49,7 @@ run_args_t *parse_args(int argc, char **argv) { printf("Error: unknown flag '%s'.\n", argv[i]); printf("Use 'fz --help' to read the usage\n"); + free(args); return NULL; } } @@ -57,6 +58,7 @@ run_args_t *parse_args(int argc, char **argv) { printf("Error: last argument MUST be a file path\n"); printf("Use 'fz --help' for help\n"); + free(args); return NULL; } @@ -73,6 +75,7 @@ int main(int argc, char **argv) else if (args->help) { print_hint(); + free(args); return 0; } @@ -80,6 +83,7 @@ int main(int argc, char **argv) if (!vm) { printf("Error: %s\n", fzl_vm_geterror()); + free(args); return -1; } @@ -90,7 +94,12 @@ int main(int argc, char **argv) int result = fzl_vm_run(vm); if (result != 0) { - printf("Error: %s\n", fzl_vm_geterror()); + char *err = fzl_vm_geterror(); + if (err && err[0]) + printf("Error: %s\n", err); + + free(args); + fzl_freevm(vm); return -1; } }