3 Commits
Author SHA1 Message Date
samsonium 801b28e27d feat: implement address deferencing 2026-10-18 18:42:02 +03:00
samsonium c0df5fc9d4 feat: add exit builtin function 2026-10-18 18:41:49 +03:00
samsonium f0e641928d upd: add exit on error in examples 2026-10-18 18:40:48 +03:00
11 changed files with 143 additions and 21 deletions
+16 -7
View File
@@ -7,12 +7,11 @@ fn doSome(A a) A
{ {
// NOTE: section below won't change `a.some` value // NOTE: section below won't change `a.some` value
// if (a.some < 1) if (a.some < 1)
// { {
// a.some = 1;
// return a;
// }
a.some = 1; a.some = 1;
return a;
}
return a; return a;
} }
@@ -27,10 +26,20 @@ fn doSomeNew() A
A a = new A; A a = new A;
a.some = 0; a.some = 0;
printline(a); if (a.some != 0)
{
printline("Test failed (first a.some != 0)");
exit(1);
}
else printline(a);
a = doSome(a); a = doSome(a);
printline(a); if (a.some != 1)
{
printline("Test failed (2nd a.some != 1)");
exit(1);
}
else printline(a);
A b = doSomeNew(); A b = doSomeNew();
printline(b); printline(b);
+5 -1
View File
@@ -28,5 +28,9 @@ printline(obj.y);
if (obj.x == 10 && obj.y == 10) if (obj.x == 10 && obj.y == 10)
printline("Test passed"); printline("Test passed");
else printline("Test failed"); else
{
printline("Test failed");
exit(1);
}
+4
View File
@@ -1,13 +1,17 @@
bool flag = true; bool flag = true;
if (!flag) if (!flag)
{
printline("buhhh, flag is not true"); printline("buhhh, flag is not true");
exit(1);
}
else if (2 + 2 >= 4) else if (2 + 2 >= 4)
{ {
printline ("two plus two is four"); printline ("two plus two is four");
} }
else { else {
printline("gotcha"); printline("gotcha");
exit(1);
} }
{ {
+10 -2
View File
@@ -15,10 +15,18 @@ printline("Test #1: fibonacci");
int result = fib(7); int result = fib(7);
if (result == 13) if (result == 13)
printline("Recurse test passed"); printline("Recurse test passed");
else printline("Recurse test failed"); else
{
printline("Recurse test failed");
exit(1);
}
printline("Test #2: sum"); printline("Test #2: sum");
if (sum(2, 2) == 4) if (sum(2, 2) == 4)
printline("Sum test passed"); printline("Sum test passed");
else printline("Sum test failed"); else
{
printline("Sum test failed");
exit(1);
}
+5 -1
View File
@@ -58,5 +58,9 @@ printline(total);
if (total == 16) if (total == 16)
printline("Tests passed!"); printline("Tests passed!");
else printline("Tests failed"); else
{
printline("Tests failed");
exit(1);
}
+14 -2
View File
@@ -21,14 +21,26 @@ a.name = "Buryatka";
a.age = 5; a.age = 5;
Animal b = a.copy(); Animal b = a.copy();
a.name = "Gavryusha"; b.name = "Gavryusha";
a.age = 10; b.age = 10;
printline(a); printline(a);
printline(b); printline(b);
printline("Types are same:");
printline(a.type == b.type);
printline("Names are NOT the same");
printline(a.name != b.name);
printline("1st age less than 2nd");
printline(a.age < b.age);
if (a.type == b.type && a.name != b.name && a.age < b.age) if (a.type == b.type && a.name != b.name && a.age < b.age)
printline("Test passed"); printline("Test passed");
else else
{
printline("Test failed"); printline("Test failed");
exit(1);
}
+2 -1
View File
@@ -3,7 +3,8 @@
typedef enum typedef enum
{ {
FZL_BUILTIN_PRINTLINE // Print message in arg with newline at end FZL_BUILTIN_PRINTLINE, // Print message in arg with newline at end
FZL_BUILTIN_EXIT, // Exit program with code specified in arg
} fzl_builtin_t; } fzl_builtin_t;
#endif // FZL_BUILTINS_H #endif // FZL_BUILTINS_H
+1
View File
@@ -25,6 +25,7 @@ typedef enum
FZL_OPCODE_GET_FIELD = 0xFA0002, // Get field N of an object at dstack FZL_OPCODE_GET_FIELD = 0xFA0002, // Get field N of an object at dstack
FZL_OPCODE_SET_FIELD = 0xFA0003, // Set field N of an object at dstack FZL_OPCODE_SET_FIELD = 0xFA0003, // Set field N of an object at dstack
FZL_OPCODE_ESCAPE_OBJECT = 0xFA0004, // Make parent envtable as owner FZL_OPCODE_ESCAPE_OBJECT = 0xFA0004, // Make parent envtable as owner
FZL_OPCODE_DEREFERENCE = 0xFA0005, // Dereference address
FZL_OPCODE_ADD = 0xA00001, // Sum two numbers in dstack FZL_OPCODE_ADD = 0xA00001, // Sum two numbers in dstack
FZL_OPCODE_SUB = 0xA00002, // Subract two numbers in dstack FZL_OPCODE_SUB = 0xA00002, // Subract two numbers in dstack
+28 -2
View File
@@ -754,6 +754,30 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
} }
current_res = (fzl_walk_res_t){.type = FZL_TYPE_NULL, .error = false}; current_res = (fzl_walk_res_t){.type = FZL_TYPE_NULL, .error = false};
} }
else if (strcmp(node->token->value, "exit") == 0)
{
if (node->call.args_count > 0)
{
for (size_t i = 0; i < node->call.args_count; i++)
{
fzl_walk_res_t res = walk(walker, node->call.args[i]);
if (res.error)
return res;
}
push_op(walker, FZL_OPCODE_CALL_BUILTIN);
push_word(walker, FZL_BUILTIN_EXIT);
if (node->call.args_count < 1)
{
snprintf(wlast_err, sizeof(wlast_err),
"'%s': 'exit' 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};
}
}
else else
{ {
if (node->call.callee->type == FZL_NODETYPE_IDENTIFIER) if (node->call.callee->type == FZL_NODETYPE_IDENTIFIER)
@@ -778,8 +802,9 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
if (!found) if (!found)
{ {
snprintf(wlast_err, sizeof(wlast_err), snprintf(wlast_err, sizeof(wlast_err),
"call to unknown function '%s'", "'%s': call to unknown function '%s' at %ld:%ld",
(char *)node->token->value); node->token->filename, (char *)node->token->value,
node->token->ln, node->token->cn);
return (fzl_walk_res_t){.error = true, .error_msg = wlast_err}; return (fzl_walk_res_t){.error = true, .error_msg = wlast_err};
} }
@@ -917,6 +942,7 @@ fzl_walk_res_t walk(fzl_walker_t *walker, fzl_node_t *node)
fzl_token_t *tok = node->token; fzl_token_t *tok = node->token;
push_op(walker, FZL_OPCODE_PUSHNUM); push_op(walker, FZL_OPCODE_PUSHNUM);
push_word(walker, 0); push_word(walker, 0);
push_op(walker, FZL_OPCODE_DEREFERENCE);
current_res = (fzl_walk_res_t){ current_res = (fzl_walk_res_t){
.type = FZL_TYPE_OBJECT, .error = false, .classname = null_name}; .type = FZL_TYPE_OBJECT, .error = false, .classname = null_name};
} }
+53 -4
View File
@@ -279,6 +279,37 @@ int fzl_vm_run(fzl_vm_t *vm)
switch (opcode) switch (opcode)
{ {
case FZL_OPCODE_DEREFERENCE:
{
if (vm->dtop < 1)
{
snprintf(last_err, sizeof(last_err),
"runtime error - expected value in data stack");
print_err_data(vm);
return -1;
}
fzl_value_t addr = vm->dstack[--vm->dtop];
if (addr.type < FZL_TYPE_INT8)
{
snprintf(last_err, sizeof(last_err),
"runtime error - expected address");
print_err_data(vm);
return -1;
}
if (addr.as.u == 0)
{
vm->dstack[vm->dtop++] =
(fzl_value_t){.type = FZL_TYPE_OBJECT, .as.obj = NULL};
break;
}
vm->dstack[vm->dtop++] = (fzl_value_t){
.type = FZL_TYPE_OBJECT, .as.obj = (fzl_vm_object_t *)addr.as.u};
break;
}
case FZL_OPCODE_CMP_EQ_STR: case FZL_OPCODE_CMP_EQ_STR:
{ {
if (vm->dtop < 2) if (vm->dtop < 2)
@@ -359,7 +390,7 @@ int fzl_vm_run(fzl_vm_t *vm)
return -1; return -1;
} }
fzl_value_t obj = vm->dstack[--vm->dtop]; fzl_value_t obj = vm->dstack[--vm->dtop];
if (obj.type != FZL_TYPE_OBJECT && obj.type < FZL_TYPE_INT8) if (obj.type != FZL_TYPE_OBJECT)
{ {
snprintf(last_err, sizeof(last_err), snprintf(last_err, sizeof(last_err),
"runtime error - cannot escape non-object type"); "runtime error - cannot escape non-object type");
@@ -538,8 +569,8 @@ int fzl_vm_run(fzl_vm_t *vm)
return -1; return -1;
} }
fzl_value_t llt = vm->dstack[--vm->dtop];
fzl_value_t rlt = vm->dstack[--vm->dtop]; fzl_value_t rlt = vm->dstack[--vm->dtop];
fzl_value_t llt = vm->dstack[--vm->dtop];
vm->dstack[vm->dtop++] = vm->dstack[vm->dtop++] =
(fzl_value_t){.type = FZL_TYPE_BOOL, .as.b = llt.as.u < rlt.as.u}; (fzl_value_t){.type = FZL_TYPE_BOOL, .as.b = llt.as.u < rlt.as.u};
break; break;
@@ -679,8 +710,21 @@ int fzl_vm_run(fzl_vm_t *vm)
fzl_value_t writevar = vm->dstack[--vm->dtop]; fzl_value_t writevar = vm->dstack[--vm->dtop];
fzl_value_t value = vm->dstack[--vm->dtop]; fzl_value_t value = vm->dstack[--vm->dtop];
fzl_vm_env_wresult_t wresult = fzl_env_writevalue( char *wrname = (char *)writevar.as.s.value;
vm->estack[vm->etop - 1], (char *)writevar.as.s.value, value); bool wrfound;
fzl_value_t wrenv;
ssize_t wrlvl = -1;
for (ssize_t i = vm->etop - 1; i >= 0; i--)
{
if ((wrfound = fzl_env_lookup(vm->estack[i], wrname, &wrenv)))
{
wrlvl = i;
break;
}
}
fzl_vm_env_wresult_t wresult =
fzl_env_writevalue(vm->estack[wrlvl], (char *)wrname, value);
if (wresult != FZL_VM_ENV_WRESULT_OK) if (wresult != FZL_VM_ENV_WRESULT_OK)
{ {
switch (wresult) switch (wresult)
@@ -769,6 +813,11 @@ int fzl_vm_run(fzl_vm_t *vm)
else if (arg.type == FZL_TYPE_OBJECT) else if (arg.type == FZL_TYPE_OBJECT)
print_object(arg.as.obj); print_object(arg.as.obj);
} }
else if (fn_id == FZL_BUILTIN_EXIT)
{
fzl_value_t arg = vm->dstack[--vm->dtop];
exit(arg.as.i);
}
else else
{ {
snprintf(last_err, sizeof(last_err), snprintf(last_err, sizeof(last_err),
+4
View File
@@ -20,6 +20,10 @@ void fzl_vm_print_ops(fzl_vm_t *vm)
switch (vm->ops[i]) switch (vm->ops[i])
{ {
case FZL_OPCODE_DEREFERENCE:
printf("DEREFERENCE\n");
break;
case FZL_OPCODE_CMP_EQ_STR: case FZL_OPCODE_CMP_EQ_STR:
printf("CMP_EQ_STR\n"); printf("CMP_EQ_STR\n");
break; break;