Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
kleene.h
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 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21/** @file
22 In admiration of [Stephen Cole Kleene](https://en.wikipedia.org/wiki/Stephen_Cole_Kleene).
23
24 The first layer of IR of the compiler. Any source level language should elaborate to this
25 IR.
26
27 The tree is deliberately small and already in A-normal form. Every operand is an
28 atom, a variable, a literal, or a global reference, and anything compound is
29 named by an enclosing `let`. The reader checks that shape and rejects input that
30 breaks it. Nodes carry no source level types.
31*/
32
33#include <stddef.h>
34#include <stdint.h>
35
36#include "serene/rt/errors.h"
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42typedef struct srn_mm_t srn_mm_t;
44typedef struct srn_value_t srn_value_t;
47
48typedef enum srn_kleene_node_tag_t : size_t {
49 /// local variable reference
51 /// literal (int, string, char)
53 /// top level name reference
55 /// closure: params, body
57 /// function application
59 /// partial application
61 /// primitive op on atoms
63 /// constructor: integer tag + atom fields
65 /// bind one expression, then continue
67 /// branch on a scrutinee's constructor tag
69 /// define a label that can jump to
71 /// jump to a label with atom args
74
76
77/// One arm of a `case`. Matches a constructor tag and binds that constructor's
78/// fields to fresh locals before running the body.
79typedef struct srn_kleene_arm_t {
80 /// Constructor tag this arm matches. This tag is basically the tag number
81 /// of a constructor in a the type.
82 int32_t tag;
83 /// Names bound to the constructor's fields, in order
84 const char **binders;
85 /// Number of fields the constructor carries
87 /// The body of the case
90
91/// SRN_KL_VAR: a reference to a bound local by name.
92typedef struct srn_kleene_local_t {
93 const char *name;
95
96/// SRN_KL_GLOBAL: a reference to a top-level definition by name.
97typedef struct srn_kleene_global_t {
98 const char *name;
100
101/// SRN_KL_FN: a closure. Free variables are captured implicitly by the lowering,
102/// the source lists only the parameters.
103typedef struct srn_kleene_fn_t {
104 /// Parameter names, in order
105 const char **params;
109
110/// SRN_KL_APP and SRN_KL_PAPP: `fn` applied to `args`. Each arg is an atom
111/// node (VAR, LIT, or GLOBAL).
117
118/// SRN_KL_PRIM: primitive `op` over atom `args`.
119typedef struct srn_kleene_prim_t {
120 /// Name of the primitive operation
121 const char *op;
123 size_t arg_count;
125
126/// SRN_KL_CTOR: build a value with constructor `tag` from atom `fields`.
127typedef struct srn_kleene_ctor_t {
128 /// Constructor tag, relative to the value's type
129 int32_t tag;
130 /// Atom fields
132 /// Number of fields
135
136/// SRN_KL_LET: evaluate `rhs`, bind it to `name`, then evaluate `body`.
137typedef struct srn_kleene_let_t {
138 /// Name the result of `rhs` is bound to
139 const char *name;
140 /// The expression to evaluate and bind
142 /// The continuation, evaluated with `name` in scope
145
146/// SRN_KL_CASE: match `scrutinee` against `arms`. The reader guarantees the tags
147/// are distinct.
148typedef struct srn_kleene_case_t {
149 /// The atom being matched
151 /// The arms, one per matched constructor tag
153 /// Number of arms
154 size_t arm_count;
156
157/// SRN_KL_LABEL: a label `name` taking `params`, whose `body` runs when jumped
158/// to, in scope of `cont`.
159typedef struct srn_kleene_label_t {
160 /// The label's name, referenced by a matching jump
161 const char *name;
162 /// Parameter names the jump supplies
163 const char **params;
164 /// Number of parameters
166 /// The code run when the label is jumped to
168 /// The continuation in scope of the label
171
172/// SRN_KL_JUMP: hand `args` to the label named `label`.
173typedef struct srn_kleene_jump_t {
174 /// Name of the target label
175 const char *label;
176 /// Atom arguments handed to the label's parameters
178 /// Number of arguments
179 size_t arg_count;
181
182/// A node of the Kleene tree. `tag` selects the active union member.
184 /// Which variant `as` holds
186
187 /// Source metadata for diagnostics, may be NULL
189
190 /// Every member is one word, a pointer or an immediate, so the union stays
191 /// word sized. The static assert below pins this.
192 union {
193 /// SRN_KL_VAR
195 /// SRN_KL_LIT: a literal the reader has already boxed
197 /// SRN_KL_GLOBAL
199 /// SRN_KL_FN
201 /// SRN_KL_APP and SRN_KL_PAPP
203 /// SRN_KL_PRIM
205 /// SRN_KL_CTOR
207 /// SRN_KL_LET
209 /// SRN_KL_CASE
211 /// SRN_KL_LABEL
213 /// SRN_KL_JUMP
215 } as;
216};
217
218_Static_assert(
219 sizeof(((srn_kleene_node_t *)0)->as) == sizeof(void *),
220 "srn_kleene_node_t's union should be word sized"
221);
222
223/// A single top-level definition, `(def name body)`.
224typedef struct {
225 const char *name; ///< the global this definition binds
226 srn_kleene_node_t *body; ///< the definition's value, often an FN
228
229/// A parsed Kleene module, the unit the reader returns and the builder consumes.
230typedef struct {
231 srn_kleene_def_t *defs; ///< top-level definitions in source order
232 size_t def_count; ///< number of definitions
234
235/**
236 * Parse the Kleene source in `src` (of length `len`) into `*out`.
237 *
238 * Nodes are allocated from `mm` and remain valid for that arena's lifetime.
239 * On success returns NULL and writes the module to `*out`. On a syntax or shape
240 * error returns an error built on `ctx`, describing the offending offset, and
241 * leaves `*out` untouched.
242 */
244
245/**
246 * Write `module` back out as Kleene text into the buffer `buf` of size `cap`.
247 *
248 * Returns the number of bytes the full text needs, not counting a terminating
249 * NUL. When that exceeds `cap` the buffer holds a truncated result, call again
250 * with a large enough buffer. Reading then printing a module yields equivalent
251 * text, which makes the format usable as a golden-test artifact.
252 */
253size_t srn_kleene_print(const srn_kleene_module_t *module, char *buf, size_t cap);
254
255#ifdef __cplusplus
256}
257#endif
Error handling for the runtime.
size_t srn_kleene_print(const srn_kleene_module_t *module, char *buf, size_t cap)
Write module back out as Kleene text into the buffer buf of size cap.
srn_kleene_node_tag_t
Definition kleene.h:48
@ SRN_KL_GLOBAL
top level name reference
Definition kleene.h:54
@ SRN_KL_CTOR
constructor: integer tag + atom fields
Definition kleene.h:64
@ SRN_KL_LIT
literal (int, string, char)
Definition kleene.h:52
@ SRN_KL_VAR
local variable reference
Definition kleene.h:50
@ SRN_KL_PRIM
primitive op on atoms
Definition kleene.h:62
@ SRN_KL_FN
closure: params, body
Definition kleene.h:56
@ SRN_KL_LABEL
define a label that can jump to
Definition kleene.h:70
@ SRN_KL_APP
function application
Definition kleene.h:58
@ SRN_KL_JUMP
jump to a label with atom args
Definition kleene.h:72
@ SRN_KL_CASE
branch on a scrutinee's constructor tag
Definition kleene.h:68
@ SRN_KL_LET
bind one expression, then continue
Definition kleene.h:66
@ SRN_KL_PAPP
partial application
Definition kleene.h:60
srn_error_t * srn_kleene_read(srn_context_t *ctx, const char *src, srn_kleene_module_t *out)
Parse the Kleene source in src (of length len) into *out.
struct srn_value_t srn_value_t
Definition kleene.h:44
struct srn_metadata_t srn_metadata_t
Definition kleene.h:45
A runtime error, a tag classifying the failure and a human-readable message.
Definition errors.h:173
SRN_KL_APP and SRN_KL_PAPP: fn applied to args.
Definition kleene.h:112
srn_kleene_node_t ** args
Definition kleene.h:114
size_t arg_count
Definition kleene.h:115
srn_kleene_node_t * fn
Definition kleene.h:113
One arm of a case.
Definition kleene.h:79
size_t binder_count
Number of fields the constructor carries.
Definition kleene.h:86
srn_kleene_node_t * body
The body of the case.
Definition kleene.h:88
int32_t tag
Constructor tag this arm matches.
Definition kleene.h:82
const char ** binders
Names bound to the constructor's fields, in order.
Definition kleene.h:84
SRN_KL_CASE: match scrutinee against arms.
Definition kleene.h:148
srn_kleene_arm_t * arms
The arms, one per matched constructor tag.
Definition kleene.h:152
srn_kleene_node_t * scrutinee
The atom being matched.
Definition kleene.h:150
size_t arm_count
Number of arms.
Definition kleene.h:154
SRN_KL_CTOR: build a value with constructor tag from atom fields.
Definition kleene.h:127
srn_kleene_node_t ** fields
Atom fields.
Definition kleene.h:131
int32_t tag
Constructor tag, relative to the value's type.
Definition kleene.h:129
size_t field_count
Number of fields.
Definition kleene.h:133
A single top-level definition, (def name body).
Definition kleene.h:224
const char * name
the global this definition binds
Definition kleene.h:225
srn_kleene_node_t * body
the definition's value, often an FN
Definition kleene.h:226
SRN_KL_FN: a closure.
Definition kleene.h:103
size_t param_count
Definition kleene.h:106
srn_kleene_node_t * body
Definition kleene.h:107
const char ** params
Parameter names, in order.
Definition kleene.h:105
SRN_KL_GLOBAL: a reference to a top-level definition by name.
Definition kleene.h:97
const char * name
Definition kleene.h:98
SRN_KL_JUMP: hand args to the label named label.
Definition kleene.h:173
size_t arg_count
Number of arguments.
Definition kleene.h:179
const char * label
Name of the target label.
Definition kleene.h:175
srn_kleene_node_t ** args
Atom arguments handed to the label's parameters.
Definition kleene.h:177
SRN_KL_LABEL: a label name taking params, whose body runs when jumped to, in scope of cont.
Definition kleene.h:159
srn_kleene_node_t * cont
The continuation in scope of the label.
Definition kleene.h:169
const char * name
The label's name, referenced by a matching jump.
Definition kleene.h:161
size_t param_count
Number of parameters.
Definition kleene.h:165
const char ** params
Parameter names the jump supplies.
Definition kleene.h:163
srn_kleene_node_t * body
The code run when the label is jumped to.
Definition kleene.h:167
SRN_KL_LET: evaluate rhs, bind it to name, then evaluate body.
Definition kleene.h:137
srn_kleene_node_t * body
The continuation, evaluated with name in scope.
Definition kleene.h:143
const char * name
Name the result of rhs is bound to.
Definition kleene.h:139
srn_kleene_node_t * rhs
The expression to evaluate and bind.
Definition kleene.h:141
SRN_KL_VAR: a reference to a bound local by name.
Definition kleene.h:92
const char * name
Definition kleene.h:93
A parsed Kleene module, the unit the reader returns and the builder consumes.
Definition kleene.h:230
srn_kleene_def_t * defs
top-level definitions in source order
Definition kleene.h:231
size_t def_count
number of definitions
Definition kleene.h:232
A node of the Kleene tree. tag selects the active union member.
Definition kleene.h:183
srn_kleene_case_t * scase
SRN_KL_CASE.
Definition kleene.h:210
srn_kleene_local_t * var
SRN_KL_VAR.
Definition kleene.h:194
srn_value_t * lit
SRN_KL_LIT: a literal the reader has already boxed.
Definition kleene.h:196
union srn_kleene_node_t::@021011016321007233225152122132222022262256275064 as
Every member is one word, a pointer or an immediate, so the union stays word sized.
srn_kleene_label_t * label
SRN_KL_LABEL.
Definition kleene.h:212
srn_kleene_prim_t * prim
SRN_KL_PRIM.
Definition kleene.h:204
srn_metadata_t * metadata
Source metadata for diagnostics, may be NULL.
Definition kleene.h:188
srn_kleene_fn_t * fn
SRN_KL_FN.
Definition kleene.h:200
srn_kleene_ctor_t * ctor
SRN_KL_CTOR.
Definition kleene.h:206
srn_kleene_jump_t * jump
SRN_KL_JUMP.
Definition kleene.h:214
srn_kleene_app_t * app
SRN_KL_APP and SRN_KL_PAPP.
Definition kleene.h:202
srn_kleene_let_t * let
SRN_KL_LET.
Definition kleene.h:208
srn_kleene_global_t * global
SRN_KL_GLOBAL.
Definition kleene.h:198
srn_kleene_node_tag_t tag
Which variant as holds.
Definition kleene.h:185
SRN_KL_PRIM: primitive op over atom args.
Definition kleene.h:119
const char * op
Name of the primitive operation.
Definition kleene.h:121
size_t arg_count
Definition kleene.h:123
srn_kleene_node_t ** args
Definition kleene.h:122
Main memory manager structure that will own all the allocated blocks and data.
Definition interface.h:112