wip: working on classes

This commit is contained in:
samsonium
2026-10-15 21:41:45 +03:00
parent 69b2253c34
commit 683dd08181
6 changed files with 532 additions and 276 deletions
+8
View File
@@ -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"
)
+32
View File
@@ -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");
+21 -1
View File
@@ -1,7 +1,6 @@
#ifndef FZL_PARSER_H
#define FZL_PARSER_H
#include "common/fzl_types.h"
#include <compiler/fzl_reader.h>
#include <compiler/fzl_token.h>
#include <stddef.h>
@@ -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;
+5 -1
View File
@@ -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
+454 -272
View File
@@ -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);
}
}
+12 -2
View File
@@ -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 == '/')