GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/lbm_c_interop.c
Date: 2024-08-06 17:32:21
Exec Total Coverage
Lines: 47 142 33.1%
Functions: 6 19 31.6%
Branches: 17 82 20.7%

Line Branch Exec Source
1 /*
2 Copyright 2022 Joel Svensson svenssonjoel@yahoo.se
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 3 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
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "lbm_c_interop.h"
19
20 /****************************************************/
21 /* Interface for loading and running programs and */
22 /* expressions */
23
24 17444 lbm_cid eval_cps_load_and_eval(lbm_char_channel_t *tokenizer, bool program, bool incremental, char *name) {
25
26 lbm_value stream;
27
28
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17444 times.
17444 if (!lift_char_channel(tokenizer, &stream)) {
29 return 0;
30 }
31
32
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17444 times.
17444 if (lbm_type_of(stream) == LBM_TYPE_SYMBOL) {
33 // TODO: Check what should be done.
34 return 0;
35 }
36
37 17444 lbm_value read_mode = ENC_SYM_READ;
38
1/2
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
17444 if (program) {
39
2/2
✓ Branch 0 taken 8722 times.
✓ Branch 1 taken 8722 times.
17444 if (incremental) {
40 8722 read_mode = ENC_SYM_READ_AND_EVAL_PROGRAM;
41 } else {
42 8722 read_mode = ENC_SYM_READ_PROGRAM;
43 }
44 }
45 /*
46 read-eval-program finishes with the result of the final expression in
47 the program. This should not be passed to eval-program as it is most likely
48 not a program. Even if it is a program, its not one we want to evaluate.
49 */
50
51 /* LISP ZONE */
52 17444 lbm_value launcher = lbm_cons(stream, ENC_SYM_NIL);
53 17444 launcher = lbm_cons(read_mode, launcher);
54 lbm_value evaluator;
55 lbm_value start_prg;
56
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17444 times.
17444 if (read_mode == ENC_SYM_READ) {
57 evaluator = lbm_cons(launcher, ENC_SYM_NIL);
58 evaluator = lbm_cons(ENC_SYM_EVAL, evaluator);
59 start_prg = lbm_cons(evaluator, ENC_SYM_NIL);
60
2/2
✓ Branch 0 taken 8722 times.
✓ Branch 1 taken 8722 times.
17444 } else if (read_mode == ENC_SYM_READ_PROGRAM) {
61 8722 evaluator = lbm_cons(launcher, ENC_SYM_NIL);
62 8722 evaluator = lbm_cons(ENC_SYM_EVAL_PROGRAM, evaluator);
63 8722 start_prg = lbm_cons(evaluator, ENC_SYM_NIL);
64 } else { // ENC_SYM_READ_AND_EVAL_PROGRAM
65 8722 evaluator = launcher; // dummy so check below passes
66 8722 start_prg = lbm_cons(launcher, ENC_SYM_NIL);
67 }
68
69 /* LISP ZONE ENDS */
70
71
2/4
✓ Branch 1 taken 17444 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
34888 if (lbm_type_of(launcher) != LBM_TYPE_CONS ||
72
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17444 times.
34888 lbm_type_of(evaluator) != LBM_TYPE_CONS ||
73 17444 lbm_type_of(start_prg) != LBM_TYPE_CONS ) {
74 //lbm_explicit_free_token_stream(stream);
75 return 0;
76 }
77 17444 return lbm_create_ctx(start_prg, ENC_SYM_NIL, 256, name);
78 }
79
80 lbm_cid eval_cps_load_and_define(lbm_char_channel_t *tokenizer, char *symbol, bool program) {
81
82 lbm_value stream;
83
84 if (!lift_char_channel(tokenizer, &stream)) {
85 return 0;
86 }
87
88 if (lbm_type_of(stream) == LBM_TYPE_SYMBOL) {
89 return 0;
90 }
91
92 lbm_uint sym_id;
93
94 if (!lbm_get_symbol_by_name(symbol, &sym_id)) {
95 if (!lbm_add_symbol_base(symbol, &sym_id,false)) { //ram
96 //lbm_explicit_free_token_stream(stream);
97 return 0;
98 }
99 }
100
101 /* LISP ZONE */
102
103 lbm_value launcher = lbm_cons(stream, lbm_enc_sym(SYM_NIL));
104 launcher = lbm_cons(lbm_enc_sym(program ? SYM_READ_PROGRAM : SYM_READ), launcher);
105 lbm_value binding = lbm_cons(launcher, lbm_enc_sym(SYM_NIL));
106 binding = lbm_cons(lbm_enc_sym(sym_id), binding);
107 lbm_value definer = lbm_cons(lbm_enc_sym(SYM_DEFINE), binding);
108 definer = lbm_cons(definer, lbm_enc_sym(SYM_NIL));
109 /* LISP ZONE ENDS */
110
111 if (lbm_type_of(launcher) != LBM_TYPE_CONS ||
112 lbm_type_of(binding) != LBM_TYPE_CONS ||
113 lbm_type_of(definer) != LBM_TYPE_CONS ) {
114 //lbm_explicit_free_token_stream(stream);
115 return 0;
116 }
117 return lbm_create_ctx(definer, lbm_enc_sym(SYM_NIL), 256, NULL);
118 }
119
120 lbm_cid lbm_eval_defined(char *symbol, bool program) {
121
122 lbm_uint sym_id;
123
124 if(!lbm_get_symbol_by_name(symbol, &sym_id)) {
125 // The symbol does not exist, so it cannot be defined
126 return 0;
127 }
128
129 lbm_value binding;
130
131 if (!lbm_global_env_lookup(&binding, lbm_enc_sym(sym_id))) {
132 return 0;
133 }
134
135 /* LISP ZONE */
136
137 lbm_value launcher = lbm_cons(lbm_enc_sym(sym_id), lbm_enc_sym(SYM_NIL));
138 lbm_value evaluator = launcher;
139 evaluator = lbm_cons(lbm_enc_sym(program ? SYM_EVAL_PROGRAM : SYM_EVAL), evaluator);
140 lbm_value start_prg = lbm_cons(evaluator, lbm_enc_sym(SYM_NIL));
141
142 /* LISP ZONE ENDS */
143
144 if (lbm_type_of(launcher) != LBM_TYPE_CONS ||
145 lbm_type_of(evaluator) != LBM_TYPE_CONS ||
146 lbm_type_of(start_prg) != LBM_TYPE_CONS ) {
147 return 0;
148 }
149 return lbm_create_ctx(start_prg, lbm_enc_sym(SYM_NIL), 256, NULL);
150 }
151
152
153
154 lbm_cid lbm_load_and_eval_expression(lbm_char_channel_t *tokenizer) {
155 return eval_cps_load_and_eval(tokenizer, false,false, NULL);
156 }
157
158 lbm_cid lbm_load_and_define_expression(lbm_char_channel_t *tokenizer, char *symbol) {
159 return eval_cps_load_and_define(tokenizer, symbol, false);
160 }
161
162 8722 lbm_cid lbm_load_and_eval_program(lbm_char_channel_t *tokenizer, char *name) {
163 8722 return eval_cps_load_and_eval(tokenizer, true, false, name);
164 }
165
166 8722 lbm_cid lbm_load_and_eval_program_incremental(lbm_char_channel_t *tokenizer, char *name) {
167 8722 return eval_cps_load_and_eval(tokenizer, true, true, name);
168 }
169
170 lbm_cid lbm_load_and_define_program(lbm_char_channel_t *tokenizer, char *symbol) {
171 return eval_cps_load_and_define(tokenizer, symbol, true);
172 }
173
174 lbm_cid lbm_eval_defined_expression(char *symbol) {
175 return lbm_eval_defined(symbol, false);
176 }
177
178 lbm_cid lbm_eval_defined_program(char *symbol) {
179 return lbm_eval_defined(symbol, true);
180 }
181
182 int lbm_send_message(lbm_cid cid, lbm_value msg) {
183 int res = 0;
184
185 if (lbm_get_eval_state() == EVAL_CPS_STATE_PAUSED) {
186
187 lbm_value v = lbm_find_receiver_and_send(cid, msg);
188
189 if (lbm_type_of(v) == LBM_TYPE_SYMBOL &&
190 lbm_dec_sym(v) == SYM_TRUE) {
191 res = 1;
192 }
193 }
194 return res;
195 }
196
197 int lbm_define(char *symbol, lbm_value value) {
198 int res = 0;
199
200 lbm_uint sym_id;
201 if (lbm_get_eval_state() == EVAL_CPS_STATE_PAUSED) {
202 if (!lbm_get_symbol_by_name(symbol, &sym_id)) {
203 if (!lbm_add_symbol_const_base(symbol, &sym_id)) {
204 return 0;
205 }
206 }
207 lbm_uint ix_key = sym_id & GLOBAL_ENV_MASK;
208 lbm_value *glob_env = lbm_get_global_env();
209 glob_env[ix_key] = lbm_env_set(glob_env[ix_key], lbm_enc_sym(sym_id), value);
210 }
211 return res;
212 }
213
214 int lbm_undefine(char *symbol) {
215 lbm_uint sym_id;
216 if (!lbm_get_symbol_by_name(symbol, &sym_id))
217 return 0;
218
219 lbm_value *glob_env = lbm_get_global_env();
220 lbm_uint ix_key = sym_id & GLOBAL_ENV_MASK;
221 lbm_value new_env = lbm_env_drop_binding(glob_env[ix_key], lbm_enc_sym(sym_id));
222
223 if (new_env == ENC_SYM_NOT_FOUND) return 0;
224 glob_env[ix_key] = new_env;
225 return 1;
226 }
227
228 int lbm_share_array(lbm_value *value, char *data, lbm_uint num_elt) {
229 return lbm_lift_array(value, data, num_elt);
230 }
231
232 112 static bool share_const_array(lbm_value flash_cell, char *data, lbm_uint num_elt) {
233 lbm_array_header_t flash_array_header;
234 112 flash_array_header.size = num_elt;
235 112 flash_array_header.data = (lbm_uint*)data;
236 lbm_uint flash_array_header_ptr;
237 112 lbm_flash_status s = lbm_write_const_raw((lbm_uint*)&flash_array_header,
238 sizeof(lbm_array_header_t) / sizeof(lbm_uint),
239 &flash_array_header_ptr);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (s != LBM_FLASH_WRITE_OK) return false;
241 112 s = write_const_car(flash_cell, flash_array_header_ptr);
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (s != LBM_FLASH_WRITE_OK) return false;
243 112 s = write_const_cdr(flash_cell, ENC_SYM_ARRAY_TYPE);
244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (s != LBM_FLASH_WRITE_OK) return false;
245 112 return true;
246 }
247
248 112 int lbm_share_const_array(lbm_value *res, char *flash_ptr, lbm_uint num_elt) {
249 112 lbm_value arr = 0;
250 112 arr = LBM_PTR_BIT | LBM_TYPE_ARRAY;
251
252 112 lbm_value flash_arr = 0;
253 112 lbm_flash_status r = request_flash_storage_cell(arr, &flash_arr);
254
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 if (r == LBM_FLASH_WRITE_OK) {
255
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
112 if (!share_const_array(flash_arr, flash_ptr, num_elt)) {
256 return 0;
257 }
258 }
259
260
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 if (r == LBM_FLASH_WRITE_OK) {
261 112 *res = flash_arr;
262 112 return 1;
263 }
264 return 0;
265 }
266
267 136420 int lbm_create_array(lbm_value *value, lbm_uint num_elt) {
268 136420 return lbm_heap_allocate_array(value, num_elt);
269 }
270
271
272 void lbm_clear_env(void) {
273
274 lbm_value *env = lbm_get_global_env();
275 for (int i = 0; i < GLOBAL_ENV_ROOTS; i ++) {
276 env[i] = ENC_SYM_NIL;
277 }
278 lbm_perform_gc();
279 }
280
281 // Evaluator should be paused when running this.
282 // Running gc will reclaim the fv storage.
283 bool lbm_flatten_env(int index, lbm_uint** data, lbm_uint *size) {
284 if (index < 0 || index >= GLOBAL_ENV_ROOTS) return false;
285 lbm_value *env = lbm_get_global_env();
286
287 lbm_value fv = flatten_value(env[index]);
288
289 if (lbm_is_symbol(fv)) return false;
290
291 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(fv);
292 *size = array->size;
293 *data = array->data;
294 return true;
295 }
296