libs: minic fixes
This commit is contained in:
+37
-27
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user