libs: minic fixes

This commit is contained in:
luboslenco
2026-05-05 08:56:14 +02:00
parent 93f05134a1
commit ec3d2a23da
4 changed files with 69 additions and 31 deletions
+37 -27
View File
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
// ████████╗ ██████╗ ██╗ ██╗███████╗███╗ ██╗
@@ -690,8 +691,13 @@ static int minic_current_line(minic_env_t *e) {
return line;
}
static void minic_error(minic_env_t *e, const char *msg) {
static void minic_error(minic_env_t *e, const char *fmt, ...) {
if (!e->error) {
char msg[256];
va_list args;
va_start(args, fmt);
vsnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
fprintf(stderr, "%s:%d: error: %s (got %s)\n", e->filename, minic_current_line(e), msg, minic_tok_name(e->lex.cur.type));
e->error = true;
e->returning = true;
@@ -700,9 +706,7 @@ static void minic_error(minic_env_t *e, const char *msg) {
static void minic_expect(minic_env_t *e, minic_tok_type_t expected) {
if (e->lex.cur.type != expected) {
char msg[128];
snprintf(msg, sizeof(msg), "expected %s", minic_tok_name(expected));
minic_error(e, msg);
minic_error(e, "expected %s", minic_tok_name(expected));
return;
}
minic_lex_next(&e->lex);
@@ -940,8 +944,7 @@ static int minic_struct_field_idx(minic_struct_def_t *def, const char *field) {
static minic_val_t minic_struct_field_get_base(minic_env_t *e, void *base, minic_struct_def_t *def, const char *field) {
int idx = minic_struct_field_idx(def, field);
if (idx < 0) {
fprintf(stderr, "%s:%d: error: struct '%s' has no field '%s'\n", e->filename, minic_current_line(e), def->name, field);
e->error = e->returning = true;
minic_error(e, "struct '%s' has no field '%s'", def->name, field);
return minic_val_int(0);
}
bool in_arena = (base != NULL && (minic_u8 *)base >= minic_active_mem && (minic_u8 *)base < minic_active_mem + MINIC_MEM_SIZE);
@@ -950,6 +953,8 @@ static minic_val_t minic_struct_field_get_base(minic_env_t *e, void *base, minic
switch (def->field_native_types[idx]) {
case MINIC_T_PTR:
return minic_val_typed_ptr(*(void **)p, def->field_deref_types[idx]);
case MINIC_T_EMBED:
return minic_val_typed_ptr(p, def->field_deref_types[idx]);
case MINIC_T_FLOAT:
return minic_val_float(*(float *)p);
default:
@@ -964,8 +969,7 @@ static minic_val_t minic_struct_field_get_base(minic_env_t *e, void *base, minic
static void minic_struct_field_set_base(minic_env_t *e, void *base, minic_struct_def_t *def, const char *field, minic_val_t val) {
int idx = minic_struct_field_idx(def, field);
if (idx < 0) {
fprintf(stderr, "%s:%d: error: struct '%s' has no field '%s'\n", e->filename, minic_current_line(e), def->name, field);
e->error = e->returning = true;
minic_error(e, "struct '%s' has no field '%s'", def->name, field);
return;
}
bool in_arena = (base != NULL && (minic_u8 *)base >= minic_active_mem && (minic_u8 *)base < minic_active_mem + MINIC_MEM_SIZE);
@@ -975,6 +979,8 @@ static void minic_struct_field_set_base(minic_env_t *e, void *base, minic_struct
case MINIC_T_PTR:
*(void **)p = minic_val_to_ptr(val);
break;
case MINIC_T_EMBED:
break; // embedded structs are mutated through their own field accessors
case MINIC_T_FLOAT:
*(float *)p = (float)minic_val_to_d(val);
break;
@@ -1105,7 +1111,23 @@ static minic_val_t minic_parse_primary(minic_env_t *e) {
else {
addr = minic_var_addr(e, aname);
}
// Handle &var->field or &var.field: follow member-access chain
minic_struct_def_t *def = minic_var_struct(e, aname);
minic_lex_next(&e->lex); // Consume ident
while (def != NULL && (e->lex.cur.type == TOK_ARROW || e->lex.cur.type == TOK_DOT)) {
minic_lex_next(&e->lex); // Consume '->' or '.'
char field[64];
strncpy(field, e->lex.cur.text, 63);
minic_lex_next(&e->lex); // Consume field name
void *base = minic_val_to_ptr(addr);
addr = minic_struct_field_get_base(e, base, def, field);
// Advance def to the field's struct type for further chaining
int fidx = minic_struct_field_idx(def, field);
if (fidx >= 0 && def->field_struct_names[fidx][0] != '\0')
def = minic_struct_get(e, def->field_struct_names[fidx]);
else
def = NULL;
}
return addr;
}
if (e->lex.cur.type == TOK_STAR) {
@@ -1204,9 +1226,7 @@ static minic_val_t minic_parse_primary(minic_env_t *e) {
if (ext != NULL) {
return minic_dispatch(ext, args, argc);
}
fprintf(stderr, "%s:%d: error: unknown function '%s'\n", e->filename, minic_current_line(e), name);
e->error = true;
e->returning = true;
minic_error(e, "unknown function '%s'", name);
return minic_val_int(0);
}
@@ -1217,8 +1237,7 @@ static minic_val_t minic_parse_primary(minic_env_t *e) {
minic_lex_next(&e->lex);
minic_struct_def_t *def = minic_var_struct(e, name);
if (def == NULL) {
fprintf(stderr, "%s:%d: error: '%s' is not a struct\n", e->filename, minic_current_line(e), name);
e->error = e->returning = true;
minic_error(e, "'%s' is not a struct", name);
return minic_val_int(0);
}
return minic_struct_field_get(e, name, def, field);
@@ -1231,8 +1250,7 @@ static minic_val_t minic_parse_primary(minic_env_t *e) {
minic_lex_next(&e->lex);
minic_struct_def_t *def = minic_var_struct(e, name);
if (def == NULL) {
fprintf(stderr, "%s:%d: error: '%s' is not a struct pointer\n", e->filename, minic_current_line(e), name);
e->error = e->returning = true;
minic_error(e, "'%s' is not a struct pointer", name);
return minic_val_int(0);
}
minic_val_t base_val = minic_var_get(e, name);
@@ -1421,8 +1439,7 @@ static void minic_parse_stmt(minic_env_t *e) {
minic_struct_def_t *def = minic_struct_get(e, sname);
if (def == NULL) {
fprintf(stderr, "%s:%d: error: unknown struct '%s'\n", e->filename, minic_current_line(e), sname);
e->error = e->returning = true;
minic_error(e, "unknown struct '%s'", sname);
return;
}
minic_vartype_set(e, vname, sname);
@@ -1588,8 +1605,7 @@ static void minic_parse_stmt(minic_env_t *e) {
minic_lex_next(&e->lex);
minic_struct_def_t *def = minic_var_struct(e, name);
if (def == NULL) {
fprintf(stderr, "%s:%d: error: '%s' is not a struct%s\n", e->filename, minic_current_line(e), name, is_arrow ? " pointer" : "");
e->error = e->returning = true;
minic_error(e, "'%s' is not a struct%s", name, is_arrow ? " pointer" : "");
return;
}
void *base;
@@ -1652,9 +1668,7 @@ static void minic_parse_stmt(minic_env_t *e) {
minic_dispatch(ext, args, argc);
}
else {
fprintf(stderr, "%s:%d: error: unknown function '%s'\n", e->filename, minic_current_line(e), name);
e->error = true;
e->returning = true;
minic_error(e, "unknown function '%s'", name);
}
}
minic_expect(e, TOK_SEMICOLON);
@@ -1963,11 +1977,7 @@ static void minic_parse_stmt(minic_env_t *e) {
return;
}
{
char msg[128];
snprintf(msg, sizeof(msg), "unexpected token at start of statement");
minic_error(e, msg);
}
minic_error(e, "unexpected token at start of statement");
}
static void minic_parse_block(minic_env_t *e) {
+1
View File
@@ -21,6 +21,7 @@ typedef enum {
MINIC_T_BOOL = 3, // used in extern-call ABI, stored as INT in vals
MINIC_T_CHAR = 4, // used in extern-call ABI, stored as INT in vals
MINIC_T_VOID = 5, // void return only; stored as INT/0 in vals
MINIC_T_EMBED = 6, // embedded struct field; field address is the pointer (no indirection)
} minic_type_t;
typedef struct {
+18 -4
View File
@@ -644,6 +644,7 @@ extern char *project_filepath;
extern context_t *g_context;
extern config_t *g_config;
extern project_t *g_project;
extern mesh_object_t_array_t *project_paint_objects;
char *project_filepath_get() {
return project_filepath;
}
@@ -659,6 +660,16 @@ config_t *script_get_config() {
project_t *script_get_project() {
return g_project;
}
object_t *script_get_object(char *s) {
for (int i = 0; i < project_paint_objects->length; ++i) {
if (string_equals(project_paint_objects->buffer[i]->base->name, s)) {
return project_paint_objects->buffer[i]->base;
}
}
return NULL;
}
void context_set_viewport_shader(void *viewport_shader);
void context_set_viewport_mode(int mode);
void context_set_camera_controls(int i);
@@ -1204,17 +1215,19 @@ void minic_register_builtins() {
minic_struct_field_set_type("mesh_object_t", "material", "material_data_t");
// transform_t
static const char *transform_fields[] = {"scale_world", "dirty", "object", "radius"};
static const char *transform_fields[] = {"loc", "scale_world", "dirty", "object", "radius"};
static const int transform_offsets[] = {
(int)offsetof(transform_t, loc),
(int)offsetof(transform_t, scale_world),
(int)offsetof(transform_t, dirty),
(int)offsetof(transform_t, object),
(int)offsetof(transform_t, radius),
};
static const minic_type_t transform_types[] = {MINIC_T_FLOAT, MINIC_T_INT, MINIC_T_PTR, MINIC_T_FLOAT};
static const minic_type_t transform_deref_types[] = {MINIC_T_FLOAT, MINIC_T_INT, MINIC_T_PTR, MINIC_T_FLOAT};
minic_register_struct_native("transform_t", transform_fields, transform_offsets, transform_types, transform_deref_types, 4);
static const minic_type_t transform_types[] = {MINIC_T_EMBED, MINIC_T_FLOAT, MINIC_T_INT, MINIC_T_PTR, MINIC_T_FLOAT};
static const minic_type_t transform_deref_types[] = {MINIC_T_PTR, MINIC_T_FLOAT, MINIC_T_INT, MINIC_T_PTR, MINIC_T_FLOAT};
minic_register_struct_native("transform_t", transform_fields, transform_offsets, transform_types, transform_deref_types, 5);
minic_struct_set_size("transform_t", (int)sizeof(transform_t));
minic_struct_field_set_type("transform_t", "loc", "vec4_t");
minic_struct_field_set_type("transform_t", "object", "object_t");
// camera_object_t
@@ -2034,6 +2047,7 @@ void minic_register_builtins() {
R(script_get_context, "p()");
R(script_get_config, "p()");
R(script_get_project, "p()");
R(script_get_object, "p(p)");
R(context_set_viewport_shader, "v(p)");
R(context_set_viewport_mode, "v(i)");
R(context_set_camera_controls, "v(i)");
+13
View File
@@ -177,6 +177,18 @@ const char *test11 = " \n\
} \n\
";
const char *test12 = " \n\
float main() { \n\
object_t *o = scene_get_child(\"Scene\"); \n\
transform_t *t = o->transform; \n\
vec4_t *v = &t->loc; \n\
v->x = 3.0; \n\
v->y = 2.0; \n\
if (t->loc.x == 3.0 && v->y == 2.0) { return 0.0; } \n\
return 1.0; \n\
} \n\
";
#define MINIC_TEST(n, src) \
do { \
minic_ctx_t *_c = minic_eval(src); \
@@ -203,6 +215,7 @@ void minic_tests() {
MINIC_TEST(9, test9);
MINIC_TEST(10, test10);
MINIC_TEST(11, test11);
MINIC_TEST(12, test12);
}
#endif