Cthulhu  0.2.10
Cthulhu compiler collection
meta.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 #include "meta.h"
3 #include "arena/arena.h"
5 #include "std/str.h"
6 
7 #include "json/query.h"
8 
9 typedef struct json_context_t
10 {
15 
16 static json_t *inner_query_type(json_context_t *context, json_t *json, const char *expr, json_kind_t kind)
17 {
18  return json_query_type(json, expr, kind, context->logger, context->arena);
19 }
20 
21 static meta_type_t get_meta_type(text_view_t id)
22 {
23  if (text_view_equal(id, (text_view_t)CT_TEXT_VIEW("mpz")))
24  {
25  return eMetaMpz;
26  }
27 
28  if (text_view_equal(id, (text_view_t)CT_TEXT_VIEW("ast")))
29  {
30  return eMetaAst;
31  }
32 
33  if (text_view_equal(id, (text_view_t)CT_TEXT_VIEW("string")))
34  {
35  return eMetaString;
36  }
37 
38  return eMetaUnknown;
39 }
40 
41 static bool parse_ast_field(json_context_t *ctx, json_t *json, typevec_t *fields)
42 {
43  json_t *name = inner_query_type(ctx, json, "$.name", eJsonString);
44  if (name == NULL)
45  {
46  return false;
47  }
48 
49  json_t *type = json_map_get(json, "type");
50  if (type == NULL)
51  {
52  msg_notify(ctx->logger, &kEvent_SymbolNotFound, node_new(ctx->scan, json->where), "no field type");
53  return false;
54  }
55 
56  meta_field_t field = {
57  .name = name->string,
58  .type = get_meta_type(type->string),
59  };
60 
61  typevec_push(fields, &field);
62 
63  return true;
64 }
65 
66 static bool parse_ast_node(json_context_t *ctx, json_t *json, typevec_t *nodes)
67 {
68  json_t *name = inner_query_type(ctx, json, "$.name", eJsonString);
69  if (name == NULL)
70  {
71  return false;
72  }
73 
74  json_t *fields = inner_query_type(ctx, json, "$.fields", eJsonArray);
75  if (fields == NULL)
76  {
77  return false;
78  }
79 
80  meta_ast_t ast = {
81  .name = name->string,
82  .fields = typevec_new(sizeof(meta_field_t), typevec_len(&fields->array), ctx->arena),
83  };
84 
85  for (size_t i = 0; i < typevec_len(&fields->array); i++)
86  {
87  json_t *field = json_array_get(fields, i);
88  if (!parse_ast_field(ctx, field, ast.fields))
89  {
90  return false;
91  }
92  }
93 
94  typevec_push(nodes, &ast);
95 
96  return true;
97 }
98 
99 meta_info_t *meta_info_parse(json_t *json, scan_t *scan, logger_t *logger, arena_t *arena)
100 {
101  json_context_t ctx = {
102  .logger = logger,
103  .arena = arena,
104  .scan = scan,
105  };
106 
107  json_t *prefix = json_query_type(json, "$.prefix", eJsonString, logger, arena);
108  if (prefix == NULL)
109  {
110  return NULL;
111  }
112 
113  json_t *nodes = json_query_type(json, "$.nodes", eJsonArray, logger, arena);
114  if (nodes == NULL)
115  {
116  return NULL;
117  }
118 
119  meta_info_t *info = ARENA_MALLOC(sizeof(meta_info_t), "meta_info_parse", NULL, arena);
120  info->prefix = prefix->string;
121 
122  size_t len = typevec_len(&nodes->array);
123  info->nodes = typevec_new(sizeof(meta_ast_t), len, arena);
124 
125  for (size_t i = 0; i < len; i++)
126  {
127  json_t *node = json_array_get(nodes, i);
128  if (!parse_ast_node(&ctx, node, info->nodes))
129  {
130  return NULL;
131  }
132  }
133 
134  return info;
135 }
#define CT_TEXT_VIEW(str)
create a text view from a string literal
Definition: text.h:39
CT_JSON_API json_t * json_array_get(const json_t *json, size_t index)
get an array element by index
Definition: json.c:28
json_kind_t
the kind of json value
Definition: json.h:34
CT_JSON_API json_t * json_map_get(const json_t *json, const char *key)
get a json value from an object by key
Definition: json.c:17
CT_NODISCARD CT_SCAN_API node_t * node_new(const scan_t *scan, where_t where)
create a new node on the heap
Definition: node.c:40
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
Definition: arena.h:392
CT_NOTIFY_API event_builder_t msg_notify(INOUT_NOTNULL logger_t *logs, const diagnostic_t *diagnostic, const node_t *node, STA_FORMAT_STRING const char *fmt,...)
notify the logger of a new message
CT_NODISCARD CT_STD_API bool text_view_equal(text_view_t lhs, text_view_t rhs)
check if two strings are equal
Definition: str.c:992
CT_STD_API void * typevec_push(typevec_t *vec, const void *src)
push a value onto the vector
Definition: vector.c:156
CT_NODISCARD CT_PUREFN CT_STD_API size_t typevec_len(const typevec_t *vec)
get the length of a vector
Definition: vector.c:120
CT_NODISCARD CT_STD_API typevec_t * typevec_new(size_t width, size_t len, arena_t *arena)
create a new typed vector on the heap
Definition: vector.c:77
meta_info_t * meta_info_parse(json_t *json, scan_t *scan, logger_t *logger, arena_t *arena)
Definition: meta.c:99
meta_type_t
Definition: meta.h:18
@ eMetaMpz
Definition: meta.h:19
@ eMetaString
Definition: meta.h:21
@ eMetaUnknown
Definition: meta.h:25
@ eMetaAst
Definition: meta.h:20
an allocator object
Definition: arena.h:86
scan_t * scan
Definition: meta.c:13
logger_t * logger
Definition: meta.c:11
arena_t * arena
Definition: meta.c:12
a json value
Definition: json.h:43
text_view_t string
the string value of this node
Definition: json.h:55
typevec_t array
the array value of this node
Definition: json.h:71
where_t where
the source location of the json value
Definition: json.h:50
a logging sink
Definition: notify.c:14
arena_t * arena
Definition: notify.c:15
text_view_t name
Definition: meta.h:44
typevec_t * fields
Definition: meta.h:46
text_view_t name
Definition: meta.h:38
text_view_t prefix
Definition: meta.h:30
typevec_t * nodes
Definition: meta.h:33
a source file scanner
Definition: scan.h:24
a non-owning view of text
Definition: text.h:24
A vector with a fixed type size.
Definition: vector.h:24
CT_JSON_API json_t * json_query_type(json_t *json, const char *query, json_kind_t kind, logger_t *logger, arena_t *arena)
query a json object and ensure it is of a specific type
Definition: query.c:115