From 683dd08181b3a00376e59b73134efe7b0ac97e59 Mon Sep 17 00:00:00 2001 From: samsonium Date: Thu, 15 Oct 2026 21:41:45 +0300 Subject: [PATCH] wip: working on classes --- CMakeLists.txt | 8 + exl/class.fzs | 32 ++ include/compiler/fzl_parser.h | 22 +- include/compiler/fzl_token.h | 6 +- src/compiler/fzl_parser.c | 726 +++++++++++++++++++++------------- src/compiler/fzl_reader.c | 14 +- 6 files changed, 532 insertions(+), 276 deletions(-) create mode 100644 exl/class.fzs diff --git a/CMakeLists.txt b/CMakeLists.txt index c6692f4..9bee88a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,10 @@ add_test( NAME compile_comment COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/comment.fzs" ) +add_test( + NAME compile_class + COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/class.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/class.fzs" +) set_tests_properties(compile_problematic_hw PROPERTIES WILL_FAIL TRUE) @@ -100,4 +104,8 @@ add_test( NAME runtime_comment COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb" ) +add_test( + NAME runtime_class + COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/class.fzb" +) diff --git a/exl/class.fzs b/exl/class.fzs new file mode 100644 index 0000000..84c7787 --- /dev/null +++ b/exl/class.fzs @@ -0,0 +1,32 @@ +class Point +{ + int x; + int y; + + // Move point by [dx,dy] + fn move(int dx, int dy) { + this.x = this.x + dx; + this.y = this.y + dy; + } +} + +// NOTE: WHY THE FUCK THIS FUCKING COMPILER REQUIRES ';' AFTER '='?! +// | +// v +Point obj = new Point; +obj.x = 1; +obj.y = 2; + +printline("Current X,Y:"); +printline(obj.x); +printline(obj.y); + +obj.move(9, 8); +printline("X,Y after move:"); +printline(obj.x); +printline(obj.y); + +if (obj.x == 10 && obj.y == 10) + printline("Test passed"); +else printline("Test failed"); + diff --git a/include/compiler/fzl_parser.h b/include/compiler/fzl_parser.h index 363d8c0..3be82e5 100644 --- a/include/compiler/fzl_parser.h +++ b/include/compiler/fzl_parser.h @@ -1,7 +1,6 @@ #ifndef FZL_PARSER_H #define FZL_PARSER_H -#include "common/fzl_types.h" #include #include #include @@ -16,6 +15,8 @@ typedef enum FZL_NODETYPE_CONDITIONAL, FZL_NODETYPE_FUNCTION, FZL_NODETYPE_RETURN, + FZL_NODETYPE_CLASS, + FZL_NODETYPE_FIELD, FZL_NODETYPE_ADD, FZL_NODETYPE_SUB, @@ -113,6 +114,25 @@ typedef struct fzl_node { struct fzl_node *value; } ret; + + // Class declaration + struct + { + fzl_token_t *name; + + struct fzl_node **fields; + size_t fields_count; + + struct fzl_node **methods; + size_t methods_count; + } class; + + // Member access + struct + { + struct fzl_node *parent; + struct fzl_node *field; + } memb; }; } fzl_node_t; diff --git a/include/compiler/fzl_token.h b/include/compiler/fzl_token.h index bb9a5de..30b5f81 100644 --- a/include/compiler/fzl_token.h +++ b/include/compiler/fzl_token.h @@ -8,7 +8,11 @@ // Token type typedef enum { - FZL_TOKTYPE_RETURN, // return + FZL_TOKTYPE_CLASS, // class + FZL_TOKTYPE_NEW, // new + + FZL_TOKTYPE_FUNCTION, // fn + FZL_TOKTYPE_RETURN, // return FZL_TOKTYPE_IF, // if FZL_TOKTYPE_ELSE, // else diff --git a/src/compiler/fzl_parser.c b/src/compiler/fzl_parser.c index 0bb7dae..ccf99f9 100644 --- a/src/compiler/fzl_parser.c +++ b/src/compiler/fzl_parser.c @@ -170,7 +170,14 @@ fzl_node_t *parse_primary(fzl_parser_t *parser) else if (is(parser, FZL_TOKTYPE_NAME)) { fzl_token_t *name = consume(parser); - return fzl_mknode(FZL_NODETYPE_IDENTIFIER, name); + if (!is(parser, FZL_TOKTYPE_NAME)) + return fzl_mknode(FZL_NODETYPE_IDENTIFIER, name); + + fzl_token_t *realname = consume(parser); // :D + fzl_node_t *decl = fzl_mknode(FZL_NODETYPE_DECLARATION, name); + decl->var.type = name; + decl->var.identifier = fzl_mknode(FZL_NODETYPE_IDENTIFIER, realname); + return decl; } else if (is(parser, FZL_TOKTYPE_TYPE)) { @@ -215,52 +222,72 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser) return NULL; } - while (is(parser, FZL_TOKTYPE_LPAREN)) + if (is(parser, FZL_TOKTYPE_LPAREN)) { - consume(parser); - - size_t args_capacity = 2; - size_t args_count = 0; - fzl_node_t **args = malloc(args_capacity * sizeof(fzl_node_t *)); - - while (!is(parser, FZL_TOKTYPE_RPAREN)) + while (is(parser, FZL_TOKTYPE_LPAREN)) { - fzl_node_t *arg = parse_expression(parser); - if (!arg) + consume(parser); + + size_t args_capacity = 2; + size_t args_count = 0; + fzl_node_t **args = malloc(args_capacity * sizeof(fzl_node_t *)); + + while (!is(parser, FZL_TOKTYPE_RPAREN)) + { + fzl_node_t *arg = parse_expression(parser); + if (!arg) + { + free(args); + return NULL; + } + + if (args_capacity <= args_count) + { + args_capacity *= 2; + args = realloc(args, args_capacity * sizeof(fzl_node_t)); + } + + args[args_count] = arg; + args_count++; + + if (is(parser, FZL_TOKTYPE_COMMA)) + consume(parser); + } + + fzl_token_t *rparen = consume(parser); + if (!rparen || rparen->type != FZL_TOKTYPE_RPAREN) { free(args); + snprintf(plast_err, sizeof(plast_err), + "'%s': expected ')' after argument list at %ld:%ld", + peek(parser)->filename, peek(parser)->ln, peek(parser)->cn); return NULL; } - if (args_capacity <= args_count) - { - args_capacity *= 2; - args = realloc(args, args_capacity * sizeof(fzl_node_t)); - } + fzl_node_t *node = fzl_mknode(FZL_NODETYPE_CALL, left->token); + node->call.callee = left; + node->call.args = args; + node->call.args_count = args_count; - args[args_count] = arg; - args_count++; - - if (is(parser, FZL_TOKTYPE_COMMA)) - consume(parser); + left = node; } - - fzl_token_t *rparen = consume(parser); - if (!rparen || rparen->type != FZL_TOKTYPE_RPAREN) + } + else if (is(parser, FZL_TOKTYPE_DOT)) + { + while (is(parser, FZL_TOKTYPE_DOT)) { - free(args); - snprintf(plast_err, sizeof(plast_err), - "'%s': expected ')' after argument list at %ld:%ld", - peek(parser)->filename, peek(parser)->ln, peek(parser)->cn); - return NULL; + consume(parser); + + fzl_node_t *right = parse_primary(parser); + if (!right) + return NULL; + + fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FIELD, right->token); + node->memb.parent = left; + node->memb.field = right; + + left = node; } - - fzl_node_t *node = fzl_mknode(FZL_NODETYPE_CALL, left->token); - node->call.callee = left; - node->call.args = args; - node->call.args_count = args_count; - - left = node; } return left; @@ -540,257 +567,395 @@ fzl_node_t *parse_or(fzl_parser_t *parser) return left; } +// Assignments parsing +fzl_node_t *parse_assignment(fzl_parser_t *parser) +{ + fzl_node_t *left = parse_or(parser); + if (!left) + return NULL; + + if (is(parser, FZL_TOKTYPE_EQ)) + { + fzl_token_t *asn = consume(parser); + if (left->type != FZL_NODETYPE_IDENTIFIER && + left->type != FZL_NODETYPE_DECLARATION && + left->type != FZL_NODETYPE_FIELD) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': cannot assign to '%s' at %ld:%ld", left->token->filename, + (char *)left->token->value, asn->ln, asn->cn); + return NULL; + } + + fzl_node_t *right = parse_assignment(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; +} + // Expression parsing -fzl_node_t *parse_expression(fzl_parser_t *parser) { return parse_and(parser); } +fzl_node_t *parse_expression(fzl_parser_t *parser) +{ + return parse_assignment(parser); +} + +fzl_node_t *parse_statement(fzl_parser_t *parser); + +// Parse class definition +fzl_node_t *parse_class(fzl_parser_t *parser) +{ + if (!parser) + return NULL; + + fzl_token_t *class = consume(parser); + fzl_token_t *name = consume(parser); + if (name->type != FZL_TOKTYPE_NAME) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected class name at %ld:%ld", name->filename, name->ln, + name->cn); + return NULL; + } + + fzl_token_t *lbrace = consume(parser); + if (lbrace->type != FZL_TOKTYPE_LBRACE) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected '{' after class name at %ld:%ld", lbrace->filename, + lbrace->ln, lbrace->cn); + return NULL; + } + + size_t fremainder = 2; + size_t fcount = 0; + fzl_node_t **fields = malloc(fremainder * sizeof(fzl_node_t *)); + if (!fields) + { + snprintf(plast_err, sizeof(plast_err), + "failed to allocate space for class fields"); + return NULL; + } + + size_t mremainder = 2; + size_t mcount = 0; + fzl_node_t **methods = malloc(mremainder * sizeof(fzl_node_t *)); + if (!methods) + { + snprintf(plast_err, sizeof(plast_err), + "failed to allocate space for class fields"); + free(fields); + return NULL; + } + + while (!is(parser, FZL_TOKTYPE_RBRACE)) + { + fzl_node_t *node = parse_statement(parser); + if (!node) + return NULL; + + if (node->type == FZL_NODETYPE_DECLARATION) + { + if (fremainder <= fcount) + { + fremainder *= 2; + fields = realloc(fields, fremainder * sizeof(fzl_node_t *)); + if (!fields) + { + snprintf(plast_err, sizeof(plast_err), + "failed to resize fields array"); + free(methods); + return NULL; + } + } + + fields[fcount++] = node; + } + else if (node->type == FZL_NODETYPE_FUNCTION) + { + if (mremainder <= mcount) + { + mremainder *= 2; + methods = realloc(methods, mremainder * sizeof(fzl_node_t *)); + if (!methods) + { + snprintf(plast_err, sizeof(plast_err), + "failed to resize methods array"); + free(fields); + return NULL; + } + } + + 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_token_t *this_tok = + fzl_mktoken(FZL_TOKTYPE_NAME, node->fn.name->ln, node->fn.name->cn, + "this", 4, node->fn.name->filename); + fzl_node_t *this_id = fzl_mknode(FZL_NODETYPE_IDENTIFIER, this_tok); + fzl_node_t *this_dec = fzl_mknode(FZL_NODETYPE_DECLARATION, name); + this_dec->var.type = name; + this_dec->var.identifier = this_id; + + new_args[0] = this_dec; + methods[mcount++] = node; + } + else + { + snprintf(plast_err, sizeof(plast_err), + "'%s': unknown type of class member at %ld:%ld", + node->token->filename, node->token->ln, node->token->cn); + free(fields); + free(methods); + return NULL; + } + } + fzl_token_t *rbra = consume(parser); + if (rbra->type != FZL_TOKTYPE_RBRACE) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected '}' after class definition at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); + free(fields); + free(methods); + return NULL; + } + + fzl_node_t *node = fzl_mknode(FZL_NODETYPE_CLASS, class); + node->class.name = name; + node->class.fields = fields; + node->class.fields_count = fcount; + node->class.methods = methods; + node->class.methods_count = mcount; + + return node; +} + +// Functions parsing +fzl_node_t *parse_function(fzl_parser_t *parser) +{ + if (!parser) + return NULL; + + fzl_token_t *fn = consume(parser); + fzl_token_t *name = consume(parser); + if (!name || name->type != FZL_TOKTYPE_NAME) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected function name at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); + return NULL; + } + + fzl_token_t *lpar = consume(parser); + if (!lpar || lpar->type != FZL_TOKTYPE_LPAREN) + { + snprintf(plast_err, sizeof(plast_err), "'%s': expected '(' at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); + return NULL; + } + + size_t remainder = 1; + size_t count = 0; + fzl_node_t **args = malloc(remainder * sizeof(fzl_node_t *)); + + while (peek(parser) && !is(parser, FZL_TOKTYPE_RPAREN)) + { + fzl_node_t *arg = parse_expression(parser); + if (!arg) + return NULL; + + if (remainder <= count) + { + remainder *= 2; + args = realloc(args, remainder * sizeof(fzl_node_t *)); + } + + args[count++] = arg; + + if (is(parser, FZL_TOKTYPE_COMMA)) + consume(parser); + } + + fzl_token_t *rpar = consume(parser); + if (!rpar || rpar->type != FZL_TOKTYPE_RPAREN) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected ')' after argument list at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); + return NULL; + } + + fzl_token_t *type; + if (is(parser, FZL_TOKTYPE_TYPE) || is(parser, FZL_TOKTYPE_NAME)) + 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); + + if (!is(parser, FZL_TOKTYPE_LBRACE)) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected '{' after function declaration at %ld:%ld", + last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); + return NULL; + } + + fzl_node_t *body = parse_statement(parser); + if (!body) + return NULL; + + fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FUNCTION, name); + node->fn.args = args; + node->fn.args_count = count; + node->fn.body = body; + node->fn.name = name; + node->fn.type = type; + + return node; +} + +// Return parsing +fzl_node_t *parse_return(fzl_parser_t *parser) +{ + if (!parser) + return NULL; + + fzl_token_t *ret = consume(parser); + fzl_node_t *node = fzl_mknode(FZL_NODETYPE_RETURN, ret); + + if (!is(parser, FZL_TOKTYPE_SEMICOLON)) + { + fzl_node_t *retval = parse_expression(parser); + if (!retval) + return NULL; + + node->ret.value = retval; + } + + return node; +} + +fzl_node_t *parse_if(fzl_parser_t *parser) +{ + if (!parser) + return NULL; + + fzl_token_t *if_tok = consume(parser); + fzl_token_t *lparen = consume(parser); + if (lparen->type != FZL_TOKTYPE_LPAREN) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected '(' before condition at %ld:%ld", lparen->filename, + lparen->ln, lparen->cn); + return NULL; + } + + fzl_node_t *condition = parse_expression(parser); + if (!condition) + return NULL; + + fzl_token_t *rparen = consume(parser); + if (rparen->type != FZL_TOKTYPE_RPAREN) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': expected ')' after condition at %ld:%ld", rparen->filename, + rparen->ln, rparen->cn); + return NULL; + } + + fzl_node_t *else_block = NULL; + fzl_node_t *true_block = parse_statement(parser); + if (!true_block) + return NULL; + + if (is(parser, FZL_TOKTYPE_ELSE)) + { + consume(parser); // else + else_block = parse_statement(parser); + if (!else_block) + return NULL; + } + + fzl_node_t *stmt_node = fzl_mknode(FZL_NODETYPE_CONDITIONAL, if_tok); + stmt_node->cond.condition = condition; + stmt_node->cond.true_block = true_block; + stmt_node->cond.else_block = else_block; + + return stmt_node; +} + +// Block statement parsing +fzl_node_t *parse_block(fzl_parser_t *parser) +{ + if (!parser) + return NULL; + + fzl_token_t *block_tok = consume(parser); + + size_t remainder = 2; + size_t count = 0; + fzl_node_t **stmts = malloc(remainder * sizeof(fzl_node_t *)); + + while (peek(parser) && !is(parser, FZL_TOKTYPE_RBRACE)) + { + fzl_node_t *node = parse_statement(parser); + if (!node) + return NULL; + + if (remainder <= count) + { + remainder *= 2; + stmts = realloc(stmts, remainder * sizeof(fzl_node_t *)); + } + + stmts[count++] = node; + } + fzl_token_t *rbrace = consume(parser); + if (rbrace && rbrace->type != FZL_TOKTYPE_RBRACE) + { + snprintf(plast_err, sizeof(plast_err), + "'%s': missing '}' after block at %ld:%ld", rbrace->filename, + rbrace->ln, rbrace->cn); + return NULL; + } + + fzl_node_t *node = fzl_mknode(FZL_NODETYPE_BLOCK, block_tok); + node->list.entries = stmts; + node->list.entry_count = count; + return node; +} // Statement parsing fzl_node_t *parse_statement(fzl_parser_t *parser) { fzl_node_t *res = NULL; - if (is(parser, FZL_TOKTYPE_TYPE)) - { - 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_LPAREN) - { - fzl_token_t *tok = consume(parser); - if (tok->type != FZL_TOKTYPE_NAME) - { - snprintf(plast_err, sizeof(plast_err), - "'%s': expected name in function definition at %ld:%ld", - tok->filename, tok->ln, tok->cn); - return NULL; - } - - fzl_token_t *lparen = consume(parser); - if (lparen->type != FZL_TOKTYPE_LPAREN) - { - snprintf(plast_err, sizeof(plast_err), - "'%s': expected '(' after name at %ld:%ld", lparen->filename, - lparen->ln, lparen->cn); - return NULL; - } - - size_t remainder = 1; - size_t count = 0; - fzl_node_t **args = malloc(remainder * sizeof(fzl_node_t *)); - - while (peek(parser) && !is(parser, FZL_TOKTYPE_RPAREN)) - { - fzl_node_t *arg = parse_expression(parser); - if (!arg) - return NULL; - - if (remainder <= count) - { - remainder *= 2; - args = realloc(args, remainder * sizeof(fzl_node_t *)); - } - - args[count++] = arg; - - if (is(parser, FZL_TOKTYPE_COMMA)) - consume(parser); - } - - fzl_token_t *rparen = consume(parser); - if (rparen->type != FZL_TOKTYPE_RPAREN) - { - snprintf(plast_err, sizeof(plast_err), - "'%s': expected ')' after argument list at %ld:%ld", - rparen->filename, rparen->ln, rparen->cn); - return NULL; - } - - if (!is(parser, FZL_TOKTYPE_LBRACE)) - { - fzl_token_t *tok = peek(parser); - snprintf(plast_err, sizeof(plast_err), "'%s': expected '{' at %ld:%ld", - tok->filename, tok->ln, tok->cn); - return NULL; - } - - fzl_node_t *body = parse_statement(parser); - if (!body) - return NULL; - - fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FUNCTION, tok); - node->fn.args = args; - node->fn.args_count = count; - node->fn.body = body; - node->fn.name = tok; - node->fn.type = type; - - return node; - } - else 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), - "'%s': expected identifier at %ld:%ld", type->filename, - 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)) - { - 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; - } - } - - res = left; - } - } - else if (is(parser, FZL_TOKTYPE_NAME) && next(parser)->type == FZL_TOKTYPE_EQ) - { - fzl_token_t *name = consume(parser); - fzl_node_t *left = fzl_mknode(FZL_NODETYPE_IDENTIFIER, name); - - while (is(parser, FZL_TOKTYPE_EQ)) - { - fzl_token_t *eq = consume(parser); - - fzl_node_t *right = parse_expression(parser); - if (!right) - return NULL; - - fzl_node_t *assn = fzl_mknode(FZL_NODETYPE_ASSIGN, eq); - assn->binary_op.left = left; - assn->binary_op.right = right; - - left = assn; - } - - res = left; - } + if (is(parser, FZL_TOKTYPE_CLASS)) + return parse_class(parser); + else if (is(parser, FZL_TOKTYPE_FUNCTION)) + return parse_function(parser); else if (is(parser, FZL_TOKTYPE_RETURN)) - { - fzl_token_t *ret = consume(parser); - fzl_node_t *node = fzl_mknode(FZL_NODETYPE_RETURN, ret); - - if (!is(parser, FZL_TOKTYPE_SEMICOLON)) - { - fzl_node_t *retval = parse_expression(parser); - if (!retval) - return NULL; - - node->ret.value = retval; - } - - res = node; - } + res = parse_return(parser); else if (is(parser, FZL_TOKTYPE_IF)) - { - fzl_token_t *if_tok = consume(parser); - fzl_token_t *lparen = consume(parser); - if (lparen->type != FZL_TOKTYPE_LPAREN) - { - snprintf(plast_err, sizeof(plast_err), - "'%s': expected '(' before condition at %ld:%ld", - lparen->filename, lparen->ln, lparen->cn); - return NULL; - } - - fzl_node_t *condition = parse_expression(parser); - if (!condition) - return NULL; - - fzl_token_t *rparen = consume(parser); - if (rparen->type != FZL_TOKTYPE_RPAREN) - { - snprintf(plast_err, sizeof(plast_err), - "'%s': expected ')' after condition at %ld:%ld", - rparen->filename, rparen->ln, rparen->cn); - return NULL; - } - - fzl_node_t *else_block = NULL; - fzl_node_t *true_block = parse_statement(parser); - if (!true_block) - return NULL; - - if (is(parser, FZL_TOKTYPE_ELSE)) - { - consume(parser); // else - else_block = parse_statement(parser); - if (!else_block) - return NULL; - } - - fzl_node_t *stmt_node = fzl_mknode(FZL_NODETYPE_CONDITIONAL, if_tok); - stmt_node->cond.condition = condition; - stmt_node->cond.true_block = true_block; - stmt_node->cond.else_block = else_block; - - return stmt_node; - } + return parse_if(parser); else if (is(parser, FZL_TOKTYPE_LBRACE)) - { - fzl_token_t *block_tok = consume(parser); - - size_t remainder = 2; - size_t count = 0; - fzl_node_t **stmts = malloc(remainder * sizeof(fzl_node_t *)); - - while (peek(parser) && !is(parser, FZL_TOKTYPE_RBRACE)) - { - fzl_node_t *node = parse_statement(parser); - if (!node) - return NULL; - - if (remainder <= count) - { - remainder *= 2; - stmts = realloc(stmts, remainder * sizeof(fzl_node_t *)); - } - - stmts[count++] = node; - } - fzl_token_t *rbrace = consume(parser); - if (rbrace && rbrace->type != FZL_TOKTYPE_RBRACE) - { - snprintf(plast_err, sizeof(plast_err), - "'%s': missing '}' after block at %ld:%ld", rbrace->filename, - rbrace->ln, rbrace->cn); - return NULL; - } - - fzl_node_t *node = fzl_mknode(FZL_NODETYPE_BLOCK, block_tok); - node->list.entries = stmts; - node->list.entry_count = count; - return node; - } + return parse_block(parser); if (!res) res = parse_expression(parser); if (!is(parser, FZL_TOKTYPE_SEMICOLON)) { - printf("Current token are %d\n", last_known_tok->type); snprintf(plast_err, sizeof(plast_err), "'%s': missing ';' at %ld:%ld", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; @@ -908,9 +1073,26 @@ void fzl_freeast(fzl_node_t *root) 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); + + 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); + } - fzl_freenode(root); root = root->next; + free(root); } } diff --git a/src/compiler/fzl_reader.c b/src/compiler/fzl_reader.c index 15752a1..bc4e3e5 100644 --- a/src/compiler/fzl_reader.c +++ b/src/compiler/fzl_reader.c @@ -70,7 +70,15 @@ fzl_token_t *parse_name(fzl_reader_t *reader) return NULL; } - if (strcmp(value, "return") == 0) + if (strcmp(value, "class") == 0) + tok = + fzl_mktoken(FZL_TOKTYPE_CLASS, l.line, l.col, value, size, l.filename); + else if (strcmp(value, "new") == 0) + tok = fzl_mktoken(FZL_TOKTYPE_NEW, l.line, l.col, value, size, l.filename); + else if (strcmp(value, "fn") == 0) + tok = fzl_mktoken(FZL_TOKTYPE_FUNCTION, l.line, l.col, value, size, + l.filename); + else if (strcmp(value, "return") == 0) tok = fzl_mktoken(FZL_TOKTYPE_RETURN, l.line, l.col, value, size, l.filename); else if (strcmp(value, "if") == 0) @@ -86,7 +94,7 @@ fzl_token_t *parse_name(fzl_reader_t *reader) 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) + strcmp(value, "u64") == 0 || strcmp(value, "null") == 0) tok = fzl_mktoken(FZL_TOKTYPE_TYPE, l.line, l.col, value, size, l.filename); else tok = fzl_mktoken(FZL_TOKTYPE_NAME, l.line, l.col, value, size, l.filename); @@ -286,6 +294,8 @@ int fzl_read(fzl_reader_t *reader) token = add_single(reader, FZL_TOKTYPE_RPAREN); else if (curr == ',') token = add_single(reader, FZL_TOKTYPE_COMMA); + else if (curr == '.') + token = add_single(reader, FZL_TOKTYPE_DOT); else if (curr == '*') token = add_single(reader, FZL_TOKTYPE_STAR); else if (curr == '/')