Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
core.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#include <stddef.h>
22#include <stdint.h>
23
24#include "llvm-c/Core.h"
25#include "llvm-c/Types.h"
26#include "serene/rt/impl/seq.h"
27
28typedef struct srn_context_t srn_context_t;
29typedef struct srn_expr_t srn_expr_t;
30typedef struct srn_value_t srn_value_t;
31typedef struct srn_closure_t srn_closure_t;
32typedef struct srn_error_t srn_error_t;
36typedef struct srn_list_t srn_list_t;
38typedef struct srn_seq_t srn_seq_t;
39typedef struct srn_map_t srn_map_t;
40
41typedef struct array_list_t array_list_t;
42typedef struct hmap_t hmap_t;
44
45// -----------------------------------------------------------------------------
46// Internal ABI
47// In C we can't mark fastcc portably; we treat codeptrs as plain fn ptrs.
48// LLVM IR will set calling convention = fastcc on definitions & calls.
49// `argv` is an array of `argc` value pointers.
50// -----------------------------------------------------------------------------
51typedef srn_value_t *(*srn_fnptr_t)(srn_context_t *ctx, srn_value_t **argv, uint32_t argc);
52
53typedef struct srn_src_location_t {
54 /// ID of the source buffer that is registered with the source manager. If we ever need to
55 /// increase this limit we have to adjust the guard at the `source_manager.c` where we check
56 /// the buffer id to be less that `UINT16_MAX`
57 uint16_t buffer_id;
58 /// Byte offset of the form's first byte in the buffer.
59 uint32_t offset;
60 /// Length of the form in bytes. Same width as `offset`, so any span the
61 /// reader can measure fits.
62 uint32_t len;
64
65typedef enum srn_ir_type_t : size_t {
68 /// IR_TYPE_Error should be last
71
72typedef struct srn_metadata_t {
73 /// `nullptr` is a valid value and represents an unknown location.
75 /// An optional pointer to the original and raw expression. We use this
76 /// to track what value/expression is a descendant of which expression.
77 void *raw_expr;
78 /// The type or better to say the category of the `raw_expr` above
81
82/// We use this for testing. Defined once in core.c.
84
85// -----------------------------------------------------------------------------
86// Values
87// This is type will be represented in LLVM like:
88// %srn_value_t = type { i64, ptr, i64 } ; { tag, loc, payload }
89// -----------------------------------------------------------------------------
108
109typedef struct srn_value_t {
112 /// IMPORTANT NOTE: The size of this union should never be larger than a word
113 union {
114 /// We represent all the immidiate numbers with this field and cast as we
115 /// to an appropriate type. It might change in the future.
116 int64_t i64;
117 double f64;
127 } as;
129
130#define SIZE_OF_VALUE_PALYLOAD 8
131_Static_assert(
132 sizeof(((srn_value_t *)0)->as) == SIZE_OF_VALUE_PALYLOAD, "srn_value_t's union has the wrong size"
133);
134
135// Shared tag-only sentinels, defined once in core.c. Declared extern (rather
136// than defined here) so every TU shares one instance with a stable address --
137// these are compared by address (e.g. `x == &false_v`), which per-TU copies
138// would break.
139extern srn_value_t nil_v;
140extern srn_value_t true_v;
141extern srn_value_t false_v;
142
143#define TYPE(value_ref) ((value_ref)->type)
144#define METADATA(value_ref) ((value_ref)->metadata)
145#define IS_A(value_ref, field) (TYPE(value_ref) == (field))
146#define IS_TRUE(value_ref) (TYPE(value_ref) == VTrue)
147#define IS_FALSE(value_ref) (TYPE(value_ref) == VFalse)
148#define IS_NIL(value_ref) (TYPE(value_ref) == VNil)
149
150#define AS_I64(value_ref) ((value_ref)->as.i64)
151#define AS_F64(value_ref) ((value_ref)->as.f64)
152#define AS_CLOSURE(value_ref) ((value_ref)->as.closure)
153#define AS_NS(value_ref) ((value_ref)->as.ns)
154#define AS_STRING(value_ref) ((value_ref)->as.string)
155#define AS_SYMBOL(value_ref) ((value_ref)->as.symbol)
156#define AS_ERROR(value_ref) ((value_ref)->as.error)
157#define AS_LIST(value_ref) ((value_ref)->as.list)
158#define AS_KEYWORD(value_ref) ((value_ref)->as.keyword)
159#define AS_SEQ(value_ref) ((value_ref)->as.seq)
160#define AS_MAP(value_ref) ((value_ref)->as.map)
161
162/// Creates a new serene value. We always heap allocate the values. So, ANY
163/// value creation should go through this function
164[[nodiscard]] [[gnu::nonnull(1)]] [[gnu::returns_nonnull]]
166srn_value_make(srn_context_t *ctx, srn_value_tag_t tag, srn_metadata_t *metadata, void *payload);
167
168/// LLVM type for srn_value_t in LLVM IR. { i64, ptr, i64 }
169static inline LLVMTypeRef srn_llvm_value_t(LLVMContextRef llctx) {
170 LLVMTypeRef i64t = LLVMInt64TypeInContext(llctx);
171
172 // opaque ptr
173 LLVMTypeRef i8t = LLVMInt8TypeInContext(llctx);
174 LLVMTypeRef ptrt = LLVMPointerType(i8t, 0);
175
176 LLVMTypeRef fields[3];
177 fields[0] = i64t; // type tag (srn_value_tag_t as i64)
178 fields[1] = ptrt; // loc pointer
179 fields[2] = i64t; // payload (the union)
180
181 LLVMTypeRef st = LLVMStructCreateNamed(llctx, "srn_value_t");
182 LLVMStructSetBody(st, fields, 3, 0);
183 return st;
184}
185
186// -----------------------------------------------------------------------------
187// Source/Value Graph
188// This graph forms the fundamental data layer to do graph reduction.
189// -----------------------------------------------------------------------------
190typedef size_t srn_node_type_t;
191
192typedef struct srn_term_t {
193 /// This type field is a bare number value that we split into a few ranges.
194 ///
195 /// Each range is dedicated to a certain level or better to say phase of the evaluation.
196 /// For example:
197 ///
198 /// - SIZE_MAX: Means the node is containing an `srn_error_t`, so the `data` pointer is pointing
199 /// to a `srn_error_t`.
200 /// - 0..1000: Is reserved to the first layer of IR (see `serene/ir/reader.h`).
201 ///
202 /// And so on. Each layer/phase of the compiler that needs to walk/transform the graph can add
203 /// its own range.
206
207 /// An opaque pointer that depending on the `type` might point to totally different type of
208 /// data.
209 void *data;
210 /// Since multiple fibers can work on the same node at the same time, writers have to acquire the
211 /// lock.
214
215typedef struct srn_graph_t {
216 // Root nodes of the tree. Each IR has a dedicated root node
217
218 /// A hashmap that maps namespace names to their value. When operating on
219 /// this map, e.g. setting the new `hmap` after inserting a namespace which will lead to a new
220 /// `hmap_t` make sure to lock `ns_map_lock`.
223 // TODO(lxsameer): Do we need a lock per namespace here? or should we have one
224 // in the namespace itself?
srn_metadata_t absurd_metadata
We use this for testing. Defined once in core.c.
Definition core.c:26
srn_value_t false_v
Definition core.c:29
srn_value_t true_v
Definition core.c:28
srn_value_t nil_v
Definition core.c:27
static LLVMTypeRef srn_llvm_value_t(LLVMContextRef llctx)
LLVM type for srn_value_t in LLVM IR. { i64, ptr, i64 }.
Definition core.h:169
srn_ir_type_t
Definition core.h:65
@ IR_TYPE_IR_READER
Definition core.h:66
@ IR_TYPE_KLEENE
Definition core.h:67
@ IR_TYPE_Error
IR_TYPE_Error should be last.
Definition core.h:69
struct srn_string_t srn_string_t
Definition core.h:34
srn_value_t * srn_value_make(srn_context_t *ctx, srn_value_tag_t tag, srn_metadata_t *metadata, void *payload)
Creates a new serene value.
Definition core.c:36
struct srn_keyword_t srn_keyword_t
Definition core.h:37
size_t srn_node_type_t
Definition core.h:190
struct srn_namespace_t srn_namespace_t
Definition core.h:33
srn_value_tag_e
Definition core.h:90
@ 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
struct srn_map_t srn_map_t
Definition core.h:39
#define SIZE_OF_VALUE_PALYLOAD
Definition core.h:130
struct srn_fiber_mutex_t srn_fiber_mutex_t
Definition core.h:43
struct srn_error_t srn_error_t
Definition core.h:32
struct srn_symbol_t srn_symbol_t
Definition core.h:35
struct hmap_t hmap_t
Definition core.h:42
struct srn_expr_t srn_expr_t
Definition core.h:29
struct srn_seq_t srn_seq_t
Definition core.h:38
struct srn_list_t srn_list_t
Definition core.h:36
enum srn_value_tag_e srn_value_tag_t
This is an implementation of bit - partitioned, persistent, immutable sequence For more information,...
A runtime error, a tag classifying the failure and a human-readable message.
Definition errors.h:173
srn_fiber_mutex_t * ns_map_lock
Definition core.h:222
hmap_t * namespaces
A hashmap that maps namespace names to their value.
Definition core.h:221
A keyword, just a name.
Definition keywords.h:29
A persistent, immutable map.
Definition maps.h:29
srn_ir_type_t ir_type
The type or better to say the category of the raw_expr above.
Definition core.h:79
srn_src_location_t * loc
nullptr is a valid value and represents an unknown location.
Definition core.h:74
void * raw_expr
An optional pointer to the original and raw expression.
Definition core.h:77
A persistent, immutable, indexed sequence.
Definition seqs.h:27
uint16_t buffer_id
ID of the source buffer that is registered with the source manager.
Definition core.h:57
uint32_t len
Length of the form in bytes.
Definition core.h:62
uint32_t offset
Byte offset of the form's first byte in the buffer.
Definition core.h:59
srn_node_type_t type
This type field is a bare number value that we split into a few ranges.
Definition core.h:204
srn_fiber_mutex_t * lock
Since multiple fibers can work on the same node at the same time, writers have to acquire the lock.
Definition core.h:212
srn_metadata_t * metadata
Definition core.h:205
void * data
An opaque pointer that depending on the type might point to totally different type of data.
Definition core.h:209
srn_metadata_t * metadata
Definition core.h:111
srn_namespace_t * ns
Definition core.h:119
srn_list_t * list
Definition core.h:123
int64_t i64
We represent all the immidiate numbers with this field and cast as we to an appropriate type.
Definition core.h:116
double f64
Definition core.h:117
srn_seq_t * seq
Definition core.h:125
srn_closure_t * closure
Definition core.h:118
union srn_value_t::@333325137367112222275110336355257173264057161216 as
IMPORTANT NOTE: The size of this union should never be larger than a word.
srn_error_t * error
Definition core.h:122
srn_map_t * map
Definition core.h:126
srn_symbol_t * symbol
Definition core.h:121
srn_value_tag_t type
Definition core.h:110
srn_keyword_t * keyword
Definition core.h:124
srn_string_t * string
Definition core.h:120