From e8f34b341ef512b0e7ef9153341fda372255faa6 Mon Sep 17 00:00:00 2001 From: Slendi Date: Fri, 1 Aug 2025 02:56:44 +0300 Subject: [PATCH] Add some evaluation stuff + versioning Signed-off-by: Slendi --- include/dcfg.h | 12 ++++ src/dcfg.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++-- src/meta.h | 16 +++++ 3 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 src/meta.h diff --git a/include/dcfg.h b/include/dcfg.h index 8eac9c0..4834ac6 100644 --- a/include/dcfg.h +++ b/include/dcfg.h @@ -49,9 +49,19 @@ typedef enum dcfg_ValueKind { dcfg_ValueType_Object, dcfg_ValueType_Array, dcfg_ValueType_Function, + dcfg_ValueType_MemberAccess, dcfg_ValueType_FunctionCall, } dcfg_ValueType; +typedef struct dcfg_Version { + int major; + int minor; + int patch; + char const *str; +} dcfg_Version; + +dcfg_Version dcfg_get_version(void); + dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info); void dcfg_destroy_instance(dcfg_Instance *instance); @@ -105,8 +115,10 @@ static inline bool dcfg_Value_get_function_body( return dcfg_Value_get_function_body_ex(value, out_value, true); } +// Allocates new values bool dcfg_call_function(dcfg_Value *function, dcfg_Value **args, size_t arg_count, dcfg_Value **out_value); +// Allocates new values bool dcfg_Value_evaluate(dcfg_Value *value, dcfg_Value **out_value); #ifdef __cplusplus diff --git a/src/dcfg.c b/src/dcfg.c index 092603e..a700b28 100644 --- a/src/dcfg.c +++ b/src/dcfg.c @@ -1,6 +1,8 @@ #include #include +#include "meta.h" + #include "vendor/utf8proc.h" #include "vendor/vec.h" @@ -137,6 +139,7 @@ typedef struct { typedef struct { StringView k; Value *v; + bool key_allocated; } ValueObjectEntry; typedef struct { @@ -165,12 +168,17 @@ typedef struct { Value **argv; } ValueFunctionCall; +typedef struct { + StringView **accessv; +} ValueMemberAccess; + struct dcfg_Value { Instance *instance; dcfg_ValueType type; SourceLocation location; int i_sourcev_idx; int i_source_pathv_idx; + int i_environment_idx; union { int64_t i; @@ -181,10 +189,34 @@ struct dcfg_Value { ValueObject o; ValueArray a; ValueFunction f; + ValueMemberAccess ma; ValueFunctionCall c; } v; }; +typedef struct Environment { + struct Environment *parent; + StringView *argv; + Value *argvv; +} Environment; + +bool environment_create(Environment *out_env, Environment *parent) +{ + out_env->argv = vector_create(); + out_env->argvv = vector_create(); + out_env->parent = parent; + return true; +} + +void environment_destroy(Environment *env) +{ + vector_free(&env->argv); + for (size_t i = 0; i < vector_size(env->argvv); i++) { + dcfg_destroy(&env->argvv[i]); + } + vector_free(&env->argvv); +} + struct dcfg_Instance { pthread_mutex_t mtx; @@ -199,6 +231,8 @@ struct dcfg_Instance { StringView *sourcev; // Strings should be freed. StringView *source_pathv; // Strings should be freed. + Environment *environmentv; + int *environment_referencesv; }; #define ALLOC(sz) (instance->alloc((sz))) @@ -213,6 +247,16 @@ int fseek_(void *f, size_t p, int o) { return fseek(f, p, o); } long ftell_(void *f) { return ftell(f); } #endif +dcfg_Version dcfg_get_version(void) +{ + return (dcfg_Version) { + .major = VERSION_MAJOR, + .minor = VERSION_MINOR, + .patch = VERSION_PATCH, + .str = VERSION_STRING, + }; +} + dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) { assert(create_info); @@ -255,6 +299,8 @@ dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) instance->sourcev = vector_create(); instance->source_pathv = vector_create(); + instance->environmentv = vector_create(); + instance->environment_referencesv = vector_create(); return instance; } @@ -263,6 +309,17 @@ void dcfg_destroy_instance(dcfg_Instance *instance) { assert(instance); + for (size_t i = 0; i < vector_size(instance->environment_referencesv); + i++) { + if (instance->environment_referencesv[i] > 0) { + environment_destroy(&instance->environmentv[i]); + } + } + vector_free(instance->environment_referencesv); + + for (size_t i = 0; i < vector_size(instance->environmentv); i++) { } + vector_free(instance->environmentv); + for (size_t i = 0; i < vector_size(instance->source_pathv); i++) { free((void *)instance->source_pathv[i].data); } @@ -1068,7 +1125,7 @@ static Value *ensure_child_obj(Instance *inst, Value *parent, StringView key) child->type = dcfg_ValueType_Object; child->v.o.entryv = vector_create(); - ValueObjectEntry e = { .k = key, .v = child }; + ValueObjectEntry e = { .k = key, .v = child, .key_allocated = false }; vector_add(&obj->entryv, ValueObjectEntry, e); return child; } @@ -1149,7 +1206,8 @@ Value *ast_to_value(dcfg_Instance *instance, AST *root) } if (!replaced) { - ValueObjectEntry new_e = { .k = field, .v = rhs }; + ValueObjectEntry new_e + = { .k = field, .v = rhs, .key_allocated = false }; vector_add(&obj->entryv, ValueObjectEntry, new_e); } } @@ -1183,6 +1241,7 @@ Value *ast_to_value(dcfg_Instance *instance, AST *root) } value->v.f.v.f.body = v; } else if (root->kind == ASTKind_MemberAccess) { + value->type = dcfg_ValueType_MemberAccess; // FIXME: Implement FREE(value); return NULL; @@ -1331,6 +1390,9 @@ void dcfg_destroy(dcfg_Value *value) case dcfg_ValueType_Object: for (size_t i = 0; i < vector_size(value->v.o.entryv); i++) { dcfg_destroy(value->v.o.entryv[i].v); + if (value->v.o.entryv[i].key_allocated) { + value->instance->free((void *)value->v.o.entryv[i].k.data); + } } vector_free(value->v.o.entryv); break; @@ -1506,9 +1568,93 @@ bool dcfg_call_function(dcfg_Value *function, dcfg_Value **args, bool dcfg_Value_evaluate(dcfg_Value *value, dcfg_Value **out_value) { - (void)value, (void)out_value; - // FIXME: Implement - return false; + assert(value); + assert(out_value); + + bool ret = true; + value->instance->last_error[0] = '\0'; + *out_value = value->instance->alloc(sizeof(**out_value)); + Value *v = *out_value; + + if (value->type == dcfg_ValueType_Nil) { + v->type = dcfg_ValueType_Nil; + } else if (value->type == dcfg_ValueType_Boolean) { + v->type = dcfg_ValueType_Boolean; + v->v.b = value->v.b; + } else if (value->type == dcfg_ValueType_Integer) { + v->type = dcfg_ValueType_Integer; + v->v.i = value->v.i; + } else if (value->type == dcfg_ValueType_Real) { + v->type = dcfg_ValueType_Real; + v->v.r = value->v.r; + } else if (value->type == dcfg_ValueType_String) { + v->type = dcfg_ValueType_String; + v->v.s = value->v.s; + } else if (value->type == dcfg_ValueType_Path) { + v->type = dcfg_ValueType_Path; + v->v.p = value->v.p; + } else if (value->type == dcfg_ValueType_Object) { + v->type = dcfg_ValueType_Object; + v->v.o.entryv = vector_create(); + for (size_t i = 0; i < vector_size(value->v.o.entryv); i++) { + ValueObjectEntry *e = &value->v.o.entryv[i]; + Value *new_v; + bool res = dcfg_Value_evaluate(e->v, &new_v); + if (!res) { + ret = false; + break; + } + ValueObjectEntry ne = { + .k = e->k, + .v = new_v, + }; + ne.k.data = value->instance->alloc(ne.k.size + 1); + memcpy((void *)ne.k.data, e->k.data, ne.k.size); + ((char *)ne.k.data)[ne.k.size] = '\0'; + vector_add(&v->v.o.entryv, ValueObjectEntry, ne); + } + } else if (value->type == dcfg_ValueType_Array) { + v->type = dcfg_ValueType_Array; + v->v.a.valuev = vector_create(); + for (size_t i = 0; i < vector_size(value->v.a.valuev); i++) { + Value *val = NULL; + bool res = dcfg_Value_evaluate(value->v.a.valuev[i], &val); + if (!res) { + ret = false; + } + vector_add(&v->v.a.valuev, Value *, val); + } + } else if (value->type == dcfg_ValueType_Function) { + Value *out_value_prev = *out_value; + bool res = dcfg_call_function(value, NULL, 0, out_value); + if (!res) { + dcfg_destroy(out_value_prev); + ret = false; + } + } else if (value->type == dcfg_ValueType_MemberAccess) { + // FIXME: Implement + ret = false; + } else if (value->type == dcfg_ValueType_FunctionCall) { + Value *function; + bool res = dcfg_Value_evaluate(value->v.c.function, &function); + if (!res || function->type != dcfg_ValueType_Function) { + ret = false; + } else { + Value *out_value_prev = *out_value; + bool res = dcfg_call_function(function, value->v.c.argv, + vector_size(value->v.c.argv), out_value); + if (!res) { + dcfg_destroy(out_value_prev); + ret = false; + } + } + } else { + assert(0 && "Invalid value type"); + } + if (!ret) { + dcfg_destroy(*out_value); + } + return ret; } // Libraries diff --git a/src/meta.h b/src/meta.h new file mode 100644 index 0000000..d06c7e6 --- /dev/null +++ b/src/meta.h @@ -0,0 +1,16 @@ +#ifndef META_H +#define META_H + +#define VERSION_MAJOR 0 +#define VERSION_MINOR 1 +#define VERSION_PATCH 0 + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +// proper version string +#define VERSION_STRING \ + TOSTRING(VERSION_MAJOR) \ + "." TOSTRING(VERSION_MINOR) "." TOSTRING(VERSION_PATCH) + +#endif // META_H