feat: enhance compiler

- Add comments and test for it
- Add semicolon as required end of some expressions
- Add new arguments parser
- Add multi-file compilation
- Add colors in output
This commit is contained in:
samsonium
2026-10-15 17:20:43 +03:00
parent 1035b9193c
commit 69b2253c34
22 changed files with 739 additions and 327 deletions
+38 -32
View File
@@ -167,12 +167,14 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (putres != FZL_SYMTABLE_RESULT_OK)
{
if (putres == FZL_SYMTABLE_RESULT_EXISTS)
snprintf(wlast_err, sizeof(wlast_err),
"cannot define already declared name '%s' at %ld:%ld",
(char *)node->fn.name->value, node->token->ln,
node->token->cn);
snprintf(
wlast_err, sizeof(wlast_err),
"'%s': cannot define already declared name '%s' at %ld:%ld",
node->token->filename, (char *)node->fn.name->value,
node->token->ln, node->token->cn);
else
snprintf(wlast_err, sizeof(wlast_err), "failed to store name '%s'",
snprintf(wlast_err, sizeof(wlast_err),
"'%s': failed to store name '%s'", node->fn.name->filename,
(char *)node->fn.name->value);
return (fzl_walk_res_t){.error = true};
@@ -216,8 +218,10 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
{
if (!walker->ctx)
{
snprintf(wlast_err, sizeof(wlast_err),
"return cannot be used outside of functions");
snprintf(
wlast_err, sizeof(wlast_err),
"'%s': return cannot be used outside of functions (at %ld:%ld)",
node->token->filename, node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -230,10 +234,11 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (!is_compatible(retres.type,
tok_to_type(walker->ctx->fn->fn.type)))
{
snprintf(wlast_err, sizeof(wlast_err),
"incompatible types between return and function type at "
"%ld:%ld",
node->token->ln, node->token->cn);
snprintf(
wlast_err, sizeof(wlast_err),
"'%s': incompatible types between return and function type at "
"%ld:%ld",
node->token->filename, node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -278,8 +283,8 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (!is_compatible(left.type, right.type))
{
snprintf(wlast_err, sizeof(wlast_err),
"incompatible types at %ld:%ld", node->token->ln,
node->token->cn);
"'%s': incompatible types at %ld:%ld", node->token->filename,
node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -325,8 +330,8 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (!is_compatible(left.type, right.type))
{
snprintf(wlast_err, sizeof(wlast_err),
"incompatible types at %ld:%ld", node->token->ln,
node->token->cn);
"'%s': incompatible types at %ld:%ld", node->token->filename,
node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -400,9 +405,9 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (!exists)
{
snprintf(wlast_err, sizeof(wlast_err),
"cannot find symbol '%s' at %ld:%ld",
(char *)node->token->value, node->token->ln,
node->token->cn);
"'%s': cannot find symbol '%s' at %ld:%ld",
node->token->filename, (char *)node->token->value,
node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -446,8 +451,8 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (node->call.args_count < 1)
{
snprintf(wlast_err, sizeof(wlast_err),
"'printline' call with zero arguments at %ld:%ld",
node->token->ln, node->token->cn);
"'%s': 'printline' call with zero arguments at %ld:%ld",
node->token->filename, node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
current_res = (fzl_walk_res_t){.type = FZL_TYPE_NULL, .error = false};
@@ -534,18 +539,19 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
{
fzl_token_t *ltok = node->binary_op.left->token;
snprintf(wlast_err, sizeof(wlast_err),
"left operand at %ld:%ld is not compatible to integer types",
ltok->ln, ltok->cn);
"'%s': left operand at %ld:%ld is not compatible to integer "
"types",
ltok->filename, ltok->ln, ltok->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
if (rres.type < FZL_TYPE_INT8)
{
fzl_token_t *rtok = node->binary_op.right->token;
snprintf(
wlast_err, sizeof(wlast_err),
"right operand at %ld:%ld is not compatible to integer types",
rtok->ln, rtok->cn);
snprintf(wlast_err, sizeof(wlast_err),
"'%s': right operand at %ld:%ld is not compatible to "
"integer types",
rtok->filename, rtok->ln, rtok->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -586,8 +592,8 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
{
fzl_token_t *tok = node->unary_op.operand->token;
snprintf(wlast_err, sizeof(wlast_err),
"incompatible with unary operator type at %ld:%ld", tok->ln,
tok->cn);
"'%s': incompatible with unary operator type at %ld:%ld",
tok->filename, tok->ln, tok->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -645,8 +651,8 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
{
fzl_token_t *tok = node->binary_op.left->token->value;
snprintf(wlast_err, sizeof(wlast_err),
"name '%s' is not exists at %ld:%ld", (char *)tok->value,
tok->ln, tok->cn);
"'%s': name '%s' is not exists at %ld:%ld", tok->filename,
(char *)tok->value, tok->ln, tok->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}
@@ -654,8 +660,8 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
{
fzl_token_t *tok = node->binary_op.right->token;
snprintf(wlast_err, sizeof(wlast_err),
"R-Value is not compatible with L-Value at %ld:%ld",
tok->ln, tok->cn);
"'%s': R-Value is not compatible with L-Value at %ld:%ld",
tok->filename, tok->ln, tok->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
}