32#include "serene/vendor/utf8.h"
34#define UNEXPECTED_CHAR_MSG_LEN 48
35#define CHAR_BUFF_SIZE 5
37#define C_LAMBDA 0x03BB
39#define DEBUG_BUF_MAX_SIZE 4096
40#define METADATA_STR_DEBUG_SIZE 48
50 utf8codepoint((
const utf8_int8_t *)p->
buffer + p->
pos, &c);
56 const utf8_int8_t *next = utf8codepoint((
const utf8_int8_t *)p->
buffer + p->
pos, &c);
57 p->
pos = (size_t)(next - (
const utf8_int8_t *)p->
buffer);
67 const utf8_int8_t *after_current =
68 utf8codepoint((
const utf8_int8_t *)p->
buffer + p->
pos, ¤t);
71 if (current ==
'\0') {
75 utf8codepoint(after_current, &next);
80 return (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r' || c ==
'\f' || c ==
'\v') != 0;
87static inline bool is_digit(utf8_int32_t c) {
return c >=
'0' && c <=
'9'; }
101 }
else if (
peek(p) ==
';') {
150 if (msg ==
nullptr) {
153 utf8catcodepoint(char_buf, c,
sizeof(char_buf) - 1);
159 size_t len = strlen(msg);
161 memcpy(error_msg, msg,
len + 1);
166 err->
layer = SRN_ERR_PARSE_LAYER;
168 err->
msg = error_msg;
169 err->
as.metadata = metadata;
182 atom->
name = (
char *)name;
192 s->
data = (
char *)data;
204 num->
text = (
char *)text;
237 n->metadata =
nullptr;
251 auto start = parser->
pos;
263 if (*err !=
nullptr) {
271 if (list->as.list->head ==
nullptr) {
273 list->as.list->head = cons;
285 *err =
parse_error(parser,
'\0',
"Unterminated list, expected ')'");
295 loc->
len = parser->
pos - start;
301 list->metadata = meta;
307 auto start = parser->
pos;
319 if (*err !=
nullptr) {
325 if (push_err !=
nullptr) {
334 *err =
parse_error(parser,
'\0',
"Unterminated list, expected ')'");
344 loc->
len = parser->
pos - start;
356 node->
as.
seq = elems;
363 auto start = parser->
pos;
369 size_t len = parser->
pos - start;
372 memcpy(name, (
const char *)parser->
buffer + start,
len);
381 loc->
len = parser->
pos - start;
389 node->metadata = meta;
400 auto start = parser->
pos;
402 if (
peek(parser) ==
'-' ||
peek(parser) ==
'+') {
417 if (
peek(parser) ==
'e' ||
peek(parser) ==
'E') {
418 auto mark = parser->
pos;
421 if (
peek(parser) ==
'-' ||
peek(parser) ==
'+') {
441 size_t len = parser->
pos - start;
444 memcpy(text, (
const char *)parser->
buffer + start,
len);
453 loc->
len = parser->
pos - start;
461 node->metadata = meta;
467 auto start = parser->
pos;
473 size_t cap = parser->
len - parser->
pos + 1;
478 utf8_int32_t c =
advance(parser);
485 utf8_int32_t escaped =
advance(parser);
507 char *dst = data + out;
508 char *next = (
char *)utf8catcodepoint((utf8_int8_t *)dst, escaped, cap - out - 1);
513 out += (size_t)(next - dst);
518 char *dst = data + out;
519 char *next = (
char *)utf8catcodepoint((utf8_int8_t *)dst, c, cap - out - 1);
521 out += (size_t)(next - dst);
526 *err =
parse_error(parser,
'\0',
"Unterminated string, expected '\"'");
539 loc->
len = parser->
pos - start;
547 node->metadata = meta;
555 utf8_int32_t c =
peek(parser);
599 const utf8_int8_t *bad = utf8nvalid((
const utf8_int8_t *)parser->
buffer, parser->
len);
600 if (bad !=
nullptr) {
601 parser->
pos = (uint32_t)(bad - (
const utf8_int8_t *)parser->
buffer);
602 return parse_error(parser,
'\0',
"Malformed UTF-8 sequence");
615 if (err !=
nullptr) {
620 if (err !=
nullptr) {
627 tree->maybe_error =
nullptr;
630 fiber_arg->
tree = tree;
657 if (buf->
data ==
nullptr || buf->
len == 0) {
658 result->maybe_error =
nullptr;
660 result->reading_context = reading_context;
666 .reading_context = reading_context,
667 .buffer_id = maybe_id.
id,
682 if (fiber_result !=
nullptr) {
719 size_t used = strlen(out);
720 size_t len = strlen(fragment);
728 memcpy(out + used, fragment,
len + 1);
736 if (metadata !=
nullptr && metadata->
loc !=
nullptr) {
738 buf,
sizeof(buf),
"%" PRIu16
":%" PRIu32
":%" PRIu32, metadata->
loc->
buffer_id,
742 (void)snprintf(buf,
sizeof(buf),
"?:?:?");
751 if (err !=
nullptr) {
756 if (err !=
nullptr) {
761 if (err !=
nullptr) {
765 switch (node->
type) {
781 if (err ==
nullptr) {
785 if (err ==
nullptr) {
798 while (cons_node !=
nullptr && err ==
nullptr) {
804 if (err ==
nullptr) {
808 if (err ==
nullptr) {
816 for (
size_t i = 0; i < node->
as.
seq->
len && err ==
nullptr; i++) {
821 if (err ==
nullptr) {
825 err = maybe.maybe_error;
835 if (err !=
nullptr) {
840 if (err !=
nullptr) {
845 if (err !=
nullptr) {
array_list_maybe_element_t array_list_get(const array_list_t *al, array_list_index_t n)
Negative index is not supported.
srn_error_t * array_list_reduce(array_list_t *al, array_list_reduce_f_t f, void *init)
array_list_t array_list_empty(const srn_context_t *ctx)
Create an empty array list in the given context ctx.
srn_error_t * array_list_push(array_list_t *al, array_list_elem_t x)
Push the given element x to the end of array_list al.
A bit-partitioned trie with a tail buffer, used as a growable indexed sequence in the runtime.
#define ALLOCN(ctx, T, N)
#define ALLOC_OR_PANIC(ctx, T)
#define ALLOCN_OR_PANIC(ctx, T, N)
void * srn_mm_malloc(srn_mm_t *mm, size_t size)
Generic allocations that do not participate in the block based pools.
char * srn_error_to_string(const srn_context_t *ctx, const srn_error_t *err)
Format err as a newly allocated string of the form [TAG]: msg, allocated in ctx.
Error handling for the runtime.
#define PUSH_AND_MOVE(ctx, from, to)
#define HAS_ERROR(x)
True when x – a value carrying an ERROR_HEADER – has an error attached.
@ STRING_LENGTH_LIMIT_EXCEEDED
#define PUSH_TRACE(ctx, x)
#define ERR(ctx, err, msg)
srn_fiber_t * srn_fiber_spawn(srn_context_t *ctx, srn_fiber_entry_t entry, void *arg)
Make and schedule a fiber with every default, the engine's scheduler, the configured stack size,...
AI Generated (🤦) Fiber subsystem overview.
void * srn_fiber_result_t
What a fiber's entry produces, type-erased.
static utf8_int32_t peek_next(srn_sexp_parser_t *p)
The codepoint one past the current one, without moving p.
static void skip_whitespace(srn_sexp_parser_t *p)
srn_sexp_node_t * srn_sexp_make_list(srn_context_t *ctx)
srn_sexp_node_t * srn_sexp_make_atom(srn_context_t *ctx, const char *name)
static bool is_atom_char(utf8_int32_t c)
srn_sexp_node_t * read_expr(srn_sexp_parser_t *parser, srn_error_t **err)
static const char * node_type_debug_name(srn_sexp_node_type_e type)
static srn_error_t * parse_error(srn_sexp_parser_t *parser, const utf8_int32_t c, const char *msg)
static srn_error_t * debug_buf_append_location(const srn_context_t *ctx, char *out, const srn_metadata_t *metadata)
srn_sexp_node_t * srn_sexp_make_num(srn_context_t *ctx, const char *text)
static srn_error_t * sexp_tree_reducer(array_list_t *exprs_array, size_t n, void *expr, void *state)
static void read_comment(srn_sexp_parser_t *p)
static srn_error_t * node_to_debug_strig(const srn_context_t *ctx, srn_sexp_node_t *node, char *out)
const char * srn_sexp_to_debug_string(srn_context_t *ctx, srn_sexp_tree_t *tree)
Convert the given sexp to a string for debugging purposes.
static srn_sexp_node_t * read_atom(srn_sexp_parser_t *parser, srn_error_t **err)
srn_sexp_tree_t * srn_sexp_read_from_string(srn_context_t *ctx, void *reading_context, const char *buf)
Read the symbolic expressions from a buffer.
static srn_sexp_node_t * read_number(srn_sexp_parser_t *parser, srn_error_t **err)
A number literal: an optional leading sign, digits, an optional '.
#define UNEXPECTED_CHAR_MSG_LEN
srn_sexp_node_t * srn_sexp_make_str(srn_context_t *ctx, const char *data)
static utf8_int32_t peek(srn_sexp_parser_t *p)
static srn_sexp_node_t * read_seq(srn_sexp_parser_t *parser, srn_error_t **err)
#define METADATA_STR_DEBUG_SIZE
static bool is_atom_start(utf8_int32_t c)
static srn_error_t * debug_buf_append(const srn_context_t *ctx, char *out, const char *fragment)
Append fragment to the end of the out debug buffer (a DEBUG_BUF_MAX_SIZE buffer, treated as a growing...
#define DEBUG_BUF_MAX_SIZE
static utf8_int32_t advance(srn_sexp_parser_t *p)
srn_fiber_result_t read_from_buffer(srn_context_t *ctx, void *arg)
srn_sexp_node_t * srn_sexp_make_node(srn_context_t *ctx, srn_sexp_node_type_e type)
static srn_sexp_node_t * read_list(srn_sexp_parser_t *parser, srn_error_t **err)
static bool is_number_start(utf8_int32_t c, utf8_int32_t next)
static bool is_at_end(srn_sexp_parser_t *p)
srn_sexp_node_t * srn_sexp_make_cons(srn_context_t *ctx, srn_sexp_node_t *head, srn_sexp_node_t *tail)
static srn_sexp_node_t * read_string(srn_sexp_parser_t *parser, srn_error_t **err)
srn_sexp_tree_t * srn_sexp_read_from_file(srn_context_t *ctx, void *reading_context, const char *path)
Read the symbolic expressions from a file.
static bool is_digit(utf8_int32_t c)
static bool is_whitespace(utf8_int32_t c)
A simple sexp reader to be used with textual IR.
srn_fiber_result_t srn_fiber_wait_for(srn_fiber_t *target)
Block the calling fiber until target finishes, then return its result.
void srn_fiber_yield(void)
Yield cooperatively, re-enqueue the running fiber and run the next ready one.
srn_sm_buffer_t * srn_sm_get_buffer(srn_sm_t *sm, srn_sm_buffer_id_t id)
Return the buffer pointer of the given id, nullptr if the id does not exists.
srn_sm_maybe_id_t srn_sm_read_buffer_file(srn_sm_t *sm, const char *filepath, bool reread)
Read and buffer the given filepath into the source manager and return the buffer id.
static size_t srn_sm_buffer_len(srn_sm_buffer_t *buf)
static const unsigned char * srn_sm_buffer_data(srn_sm_buffer_t *buf)
size_t len
logical length.
const srn_context_t * ctx
The context that owns every allocation the array list retains.
srn_sexp_parser_t * parser
srn_engine_t * engine
Long term state of the compiler.
srn_mm_t * mm
Memory manager.
A runtime error, a tag classifying the failure and a human-readable message.
union srn_error_t::@110141362101221075206211275212023153042233307220 as
union srn_sexp_node_t::@313353022266020117306231170157030062126255275140 as
srn_sexp_node_type_e type
srn_metadata_t * metadata
A number literal, kept as the raw text it was written with (e.g.
const unsigned char * buffer
void * reading_context
We store whatever the caller passes as reading context to pass it back later on in the parsed tree.
const srn_sm_buffer_id_t buffer_id
unsigned char * data
nullptr when the source file was empty (no mapping exists)
uint16_t buffer_id
ID of the source buffer that is registered with the source manager.
uint32_t len
Length of the form in bytes.
uint32_t offset
Byte offset of the form's first byte in the buffer.
#define PANIC_IF_NULL(ptr)
#define SNPRINTF(buf, s, f,...)
#define PANIC_IF(cond, msg)