GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/lbm_c_interop.c
Date: 2024-11-05 17:11:09
Exec Total Coverage
Lines: 47 141 33.3%
Functions: 6 19 31.6%
Branches: 17 80 21.2%

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