Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
print.c
Go to the documentation of this file.
1/* -*- C -*-
2 * Serene programming language
3 * Copyright (C) 2019-2026 Sameer Rahmani <lxsameer@lxsameer.com>
4 *
5 * This library is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 */
15#include "serene/rt/print.h"
16
17#include <inttypes.h>
18
19#include "serene/rt/context.h"
20#include "serene/rt/core.h"
21#include "serene/rt/errors.h"
22#include "serene/rt/impl/seq.h"
23#include "serene/rt/keywords.h"
24#include "serene/rt/lists.h"
25#include "serene/rt/maps.h"
27#include "serene/rt/seqs.h"
28#include "serene/rt/strings.h"
29#include "serene/rt/symbols.h"
30#include "serene/utils.h"
31
32static void print_string_payload(FILE *out, const srn_string_t *s) {
33 fputc('"', out);
34 for (size_t i = 0; i < s->len; i++) {
35 uint8_t c = s->buffer[i];
36 switch (c) {
37 case '"':
38 fputs("\\\"", out);
39 break;
40 case '\\':
41 fputs("\\\\", out);
42 break;
43 case '\n':
44 fputs("\\n", out);
45 break;
46 case '\t':
47 fputs("\\t", out);
48 break;
49 case '\r':
50 fputs("\\r", out);
51 break;
52 default:
53 fputc((int)c, out);
54 break;
55 }
56 }
57 fputc('"', out);
58}
59
60static inline void write_bytes(FILE *out, const uint8_t *buf, size_t len) {
61 if (len > 0) {
62 (void)fwrite(buf, 1, len, out);
63 }
64}
65
66static void print_list(FILE *out, srn_context_t *ctx, const srn_value_t *v) {
67 fputc('(', out);
68 srn_list_t *l = AS_LIST(v);
69 bool first = true;
70 for (srn_list_node_t *n = l->head; n != nullptr; n = n->next) {
71 if (!first) {
72 fputc(' ', out);
73 }
74 first = false;
75 srn_value_print(out, ctx, n->value);
76 }
77 fputc(')', out);
78}
79
80static void print_seq(FILE *out, srn_context_t *ctx, const srn_value_t *v) {
81 fputc('[', out);
82 srn_seq_t *s = AS_SEQ(v);
83 for (size_t i = 0; i < s->inner.len; i++) {
84 if (i > 0) {
85 fputc(' ', out);
86 }
88 if (r.maybe_error != nullptr) {
89 fputs("#<seq-error>", out);
90 continue;
91 }
92 srn_value_print(out, ctx, (srn_value_t *)r.data);
93 }
94 fputc(']', out);
95}
96
97void srn_value_print(FILE *out, srn_context_t *ctx, const srn_value_t *v) {
98 PANIC_IF_NULL(out);
99 PANIC_IF_NULL(ctx);
100 PANIC_IF_NULL(v);
101
102 switch (v->type) {
103 case VNil:
104 fputs("nil", out);
105 break;
106 case VTrue:
107 fputs("true", out);
108 break;
109 case VFalse:
110 fputs("false", out);
111 break;
112
113 case VI64:
114 (void)fprintf(out, "%" PRId64, AS_I64(v));
115 break;
116
117 case VF64:
118 // %.17g is enough digits to round-trip a double exactly.
119 (void)fprintf(out, "%.17g", AS_F64(v));
120 break;
121
122 case VString:
124 break;
125
126 case VSymbol: {
127 srn_symbol_t *sym = AS_SYMBOL(v);
128 // The qualified form, so the printed atom names one symbol, symbols
129 // intern per namespace and the bare name alone is ambiguous across them.
130 if (sym->ns != nullptr) {
131 write_bytes(out, sym->ns->name->buffer, sym->ns->name->len);
132 fputc('/', out);
133 }
134 write_bytes(out, sym->name->buffer, sym->name->len);
135 break;
136 }
137
138 case VKeyword: {
140 fputc(':', out);
141 write_bytes(out, k->name->buffer, k->name->len);
142 break;
143 }
144
145 case VNamespace: {
146 srn_namespace_t *ns = AS_NS(v);
147 fputs("#<ns ", out);
148 write_bytes(out, ns->name->buffer, ns->name->len);
149 fputc('>', out);
150 break;
151 }
152
153 case VList:
154 print_list(out, ctx, v);
155 break;
156
157 case VSeq:
158 print_seq(out, ctx, v);
159 break;
160
161 case VMap: {
162 // CHAMT walker is not exposed; show size only for now.
163 srn_map_t *m = AS_MAP(v);
164 (void)fprintf(out, "#<map size=%zu>", m->inner.len);
165 break;
166 }
167
168 case VClosure:
169 fputs("#<closure>", out);
170 break;
171
172 case VError: {
173 srn_error_t *e = AS_ERROR(v);
174 (void)fprintf(out, "#<error tag=%d", (int)e->tag);
175 if (e->msg != nullptr) {
176 (void)fprintf(out, " %s", e->msg);
177 }
178 fputc('>', out);
179 break;
180 }
181
182 case VQuote:
183 fputs("#<quote>", out);
184 break;
185
186 default:
187 fputs("#<unknown>", out);
188 break;
189 }
190}
191
192void srn_value_println(FILE *out, srn_context_t *ctx, const srn_value_t *v) {
193 srn_value_print(out, ctx, v);
194 fputc('\n', out);
195}
int n
Definition acutest.h:525
#define AS_LIST(value_ref)
Definition core.h:157
#define AS_F64(value_ref)
Definition core.h:151
#define AS_SYMBOL(value_ref)
Definition core.h:155
@ VQuote
Definition core.h:98
@ VSeq
Definition core.h:97
@ VNamespace
Definition core.h:100
@ VClosure
Definition core.h:99
@ VNil
Definition core.h:91
@ VList
Definition core.h:96
@ VFalse
Definition core.h:93
@ VF64
Definition core.h:95
@ VSymbol
Definition core.h:102
@ VI64
Definition core.h:94
@ VMap
Definition core.h:104
@ VError
VError should be last.
Definition core.h:106
@ VKeyword
Definition core.h:103
@ VTrue
Definition core.h:92
@ VString
Definition core.h:101
#define AS_STRING(value_ref)
Definition core.h:154
#define AS_NS(value_ref)
Definition core.h:153
#define AS_I64(value_ref)
Definition core.h:150
#define AS_MAP(value_ref)
Definition core.h:160
#define AS_SEQ(value_ref)
Definition core.h:159
#define AS_ERROR(value_ref)
Definition core.h:156
#define AS_KEYWORD(value_ref)
Definition core.h:158
Error handling for the runtime.
A namespace is an isolation for names nad technically a compilation unit.
void srn_value_print(FILE *out, srn_context_t *ctx, const srn_value_t *v)
Print a value to out in its S-expression form.
Definition print.c:97
static void print_list(FILE *out, srn_context_t *ctx, const srn_value_t *v)
Definition print.c:66
static void print_seq(FILE *out, srn_context_t *ctx, const srn_value_t *v)
Definition print.c:80
void srn_value_println(FILE *out, srn_context_t *ctx, const srn_value_t *v)
Same as srn_value_print followed by ' '.
Definition print.c:192
static void print_string_payload(FILE *out, const srn_string_t *s)
Definition print.c:32
static void write_bytes(FILE *out, const uint8_t *buf, size_t len)
Definition print.c:60
seq_lookup_result_t seq_get(const seq_t *seq, size_t n)
Negative index is not supported.
Definition seq.c:205
This is an implementation of bit - partitioned, persistent, immutable sequence For more information,...
const size_t len
auto first
size_t len
Number of key/value pairs in the map.
Definition hashmap.h:97
seq_elem_t data
Definition seq.h:135
size_t len
logical length.
Definition seq.h:161
A runtime error, a tag classifying the failure and a human-readable message.
Definition errors.h:173
char * msg
Definition errors.h:176
srn_error_tag_t tag
Definition errors.h:175
A keyword, just a name.
Definition keywords.h:29
srn_string_t * name
Definition keywords.h:30
A list is a singly linked sequence of values.
Definition lists.h:30
srn_list_node_t * head
Definition lists.h:37
A persistent, immutable map.
Definition maps.h:29
hmap_t inner
Definition maps.h:30
srn_string_t * name
Definition namespaces.h:40
A persistent, immutable, indexed sequence.
Definition seqs.h:27
seq_t inner
Definition seqs.h:28
uint8_t buffer[]
The buffer that holds the WTF8 sequence.
Definition strings.h:66
size_t len
length of the WTF-8 sequence in bytes
Definition strings.h:64
srn_namespace_t * ns
Definition symbols.h:32
srn_string_t * name
Definition symbols.h:31
srn_value_tag_t type
Definition core.h:110
#define PANIC_IF_NULL(ptr)
Definition utils.h:66