move include/expel to include/ubik
Haldean Brown
6 years ago
0 | nobase_include_HEADERS = expel/bdagc.h expel/stream.h expel/timer.h expel/ast.h expel/const.h expel/assert.h expel/env.h expel/token.h expel/gen.h expel/natives.h expel/expel.h expel/dagc.h expel/uri.h expel/def-native.h expel/value.h expel/string.h expel/util.h expel/gc.h expel/compile.h expel/pointerset.h expel/schedule.h expel/parse.h expel/types.h expel/vector.h expel/resolve.h expel/closure.h expel/streamutil.h | |
0 | nobase_include_HEADERS = ubik/bdagc.h ubik/stream.h ubik/timer.h ubik/ast.h ubik/const.h ubik/assert.h ubik/env.h ubik/token.h ubik/gen.h ubik/natives.h ubik/ubik.h ubik/dagc.h ubik/uri.h ubik/def-native.h ubik/value.h ubik/string.h ubik/util.h ubik/gc.h ubik/compile.h ubik/pointerset.h ubik/schedule.h ubik/parse.h ubik/types.h ubik/vector.h ubik/resolve.h ubik/closure.h ubik/streamutil.h | |
1 | 1 | |
2 | expel/const.h: ../res/const.txt | |
2 | ubik/const.h: ../res/const.txt | |
3 | 3 | $(AWK) -f ../res/compile-const.awk $< > $@ |
0 | /* | |
1 | * assert.h: compile-conditional assertions | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef XL_RECKLESS | |
20 | #include <stdio.h> | |
21 | #include <stdlib.h> | |
22 | #include "expel/util.h" | |
23 | ||
24 | int | |
25 | break_on_assert(); | |
26 | ||
27 | #define xl_assert(x) do { \ | |
28 | if (!(x)) { \ | |
29 | fprintf(stderr, \ | |
30 | "assertion %s:%d failed: %s\n", \ | |
31 | __FILE__, __LINE__, #x); \ | |
32 | break_on_assert(); \ | |
33 | xl_trace_print(); \ | |
34 | exit(EXIT_FAILURE); \ | |
35 | }} while (0) | |
36 | #else | |
37 | #define xl_assert(x) | |
38 | #endif |
0 | /* | |
1 | * ast.h: in-memory ast representation | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "expel/expel.h" | |
21 | #include "expel/vector.h" | |
22 | ||
23 | #include <stdbool.h> | |
24 | ||
25 | /* The maximum number of subexpressions any one expression can have. */ | |
26 | #define XL_MAX_SUBEXPRS 8 | |
27 | ||
28 | enum expr_type | |
29 | { | |
30 | EXPR_APPLY = 1, | |
31 | EXPR_ATOM, | |
32 | EXPR_LAMBDA, | |
33 | EXPR_CONSTRUCTOR, | |
34 | EXPR_CONDITIONAL, | |
35 | EXPR_BLOCK | |
36 | }; | |
37 | ||
38 | enum type_expr_type | |
39 | { | |
40 | TYPE_EXPR_APPLY = 1, | |
41 | TYPE_EXPR_ATOM | |
42 | }; | |
43 | ||
44 | enum atom_type | |
45 | { | |
46 | ATOM_INT = 1, | |
47 | ATOM_NUM, | |
48 | ATOM_NAME, | |
49 | ATOM_QUALIFIED, | |
50 | ATOM_TYPE_NAME, | |
51 | ATOM_STRING | |
52 | }; | |
53 | ||
54 | struct xl_ast; | |
55 | struct xl_resolve_scope; | |
56 | struct xl_resolve_name_loc; | |
57 | ||
58 | enum type_type | |
59 | { | |
60 | TYPE_RECORD = 1, | |
61 | }; | |
62 | ||
63 | struct xl_ast_loc | |
64 | { | |
65 | size_t line_start; | |
66 | size_t line_end; | |
67 | size_t col_start; | |
68 | size_t col_end; | |
69 | }; | |
70 | ||
71 | struct xl_ast_atom | |
72 | { | |
73 | union | |
74 | { | |
75 | char *str; | |
76 | xl_word integer; | |
77 | xl_float number; | |
78 | struct | |
79 | { | |
80 | char *head; | |
81 | char *tail; | |
82 | } qualified; | |
83 | }; | |
84 | enum atom_type atom_type; | |
85 | struct xl_resolve_name_loc *name_loc; | |
86 | struct xl_ast_loc loc; | |
87 | }; | |
88 | ||
89 | struct xl_ast_arg_list | |
90 | { | |
91 | char *name; | |
92 | struct xl_ast_arg_list *next; | |
93 | struct xl_dagc_node *gen; | |
94 | struct xl_ast_loc loc; | |
95 | }; | |
96 | ||
97 | struct xl_ast_expr | |
98 | { | |
99 | union | |
100 | { | |
101 | struct xl_ast_atom *atom; | |
102 | struct | |
103 | { | |
104 | struct xl_ast_expr *head; | |
105 | struct xl_ast_expr *tail; | |
106 | } apply; | |
107 | struct | |
108 | { | |
109 | struct xl_ast_arg_list *args; | |
110 | struct xl_ast_expr *body; | |
111 | } lambda; | |
112 | struct | |
113 | { | |
114 | char *type_name; | |
115 | struct xl_ast *scope; | |
116 | } constructor; | |
117 | struct | |
118 | { | |
119 | struct xl_ast_expr *cond; | |
120 | struct xl_ast_expr *implied; | |
121 | struct xl_ast_expr *opposed; | |
122 | } condition; | |
123 | struct xl_ast *block; | |
124 | }; | |
125 | enum expr_type expr_type; | |
126 | ||
127 | struct xl_resolve_scope *scope; | |
128 | struct xl_dagc_node *gen; | |
129 | struct xl_ast_loc loc; | |
130 | }; | |
131 | ||
132 | struct xl_ast_type_expr | |
133 | { | |
134 | union | |
135 | { | |
136 | char *name; | |
137 | struct | |
138 | { | |
139 | struct xl_ast_type_expr *head; | |
140 | struct xl_ast_type_expr *tail; | |
141 | } apply; | |
142 | }; | |
143 | enum type_expr_type type_expr_type; | |
144 | struct xl_ast_loc loc; | |
145 | }; | |
146 | ||
147 | struct xl_ast_binding | |
148 | { | |
149 | char *name; | |
150 | struct xl_ast_expr *expr; | |
151 | struct xl_ast_type_expr *type_expr; | |
152 | struct xl_ast_loc loc; | |
153 | }; | |
154 | ||
155 | struct xl_ast_import_list | |
156 | { | |
157 | char *name; | |
158 | struct xl_ast_loc loc; | |
159 | struct xl_ast_import_list *next; | |
160 | }; | |
161 | ||
162 | struct xl_ast_member_list | |
163 | { | |
164 | char *name; | |
165 | struct xl_ast_type_expr *type; | |
166 | struct xl_ast_loc loc; | |
167 | struct xl_ast_member_list *next; | |
168 | }; | |
169 | ||
170 | struct xl_ast_type | |
171 | { | |
172 | union | |
173 | { | |
174 | struct xl_ast_member_list *members; | |
175 | }; | |
176 | char *name; | |
177 | enum type_type type; | |
178 | struct xl_ast_loc loc; | |
179 | }; | |
180 | ||
181 | struct xl_ast | |
182 | { | |
183 | /* members are struct xl_ast_binding pointers */ | |
184 | struct xl_vector bindings; | |
185 | /* members are struct xl_ast_type pointers */ | |
186 | struct xl_vector types; | |
187 | /* to run when ast is evaluted */ | |
188 | struct xl_ast_expr *immediate; | |
189 | /* things this depends on existing */ | |
190 | struct xl_ast_import_list *imports; | |
191 | /* everything in scope in this ast */ | |
192 | struct xl_resolve_scope *scope; | |
193 | /* the location of this ast (useful because there are sub-ASTs whose | |
194 | * location is actually interesting) */ | |
195 | struct xl_ast_loc loc; | |
196 | }; | |
197 | ||
198 | /* Allocates a new AST. */ | |
199 | no_ignore xl_error | |
200 | xl_ast_new(struct xl_ast **ast); | |
201 | ||
202 | no_ignore xl_error | |
203 | xl_ast_free(struct xl_ast *ast); | |
204 | ||
205 | void | |
206 | xl_ast_error_loc_free(struct xl_ast_loc *err_loc); | |
207 | ||
208 | /* Prints the AST to stdout. */ | |
209 | no_ignore xl_error | |
210 | xl_ast_print(struct xl_ast *ast); | |
211 | ||
212 | no_ignore xl_error | |
213 | xl_ast_bind( | |
214 | struct xl_ast *ast, | |
215 | struct xl_ast_binding *bind); | |
216 | ||
217 | no_ignore xl_error | |
218 | xl_ast_add_type( | |
219 | struct xl_ast *ast, | |
220 | struct xl_ast_type *type); | |
221 | ||
222 | no_ignore xl_error | |
223 | xl_ast_atom_new_qualified( | |
224 | struct xl_ast_atom **atom, | |
225 | char *name); | |
226 | ||
227 | no_ignore xl_error | |
228 | xl_ast_import( | |
229 | struct xl_ast *ast, | |
230 | struct xl_ast_import_list *import_list); | |
231 | ||
232 | no_ignore xl_error | |
233 | xl_ast_subexprs( | |
234 | struct xl_ast **subast, | |
235 | struct xl_ast_expr **subexprs, | |
236 | size_t *n_subexprs, | |
237 | struct xl_ast_expr *expr); | |
238 | ||
239 | void | |
240 | xl_ast_merge_loc( | |
241 | struct xl_ast_loc *res, | |
242 | struct xl_ast_loc *l1, | |
243 | struct xl_ast_loc *l2); |
0 | /* | |
1 | * bdagc.h: graph builder | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "expel/dagc.h" | |
21 | #include "expel/expel.h" | |
22 | ||
23 | struct xl_graph_builder | |
24 | { | |
25 | struct xl_dagc_node **nodes; | |
26 | size_t n_nodes; | |
27 | size_t cap_nodes; | |
28 | ||
29 | struct xl_dagc_node *result; | |
30 | }; | |
31 | ||
32 | no_ignore xl_error | |
33 | xl_bdagc_init(struct xl_graph_builder *b); | |
34 | ||
35 | /* Adds a node to the graph. */ | |
36 | no_ignore xl_error | |
37 | xl_bdagc_push_node( | |
38 | struct xl_graph_builder *b, | |
39 | struct xl_dagc_node *node); | |
40 | ||
41 | /* Builds the graph. */ | |
42 | no_ignore xl_error | |
43 | xl_bdagc_build( | |
44 | struct xl_dagc **graph, | |
45 | struct xl_graph_builder *b); |
0 | /* | |
1 | * closure.h: closure transformation on ASTs | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "expel/ast.h" | |
21 | #include "expel/expel.h" | |
22 | #include "expel/resolve.h" | |
23 | ||
24 | /* Takes an AST and transforms closures into partially-applied functions. This | |
25 | * transformation is explained in-depth in the "Code generation" portion of the | |
26 | * architecture document. */ | |
27 | no_ignore xl_error | |
28 | xl_reduce_closures( | |
29 | struct xl_resolve_context *ctx, | |
30 | struct xl_ast *ast); |
0 | /* | |
1 | * compile.h: expel compilation | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "expel/expel.h" | |
21 | #include "expel/ast.h" | |
22 | ||
23 | ||
24 | struct xl_compilation_env | |
25 | { | |
26 | char *scratch_dir; | |
27 | ||
28 | char **include_dirs; | |
29 | size_t n_include_dirs; | |
30 | }; | |
31 | ||
32 | no_ignore xl_error | |
33 | xl_compile_env_default(struct xl_compilation_env *cenv); | |
34 | ||
35 | no_ignore xl_error | |
36 | xl_compile_env_free(struct xl_compilation_env *cenv); | |
37 | ||
38 | no_ignore xl_error | |
39 | xl_compile( | |
40 | struct xl_dagc ***graphs, | |
41 | size_t *n_graphs, | |
42 | char *source_name, | |
43 | struct xl_stream *in_stream, | |
44 | struct xl_compilation_env *cenv); | |
45 | ||
46 | no_ignore xl_error | |
47 | xl_compile_ast( | |
48 | struct xl_dagc ***graphs, | |
49 | size_t *n_graphs, | |
50 | struct xl_ast *ast, | |
51 | struct xl_compilation_env *cenv); | |
52 |
0 | /* | |
1 | * dagc.h: directed acyclic graphs of computation | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef EXPEL_DAGC_H | |
20 | #define EXPEL_DAGC_H | |
21 | ||
22 | #include "expel/expel.h" | |
23 | ||
24 | /* node is fully evaluated */ | |
25 | #define XL_DAGC_FLAG_COMPLETE 0x01 | |
26 | /* waiting on node's first dependency */ | |
27 | #define XL_DAGC_FLAG_WAIT_D1 0x02 | |
28 | /* waiting on node's second dependency */ | |
29 | #define XL_DAGC_FLAG_WAIT_D2 0x04 | |
30 | /* waiting on node's third dependency */ | |
31 | #define XL_DAGC_FLAG_WAIT_D3 0x08 | |
32 | /* waiting on evaluation */ | |
33 | #define XL_DAGC_FLAG_WAIT_EVAL 0x10 | |
34 | /* waiting on data to exist */ | |
35 | #define XL_DAGC_FLAG_WAIT_DATA 0x20 | |
36 | /* wait_d1 | wait_d2 | wait_d3 | wait_eval */ | |
37 | #define XL_DAGC_WAIT_MASK 0x2E | |
38 | ||
39 | struct xl_dagc_adjacency | |
40 | { | |
41 | struct xl_dagc_node *child; | |
42 | struct xl_dagc_node **parents; | |
43 | size_t n_parents; | |
44 | }; | |
45 | ||
46 | struct xl_dagc_apply | |
47 | { | |
48 | struct xl_dagc_node head; | |
49 | /* Function to call */ | |
50 | struct xl_dagc_node *func; | |
51 | /* Argument to apply to function */ | |
52 | struct xl_dagc_node *arg; | |
53 | }; | |
54 | ||
55 | struct xl_dagc_const | |
56 | { | |
57 | struct xl_dagc_node head; | |
58 | /* Type of constant */ | |
59 | struct xl_value *type; | |
60 | /* Value of constant */ | |
61 | union xl_value_or_graph value; | |
62 | }; | |
63 | ||
64 | struct xl_dagc_load | |
65 | { | |
66 | struct xl_dagc_node head; | |
67 | /* Where to load from */ | |
68 | struct xl_uri *loc; | |
69 | }; | |
70 | ||
71 | struct xl_dagc_store | |
72 | { | |
73 | struct xl_dagc_node head; | |
74 | /* Location to store */ | |
75 | struct xl_uri *loc; | |
76 | /* Value to store */ | |
77 | struct xl_dagc_node *value; | |
78 | }; | |
79 | ||
80 | struct xl_dagc_input | |
81 | { | |
82 | struct xl_dagc_node head; | |
83 | /* The argument that this corresponds to */ | |
84 | xl_word arg_num; | |
85 | }; | |
86 | ||
87 | struct xl_dagc_ref | |
88 | { | |
89 | struct xl_dagc_node head; | |
90 | /* The node to copy the value from */ | |
91 | struct xl_dagc_node *referrent; | |
92 | }; | |
93 | ||
94 | /* The native_out node is a piece of magic that is enabled | |
95 | * by the graph evaluator; if a graph has the native tag, | |
96 | * then the evaluator evalutes the value of the graph using | |
97 | * native code and populates the native node in the graph | |
98 | * with the result. The native node is provided only as a | |
99 | * thing for the caller to latch on to for the result. */ | |
100 | struct xl_dagc_native_out | |
101 | { | |
102 | struct xl_dagc_node head; | |
103 | }; | |
104 | ||
105 | struct xl_dagc_cond | |
106 | { | |
107 | struct xl_dagc_node head; | |
108 | /* The node that contains the condition */ | |
109 | struct xl_dagc_node *condition; | |
110 | /* The node that contains the value that is used if | |
111 | * the condition evaluates to true */ | |
112 | struct xl_dagc_node *if_true; | |
113 | /* The node that contains the value that is used if | |
114 | * the condition evaluates to false */ | |
115 | struct xl_dagc_node *if_false; | |
116 | }; | |
117 | ||
118 | /* This syntax is terrible; it defines xl_native_evaluator_t as a | |
119 | * function pointer that takes an env and a dagc and returns an | |
120 | * xl_error. */ | |
121 | typedef xl_error (*xl_native_evaluator_t)( | |
122 | struct xl_env *env, struct xl_dagc *graph); | |
123 | ||
124 | struct xl_dagc_native | |
125 | { | |
126 | /* xl_dagc_native pointers are equivalent to an xl_dagc | |
127 | * pointer */ | |
128 | struct xl_dagc graph; | |
129 | ||
130 | /* The function used to evaluate this graph. */ | |
131 | xl_native_evaluator_t evaluator; | |
132 | }; | |
133 | ||
134 | /* It can be anything you want it to be. | |
135 | * | |
136 | * It also happens to be the maximum size of all of the nodes, | |
137 | * which has advantages for allocating big lists of nodes. */ | |
138 | union xl_dagc_any_node | |
139 | { | |
140 | struct xl_dagc_node node; | |
141 | struct xl_dagc_apply as_apply; | |
142 | struct xl_dagc_cond as_cond; | |
143 | struct xl_dagc_const as_const; | |
144 | struct xl_dagc_input as_input; | |
145 | struct xl_dagc_load as_load; | |
146 | struct xl_dagc_ref as_ref; | |
147 | struct xl_dagc_store as_store; | |
148 | }; | |
149 | ||
150 | /* Allocates a graph object in a memory region of the given size. | |
151 | * | |
152 | * If copy_from is not NULL, this also copies size bytes from | |
153 | * copy_from into the graph before allocating all of the | |
154 | * substructures of the graph. */ | |
155 | no_ignore xl_error | |
156 | xl_dagc_alloc( | |
157 | struct xl_dagc **graph, | |
158 | size_t n_nodes, | |
159 | size_t size, | |
160 | void *copy_from); | |
161 | ||
162 | /* Gets the dependencies of a node. | |
163 | * | |
164 | * For nodes with N dependencies, d1 through dN will be filled in | |
165 | * and the result will be NULL. */ | |
166 | no_ignore xl_error | |
167 | xl_dagc_get_deps( | |
168 | struct xl_dagc_node **d1, | |
169 | struct xl_dagc_node **d2, | |
170 | struct xl_dagc_node **d3, | |
171 | struct xl_dagc_node *n); | |
172 | ||
173 | /* Modifies any references from the given node into the proto list | |
174 | * of nodes to point at the corresponding node in the list of new | |
175 | * nodes. | |
176 | * | |
177 | * This is useful when copying graphs or inserting nodes into | |
178 | * graphs. */ | |
179 | no_ignore xl_error | |
180 | xl_dagc_replace_node_refs( | |
181 | struct xl_dagc_node *node, | |
182 | struct xl_dagc_node **proto, | |
183 | struct xl_dagc_node **new, | |
184 | size_t n); | |
185 | ||
186 | /* Retrieve the parents of the given node. | |
187 | * | |
188 | * Returns OK on success or a nonzero error code on error. | |
189 | * It is imperative that callers do not modify the contents | |
190 | * of the returned array. | |
191 | * | |
192 | * I know a triple-pointer seems ridiculous, but hear me | |
193 | * out; we're returning a pointer to the caller, but we're | |
194 | * returning multiple values so we want it as an outparam, | |
195 | * which means we need to be passed a pointer to the | |
196 | * pointer. The pointer we're returning is itself a pointer | |
197 | * to a list of pointers. So we're asking you to pass us a | |
198 | * pointer to a pointer of pointers. I'm sorry. */ | |
199 | no_ignore xl_error | |
200 | xl_dagc_get_parents( | |
201 | struct xl_dagc_node ***parents, | |
202 | size_t *n_parents, | |
203 | struct xl_dagc *graph, | |
204 | struct xl_dagc_node *child); | |
205 | ||
206 | /* Evaluates a node and marks it as complete. */ | |
207 | no_ignore xl_error | |
208 | xl_dagc_node_eval( | |
209 | struct xl_env *env, | |
210 | struct xl_dagc_node *node); | |
211 | ||
212 | /* Returns the size of the node structure in bytes. */ | |
213 | no_ignore xl_error | |
214 | xl_dagc_node_sizeof( | |
215 | size_t *size, | |
216 | struct xl_dagc_node *node); | |
217 | ||
218 | /* Performs a copy from proto to result. | |
219 | * | |
220 | * This is a deep copy of the nodes but not the values within | |
221 | * them. This copies all information, including adjacency, and | |
222 | * updates all internal references between nodes. */ | |
223 | no_ignore xl_error | |
224 | xl_dagc_copy( | |
225 | struct xl_dagc **result, | |
226 | struct xl_dagc *proto); | |
227 | ||
228 | #endif |
0 | /* | |
1 | * def-native.h: defines a native function | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef DEF_OP | |
20 | #error "no DEF_OP specified, should be name of operation's _register method" | |
21 | #endif | |
22 | ||
23 | #ifndef DEF_OP_EVAL | |
24 | #error "no DEF_OP_EVAL specified, should be name of graph evaluator" | |
25 | #endif | |
26 | ||
27 | #ifndef DEF_OP_URI | |
28 | #error "no DEF_OP_URI specified, should be const char* of method name" | |
29 | #endif | |
30 | ||
31 | #ifndef DEF_ARG_TYPE | |
32 | #error "no DEF_ARG_TYPE specified, should be name of type constructor for arguments" | |
33 | #endif | |
34 | ||
35 | #ifndef concat | |
36 | #define concat(a, ...) concatr(a, __VA_ARGS__) | |
37 | #define concatr(a, ...) a ## __VA_ARGS__ | |
38 | #endif | |
39 | ||
40 | #define _op_name concat(_register_, DEF_OP) | |
41 | ||
42 | #ifdef DEF_BINARY | |
43 | ||
44 | no_ignore static xl_error | |
45 | _op_name(struct xl_env *env) | |
46 | { | |
47 | xl_error err; | |
48 | ||
49 | struct xl_dagc *ngraph; | |
50 | struct xl_uri *uri; | |
51 | struct xl_value *type; | |
52 | union xl_value_or_graph ins; | |
53 | ||
54 | ngraph = NULL; | |
55 | err = _create_op(&ngraph, 2, DEF_OP_EVAL); | |
56 | if (err != OK) | |
57 | return err; | |
58 | ||
59 | err = _native_uri(&uri, DEF_OP_URI); | |
60 | if (err != OK) | |
61 | return err; | |
62 | ||
63 | ngraph->identity = uri; | |
64 | err = xl_take(uri); | |
65 | if (err != OK) | |
66 | return err; | |
67 | ||
68 | err = xl_value_new(&type); | |
69 | if (err != OK) | |
70 | return err; | |
71 | /* TODO: set type here */ | |
72 | ||
73 | ins.graph = ngraph; | |
74 | err = xl_env_set(env, uri, ins, type); | |
75 | if (err != OK) | |
76 | return err; | |
77 | ||
78 | err = xl_release(type); | |
79 | if (err != OK) | |
80 | return err; | |
81 | err = xl_release(ngraph); | |
82 | if (err != OK) | |
83 | return err; | |
84 | ||
85 | return OK; | |
86 | } | |
87 | ||
88 | #elif defined(DEF_UNARY) | |
89 | ||
90 | no_ignore static xl_error | |
91 | _op_name(struct xl_env *env) | |
92 | { | |
93 | xl_error err; | |
94 | ||
95 | struct xl_dagc *ngraph; | |
96 | struct xl_uri *uri; | |
97 | struct xl_value *type; | |
98 | union xl_value_or_graph ins; | |
99 | ||
100 | ngraph = NULL; | |
101 | err = _create_op(&ngraph, 1, DEF_OP_EVAL); | |
102 | if (err != OK) | |
103 | return err; | |
104 | ||
105 | err = _native_uri(&uri, DEF_OP_URI); | |
106 | if (err != OK) | |
107 | return err; | |
108 | ||
109 | ngraph->identity = uri; | |
110 | err = xl_take(uri); | |
111 | if (err != OK) | |
112 | return err; | |
113 | ||
114 | err = xl_value_new(&type); | |
115 | if (err != OK) | |
116 | return err; | |
117 | /* TODO: set type here */ | |
118 | ||
119 | ins.graph = ngraph; | |
120 | err = xl_env_set(env, uri, ins, type); | |
121 | if (err != OK) | |
122 | return err; | |
123 | ||
124 | err = xl_release(type); | |
125 | if (err != OK) | |
126 | return err; | |
127 | err = xl_release(ngraph); | |
128 | if (err != OK) | |
129 | return err; | |
130 | ||
131 | return OK; | |
132 | } | |
133 | ||
134 | #else | |
135 | #error operation was not one of [DEF_BINARY, DEF_UNARY] | |
136 | #endif | |
137 | ||
138 | #undef DEF_OP | |
139 | #undef DEF_OP_EVAL | |
140 | #undef DEF_OP_URI | |
141 | #undef DEF_BINARY | |
142 | #undef DEF_UNARY | |
143 | #undef DEF_ARG_TYPE | |
144 | #undef _op_name |
0 | /* | |
1 | * env.h: expel environment definitions | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | ||
21 | #include "expel/expel.h" | |
22 | #include "expel/uri.h" | |
23 | ||
24 | #include <stdbool.h> | |
25 | #include <stdint.h> | |
26 | #include <stdlib.h> | |
27 | ||
28 | ||
29 | typedef xl_error (*xl_env_cb)( | |
30 | void *arg, | |
31 | struct xl_env *env, | |
32 | struct xl_uri *uri); | |
33 | ||
34 | /* An association between a URI and a value */ | |
35 | struct xl_binding | |
36 | { | |
37 | struct xl_uri *uri; | |
38 | union xl_value_or_graph value; | |
39 | struct xl_value *type; | |
40 | }; | |
41 | ||
42 | struct xl_env_watch | |
43 | { | |
44 | struct xl_uri *uri; | |
45 | struct xl_env *target_env; | |
46 | xl_env_cb cb; | |
47 | void *arg; | |
48 | ||
49 | /* Fired is set to true once the watcher has fired once; if this is | |
50 | * true, it means means that the watcher is dead. */ | |
51 | bool fired; | |
52 | ||
53 | /* The number of environments on which this watch was placed. */ | |
54 | xl_word refcount; | |
55 | }; | |
56 | ||
57 | struct xl_env_watch_list | |
58 | { | |
59 | struct xl_env_watch *watch; | |
60 | ||
61 | struct xl_env_watch_list *prev; | |
62 | struct xl_env_watch_list *next; | |
63 | }; | |
64 | ||
65 | /* A hash mapping from URI to value. */ | |
66 | struct xl_env | |
67 | { | |
68 | struct xl_binding *bindings; | |
69 | size_t n; | |
70 | size_t cap; | |
71 | struct xl_env *parent; | |
72 | ||
73 | struct xl_env_watch_list *watches; | |
74 | }; | |
75 | ||
76 | /* Initializes a new environment struct. */ | |
77 | no_ignore xl_error | |
78 | xl_env_init(struct xl_env *env); | |
79 | ||
80 | /* Creates a child environment from the given env. */ | |
81 | no_ignore xl_error | |
82 | xl_env_make_child(struct xl_env *child, struct xl_env *parent); | |
83 | ||
84 | /* Returns the root environment. | |
85 | * | |
86 | * This environment is the parent of any environment that isn't | |
87 | * explicitly created as a child. */ | |
88 | struct xl_env * | |
89 | xl_env_get_root(); | |
90 | ||
91 | /* Frees memory associated with the environment struct. | |
92 | * | |
93 | * Returns OK if successful. If this method returns an error code, | |
94 | * there is no guarantee that the environment is in a usable | |
95 | * state. If OK is returned, the environment can still be used | |
96 | * with xl_get and xl_set after calling xl_env_free; this is a | |
97 | * clear operation that does not destroy the env. */ | |
98 | no_ignore xl_error | |
99 | xl_env_free(struct xl_env *env); | |
100 | ||
101 | /* Finds the value associated wth the given URI in the environment. | |
102 | * | |
103 | * If the value is found, OK is returned and the out pointer is | |
104 | * set to the pointer to the assigned value. If the value is not | |
105 | * found, ERR_ABSENT is returned and the out pointer is unchanged. | |
106 | * */ | |
107 | no_ignore xl_error | |
108 | xl_env_get( | |
109 | union xl_value_or_graph *value, | |
110 | struct xl_value **type, | |
111 | struct xl_env *env, | |
112 | struct xl_uri *uri); | |
113 | ||
114 | /* Inserts the given value in at the given URI, overwriting an | |
115 | * existing value if present. | |
116 | * | |
117 | * The URI is copied into the environment but the value is not; | |
118 | * later modifications to the passed-in URI will not change the | |
119 | * bindings but modifications to the value will modify the value | |
120 | * stored in the environment. */ | |
121 | no_ignore xl_error | |
122 | xl_env_overwrite( | |
123 | struct xl_env *env, | |
124 | struct xl_uri *uri, | |
125 | union xl_value_or_graph value, | |
126 | struct xl_value *type); | |
127 | ||
128 | /* Inserts the given value in at the given URI if the URI is | |
129 | * not already defined. | |
130 | * | |
131 | * If the URI is already bound, this will return ERR_PRESENT | |
132 | * and the existing binding will not be modified. | |
133 | * | |
134 | * The URI is copied into the environment but the value is not; | |
135 | * later modifications to the passed-in URI will not change the | |
136 | * bindings but modifications to the value will modify the value | |
137 | * stored in the environment. */ | |
138 | no_ignore xl_error | |
139 | xl_env_set( | |
140 | struct xl_env *env, | |
141 | struct xl_uri *uri, | |
142 | union xl_value_or_graph value, | |
143 | struct xl_value *type); | |
144 | ||
145 | /* Returns true if the provided URI is present in the environment. */ | |
146 | no_ignore xl_error | |
147 | xl_env_present( | |
148 | bool *is_present, | |
149 | struct xl_env *env, | |
150 | struct xl_uri *uri); | |
151 | ||
152 | /* Calls the provided callback function once for every item. */ | |
153 | no_ignore xl_error | |
154 | xl_env_iterate( | |
155 | xl_env_cb callback, | |
156 | struct xl_env *env, | |
157 | void *callback_arg); | |
158 | ||
159 | /* Calls the provided callback function when a URI is inserted or modified. | |
160 | * | |
161 | * Note that a watch is only ever triggered once; after being triggered it is | |
162 | * removed from the list of watchers. */ | |
163 | no_ignore xl_error | |
164 | xl_env_watch( | |
165 | xl_env_cb callback, | |
166 | struct xl_env *env, | |
167 | struct xl_uri *uri, | |
168 | void *callback_arg); | |
169 |
0 | /* | |
1 | * expel.h: minimal public API | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef EXPEL_EXPEL_H | |
20 | #define EXPEL_EXPEL_H | |
21 | ||
22 | #include <stddef.h> | |
23 | #include <stdint.h> | |
24 | ||
25 | #include "expel/const.h" | |
26 | ||
27 | typedef uint16_t xl_tag; | |
28 | typedef uint64_t xl_word; | |
29 | ||
30 | #if __SIZEOF_DOUBLE__ == 8 | |
31 | typedef double xl_float; | |
32 | #elif __SIZEOF_FLOAT__ == 8 | |
33 | typedef float xl_float; | |
34 | #elif __SIZEOF_LONG_DOUBLE__ == 8 | |
35 | typedef long double xl_float; | |
36 | #else | |
37 | #error "word size and float size do not match" | |
38 | #endif | |
39 | ||
40 | #define TAG_TYPE_MASK 0xF000 | |
41 | #define TAG_VALUE 0x1000 | |
42 | #define TAG_GRAPH 0x2000 | |
43 | #define TAG_URI 0x3000 | |
44 | ||
45 | /* Tree tags */ | |
46 | #define TAG_LEFT_NODE 0x0010 | |
47 | #define TAG_LEFT_WORD 0x0020 | |
48 | #define TAG_LEFT_GRAPH 0x0040 | |
49 | #define TAG_RIGHT_NODE 0x0001 | |
50 | #define TAG_RIGHT_WORD 0x0002 | |
51 | #define TAG_RIGHT_GRAPH 0x0004 | |
52 | ||
53 | /* Graph tags */ | |
54 | #define TAG_GRAPH_NATIVE 0x0001 | |
55 | /* an unresolved graph is one that contains URIs that have not been resolved to | |
56 | * a specific resource yet. */ | |
57 | #define TAG_GRAPH_UNRESOLVED 0x0002 | |
58 | /* a modinit graph represents a graph that should be run when bytecode is | |
59 | * loaded. */ | |
60 | #define TAG_GRAPH_MODINIT 0x0004 | |
61 | ||
62 | /* The maximum Expel bytecode version that this library supports. */ | |
63 | #define CURRENT_ENCODING_VERSION 1 | |
64 | ||
65 | /* Private data structures referenced by public data structures. */ | |
66 | struct xl_alloc_page; | |
67 | struct xl_env; | |
68 | struct xl_stream; | |
69 | struct xl_user; | |
70 | struct xl_uri; | |
71 | struct xl_dagc_adjacency; | |
72 | ||
73 | struct xl_dagc; | |
74 | ||
75 | /* Used to communicate errors through the stack. */ | |
76 | struct xl_error | |
77 | { | |
78 | xl_word error_code; | |
79 | const char *tag; | |
80 | const char *file; | |
81 | const char *function; | |
82 | uint32_t lineno; | |
83 | }; | |
84 | typedef struct xl_error * xl_error; | |
85 | #define OK ((xl_error) NULL) | |
86 | ||
87 | #define no_ignore __attribute__((__warn_unused_result__)) | |
88 | ||
89 | union xl_atom | |
90 | { | |
91 | struct xl_value *t; | |
92 | struct xl_dagc *g; | |
93 | void *any; | |
94 | xl_word w; | |
95 | xl_float f; | |
96 | }; | |
97 | ||
98 | /* The base type of all data in Expel; it's a cons cell. */ | |
99 | struct xl_value | |
100 | { | |
101 | /* A bitset of the TAG_ constants. One each of the | |
102 | * TAG_LEFT_ and TAG_RIGHT_ bits must be set, along with | |
103 | * the TAG_VALUE bit. */ | |
104 | xl_tag tag; | |
105 | ||
106 | union xl_atom left; | |
107 | union xl_atom right; | |
108 | ||
109 | /* The page in which the value was allocated, used by the | |
110 | * garbage collector. */ | |
111 | struct xl_alloc_page *alloc_page; | |
112 | /* The number of references to the value, used by the | |
113 | * garbage collector. Special hell awaits those who modify | |
114 | * this value. */ | |
115 | uint64_t refcount; | |
116 | }; | |
117 | ||
118 | struct xl_dagc; | |
119 | ||
120 | union xl_value_or_graph | |
121 | { | |
122 | struct xl_value *tree; | |
123 | struct xl_dagc *graph; | |
124 | void *any; | |
125 | xl_tag *tag; | |
126 | }; | |
127 | ||
128 | struct xl_dagc_node | |
129 | { | |
130 | /* One of the DAGC_NODE constants */ | |
131 | xl_word node_type; | |
132 | /* The unique identifier of this node */ | |
133 | xl_word id; | |
134 | /* The evaluated type of the node, populated after the | |
135 | * node is evaluated by xl_dagc_eval. */ | |
136 | struct xl_value *known_type; | |
137 | /* The evaluated computation graph of the node, populated | |
138 | * after the node is evaluated by xl_dagc_eval. The | |
139 | * tag field tells you which member of the union to | |
140 | * access. */ | |
141 | union xl_value_or_graph known; | |
142 | /* Nonzero if we want the value of this node at the end of | |
143 | * evaluation */ | |
144 | uint8_t is_terminal; | |
145 | /* A bitsest of the XL_DAGC_FLAG constants */ | |
146 | uint8_t flags; | |
147 | }; | |
148 | ||
149 | struct xl_dagc | |
150 | { | |
151 | /* Used to determine if a void* is a graph or a value. | |
152 | * This is set by xl_dagc_init; users of the DAGC API | |
153 | * should not touch it. */ | |
154 | xl_tag tag; | |
155 | ||
156 | /* The identity of the graph, in URI form. */ | |
157 | struct xl_uri *identity; | |
158 | ||
159 | /* The nodes participating in the graph. */ | |
160 | struct xl_dagc_node **nodes; | |
161 | /* The number of nodes in the graph. */ | |
162 | size_t n; | |
163 | ||
164 | /* Below this is only members that are populated by | |
165 | * calling xl_dagc_init; callers should initialize nodes | |
166 | * and n above and then call init to take care of | |
167 | * everything else. */ | |
168 | ||
169 | /* Number of references held to this graph. */ | |
170 | uint64_t refcount; | |
171 | ||
172 | /* A list of structs which encode backlinks from child to | |
173 | * parent. */ | |
174 | struct xl_dagc_adjacency *adjacency; | |
175 | ||
176 | /* The input nodes in the graph. */ | |
177 | struct xl_dagc_node **inputs; | |
178 | size_t in_arity; | |
179 | ||
180 | /* The terminal nodes in the graph. */ | |
181 | struct xl_dagc_node **terminals; | |
182 | size_t out_arity; | |
183 | ||
184 | /* The result node in the graph. */ | |
185 | struct xl_dagc_node *result; | |
186 | }; | |
187 | ||
188 | /* Starts the expel runtime. | |
189 | * | |
190 | * Returns OK on success. */ | |
191 | no_ignore xl_error | |
192 | xl_start(); | |
193 | ||
194 | /* Stops the expel runtime. | |
195 | * | |
196 | * Returns OK on success. */ | |
197 | no_ignore xl_error | |
198 | xl_teardown(); | |
199 | ||
200 | /* Creates a new value. | |
201 | * | |
202 | * The returned value has a refcount of one; callers to xl_new do | |
203 | * not need to take the result. This may result in an allocation | |
204 | * but is not guaranteed to; xl_values are allocated in pages. */ | |
205 | no_ignore xl_error | |
206 | xl_value_new(struct xl_value **v); | |
207 | ||
208 | /* Takes a reference to the given tree or graph. | |
209 | * | |
210 | * Returns OK on success, or a nonzero error code on failure. */ | |
211 | no_ignore xl_error | |
212 | xl_take(void *v); | |
213 | ||
214 | /* Releases a reference to the given tree or graph. | |
215 | * | |
216 | * Returns OK on success, or a nonzero error code on failure. If | |
217 | * passed a value, this may result in a free but is not guaranteed | |
218 | * to; xl_values are garbage-collected periodically. If passed a | |
219 | * graph and the releaser was the last owner of the graph, this | |
220 | * will free the graph. */ | |
221 | no_ignore xl_error | |
222 | xl_release(void *v); | |
223 | ||
224 | /* Loads an expel bytecode blob from a stream. | |
225 | * | |
226 | * Returns OK on success, or a nonzero error word. */ | |
227 | no_ignore xl_error | |
228 | xl_load(struct xl_dagc ***out, size_t *n_graphs, struct xl_stream *sp); | |
229 | ||
230 | /* Saves a list of graphs and all accessible subgraphs to a stream. | |
231 | * | |
232 | * Returns OK on success, or a nonzero error word. */ | |
233 | no_ignore xl_error | |
234 | xl_save(struct xl_stream *sp, struct xl_dagc **graphs, size_t n); | |
235 | ||
236 | /* Loads a tree from a stream. | |
237 | * | |
238 | * Note that any contained graph references are initialized to the index | |
239 | * of the graph in some other structure; if you're loading values with | |
240 | * graph references you probably want to load the whole thing in one go | |
241 | * with xl_load. | |
242 | * | |
243 | * The returned tree is not taken; it is up to the caller to take the | |
244 | * tree. Returns OK on success, or a nonzero error word. */ | |
245 | no_ignore xl_error | |
246 | xl_value_load(struct xl_value *out, struct xl_stream *sp); | |
247 | ||
248 | /* Saves a tree to a stream. | |
249 | * | |
250 | * Note that this cannot save any values that contain any graph | |
251 | * references; for that you'll need to serialize the entire structure | |
252 | * with xl_save. | |
253 | * | |
254 | * Returns OK on success, or a nonzero error word. */ | |
255 | no_ignore xl_error | |
256 | xl_value_save(struct xl_stream *sp, struct xl_value *in); | |
257 | ||
258 | /* Allocates a graph object. | |
259 | * | |
260 | * All graph objects must be allocated on the heap; call into this | |
261 | * method to allocate a graph of a given size. */ | |
262 | no_ignore xl_error | |
263 | xl_dagc_new(struct xl_dagc **g, size_t n); | |
264 | ||
265 | /* Initializes derived quantities on graphs. | |
266 | * | |
267 | * Callers should create a dagc struct, populate the nodes and the | |
268 | * n fields, and then call this method to compute all derived | |
269 | * quantities. | |
270 | * | |
271 | * This resets the refcount of the given graph to 1; initializers | |
272 | * of graph structs do not need to take a reference to the graph | |
273 | * after initialization. */ | |
274 | no_ignore xl_error | |
275 | xl_dagc_init(struct xl_dagc *graph); | |
276 | ||
277 | /* Creates a string representation of a node. | |
278 | * | |
279 | * Useful for debugging, but not much else. */ | |
280 | char * | |
281 | xl_node_explain(struct xl_dagc_node *n); | |
282 | ||
283 | /* Create an error object. */ | |
284 | xl_error | |
285 | xl_error_new( | |
286 | const xl_word code, | |
287 | const char *tag, | |
288 | const char *file, | |
289 | const uint32_t lineno, | |
290 | const char *function); | |
291 | ||
292 | /* Creates a string representation of an error object. */ | |
293 | char * | |
294 | xl_error_explain(xl_error err); | |
295 | ||
296 | /* Raise an error with the current file and line populated. */ | |
297 | #define xl_raise(code, tag) \ | |
298 | xl_error_new((code), (tag), __FILE__, __LINE__, __FUNCTION__) | |
299 | ||
300 | #define local(type) __attribute__((cleanup(xl_ ## type ## _free))) | |
301 | ||
302 | #endif |
0 | /* | |
1 | * gc.h: garbage collector introspection | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include "expel/expel.h" | |
20 | ||
21 | struct xl_gc_info | |
22 | { | |
23 | #ifdef XL_GC_DEBUG | |
24 | uint64_t n_val_allocs; | |
25 | uint64_t n_val_frees; | |
26 | uint64_t n_graph_allocs; | |
27 | uint64_t n_graph_frees; | |
28 | #endif | |
29 | }; | |
30 | ||
31 | /* Initialize the garbage collector. | |
32 | * | |
33 | * This must be called before xl_new can be called. Calling this | |
34 | * drops all existing GC state, and thus don't call it more than | |
35 | * once unless you /really/ know what you're doing. */ | |
36 | void | |
37 | xl_gc_start(); | |
38 | ||
39 | /* Teardown the garbage collector. | |
40 | * | |
41 | * Frees all memory known to the garbage collector. After calling | |
42 | * this, ou must call xl_gc_start again if you want to use the | |
43 | * runtime again. */ | |
44 | void | |
45 | xl_gc_teardown(); | |
46 | ||
47 | /* Get garbage collector stats. */ | |
48 | void | |
49 | xl_gc_get_stats(struct xl_gc_info *stats); | |
50 | ||
51 | /* Free everything the garbage collector knows about. | |
52 | * | |
53 | * This will seriously fuck with the runtime, because pretty much | |
54 | * every pointer becomes invalid. You have been warned. */ | |
55 | void | |
56 | xl_gc_free_all(); | |
57 |
0 | /* | |
1 | * gen.h: expel bytecode generation | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "expel/expel.h" | |
21 | #include "expel/ast.h" | |
22 | #include "expel/uri.h" | |
23 | ||
24 | struct xl_gen_requires | |
25 | { | |
26 | struct xl_uri *dependency; | |
27 | struct xl_gen_requires *next; | |
28 | }; | |
29 | ||
30 | enum xl_load_reason | |
31 | { | |
32 | LOAD_MAIN = 1, | |
33 | LOAD_IMPORTED, | |
34 | LOAD_BLOCK | |
35 | }; | |
36 | ||
37 | /* Frees a requirement list. */ | |
38 | no_ignore xl_error | |
39 | xl_gen_requires_free(struct xl_gen_requires *); | |
40 | ||
41 | /* Compiles a single compilation unit down to a series of graphs. | |
42 | * | |
43 | * The graphs and n_graphs parameters are filled in with the result of | |
44 | * compilation, as is the requires struct, which is created with a bunch of URIs | |
45 | * that need to be satisfied for the compilation result to be valid. The ast | |
46 | * parameter is the AST that's being compiled, the load_reason is the reason | |
47 | * we're being compiled (some things behave differently if they're imported or | |
48 | * they're the main event), and uri_source is the source prefix to put on all of | |
49 | * the URIs for all the bindings in the AST. */ | |
50 | no_ignore xl_error | |
51 | xl_compile_unit( | |
52 | struct xl_dagc ***graphs, | |
53 | size_t *n_graphs, | |
54 | struct xl_gen_requires **requires, | |
55 | struct xl_ast *ast, | |
56 | enum xl_load_reason load_reason, | |
57 | char *uri_source); |
0 | /* | |
1 | * natives.h: built-in native methods | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include "expel/expel.h" | |
20 | ||
21 | no_ignore xl_error | |
22 | xl_natives_register(struct xl_env *env); | |
23 |
0 | /* | |
1 | * parse.h: expel language parser | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | ||
21 | #include "expel/expel.h" | |
22 | #include "expel/ast.h" | |
23 | #include "expel/stream.h" | |
24 | #include "expel/vector.h" | |
25 | ||
26 | struct xl_parse_context | |
27 | { | |
28 | struct xl_ast *ast; | |
29 | ||
30 | struct xl_ast_loc *err_loc; | |
31 | char *err_msg; | |
32 | ||
33 | /* we keep track of everything allocated during parsing so that we can | |
34 | * clean up if the parse fails halfway through. */ | |
35 | struct xl_vector allocs; | |
36 | }; | |
37 | ||
38 | no_ignore xl_error | |
39 | xl_parse(struct xl_ast **ast, char *source_name, struct xl_stream *stream); |
0 | /* | |
1 | * pointerset.h: ordered sets of pointers | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | ||
20 | #include <stdbool.h> | |
21 | #include <stdint.h> | |
22 | ||
23 | #include "expel/expel.h" | |
24 | #include "expel/vector.h" | |
25 | ||
26 | /* Pointer sets represent sets of objects where the identity of an object is the | |
27 | * address at which it is stored. | |
28 | * | |
29 | * To create a pointer set, it is sufficient to zero the struct entirely. This | |
30 | * can be done with calloc or with a static '= {0}' initializer. | |
31 | * | |
32 | * Pointer sets are designed to be fast to perform a membership check, fast | |
33 | * to iterate and indexable, while being slow to insert is okay. They | |
34 | * have the property that every item in them is assigned an integer index, and | |
35 | * the set of indeces in the set at any time is guaranteed to be sequential and | |
36 | * rooted at zero. They are not multisets; a given pointer can only exist in the | |
37 | * set once. They are intended for building sets of things that are indexed and | |
38 | * then doing a number of queries to see what the index of a given item in the | |
39 | * set is. | |
40 | * | |
41 | * With that in mind, pointer sets are stored in flat arrays in sorted order. | |
42 | * The index of an item is naturally expressed as its position in the array. | |
43 | * Membership searches for the item in the array using binary search and is thus | |
44 | * O(n log n), as is finding the index of an object. Retrieving an item by index | |
45 | * is O(1). Insertion is expensive, as it requires a full rebuild in general, | |
46 | * and thus is O(n). | |
47 | */ | |
48 | ||
49 | /* Adds item to the given pointer set. If added is not NULL, sets bool to true | |
50 | * only if the item was not already present in the set. If the item is already | |
51 | * present in the set, no mutation occurs on the pointer set and bool is set to | |
52 | * false. */ | |
53 | no_ignore xl_error | |
54 | xl_pointer_set_add(bool *added, struct xl_vector *, void *item); | |
55 | ||
56 | /* Sets present to true or false if the item is or is not in the set. */ | |
57 | no_ignore xl_error | |
58 | xl_pointer_set_present(bool *present, struct xl_vector *, void *item); | |
59 | ||
60 | /* Sets index to the index of the given item. If the item does not exist in the | |
61 | * set, raises ERR_ABSENT. */ | |
62 | no_ignore xl_error | |
63 | xl_pointer_set_find(size_t *index, struct xl_vector *, void *item); |
0 | /* | |
1 | * resolve.h: name resolution at compile time | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "expel/expel.h" | |
21 | #include "expel/ast.h" | |
22 | #include "expel/vector.h" | |
23 | ||
24 | enum xl_resolve_type | |
25 | { | |
26 | /* if a name resolves locally, then the name should be accessed by using | |
27 | * a ref node to the appropriate node for the name. */ | |
28 | RESOLVE_LOCAL = 1, | |
29 | /* if a name resolves globally, then the name should be accessed by | |
30 | * using a load node with the userdef scope. */ | |
31 | RESOLVE_GLOBAL, | |
32 | /* if a name resolves through closure, then the ast needs to be | |
33 | * transformed such that the name can be accessed as a local. */ | |
34 | RESOLVE_CLOSURE, | |
35 | }; | |
36 | ||
37 | struct xl_resolve_name | |
38 | { | |
39 | char *name; | |
40 | enum xl_resolve_type type; | |
41 | struct xl_dagc_node *node; | |
42 | }; | |
43 | ||
44 | struct xl_resolve_name_loc | |
45 | { | |
46 | enum xl_resolve_type type; | |
47 | }; | |
48 | ||
49 | /* Scope boundaries are used to determine whether something is | |
50 | * accessible in the current scope or not; it is useful for the closure | |
51 | * transformation to know about things in enclosing but inaccessible | |
52 | * scopes. If a scope has a BOUNDARY_BLOCK boundary type, then its | |
53 | * parent is accessible (as it's just a scope object inside another | |
54 | * scope). If a scope has a BOUNDARY_FUNCTION boundary type, its parent | |
55 | * is not accessible as they exist in separate functions, and we need to | |
56 | * close over its parents' values. If a scope has a BOUNDARY_GLOBAL boundary | |
57 | * type, its members can be accessed using load nodes instead of ref nodes and | |
58 | * thus they don't have to be closed over. */ | |
59 | enum xl_resolve_boundary_type | |
60 | { | |
61 | BOUNDARY_BLOCK = 1, | |
62 | BOUNDARY_GLOBAL, | |
63 | BOUNDARY_FUNCTION, | |
64 | }; | |
65 | ||
66 | struct xl_resolve_scope | |
67 | { | |
68 | /* members of are struct xl_resolve_name pointers */ | |
69 | struct xl_vector names; | |
70 | ||
71 | struct xl_resolve_scope *parent; | |
72 | enum xl_resolve_boundary_type boundary; | |
73 | ||
74 | /* This thing is complicated. There's a long explanation in closure.c | |
75 | * about what it means. Go read that. */ | |
76 | bool needs_closure_appl; | |
77 | }; | |
78 | ||
79 | enum xl_resolve_error_type | |
80 | { | |
81 | RESOLVE_ERR_NAME_NOT_FOUND = 1, | |
82 | }; | |
83 | ||
84 | struct xl_resolve_error | |
85 | { | |
86 | enum xl_resolve_error_type err_type; | |
87 | char *name; | |
88 | struct xl_ast_loc loc; | |
89 | }; | |
90 | ||
91 | struct xl_resolve_context | |
92 | { | |
93 | struct xl_resolve_scope *native_scope; | |
94 | struct xl_vector scope_allocs; | |
95 | struct xl_vector allocs; | |
96 | struct xl_vector errors; | |
97 | }; | |
98 | ||
99 | no_ignore xl_error | |
100 | xl_resolve( | |
101 | struct xl_ast *ast, | |
102 | char *source_name, | |
103 | struct xl_stream *stream, | |
104 | struct xl_resolve_context *ctx); | |
105 | ||
106 | void | |
107 | xl_resolve_context_free(struct xl_resolve_context *ctx); |
0 | /* | |
1 | * schedule.h: definitions for the expel scheduler | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include "expel/expel.h" | |
20 | ||
21 | struct xl_scheduler; | |
22 | struct xl_exec_unit; | |
23 | ||
24 | typedef xl_error (*xl_exec_notify_func)( | |
25 | void *arg, | |
26 | struct xl_scheduler *s, | |
27 | struct xl_exec_unit *e); | |
28 | ||
29 | struct xl_exec_notify | |
30 | { | |
31 | /* The function called when a unit of execution has completed */ | |
32 | xl_exec_notify_func notify; | |
33 | ||
34 | /* The first argument provided to the function when called */ | |
35 | void *arg; | |
36 | }; | |
37 | ||
38 | struct xl_exec_unit | |
39 | { | |
40 | /* The node to be evaluated */ | |
41 | struct xl_dagc_node *node; | |
42 | ||
43 | /* The graph in which the node exists */ | |
44 | struct xl_dagc *graph; | |
45 | ||
46 | /* The environment in which to execute the node */ | |
47 | struct xl_env *env; | |
48 | ||
49 | /* The function to call once execution is complete */ | |
50 | struct xl_exec_notify *notify; | |
51 | ||
52 | /* The next execution unit in the stack; callers to xl_schedule_push | |
53 | * need not set this field, as the result will be overwritten anyawy. */ | |
54 | struct xl_exec_unit *next; | |
55 | }; | |
56 | ||
57 | /* Creates a scheduler. */ | |
58 | no_ignore xl_error | |
59 | xl_schedule_new(struct xl_scheduler **s); | |
60 | ||
61 | /* Destroys a scheduler. */ | |
62 | no_ignore xl_error | |
63 | xl_schedule_free(struct xl_scheduler *s); | |
64 | ||
65 | /* Pushes a graph into the scheduler for execution. */ | |
66 | no_ignore xl_error | |
67 | xl_schedule_push( | |
68 | struct xl_scheduler *s, | |
69 | struct xl_dagc *graph, | |
70 | struct xl_env *env, | |
71 | struct xl_exec_notify *notify); | |
72 | ||
73 | /* Marks an execution unit complete. */ | |
74 | no_ignore xl_error | |
75 | xl_schedule_complete(struct xl_scheduler *s, struct xl_exec_unit *e); | |
76 | ||
77 | /* Runs all queued jobs on the scheduler. */ | |
78 | no_ignore xl_error | |
79 | xl_schedule_run(struct xl_scheduler *s); | |
80 | ||
81 | /* Dumps information about what's scheduled to stdout. */ | |
82 | no_ignore xl_error | |
83 | xl_schedule_dump(struct xl_scheduler *s); |
0 | /* | |
1 | * stream.h: stream interface | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef EXPEL_STREAM_H | |
20 | #define EXPEL_STREAM_H | |
21 | ||
22 | #include <stdio.h> | |
23 | ||
24 | #include "expel/expel.h" | |
25 | ||
26 | struct _xl_buf { | |
27 | uint8_t *start; | |
28 | uint8_t *read; | |
29 | uint8_t *write; | |
30 | uint8_t *end; | |
31 | }; | |
32 | ||
33 | struct xl_stream { | |
34 | union { | |
35 | FILE *file; | |
36 | struct _xl_buf *buffer; | |
37 | }; | |
38 | xl_word stream_type; | |
39 | }; | |
40 | ||
41 | /* Opens a stream for reading from the given file. */ | |
42 | no_ignore xl_error | |
43 | xl_stream_rfile(struct xl_stream *sp, char *file); | |
44 | ||
45 | /* Opens a stream for writing to the given file. */ | |
46 | no_ignore xl_error | |
47 | xl_stream_wfile(struct xl_stream *sp, char *file); | |
48 | ||
49 | /* Opens a stream for reading from the given file pointer. */ | |
50 | no_ignore xl_error | |
51 | xl_stream_rfilep(struct xl_stream *sp, FILE *file); | |
52 | ||
53 | /* Opens a stream for writing to the given file pointer. */ | |
54 | no_ignore xl_error | |
55 | xl_stream_wfilep(struct xl_stream *sp, FILE *file); | |
56 | ||
57 | /* Opens a stream backed by an in-memory buffer. */ | |
58 | no_ignore xl_error | |
59 | xl_stream_buffer(struct xl_stream *sp); | |
60 | ||
61 | /* Attempts to read the specified number of bytes from the stream, returning the | |
62 | * number of bytes read. */ | |
63 | no_ignore size_t | |
64 | xl_stream_read(void *dst, struct xl_stream *src, size_t len); | |
65 | ||
66 | /* Attempts to write the specified number of bytes to the stream, returning the | |
67 | * number of bytes written. */ | |
68 | no_ignore size_t | |
69 | xl_stream_write(struct xl_stream *dst, void *src, size_t len); | |
70 | ||
71 | /* Drops a number of bytes from the stream, returning the number of bytes | |
72 | * dropped successfully. */ | |
73 | no_ignore size_t | |
74 | xl_stream_drop(struct xl_stream *src, size_t len); | |
75 | ||
76 | /* Gets a file pointer representing the contents of the stream. | |
77 | * | |
78 | * If the stream has been read from or written to, you should not make | |
79 | * assumptions about the location of the read/write heads in this stream; | |
80 | * instead, you should seek it to wherever you need the stream head to be. */ | |
81 | FILE * | |
82 | xl_stream_fp(struct xl_stream *sp); | |
83 | ||
84 | /* Resets a stream to the start. | |
85 | * | |
86 | * In some cases this may be equivalent to closing and reopening the stream. */ | |
87 | void | |
88 | xl_stream_reset(struct xl_stream *sp); | |
89 | ||
90 | /* Closes a stream. */ | |
91 | void | |
92 | xl_stream_close(struct xl_stream *sp); | |
93 | ||
94 | #endif |
0 | /* | |
1 | * streamutil.h: generally useful stream helpers | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include "expel/stream.h" | |
20 | ||
21 | /* Takes the line with index i from stream and copies it into the n-length | |
22 | * buffer res. */ | |
23 | no_ignore xl_error | |
24 | xl_streamutil_get_line( | |
25 | char *res, | |
26 | struct xl_stream *stream, | |
27 | size_t i, | |
28 | size_t n); |
0 | /* | |
1 | * string.h: extensions to the strings API provided by glibc | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include <strings.h> | |
20 | #include "expel/expel.h" | |
21 | ||
22 | /* Splits a NULL-terminated string into multiple smaller NULL-terminated | |
23 | * strings, each separated by the delim character. */ | |
24 | no_ignore xl_error | |
25 | xl_string_split( | |
26 | char ***out, | |
27 | size_t *n_out, | |
28 | char *in, | |
29 | size_t n_in, | |
30 | char delim); | |
31 | ||
32 | /* Joins two NULL-terminated path segments into a single path. */ | |
33 | no_ignore xl_error | |
34 | xl_string_path_concat( | |
35 | char **out, | |
36 | char *first, | |
37 | char *second); |
0 | /* | |
1 | * timer.h: x-platform timing code | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include "expel/expel.h" | |
20 | ||
21 | struct xl_timer; | |
22 | ||
23 | no_ignore xl_error | |
24 | xl_timer_new(struct xl_timer **t); | |
25 | ||
26 | no_ignore xl_error | |
27 | xl_timer_start(struct xl_timer *t); | |
28 | ||
29 | no_ignore xl_error | |
30 | xl_timer_elapsed(int64_t *microsec, struct xl_timer *t); |
0 | /* | |
1 | * token.h: expel language tokenizer | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include "expel/expel.h" | |
20 | #include "expel/stream.h" | |
21 | ||
22 | struct xl_token | |
23 | { | |
24 | int token_code; | |
25 | char *text; | |
26 | size_t text_len; | |
27 | int line_no; | |
28 | }; | |
29 | ||
30 | typedef xl_error (*xl_token_cb)(struct xl_token t); | |
31 | ||
32 | no_ignore xl_error | |
33 | xl_tokenize(xl_token_cb callback, struct xl_stream *stream); |
0 | /* | |
1 | * types.h: runtime type system for expel | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include <stdbool.h> | |
20 | ||
21 | #include "expel/expel.h" | |
22 | ||
23 | bool | |
24 | xl_type_satisfied( | |
25 | struct xl_value *constraint, | |
26 | struct xl_value *type); | |
27 | ||
28 | /* Creates a type object that is the result of applying a single argument to the | |
29 | * given function type. */ | |
30 | no_ignore xl_error | |
31 | xl_type_func_apply( | |
32 | struct xl_value *result, | |
33 | struct xl_value *func_type); | |
34 | ||
35 | /* Given the value implementation of a function, returns the graph appropriate | |
36 | * for an argument of the given type. */ | |
37 | no_ignore xl_error | |
38 | xl_type_match_polyfunc( | |
39 | struct xl_dagc **result, | |
40 | struct xl_value *def, | |
41 | struct xl_value *arg_type); | |
42 | ||
43 | char * | |
44 | xl_type_explain(struct xl_value *type); | |
45 | ||
46 | /* Returns true if the values of the given type are "primitive words", meaning | |
47 | * that their representation is entirely contained in the left value of their | |
48 | * associated node. */ | |
49 | bool | |
50 | xl_type_is_prim_word(struct xl_value *value); | |
51 | ||
52 | no_ignore xl_error | |
53 | xl_type_word(struct xl_value *value); | |
54 | ||
55 | no_ignore xl_error | |
56 | xl_type_string(struct xl_value *value); | |
57 | ||
58 | no_ignore xl_error | |
59 | xl_type_bool(struct xl_value *value); | |
60 | ||
61 | no_ignore xl_error | |
62 | xl_type_float(struct xl_value *value); | |
63 | ||
64 | no_ignore xl_error | |
65 | xl_type_tuple( | |
66 | struct xl_value *product, | |
67 | struct xl_value **field_types, | |
68 | size_t n_field_types); | |
69 | ||
70 | no_ignore xl_error | |
71 | xl_type_builtin_from_name( | |
72 | struct xl_value *value, | |
73 | char *name); |
0 | /* | |
1 | * uri.h: expel content identifiers | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include <stdbool.h> | |
21 | #include <stdint.h> | |
22 | ||
23 | #include "expel/expel.h" | |
24 | ||
25 | /* Identifies values in the expel substrate */ | |
26 | struct xl_uri { | |
27 | xl_tag tag; | |
28 | xl_word hash; | |
29 | ||
30 | char *name; | |
31 | size_t name_len; | |
32 | char *source; | |
33 | size_t source_len; | |
34 | xl_word version; | |
35 | xl_word scope; | |
36 | ||
37 | uint64_t refcount; | |
38 | ||
39 | /* The value representation of the URI. Generated and cached by | |
40 | * xl_uri_attach_value. */ | |
41 | struct xl_value *as_value; | |
42 | }; | |
43 | ||
44 | /* Creates a URI for a resource of unknown scope. */ | |
45 | no_ignore xl_error | |
46 | xl_uri_unknown( | |
47 | struct xl_uri *uri, | |
48 | char *name); | |
49 | ||
50 | /* Creates a URI for a local resource. */ | |
51 | no_ignore xl_error | |
52 | xl_uri_user( | |
53 | struct xl_uri *uri, | |
54 | char *name); | |
55 | ||
56 | /* Creates a URI for a package-scoped resource. */ | |
57 | no_ignore xl_error | |
58 | xl_uri_package( | |
59 | struct xl_uri *uri, | |
60 | char *package, | |
61 | char *name); | |
62 | ||
63 | /* Creates a URI for a global, runtime-provided resource. */ | |
64 | no_ignore xl_error | |
65 | xl_uri_native( | |
66 | struct xl_uri *uri, | |
67 | char *name); | |
68 | ||
69 | /* Creates a URI struct from a value-encoded URI. */ | |
70 | no_ignore xl_error | |
71 | xl_uri_from_value(struct xl_uri *uri, struct xl_value *uri_val); | |
72 | ||
73 | /* Returns true if the provided URIs are equal. */ | |
74 | bool | |
75 | xl_uri_eq(struct xl_uri *u0, struct xl_uri *u1); | |
76 | ||
77 | /* Generates a value representation for the URI and stores it in the URI's | |
78 | * as_value field. If the field is already initialized, this function is a | |
79 | * no-op. */ | |
80 | no_ignore xl_error | |
81 | xl_uri_attach_value(struct xl_uri *uri); | |
82 | ||
83 | /* Parses a URI string into a URI struct. Returns struct has no references; | |
84 | * caller must take a reference to it. */ | |
85 | no_ignore xl_error | |
86 | xl_uri_parse(struct xl_uri *uri, char *str); | |
87 | ||
88 | /* Creates a string representation of a URI. */ | |
89 | char * | |
90 | xl_uri_explain(struct xl_uri *uri); |
0 | /* | |
1 | * util.h: internal runtime utilities | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef EXPEL_UTIL_H__ | |
20 | #define EXPEL_UTIL_H__ | |
21 | ||
22 | #define unused(x) (void)(x) | |
23 | #define likely(x) __builtin_expect((x), 1) | |
24 | #define unlikely(x) __builtin_expect((x), 0) | |
25 | ||
26 | #include "expel/expel.h" | |
27 | ||
28 | size_t | |
29 | size_max(size_t a, size_t b); | |
30 | ||
31 | size_t | |
32 | size_min(size_t a, size_t b); | |
33 | ||
34 | /* Converts a word from host byte order to network byte order */ | |
35 | xl_word | |
36 | htonw(xl_word); | |
37 | ||
38 | /* Converts a word from network byte order to host byte order */ | |
39 | xl_word | |
40 | ntohw(xl_word); | |
41 | ||
42 | /* Prints a stack trace to stderr. */ | |
43 | void | |
44 | xl_trace_print(void); | |
45 | ||
46 | /* Converts a constant to its string value. */ | |
47 | char * | |
48 | xl_word_explain(xl_word); | |
49 | ||
50 | #endif |
0 | /* | |
1 | * value.h: encoding and decoding xl_values | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #include <stdbool.h> | |
20 | ||
21 | #include "expel/expel.h" | |
22 | ||
23 | bool | |
24 | xl_value_eq(struct xl_value *v1, struct xl_value *v2); | |
25 | ||
26 | no_ignore xl_error | |
27 | xl_value_print(struct xl_stream *out, struct xl_value *v); | |
28 | ||
29 | no_ignore xl_error | |
30 | xl_packed_read(uint8_t **dest, size_t *n, struct xl_value *src); | |
31 | ||
32 | no_ignore xl_error | |
33 | xl_string_read(char **dest, size_t *n, struct xl_value *src); | |
34 | ||
35 | no_ignore xl_error | |
36 | xl_value_as_bool(bool *res, struct xl_value *v); | |
37 | ||
38 | no_ignore xl_error | |
39 | xl_value_pack_string(struct xl_value *dest, char *src, size_t n); |
0 | /* | |
1 | * vector.h: growable arrays | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include <stdint.h> | |
21 | #include "expel/expel.h" | |
22 | ||
23 | struct xl_vector | |
24 | { | |
25 | void **elems; | |
26 | size_t n; | |
27 | size_t cap; | |
28 | }; | |
29 | ||
30 | /* Ensures that the vector has the capacity to hold at least the given size. */ | |
31 | no_ignore xl_error | |
32 | xl_vector_ensure_size(struct xl_vector *, size_t size); | |
33 | ||
34 | /* Appends an element onto the list. */ | |
35 | no_ignore xl_error | |
36 | xl_vector_append(struct xl_vector *, void *elem); | |
37 | ||
38 | /* Frees all memory associated with a vector. */ | |
39 | void | |
40 | xl_vector_free(struct xl_vector *); |
0 | const.h |
0 | /* | |
1 | * assert.h: compile-conditional assertions | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef XL_RECKLESS | |
20 | #include <stdio.h> | |
21 | #include <stdlib.h> | |
22 | #include "ubik/util.h" | |
23 | ||
24 | int | |
25 | break_on_assert(); | |
26 | ||
27 | #define xl_assert(x) do { \ | |
28 | if (!(x)) { \ | |
29 | fprintf(stderr, \ | |
30 | "assertion %s:%d failed: %s\n", \ | |
31 | __FILE__, __LINE__, #x); \ | |
32 | break_on_assert(); \ | |
33 | xl_trace_print(); \ | |
34 | exit(EXIT_FAILURE); \ | |
35 | }} while (0) | |
36 | #else | |
37 | #define xl_assert(x) | |
38 | #endif |
0 | /* | |
1 | * ast.h: in-memory ast representation | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "ubik/expel.h" | |
21 | #include "ubik/vector.h" | |
22 | ||
23 | #include <stdbool.h> | |
24 | ||
25 | /* The maximum number of subexpressions any one expression can have. */ | |
26 | #define XL_MAX_SUBEXPRS 8 | |
27 | ||
28 | enum expr_type | |
29 | { | |
30 | EXPR_APPLY = 1, | |
31 | EXPR_ATOM, | |
32 | EXPR_LAMBDA, | |
33 | EXPR_CONSTRUCTOR, | |
34 | EXPR_CONDITIONAL, | |
35 | EXPR_BLOCK | |
36 | }; | |
37 | ||
38 | enum type_expr_type | |
39 | { | |
40 | TYPE_EXPR_APPLY = 1, | |
41 | TYPE_EXPR_ATOM | |
42 | }; | |
43 | ||
44 | enum atom_type | |
45 | { | |
46 | ATOM_INT = 1, | |
47 | ATOM_NUM, | |
48 | ATOM_NAME, | |
49 | ATOM_QUALIFIED, | |
50 | ATOM_TYPE_NAME, | |
51 | ATOM_STRING | |
52 | }; | |
53 | ||
54 | struct xl_ast; | |
55 | struct xl_resolve_scope; | |
56 | struct xl_resolve_name_loc; | |
57 | ||
58 | enum type_type | |
59 | { | |
60 | TYPE_RECORD = 1, | |
61 | }; | |
62 | ||
63 | struct xl_ast_loc | |
64 | { | |
65 | size_t line_start; | |
66 | size_t line_end; | |
67 | size_t col_start; | |
68 | size_t col_end; | |
69 | }; | |
70 | ||
71 | struct xl_ast_atom | |
72 | { | |
73 | union | |
74 | { | |
75 | char *str; | |
76 | xl_word integer; | |
77 | xl_float number; | |
78 | struct | |
79 | { | |
80 | char *head; | |
81 | char *tail; | |
82 | } qualified; | |
83 | }; | |
84 | enum atom_type atom_type; | |
85 | struct xl_resolve_name_loc *name_loc; | |
86 | struct xl_ast_loc loc; | |
87 | }; | |
88 | ||
89 | struct xl_ast_arg_list | |
90 | { | |
91 | char *name; | |
92 | struct xl_ast_arg_list *next; | |
93 | struct xl_dagc_node *gen; | |
94 | struct xl_ast_loc loc; | |
95 | }; | |
96 | ||
97 | struct xl_ast_expr | |
98 | { | |
99 | union | |
100 | { | |
101 | struct xl_ast_atom *atom; | |
102 | struct | |
103 | { | |
104 | struct xl_ast_expr *head; | |
105 | struct xl_ast_expr *tail; | |
106 | } apply; | |
107 | struct | |
108 | { | |
109 | struct xl_ast_arg_list *args; | |
110 | struct xl_ast_expr *body; | |
111 | } lambda; | |
112 | struct | |
113 | { | |
114 | char *type_name; | |
115 | struct xl_ast *scope; | |
116 | } constructor; | |
117 | struct | |
118 | { | |
119 | struct xl_ast_expr *cond; | |
120 | struct xl_ast_expr *implied; | |
121 | struct xl_ast_expr *opposed; | |
122 | } condition; | |
123 | struct xl_ast *block; | |
124 | }; | |
125 | enum expr_type expr_type; | |
126 | ||
127 | struct xl_resolve_scope *scope; | |
128 | struct xl_dagc_node *gen; | |
129 | struct xl_ast_loc loc; | |
130 | }; | |
131 | ||
132 | struct xl_ast_type_expr | |
133 | { | |
134 | union | |
135 | { | |
136 | char *name; | |
137 | struct | |
138 | { | |
139 | struct xl_ast_type_expr *head; | |
140 | struct xl_ast_type_expr *tail; | |
141 | } apply; | |
142 | }; | |
143 | enum type_expr_type type_expr_type; | |
144 | struct xl_ast_loc loc; | |
145 | }; | |
146 | ||
147 | struct xl_ast_binding | |
148 | { | |
149 | char *name; | |
150 | struct xl_ast_expr *expr; | |
151 | struct xl_ast_type_expr *type_expr; | |
152 | struct xl_ast_loc loc; | |
153 | }; | |
154 | ||
155 | struct xl_ast_import_list | |
156 | { | |
157 | char *name; | |
158 | struct xl_ast_loc loc; | |
159 | struct xl_ast_import_list *next; | |
160 | }; | |
161 | ||
162 | struct xl_ast_member_list | |
163 | { | |
164 | char *name; | |
165 | struct xl_ast_type_expr *type; | |
166 | struct xl_ast_loc loc; | |
167 | struct xl_ast_member_list *next; | |
168 | }; | |
169 | ||
170 | struct xl_ast_type | |
171 | { | |
172 | union | |
173 | { | |
174 | struct xl_ast_member_list *members; | |
175 | }; | |
176 | char *name; | |
177 | enum type_type type; | |
178 | struct xl_ast_loc loc; | |
179 | }; | |
180 | ||
181 | struct xl_ast | |
182 | { | |
183 | /* members are struct xl_ast_binding pointers */ | |
184 | struct xl_vector bindings; | |
185 | /* members are struct xl_ast_type pointers */ | |
186 | struct xl_vector types; | |
187 | /* to run when ast is evaluted */ | |
188 | struct xl_ast_expr *immediate; | |
189 | /* things this depends on existing */ | |
190 | struct xl_ast_import_list *imports; | |
191 | /* everything in scope in this ast */ | |
192 | struct xl_resolve_scope *scope; | |
193 | /* the location of this ast (useful because there are sub-ASTs whose | |
194 | * location is actually interesting) */ | |
195 | struct xl_ast_loc loc; | |
196 | }; | |
197 | ||
198 | /* Allocates a new AST. */ | |
199 | no_ignore xl_error | |
200 | xl_ast_new(struct xl_ast **ast); | |
201 | ||
202 | no_ignore xl_error | |
203 | xl_ast_free(struct xl_ast *ast); | |
204 | ||
205 | void | |
206 | xl_ast_error_loc_free(struct xl_ast_loc *err_loc); | |
207 | ||
208 | /* Prints the AST to stdout. */ | |
209 | no_ignore xl_error | |
210 | xl_ast_print(struct xl_ast *ast); | |
211 | ||
212 | no_ignore xl_error | |
213 | xl_ast_bind( | |
214 | struct xl_ast *ast, | |
215 | struct xl_ast_binding *bind); | |
216 | ||
217 | no_ignore xl_error | |
218 | xl_ast_add_type( | |
219 | struct xl_ast *ast, | |
220 | struct xl_ast_type *type); | |
221 | ||
222 | no_ignore xl_error | |
223 | xl_ast_atom_new_qualified( | |
224 | struct xl_ast_atom **atom, | |
225 | char *name); | |
226 | ||
227 | no_ignore xl_error | |
228 | xl_ast_import( | |
229 | struct xl_ast *ast, | |
230 | struct xl_ast_import_list *import_list); | |
231 | ||
232 | no_ignore xl_error | |
233 | xl_ast_subexprs( | |
234 | struct xl_ast **subast, | |
235 | struct xl_ast_expr **subexprs, | |
236 | size_t *n_subexprs, | |
237 | struct xl_ast_expr *expr); | |
238 | ||
239 | void | |
240 | xl_ast_merge_loc( | |
241 | struct xl_ast_loc *res, | |
242 | struct xl_ast_loc *l1, | |
243 | struct xl_ast_loc *l2); |
0 | /* | |
1 | * bdagc.h: graph builder | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "ubik/dagc.h" | |
21 | #include "ubik/expel.h" | |
22 | ||
23 | struct xl_graph_builder | |
24 | { | |
25 | struct xl_dagc_node **nodes; | |
26 | size_t n_nodes; | |
27 | size_t cap_nodes; | |
28 | ||
29 | struct xl_dagc_node *result; | |
30 | }; | |
31 | ||
32 | no_ignore xl_error | |
33 | xl_bdagc_init(struct xl_graph_builder *b); | |
34 | ||
35 | /* Adds a node to the graph. */ | |
36 | no_ignore xl_error | |
37 | xl_bdagc_push_node( | |
38 | struct xl_graph_builder *b, | |
39 | struct xl_dagc_node *node); | |
40 | ||
41 | /* Builds the graph. */ | |
42 | no_ignore xl_error | |
43 | xl_bdagc_build( | |
44 | struct xl_dagc **graph, | |
45 | struct xl_graph_builder *b); |
0 | /* | |
1 | * closure.h: closure transformation on ASTs | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "ubik/ast.h" | |
21 | #include "ubik/expel.h" | |
22 | #include "ubik/resolve.h" | |
23 | ||
24 | /* Takes an AST and transforms closures into partially-applied functions. This | |
25 | * transformation is explained in-depth in the "Code generation" portion of the | |
26 | * architecture document. */ | |
27 | no_ignore xl_error | |
28 | xl_reduce_closures( | |
29 | struct xl_resolve_context *ctx, | |
30 | struct xl_ast *ast); |
0 | /* | |
1 | * compile.h: expel compilation | |
2 | * Copyright (C) 2016, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | #include "ubik/expel.h" | |
21 | #include "ubik/ast.h" | |
22 | ||
23 | ||
24 | struct xl_compilation_env | |
25 | { | |
26 | char *scratch_dir; | |
27 | ||
28 | char **include_dirs; | |
29 | size_t n_include_dirs; | |
30 | }; | |
31 | ||
32 | no_ignore xl_error | |
33 | xl_compile_env_default(struct xl_compilation_env *cenv); | |
34 | ||
35 | no_ignore xl_error | |
36 | xl_compile_env_free(struct xl_compilation_env *cenv); | |
37 | ||
38 | no_ignore xl_error | |
39 | xl_compile( | |
40 | struct xl_dagc ***graphs, | |
41 | size_t *n_graphs, | |
42 | char *source_name, | |
43 | struct xl_stream *in_stream, | |
44 | struct xl_compilation_env *cenv); | |
45 | ||
46 | no_ignore xl_error | |
47 | xl_compile_ast( | |
48 | struct xl_dagc ***graphs, | |
49 | size_t *n_graphs, | |
50 | struct xl_ast *ast, | |
51 | struct xl_compilation_env *cenv); | |
52 |
0 | /* | |
1 | * dagc.h: directed acyclic graphs of computation | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef EXPEL_DAGC_H | |
20 | #define EXPEL_DAGC_H | |
21 | ||
22 | #include "ubik/expel.h" | |
23 | ||
24 | /* node is fully evaluated */ | |
25 | #define XL_DAGC_FLAG_COMPLETE 0x01 | |
26 | /* waiting on node's first dependency */ | |
27 | #define XL_DAGC_FLAG_WAIT_D1 0x02 | |
28 | /* waiting on node's second dependency */ | |
29 | #define XL_DAGC_FLAG_WAIT_D2 0x04 | |
30 | /* waiting on node's third dependency */ | |
31 | #define XL_DAGC_FLAG_WAIT_D3 0x08 | |
32 | /* waiting on evaluation */ | |
33 | #define XL_DAGC_FLAG_WAIT_EVAL 0x10 | |
34 | /* waiting on data to exist */ | |
35 | #define XL_DAGC_FLAG_WAIT_DATA 0x20 | |
36 | /* wait_d1 | wait_d2 | wait_d3 | wait_eval */ | |
37 | #define XL_DAGC_WAIT_MASK 0x2E | |
38 | ||
39 | struct xl_dagc_adjacency | |
40 | { | |
41 | struct xl_dagc_node *child; | |
42 | struct xl_dagc_node **parents; | |
43 | size_t n_parents; | |
44 | }; | |
45 | ||
46 | struct xl_dagc_apply | |
47 | { | |
48 | struct xl_dagc_node head; | |
49 | /* Function to call */ | |
50 | struct xl_dagc_node *func; | |
51 | /* Argument to apply to function */ | |
52 | struct xl_dagc_node *arg; | |
53 | }; | |
54 | ||
55 | struct xl_dagc_const | |
56 | { | |
57 | struct xl_dagc_node head; | |
58 | /* Type of constant */ | |
59 | struct xl_value *type; | |
60 | /* Value of constant */ | |
61 | union xl_value_or_graph value; | |
62 | }; | |
63 | ||
64 | struct xl_dagc_load | |
65 | { | |
66 | struct xl_dagc_node head; | |
67 | /* Where to load from */ | |
68 | struct xl_uri *loc; | |
69 | }; | |
70 | ||
71 | struct xl_dagc_store | |
72 | { | |
73 | struct xl_dagc_node head; | |
74 | /* Location to store */ | |
75 | struct xl_uri *loc; | |
76 | /* Value to store */ | |
77 | struct xl_dagc_node *value; | |
78 | }; | |
79 | ||
80 | struct xl_dagc_input | |
81 | { | |
82 | struct xl_dagc_node head; | |
83 | /* The argument that this corresponds to */ | |
84 | xl_word arg_num; | |
85 | }; | |
86 | ||
87 | struct xl_dagc_ref | |
88 | { | |
89 | struct xl_dagc_node head; | |
90 | /* The node to copy the value from */ | |
91 | struct xl_dagc_node *referrent; | |
92 | }; | |
93 | ||
94 | /* The native_out node is a piece of magic that is enabled | |
95 | * by the graph evaluator; if a graph has the native tag, | |
96 | * then the evaluator evalutes the value of the graph using | |
97 | * native code and populates the native node in the graph | |
98 | * with the result. The native node is provided only as a | |
99 | * thing for the caller to latch on to for the result. */ | |
100 | struct xl_dagc_native_out | |
101 | { | |
102 | struct xl_dagc_node head; | |
103 | }; | |
104 | ||
105 | struct xl_dagc_cond | |
106 | { | |
107 | struct xl_dagc_node head; | |
108 | /* The node that contains the condition */ | |
109 | struct xl_dagc_node *condition; | |
110 | /* The node that contains the value that is used if | |
111 | * the condition evaluates to true */ | |
112 | struct xl_dagc_node *if_true; | |
113 | /* The node that contains the value that is used if | |
114 | * the condition evaluates to false */ | |
115 | struct xl_dagc_node *if_false; | |
116 | }; | |
117 | ||
118 | /* This syntax is terrible; it defines xl_native_evaluator_t as a | |
119 | * function pointer that takes an env and a dagc and returns an | |
120 | * xl_error. */ | |
121 | typedef xl_error (*xl_native_evaluator_t)( | |
122 | struct xl_env *env, struct xl_dagc *graph); | |
123 | ||
124 | struct xl_dagc_native | |
125 | { | |
126 | /* xl_dagc_native pointers are equivalent to an xl_dagc | |
127 | * pointer */ | |
128 | struct xl_dagc graph; | |
129 | ||
130 | /* The function used to evaluate this graph. */ | |
131 | xl_native_evaluator_t evaluator; | |
132 | }; | |
133 | ||
134 | /* It can be anything you want it to be. | |
135 | * | |
136 | * It also happens to be the maximum size of all of the nodes, | |
137 | * which has advantages for allocating big lists of nodes. */ | |
138 | union xl_dagc_any_node | |
139 | { | |
140 | struct xl_dagc_node node; | |
141 | struct xl_dagc_apply as_apply; | |
142 | struct xl_dagc_cond as_cond; | |
143 | struct xl_dagc_const as_const; | |
144 | struct xl_dagc_input as_input; | |
145 | struct xl_dagc_load as_load; | |
146 | struct xl_dagc_ref as_ref; | |
147 | struct xl_dagc_store as_store; | |
148 | }; | |
149 | ||
150 | /* Allocates a graph object in a memory region of the given size. | |
151 | * | |
152 | * If copy_from is not NULL, this also copies size bytes from | |
153 | * copy_from into the graph before allocating all of the | |
154 | * substructures of the graph. */ | |
155 | no_ignore xl_error | |
156 | xl_dagc_alloc( | |
157 | struct xl_dagc **graph, | |
158 | size_t n_nodes, | |
159 | size_t size, | |
160 | void *copy_from); | |
161 | ||
162 | /* Gets the dependencies of a node. | |
163 | * | |
164 | * For nodes with N dependencies, d1 through dN will be filled in | |
165 | * and the result will be NULL. */ | |
166 | no_ignore xl_error | |
167 | xl_dagc_get_deps( | |
168 | struct xl_dagc_node **d1, | |
169 | struct xl_dagc_node **d2, | |
170 | struct xl_dagc_node **d3, | |
171 | struct xl_dagc_node *n); | |
172 | ||
173 | /* Modifies any references from the given node into the proto list | |
174 | * of nodes to point at the corresponding node in the list of new | |
175 | * nodes. | |
176 | * | |
177 | * This is useful when copying graphs or inserting nodes into | |
178 | * graphs. */ | |
179 | no_ignore xl_error | |
180 | xl_dagc_replace_node_refs( | |
181 | struct xl_dagc_node *node, | |
182 | struct xl_dagc_node **proto, | |
183 | struct xl_dagc_node **new, | |
184 | size_t n); | |
185 | ||
186 | /* Retrieve the parents of the given node. | |
187 | * | |
188 | * Returns OK on success or a nonzero error code on error. | |
189 | * It is imperative that callers do not modify the contents | |
190 | * of the returned array. | |
191 | * | |
192 | * I know a triple-pointer seems ridiculous, but hear me | |
193 | * out; we're returning a pointer to the caller, but we're | |
194 | * returning multiple values so we want it as an outparam, | |
195 | * which means we need to be passed a pointer to the | |
196 | * pointer. The pointer we're returning is itself a pointer | |
197 | * to a list of pointers. So we're asking you to pass us a | |
198 | * pointer to a pointer of pointers. I'm sorry. */ | |
199 | no_ignore xl_error | |
200 | xl_dagc_get_parents( | |
201 | struct xl_dagc_node ***parents, | |
202 | size_t *n_parents, | |
203 | struct xl_dagc *graph, | |
204 | struct xl_dagc_node *child); | |
205 | ||
206 | /* Evaluates a node and marks it as complete. */ | |
207 | no_ignore xl_error | |
208 | xl_dagc_node_eval( | |
209 | struct xl_env *env, | |
210 | struct xl_dagc_node *node); | |
211 | ||
212 | /* Returns the size of the node structure in bytes. */ | |
213 | no_ignore xl_error | |
214 | xl_dagc_node_sizeof( | |
215 | size_t *size, | |
216 | struct xl_dagc_node *node); | |
217 | ||
218 | /* Performs a copy from proto to result. | |
219 | * | |
220 | * This is a deep copy of the nodes but not the values within | |
221 | * them. This copies all information, including adjacency, and | |
222 | * updates all internal references between nodes. */ | |
223 | no_ignore xl_error | |
224 | xl_dagc_copy( | |
225 | struct xl_dagc **result, | |
226 | struct xl_dagc *proto); | |
227 | ||
228 | #endif |
0 | /* | |
1 | * def-native.h: defines a native function | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef DEF_OP | |
20 | #error "no DEF_OP specified, should be name of operation's _register method" | |
21 | #endif | |
22 | ||
23 | #ifndef DEF_OP_EVAL | |
24 | #error "no DEF_OP_EVAL specified, should be name of graph evaluator" | |
25 | #endif | |
26 | ||
27 | #ifndef DEF_OP_URI | |
28 | #error "no DEF_OP_URI specified, should be const char* of method name" | |
29 | #endif | |
30 | ||
31 | #ifndef DEF_ARG_TYPE | |
32 | #error "no DEF_ARG_TYPE specified, should be name of type constructor for arguments" | |
33 | #endif | |
34 | ||
35 | #ifndef concat | |
36 | #define concat(a, ...) concatr(a, __VA_ARGS__) | |
37 | #define concatr(a, ...) a ## __VA_ARGS__ | |
38 | #endif | |
39 | ||
40 | #define _op_name concat(_register_, DEF_OP) | |
41 | ||
42 | #ifdef DEF_BINARY | |
43 | ||
44 | no_ignore static xl_error | |
45 | _op_name(struct xl_env *env) | |
46 | { | |
47 | xl_error err; | |
48 | ||
49 | struct xl_dagc *ngraph; | |
50 | struct xl_uri *uri; | |
51 | struct xl_value *type; | |
52 | union xl_value_or_graph ins; | |
53 | ||
54 | ngraph = NULL; | |
55 | err = _create_op(&ngraph, 2, DEF_OP_EVAL); | |
56 | if (err != OK) | |
57 | return err; | |
58 | ||
59 | err = _native_uri(&uri, DEF_OP_URI); | |
60 | if (err != OK) | |
61 | return err; | |
62 | ||
63 | ngraph->identity = uri; | |
64 | err = xl_take(uri); | |
65 | if (err != OK) | |
66 | return err; | |
67 | ||
68 | err = xl_value_new(&type); | |
69 | if (err != OK) | |
70 | return err; | |
71 | /* TODO: set type here */ | |
72 | ||
73 | ins.graph = ngraph; | |
74 | err = xl_env_set(env, uri, ins, type); | |
75 | if (err != OK) | |
76 | return err; | |
77 | ||
78 | err = xl_release(type); | |
79 | if (err != OK) | |
80 | return err; | |
81 | err = xl_release(ngraph); | |
82 | if (err != OK) | |
83 | return err; | |
84 | ||
85 | return OK; | |
86 | } | |
87 | ||
88 | #elif defined(DEF_UNARY) | |
89 | ||
90 | no_ignore static xl_error | |
91 | _op_name(struct xl_env *env) | |
92 | { | |
93 | xl_error err; | |
94 | ||
95 | struct xl_dagc *ngraph; | |
96 | struct xl_uri *uri; | |
97 | struct xl_value *type; | |
98 | union xl_value_or_graph ins; | |
99 | ||
100 | ngraph = NULL; | |
101 | err = _create_op(&ngraph, 1, DEF_OP_EVAL); | |
102 | if (err != OK) | |
103 | return err; | |
104 | ||
105 | err = _native_uri(&uri, DEF_OP_URI); | |
106 | if (err != OK) | |
107 | return err; | |
108 | ||
109 | ngraph->identity = uri; | |
110 | err = xl_take(uri); | |
111 | if (err != OK) | |
112 | return err; | |
113 | ||
114 | err = xl_value_new(&type); | |
115 | if (err != OK) | |
116 | return err; | |
117 | /* TODO: set type here */ | |
118 | ||
119 | ins.graph = ngraph; | |
120 | err = xl_env_set(env, uri, ins, type); | |
121 | if (err != OK) | |
122 | return err; | |
123 | ||
124 | err = xl_release(type); | |
125 | if (err != OK) | |
126 | return err; | |
127 | err = xl_release(ngraph); | |
128 | if (err != OK) | |
129 | return err; | |
130 | ||
131 | return OK; | |
132 | } | |
133 | ||
134 | #else | |
135 | #error operation was not one of [DEF_BINARY, DEF_UNARY] | |
136 | #endif | |
137 | ||
138 | #undef DEF_OP | |
139 | #undef DEF_OP_EVAL | |
140 | #undef DEF_OP_URI | |
141 | #undef DEF_BINARY | |
142 | #undef DEF_UNARY | |
143 | #undef DEF_ARG_TYPE | |
144 | #undef _op_name |
0 | /* | |
1 | * env.h: expel environment definitions | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #pragma once | |
20 | ||
21 | #include "ubik/expel.h" | |
22 | #include "ubik/uri.h" | |
23 | ||
24 | #include <stdbool.h> | |
25 | #include <stdint.h> | |
26 | #include <stdlib.h> | |
27 | ||
28 | ||
29 | typedef xl_error (*xl_env_cb)( | |
30 | void *arg, | |
31 | struct xl_env *env, | |
32 | struct xl_uri *uri); | |
33 | ||
34 | /* An association between a URI and a value */ | |
35 | struct xl_binding | |
36 | { | |
37 | struct xl_uri *uri; | |
38 | union xl_value_or_graph value; | |
39 | struct xl_value *type; | |
40 | }; | |
41 | ||
42 | struct xl_env_watch | |
43 | { | |
44 | struct xl_uri *uri; | |
45 | struct xl_env *target_env; | |
46 | xl_env_cb cb; | |
47 | void *arg; | |
48 | ||
49 | /* Fired is set to true once the watcher has fired once; if this is | |
50 | * true, it means means that the watcher is dead. */ | |
51 | bool fired; | |
52 | ||
53 | /* The number of environments on which this watch was placed. */ | |
54 | xl_word refcount; | |
55 | }; | |
56 | ||
57 | struct xl_env_watch_list | |
58 | { | |
59 | struct xl_env_watch *watch; | |
60 | ||
61 | struct xl_env_watch_list *prev; | |
62 | struct xl_env_watch_list *next; | |
63 | }; | |
64 | ||
65 | /* A hash mapping from URI to value. */ | |
66 | struct xl_env | |
67 | { | |
68 | struct xl_binding *bindings; | |
69 | size_t n; | |
70 | size_t cap; | |
71 | struct xl_env *parent; | |
72 | ||
73 | struct xl_env_watch_list *watches; | |
74 | }; | |
75 | ||
76 | /* Initializes a new environment struct. */ | |
77 | no_ignore xl_error | |
78 | xl_env_init(struct xl_env *env); | |
79 | ||
80 | /* Creates a child environment from the given env. */ | |
81 | no_ignore xl_error | |
82 | xl_env_make_child(struct xl_env *child, struct xl_env *parent); | |
83 | ||
84 | /* Returns the root environment. | |
85 | * | |
86 | * This environment is the parent of any environment that isn't | |
87 | * explicitly created as a child. */ | |
88 | struct xl_env * | |
89 | xl_env_get_root(); | |
90 | ||
91 | /* Frees memory associated with the environment struct. | |
92 | * | |
93 | * Returns OK if successful. If this method returns an error code, | |
94 | * there is no guarantee that the environment is in a usable | |
95 | * state. If OK is returned, the environment can still be used | |
96 | * with xl_get and xl_set after calling xl_env_free; this is a | |
97 | * clear operation that does not destroy the env. */ | |
98 | no_ignore xl_error | |
99 | xl_env_free(struct xl_env *env); | |
100 | ||
101 | /* Finds the value associated wth the given URI in the environment. | |
102 | * | |
103 | * If the value is found, OK is returned and the out pointer is | |
104 | * set to the pointer to the assigned value. If the value is not | |
105 | * found, ERR_ABSENT is returned and the out pointer is unchanged. | |
106 | * */ | |
107 | no_ignore xl_error | |
108 | xl_env_get( | |
109 | union xl_value_or_graph *value, | |
110 | struct xl_value **type, | |
111 | struct xl_env *env, | |
112 | struct xl_uri *uri); | |
113 | ||
114 | /* Inserts the given value in at the given URI, overwriting an | |
115 | * existing value if present. | |
116 | * | |
117 | * The URI is copied into the environment but the value is not; | |
118 | * later modifications to the passed-in URI will not change the | |
119 | * bindings but modifications to the value will modify the value | |
120 | * stored in the environment. */ | |
121 | no_ignore xl_error | |
122 | xl_env_overwrite( | |
123 | struct xl_env *env, | |
124 | struct xl_uri *uri, | |
125 | union xl_value_or_graph value, | |
126 | struct xl_value *type); | |
127 | ||
128 | /* Inserts the given value in at the given URI if the URI is | |
129 | * not already defined. | |
130 | * | |
131 | * If the URI is already bound, this will return ERR_PRESENT | |
132 | * and the existing binding will not be modified. | |
133 | * | |
134 | * The URI is copied into the environment but the value is not; | |
135 | * later modifications to the passed-in URI will not change the | |
136 | * bindings but modifications to the value will modify the value | |
137 | * stored in the environment. */ | |
138 | no_ignore xl_error | |
139 | xl_env_set( | |
140 | struct xl_env *env, | |
141 | struct xl_uri *uri, | |
142 | union xl_value_or_graph value, | |
143 | struct xl_value *type); | |
144 | ||
145 | /* Returns true if the provided URI is present in the environment. */ | |
146 | no_ignore xl_error | |
147 | xl_env_present( | |
148 | bool *is_present, | |
149 | struct xl_env *env, | |
150 | struct xl_uri *uri); | |
151 | ||
152 | /* Calls the provided callback function once for every item. */ | |
153 | no_ignore xl_error | |
154 | xl_env_iterate( | |
155 | xl_env_cb callback, | |
156 | struct xl_env *env, | |
157 | void *callback_arg); | |
158 | ||
159 | /* Calls the provided callback function when a URI is inserted or modified. | |
160 | * | |
161 | * Note that a watch is only ever triggered once; after being triggered it is | |
162 | * removed from the list of watchers. */ | |
163 | no_ignore xl_error | |
164 | xl_env_watch( | |
165 | xl_env_cb callback, | |
166 | struct xl_env *env, | |
167 | struct xl_uri *uri, | |
168 | void *callback_arg); | |
169 |
0 | /* | |
1 | * expel.h: minimal public API | |
2 | * Copyright (C) 2015, Haldean Brown | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 | */ | |
18 | ||
19 | #ifndef EXPEL_EXPEL_H | |
20 | #define EXPEL_EXPEL_H | |
21 | ||
22 | #include <stddef.h> | |
23 | #include <stdint.h> | |
24 | ||
25 | #include "ubik/const.h" | |
26 | ||
27 | typedef uint16_t xl_tag; | |
28 | typedef uint64_t xl_word; | |
29 | ||
30 | #if __SIZEOF_DOUBLE__ == 8 | |
31 | typedef double xl_float; | |
32 | #elif __SIZEOF_FLOAT__ == 8 | |
33 | typedef float xl_float; | |
34 | #elif __SIZEOF_LONG_DOUBLE__ == 8 | |
35 | typedef long double xl_float; | |
36 | #else | |
37 | #error "word size and float size do not match" | |
38 | #endif | |
39 | ||
40 | #define TAG_TYPE_MASK 0xF000 | |
41 | #define TAG_VALUE 0x1000 | |
42 | #define TAG_GRAPH 0x2000 | |
43 | #define TAG_URI 0x3000 | |
44 | ||
45 | /* Tree tags */ | |
46 | #define TAG_LEFT_NODE 0x0010 | |
47 | #define TAG_LEFT_WORD 0x0020 | |
48 | #define TAG_LEFT_GRAPH 0x0040 | |
49 | #define TAG_RIGHT_NODE 0x0001 | |
50 | #define TAG_RIGHT_WORD 0x0002 | |
51 | #define TAG_RIGHT_GRAPH 0x0004 | |
52 | ||
53 | /* Graph tags */ | |
54 | #define TAG_GRAPH_NATIVE 0x0001 | |
55 | /* an unresolved graph is one that contains URIs that have not been resolved to | |
56 | * a specific resource yet. */ | |
57 | #define TAG_GRAPH_UNRESOLVED 0x0002 | |
58 | /* a modinit graph represents a graph that should be run when bytecode is | |
59 | * loaded. */ | |
60 | #define TAG_GRAPH_MODINIT 0x0004 | |
61 | ||
62 | /* The maximum Expel bytecode version that this library supports. */ | |
63 | #define CURRENT_ENCODING_VERSION 1 | |
64 | ||
65 | /* Private data structures referenced by public data structures. */ | |
66 | struct xl_alloc_page; | |
67 | struct xl_env; | |
68 | struct xl_stream; | |
69 | struct xl_user; | |
70 | struct xl_uri; | |
71 | struct xl_dagc_adjacency; | |
72 | ||
73 | struct xl_dagc; | |
74 | ||
75 | /* Used to communicate errors through the stack. */ | |
76 | struct xl_error | |
77 | { | |
78 | xl_word error_code; | |
79 | const char *tag; | |
80 | const char *file; | |
81 | const char *function; | |
82 | uint32_t lineno; | |
83 | }; | |
84 | typedef struct xl_error * xl_error; | |
85 | #define OK ((xl_error) NULL) | |
86 | ||
87 | #define no_ignore __attribute__((__warn_unused_result__)) | |
88 | ||
89 | union xl_atom | |
90 | { | |
91 | struct xl_value *t; | |
92 | struct xl_dagc *g; | |
93 | void *any; | |
94 | xl_word w; | |
95 | xl_float f; | |
96 | }; | |
97 | ||
98 | /* The base type of all data in Expel; it's a cons cell. */ | |
99 | struct xl_value | |
100 | { | |
101 | /* A bitset of the TAG_ constants. One each of the | |
102 | * TAG_LEFT_ and TAG_RIGHT_ bits must be set, along with | |
103 | * the TAG_VALUE bit. */ | |
104 | xl_tag tag; | |
105 | ||
106 | union xl_atom left; | |
107 | union xl_atom right; | |
108 | ||
109 | /* The page in which the value was allocated, used by the | |
110 | * garbage collector. */ | |
111 | struct xl_alloc_page *alloc_page; | |
112 | /* The number of references to the value, used by the | |
113 | * garbage collector. Special hell awaits those who modify | |
114 | * this value. */ | |
115 | uint64_t refcount; | |
116 | }; | |
117 | ||
118 | struct xl_dagc; | |
119 | ||
120 | union xl_value_or_graph | |
121 | { | |
122 | struct xl_value *tree; | |
123 | struct xl_dagc *graph; | |
124 | void *any; | |
125 | xl_tag *tag; | |
126 | }; | |
127 | ||
128 | struct xl_dagc_node | |
129 | { | |
130 | /* One of the DAGC_NODE constants */ | |
131 | xl_word node_type; | |
132 | /* The unique identifier of this node */ | |
133 | xl_word id; | |
134 | /* The evaluated type of the node, populated after the | |
135 | * node is evaluated by xl_dagc_eval. */ | |
136 | struct xl_value *known_type; | |
137 | /* The evaluated computation graph of the node, populated | |
138 | * after the node is evaluated by xl_dagc_eval. The | |
139 | * tag field tells you which member of the union to | |
140 | * access. */ | |
141 | union xl_value_or_graph known; | |
142 | /* Nonzero if we want the value of this node at the end of | |
143 | * evaluation */ | |
144 | uint8_t is_terminal; | |
145 | /* A bitsest of the XL_DAGC_FLAG constants */ | |
146 | uint8_t flags; | |
147 | }; | |
148 | ||
149 | struct xl_dagc | |
150 | { | |
151 | /* Used to determine if a void* is a graph or a value. | |
152 | * This is set by xl_dagc_init; users of the DAGC API | |
153 | * should not touch it. */ | |
154 | xl_tag tag; | |
155 | ||
156 | /* The identity of the graph, in URI form. */ | |
157 | struct xl_uri *identity; | |
158 | ||
159 | /* The nodes participating in the graph. */ | |
160 | struct xl_dagc_node **nodes; | |
161 | /* The number of nodes in the graph. */ | |
162 | size_t n; | |
163 | ||
164 | /* Below this is only members that are populated by | |
165 | * calling xl_dagc_init; callers should initialize nodes | |
166 | * and n above and then call init to take care of | |
167 | * everything else. */ | |
168 | ||
169 | /* Number of references held to this graph. */ | |
170 | uint64_t refcount; | |
171 | ||
172 | /* A list of structs which encode backlinks from child to | |
173 | * parent. */ | |
174 | struct xl_dagc_adjacency *adjacency; | |
175 | ||
176 | /* The input nodes in the graph. */ | |
177 | struct xl_dagc_node **inputs; | |
178 | size_t in_arity; | |
179 | ||
180 | /* The terminal nodes in the graph. */ | |
181 | struct xl_dagc_node **terminals; | |
182 | size_t out_arity; | |
183 | ||
184 | /* The result node in the graph. */ | |
185 | struct xl_dagc_node *result; | |
186 | }; | |
187 | ||
188 | /* Starts the expel runtime. | |
189 | * | |
190 | * Returns OK on success. */ | |
191 | no_ignore xl_error | |
192 | xl_start(); | |
193 | ||
194 | /* Stops the expel runtime. | |
195 | * | |
196 | * Returns OK on success. */ | |
197 | no_ignore xl_error | |
198 | xl_teardown(); | |
199 | ||
200 | /* Creates a new value. | |
201 | * | |
202 | * The returned value has a refcount of one; callers to xl_new do | |
203 | * not need to take the result. This may result in an allocation | |
204 | * but is not guaranteed to; xl_values are allocated in pages. */ | |
205 | no_ignore xl_error | |
206 | xl_value_new(struct xl_value **v); | |
207 | ||
208 | /* Takes a reference to the given tree or graph. | |
209 | * | |
210 | * Returns OK on success, or a nonzero error code on failure. */ | |
211 | no_ignore xl_error | |
212 | xl_take(void *v); | |
213 | ||
214 | /* Releases a reference to the given tree or graph. | |
215 | * | |
216 | * Returns OK on success, or a nonzero error code on failure. If | |
217 | * passed a value, this may result in a free but is not guaranteed | |
218 | * to; xl_values are garbage-collected periodically. If passed a | |
219 | * graph and the releaser was the last owner of the graph, this | |
220 | * will free the graph. */ | |
221 | no_ignore xl_error | |
222 | xl_release(void *v); | |
223 | ||
224 | /* Loads an expel bytecode blob from a stream. | |
225 | * | |
226 | * Returns OK on success, or a nonzero error word. */ | |
227 | no_ignore xl_error | |
228 | xl_load(struct xl_dagc ***out, size_t *n_graphs, struct xl_stream *sp); | |
229 | ||
230 | /* Saves a list of graphs and all accessible subgraphs to a stream. | |
231 | * | |
232 | * Returns OK on success, or a nonzero error word. */ | |
233 | no_ignore xl_error | |
234 | xl_save(struct xl_stream *sp, struct xl_dagc **graphs, size_t n); | |
235 | ||
236 | /* Loads a tree from a stream. | |
237 | * | |
238 | * Note that any contained graph references are initialized to the index | |
239 | * of the graph in some other structure; if you're loading values with | |
240 | * graph references you probably want to load the whole thing in one go | |
241 | * with xl_load. | |
242 | * | |
243 | * The returned tree is not taken; it is up to the caller to take the | |
244 | * tree. Returns OK on success, or a nonzero error word. */ | |
245 | no_ignore xl_error | |
246 | xl_value_load(struct xl_value *out, struct xl_stream *sp); | |
247 | ||
248 | /* Saves a tree to a stream. | |
249 | * | |
250 | * Note that this cannot save any values that contain any graph | |
251 | * references; for that you'll need to serialize the entire structure | |
252 | * with xl_save. | |
253 | * | |
254 | * Returns OK on success, or a nonzero error word. */ | |
255 | no_ignore xl_error | |
256 | xl_value_save(struct xl_stream *sp, struct xl_value *in); | |
257 | ||
258 | /* Allocates a graph object. | |
259 | * | |
260 | * All graph objects must be allocated on the heap; call into this | |
261 | * method to allocate a graph of a given size. */ | |
262 | no_ignore xl_error | |
263 | xl_dagc_new(struct xl_dagc **g, size_t n); | |
264 | ||
265 | /* Initializes derived quantities on graphs. | |
266 | * | |
267 | * Callers should create a dagc struct, populate the nodes and the | |
268 | * n fields, and then call this method to compute all derived | |
269 | * quantities. | |
270 | * | |
271 | * This resets the refcount of the given graph to 1; initializers | |
272 | * of graph structs do not need to take a reference to the graph | |
273 | * after initialization. */ | |
274 | no_ignore xl_error | |
275 | xl_dagc |