From 5fcbb97f7a0c8fac3eceaabed4d77b9900b22ce9 Mon Sep 17 00:00:00 2001 From: Slendi Date: Sun, 27 Jul 2025 21:56:54 +0300 Subject: [PATCH] Add object support Signed-off-by: Slendi --- programs/dcfg_dump.c | 34 +++++++++++++----------- samples/testing.dcfg | 12 ++++++++- src/dcfg.c | 62 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/programs/dcfg_dump.c b/programs/dcfg_dump.c index 26b5b75..713bb92 100644 --- a/programs/dcfg_dump.c +++ b/programs/dcfg_dump.c @@ -1,10 +1,18 @@ #include +#include #include #include #include -void walk_value(dcfg_Value *value, bool evaluate, int indent); +void walk_value(dcfg_Value *value, bool evaluate, int indent, bool first); +#define WALK(v, e, i) walk_value((v), (e), (i), true) + +static void print_indent(int indent) +{ + for (int i = 0; i < indent; ++i) + putchar('\t'); +} int main(int argc, char *argv[]) { @@ -28,21 +36,16 @@ int main(int argc, char *argv[]) return 1; } - walk_value(value, false, 0); + WALK(value, false, 0); dcfg_destroy(value); dcfg_destroy_instance(instance); } -static void print_indent(int indent) +void walk_value(dcfg_Value *value, bool evaluate, int indent, bool first) { - for (int i = 0; i < indent; ++i) - putchar('\t'); -} - -void walk_value(dcfg_Value *value, bool evaluate, int indent) -{ - print_indent(indent); + if (first) + print_indent(indent); dcfg_ValueType type = dcfg_Value_type_ex(value, evaluate); @@ -97,7 +100,7 @@ void walk_value(dcfg_Value *value, bool evaluate, int indent) print_indent(indent + 1); printf("\"%.*s\": ", (int)keys[i].size, keys[i].data); - walk_value(child, evaluate, indent + 1); + walk_value(child, evaluate, indent + 1, false); if (i + 1 < n) printf(","); printf("\n"); @@ -116,7 +119,8 @@ void walk_value(dcfg_Value *value, bool evaluate, int indent) if (!dcfg_Value_get_array_item_ex(value, i, &item, evaluate)) continue; - walk_value(item, evaluate, indent + 1); + print_indent(indent + 1); + walk_value(item, evaluate, indent + 1, false); if (i + 1 < sz) printf(","); printf("\n"); @@ -129,8 +133,8 @@ void walk_value(dcfg_Value *value, bool evaluate, int indent) dcfg_Value *body = NULL; if (dcfg_Value_get_function_body_ex(value, &body, evaluate) && body) { - printf(" "); - walk_value(body, evaluate, indent + 1); + printf("\t"); + walk_value(body, evaluate, indent + 1, false); } else { printf(""); } @@ -140,7 +144,7 @@ void walk_value(dcfg_Value *value, bool evaluate, int indent) if (evaluate) { dcfg_Value *res; if (dcfg_Value_evaluate(value, &res)) - walk_value(res, evaluate, indent); + walk_value(res, evaluate, indent, first); else printf(""); } else { diff --git a/samples/testing.dcfg b/samples/testing.dcfg index 24fd069..ef20c21 100644 --- a/samples/testing.dcfg +++ b/samples/testing.dcfg @@ -1,2 +1,12 @@ -fn lib = [ 123 "string" ./path 80085.3 ] +fn lib = [ + 123 + "string" + ./path + 80085.3 + { + key1 = 123 + key2.member = "str" + key2.another_member = ./amazing + } +] diff --git a/src/dcfg.c b/src/dcfg.c index a5518b3..ebf5f88 100644 --- a/src/dcfg.c +++ b/src/dcfg.c @@ -1014,6 +1014,26 @@ AST *Parser_parse(Parser *parser) { return parser_parse_value(parser); } #define ALLOC(sz) (instance->alloc((sz))) #define FREE(ptr) (instance->free((ptr))) +static Value *ensure_child_obj(Instance *inst, Value *parent, StringView key) +{ + ValueObject *obj = &parent->v.o; + + for (size_t i = 0; i < vector_size(obj->entryv); ++i) { + if (sv_eq(obj->entryv[i].k, key)) { + return obj->entryv[i].v; + } + } + + Value *child = inst->alloc(sizeof *child); + child->instance = inst; + child->type = dcfg_ValueType_Object; + child->v.o.entryv = vector_create(); + + ValueObjectEntry e = { .k = key, .v = child }; + vector_add(&obj->entryv, e); + return child; +} + Value *ast_to_value(dcfg_Instance *instance, AST *root) { Value *value = ALLOC(sizeof(*value)); @@ -1040,9 +1060,45 @@ Value *ast_to_value(dcfg_Instance *instance, AST *root) value->type = dcfg_ValueType_Real; value->v.r = root->v.r; } else if (root->kind == ASTKind_Block) { - // FIXME: Implement - FREE(value); - return NULL; + value->type = dcfg_ValueType_Object; + value->v.o.entryv = vector_create(); + + for (size_t i = 0; i < vector_size(root->v.bl.entryv); ++i) { + ASTBlock_Entry *e = &root->v.bl.entryv[i]; + Value *rhs = ast_to_value(instance, e->v); + if (!rhs) { + // FIXME: Free + return NULL; + } + + Value *target = value; + StringView field; + + if (e->k->kind == ASTKind_Key) { + field = e->k->v.s.s; + } else { + ASTMemberAccess *ma = &e->k->v.m; + for (size_t j = 0; j + 1 < vector_size(ma->accessv); ++j) + target = ensure_child_obj(instance, target, ma->accessv[j]); + field = ma->accessv[vector_size(ma->accessv) - 1]; + } + + ValueObject *obj = &target->v.o; + bool replaced = false; + for (size_t j = 0; j < vector_size(obj->entryv); ++j) { + if (sv_eq(obj->entryv[j].k, field)) { + dcfg_destroy(obj->entryv[j].v); + obj->entryv[j].v = rhs; + replaced = true; + break; + } + } + + if (!replaced) { + ValueObjectEntry new_e = { .k = field, .v = rhs }; + vector_add(&obj->entryv, new_e); + } + } } else if (root->kind == ASTKind_Array) { value->type = dcfg_ValueType_Array; value->v.a.valuev = vector_create();