GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/fundamental.c Lines: 806 855 94.3 %
Date: 2025-04-14 11:29:35 Branches: 568 651 87.3 %

Line Branch Exec Source
1
/*
2
    Copyright 2019, 2021 - 2025      Joel Svensson   svenssonjoel@yahoo.se
3
                           2022      Benjamin Vedder
4
5
    This program is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 3 of the License, or
8
    (at your option) any later version.
9
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
#include <lbm_types.h>
19
#include "symrepr.h"
20
#include "stack.h"
21
#include "heap.h"
22
#include "eval_cps.h"
23
#include "env.h"
24
#include "lbm_utils.h"
25
#include "lbm_custom_type.h"
26
#include "lbm_constants.h"
27
#include "fundamental.h"
28
#include "lbm_defrag_mem.h"
29
#include "print.h" // printable string?
30
31
#include <stdio.h>
32
#include <math.h>
33
34
/* Type promotion ranks
35
36
   32bit LBM:
37
   byte < i < u < i32 < u32 < i64 < u64 < float < double
38
39
   64bit LBM:
40
   byte < i32 < u32 < i < u < i64 < u64 < float < double
41
 */
42
43
// PROMOTE_SWAP is for commutative operations
44
// PROMOTE is for non-commutative operations
45
46
#ifndef LBM64
47
#define PROMOTE_SWAP(t, a, b)                                  \
48
  if (lbm_type_of_functional(a) < lbm_type_of_functional(b)) { \
49
    lbm_value tmp = a;                                         \
50
    a = b;                                                     \
51
    b = tmp;                                                   \
52
  }                                                            \
53
  t = lbm_type_of_functional(a);
54
#else
55
#define PROMOTE_SWAP(t, a, b)                                           \
56
  if (lbm_type_of_functional(b) == LBM_TYPE_FLOAT && (lbm_type_of_functional(a) < LBM_TYPE_DOUBLE)) { \
57
      lbm_value tmp = a;                                                \
58
      a = b;                                                            \
59
      b = tmp;                                                          \
60
  } if (lbm_type_of_functional(a) == LBM_TYPE_FLOAT && (lbm_type_of_functional(b) < LBM_TYPE_DOUBLE)) { \
61
    /* DO NOTHING */                                                    \
62
  } else if (lbm_type_of_functional(a) < lbm_type_of_functional(b)) {   \
63
    lbm_value tmp = a;                                                  \
64
    a = b;                                                              \
65
    b = tmp;                                                            \
66
  }                                                                     \
67
  t = lbm_type_of_functional(a);
68
#endif
69
70
#ifndef LBM64
71
#define PROMOTE(t, a, b)                                                \
72
  t = lbm_type_of_functional(a);                                        \
73
  lbm_uint t_b = lbm_type_of_functional(b);                             \
74
  if (t < t_b) {                                                        \
75
    t  = t_b;                                                           \
76
  }
77
78
#else
79
#define PROMOTE(t, a, b)                                                \
80
  if (lbm_type_of_functional(b) == LBM_TYPE_FLOAT) {                    \
81
    if (lbm_type_of_functional(a) < LBM_TYPE_DOUBLE) {                  \
82
      t = LBM_TYPE_FLOAT;                                               \
83
    } else {                                                            \
84
      t = lbm_type_of_functional(a);                                    \
85
    }                                                                   \
86
  }  else if (lbm_type_of_functional(a) < lbm_type_of_functional(b)) {  \
87
    t = lbm_type_of_functional(b);                                      \
88
  } else {                                                              \
89
    t = lbm_type_of_functional(a);                                      \
90
  }
91
#endif
92
93
94
#define IS_NUMBER lbm_is_number
95
96
// Todo: It may be possible perform some of these operations
97
//       on encoded values followed by a "correction" of the result values
98
//       type bits.
99
//       But the checks required to figure out if it is possible to apply the
100
//       operation in this way has a cost too...
101
102
70076634
static lbm_uint mul2(lbm_uint a, lbm_uint b) {
103
70076634
  lbm_uint retval = ENC_SYM_TERROR;
104

70076634
  if (IS_NUMBER(a) && IS_NUMBER(b)) {
105
    lbm_type t;
106
70076466
    PROMOTE_SWAP(t, a, b);
107


70076466
    switch (t) {
108
280
    case LBM_TYPE_CHAR: retval = lbm_enc_char((uint8_t)(lbm_dec_char(a) * lbm_dec_char(b))); break;
109
#ifdef LBM64
110
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(a) * lbm_dec_as_i64(b)); break;
111
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(a) * lbm_dec_as_u64(b)); break;
112
#else
113
2800812
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(a) * lbm_dec_as_i32(b)); break;
114
392
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(a) * lbm_dec_as_u32(b)); break;
115
#endif
116
504
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(a) * lbm_dec_as_u32(b)); break;
117
448
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(a) * lbm_dec_as_i32(b)); break;
118
67272126
    case LBM_TYPE_FLOAT: retval = lbm_enc_float(lbm_dec_float(a) * lbm_dec_as_float(b)); break;
119
616
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(a) * lbm_dec_as_u64(b)); break;
120
560
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(a) * lbm_dec_as_i64(b)); break;
121
728
    case LBM_TYPE_DOUBLE: retval = lbm_enc_double(lbm_dec_double(a) * lbm_dec_as_double(b)); break;
122
    }
123
70076466
  } else {
124
168
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
125
  }
126
70076634
  return retval;
127
}
128
129
1176
static lbm_uint div2(lbm_uint a, lbm_uint b) {
130
1176
  lbm_uint retval = ENC_SYM_TERROR;
131

1176
  if (IS_NUMBER(a) && IS_NUMBER(b)) {
132
    lbm_type t;
133
1064
    PROMOTE(t, a, b);
134


1064
    switch (t) {
135
56
    case LBM_TYPE_CHAR: if (lbm_dec_char(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_char((uint8_t)(lbm_dec_char(a) / lbm_dec_char(b))); break;
136
#ifdef LBM64
137
    case LBM_TYPE_I: if (lbm_dec_i(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i(lbm_dec_as_i64(a) / lbm_dec_as_i64(b)); break;
138
    case LBM_TYPE_U: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u(lbm_dec_as_u64(a) / lbm_dec_as_u64(b)); break;
139
#else
140
532
    case LBM_TYPE_I: if (lbm_dec_i(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i(lbm_dec_as_i32(a) / lbm_dec_as_i32(b)); break;
141
56
    case LBM_TYPE_U: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u(lbm_dec_as_u32(a) / lbm_dec_as_u32(b)); break;
142
#endif
143
56
    case LBM_TYPE_U32: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u32(lbm_dec_as_u32(a) / lbm_dec_as_u32(b)); break;
144
56
    case LBM_TYPE_I32: if (lbm_dec_as_i32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i32(lbm_dec_as_i32(a) / lbm_dec_as_i32(b)); break;
145

112
    case LBM_TYPE_FLOAT: if (lbm_dec_as_float(b) == 0.0f || lbm_dec_as_float(b) == -0.0f) {return ENC_SYM_DIVZERO;} retval = lbm_enc_float(lbm_dec_as_float(a) / lbm_dec_as_float(b)); break;
146
56
    case LBM_TYPE_U64: if (lbm_dec_as_u64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u64(lbm_dec_as_u32(a) / lbm_dec_as_u64(b)); break;
147
56
    case LBM_TYPE_I64: if (lbm_dec_as_i64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i64(lbm_dec_as_i32(a) / lbm_dec_as_i64(b)); break;
148

84
    case LBM_TYPE_DOUBLE: if (lbm_dec_as_double(b) == (double)0.0 || lbm_dec_as_double(b) == (double)-0.0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_double(lbm_dec_as_double(a) / lbm_dec_as_double(b)); break;
149
    }
150
616
  } else {
151
112
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
152
  }
153
728
  return retval;
154
}
155
156
8784
static lbm_uint mod2(lbm_uint a, lbm_uint b) {
157
8784
  lbm_uint retval = ENC_SYM_TERROR;
158

8784
  if (IS_NUMBER(a) && IS_NUMBER(b)) {
159
    lbm_type t;
160
8672
    PROMOTE(t, a, b);
161


8672
    switch (t) {
162
56
    case LBM_TYPE_CHAR: if (lbm_dec_char(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_char((uint8_t)(lbm_dec_char(a) % lbm_dec_as_i32(b))); break;
163
#ifdef LBM64
164
    case LBM_TYPE_I: if (lbm_dec_i(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i(lbm_dec_as_i64(a) % lbm_dec_as_i64(b)); break;
165
    case LBM_TYPE_U: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u(lbm_dec_as_u64(a) % lbm_dec_as_u64(b)); break;
166
#else
167
224
    case LBM_TYPE_I: if (lbm_dec_i(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i(lbm_dec_as_i32(a) % lbm_dec_as_i32(b)); break;
168
8056
    case LBM_TYPE_U: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u(lbm_dec_as_u32(a) % lbm_dec_as_u32(b)); break;
169
#endif
170
56
    case LBM_TYPE_U32: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u32(lbm_dec_as_u32(a) % lbm_dec_as_u32(b)); break;
171
56
    case LBM_TYPE_I32: if (lbm_dec_as_i32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i32(lbm_dec_as_i32(a) % lbm_dec_as_i32(b)); break;
172

56
    case LBM_TYPE_FLOAT: if (lbm_dec_as_float(b) == 0.0f || lbm_dec_as_float(b) == -0.0f) {return ENC_SYM_DIVZERO;} retval = lbm_enc_float(fmodf(lbm_dec_as_float(a), lbm_dec_as_float(b))); break;
173
56
    case LBM_TYPE_U64: if (lbm_dec_as_u64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u64(lbm_dec_as_u64(a) % lbm_dec_as_u64(b)); break;
174
56
    case LBM_TYPE_I64: if (lbm_dec_as_i64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i64(lbm_dec_as_i64(a) % lbm_dec_as_i64(b)); break;
175

56
    case LBM_TYPE_DOUBLE: if (lbm_dec_as_double(b) == (double)0.0 || lbm_dec_as_double(b) == (double)-0.0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_double(fmod(lbm_dec_as_double(a), lbm_dec_as_double(b))); break;
176
    }
177
8392
  } else {
178
112
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
179
  }
180
8504
  return retval;
181
}
182
183
26803858
static lbm_uint sub2(lbm_uint a, lbm_uint b) {
184
26803858
  lbm_uint retval = ENC_SYM_TERROR;
185

26803858
  if (IS_NUMBER(a) && IS_NUMBER(b)) {
186
    lbm_uint t;
187
26803662
    PROMOTE(t, a, b);
188


26803662
    switch (t) {
189
56
    case LBM_TYPE_BYTE: retval = lbm_enc_char((uint8_t)(lbm_dec_char(a) - lbm_dec_char(b))); break;
190
#ifdef LBM64
191
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_as_i64(a) - lbm_dec_as_i64(b)); break;
192
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_as_u64(a) - lbm_dec_as_u64(b)); break;
193
#else
194
26522536
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_as_i32(a) - lbm_dec_as_i32(b)); break;
195
56
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_as_u32(a) - lbm_dec_as_u32(b)); break;
196
#endif
197
280566
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_as_u32(a) - lbm_dec_as_u32(b)); break;
198
84
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_as_i32(a) - lbm_dec_as_i32(b)); break;
199
168
    case LBM_TYPE_FLOAT: retval = lbm_enc_float(lbm_dec_as_float(a) - lbm_dec_as_float(b)); break;
200
56
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_as_u64(a) - lbm_dec_as_u64(b)); break;
201
84
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_as_i64(a) - lbm_dec_as_i64(b)); break;
202
56
    case LBM_TYPE_DOUBLE: retval = lbm_enc_double(lbm_dec_as_double(a) - lbm_dec_as_double(b)); break;
203
    }
204
26803662
  } else {
205
196
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
206
  }
207
26803858
  return retval;
208
}
209
210
// a and b must be bytearrays!
211
10136
static bool bytearray_equality(lbm_value a, lbm_value b) {
212
10136
  lbm_array_header_t *a_ = (lbm_array_header_t*)lbm_car(a);
213
10136
  lbm_array_header_t *b_ = (lbm_array_header_t*)lbm_car(b);
214
10136
  bool res = false;
215
  // A NULL array arriving here should be impossible.
216
  // if the a and b are not valid arrays at this point, the data
217
  // is most likely nonsense - corrupted by cosmic radiation.
218

10136
  if ((a_ && b_) && a_->size == b_->size) {
219
9968
    res = (memcmp((char*)a_->data, (char*)b_->data, a_->size) == 0);
220
  }
221
10136
  return res;
222
}
223
224
// a and b must be arrays!
225
336
static bool array_struct_equality(lbm_value a, lbm_value b) {
226
336
  lbm_array_header_t *a_ = (lbm_array_header_t*)lbm_car(a);
227
336
  lbm_array_header_t *b_ = (lbm_array_header_t*)lbm_car(b);
228
336
  bool res = false;
229

336
  if ((a_ && b_) &&  a_->size == b_->size) {
230
308
    res = true;
231
308
    lbm_value *adata = (lbm_value*)a_->data;
232
308
    lbm_value *bdata = (lbm_value*)b_->data;
233
308
    lbm_uint size = (lbm_uint)a_->size / (lbm_uint)sizeof(lbm_value);
234
1036
    for (lbm_uint i = 0; i < size; i ++ ) {
235
756
      res = struct_eq(adata[i], bdata[i]);
236
756
      if (!res) break;
237
    }
238
  }
239
336
  return res;
240
}
241
242
235964
bool struct_eq(lbm_value a, lbm_value b) {
243
244
235964
  bool res = false;
245
235964
  lbm_type ta = lbm_type_of_functional(a);
246
235964
  lbm_type tb = lbm_type_of_functional(b);
247
248
235964
  if (ta == tb) {
249



218436
    switch(ta){
250
62564
    case LBM_TYPE_SYMBOL:
251
62564
      res = (lbm_dec_sym(a) == lbm_dec_sym(b)); break;
252
52820
    case LBM_TYPE_I:
253
52820
      res =  (lbm_dec_i(a) == lbm_dec_i(b)); break;
254
588
    case LBM_TYPE_U:
255
588
      res = (lbm_dec_u(a) == lbm_dec_u(b)); break;
256
4620
    case LBM_TYPE_CHAR:
257
4620
      res = (lbm_dec_char(a) == lbm_dec_char(b)); break;
258
73736
    case LBM_TYPE_CONS:
259

147416
      res = ( struct_eq(lbm_car(a),lbm_car(b)) &&
260
147416
              struct_eq(lbm_cdr(a),lbm_cdr(b)) ); break;
261
1820
    case LBM_TYPE_I32:
262
1820
      res = (lbm_dec_i32(a) == lbm_dec_i32(b)); break;
263
3584
    case LBM_TYPE_U32:
264
3584
      res = (lbm_dec_u32(a) == lbm_dec_u32(b)); break;
265
6720
    case LBM_TYPE_FLOAT:
266
6720
      res = (lbm_dec_float(a) == lbm_dec_float(b)); break;
267
560
    case LBM_TYPE_I64:
268
560
      res =  (lbm_dec_i64(a) == lbm_dec_i64(b)); break;
269
560
    case LBM_TYPE_U64:
270
560
      res = (lbm_dec_u64(a) == lbm_dec_u64(b)); break;
271
392
    case LBM_TYPE_DOUBLE:
272
392
      res = (lbm_dec_double(a) == lbm_dec_double(b)); break;
273
10136
    case LBM_TYPE_ARRAY:
274
10136
      res =  bytearray_equality(a, b); break;
275
336
    case LBM_TYPE_LISPARRAY:
276
336
      res =  array_struct_equality(a, b); break;
277
    }
278
17528
  }
279
235964
  return res;
280
}
281
282
283
/* returns -1 if a < b; 0 if a = b; 1 if a > b
284
   args must be numbers
285
*/
286
75759531
static int compare_num(lbm_uint a, lbm_uint b) {
287
288
75759531
  int retval = 0;
289
290
  lbm_uint t;
291
75759531
  PROMOTE(t, a, b);
292


75759531
  switch (t) {
293
28
  case LBM_TYPE_CHAR: retval = CMP(lbm_dec_char(a), lbm_dec_char(b)); break;
294
#ifdef LBM64
295
  case LBM_TYPE_I: retval = CMP(lbm_dec_as_i64(a), lbm_dec_as_i64(b)); break;
296
  case LBM_TYPE_U: retval = CMP(lbm_dec_as_u64(a), lbm_dec_as_u64(b)); break;
297
#else
298
37672427
  case LBM_TYPE_I: retval = CMP(lbm_dec_as_i32(a), lbm_dec_as_i32(b)); break;
299
5284
  case LBM_TYPE_U: retval = CMP(lbm_dec_as_u32(a), lbm_dec_as_u32(b)); break;
300
#endif
301
560728
  case LBM_TYPE_U32: retval = CMP(lbm_dec_as_u32(a), lbm_dec_as_u32(b)); break;
302
280056
  case LBM_TYPE_I32: retval = CMP(lbm_dec_as_i32(a), lbm_dec_as_i32(b)); break;
303
36400672
  case LBM_TYPE_FLOAT: retval = CMP(lbm_dec_as_float(a), lbm_dec_as_float(b)); break;
304
280084
  case LBM_TYPE_U64: retval = CMP(lbm_dec_as_u64(a), lbm_dec_as_u64(b)); break;
305
560084
  case LBM_TYPE_I64: retval = CMP(lbm_dec_as_i64(a), lbm_dec_as_i64(b)); break;
306
168
  case LBM_TYPE_DOUBLE: retval = CMP(lbm_dec_as_double(a), lbm_dec_as_double(b)); break;
307
  }
308
75759531
  return retval;
309
}
310
311
336
static lbm_value assoc_lookup(lbm_value key, lbm_value assoc) {
312
336
  lbm_value curr = assoc;
313
336
  lbm_value res = ENC_SYM_NO_MATCH;
314
812
  while (lbm_is_cons(curr)) {
315
784
    lbm_value c = lbm_ref_cell(curr)->car;
316
784
    if (lbm_is_cons(c)) {
317
756
      if (struct_eq(lbm_ref_cell(c)->car, key)) {
318
280
        res = lbm_ref_cell(c)->cdr;
319
280
        break;
320
      }
321
    } else {
322
28
      res = ENC_SYM_EERROR;
323
28
      break;
324
    }
325
476
    curr = lbm_ref_cell(curr)->cdr;
326
  }
327
336
  return res;
328
}
329
330
336
static lbm_value cossa_lookup(lbm_value key, lbm_value assoc) {
331
336
  lbm_value curr = assoc;
332
840
  while (lbm_is_cons(curr)) {
333
812
    lbm_value c = lbm_ref_cell(curr)->car;
334
812
    if (lbm_is_cons(c)) {
335
784
      if (struct_eq(lbm_ref_cell(c)->cdr, key)) {
336
280
        return lbm_ref_cell(c)->car;
337
      }
338
    } else {
339
28
      return ENC_SYM_EERROR;
340
    }
341
504
    curr = lbm_ref_cell(curr)->cdr;
342
  }
343
28
  return ENC_SYM_NO_MATCH;
344
}
345
346
347
348
/***************************************************/
349
/* Fundamental operations                          */
350
351
77910472
static lbm_value fundamental_add(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
352
  (void) ctx;
353
77910472
  lbm_uint sum = lbm_enc_char(0);
354
279664878
  for (lbm_uint i = 0; i < nargs; i ++) {
355
201856582
    lbm_value v = args[i];
356
201856582
    if (IS_NUMBER(v)) { // inlining add2 explicitly removes one condition.
357
        lbm_type t;
358
201856386
        PROMOTE_SWAP(t, sum, v);
359


201856386
        switch (t) {
360
280
        case LBM_TYPE_BYTE: sum = lbm_enc_char((uint8_t)(lbm_dec_char(sum) + lbm_dec_char(v))); break;
361
#ifdef LBM64
362
        case LBM_TYPE_I: sum = lbm_enc_i(lbm_dec_i(sum) + lbm_dec_as_i64(v)); break;
363
        case LBM_TYPE_U: sum = lbm_enc_u(lbm_dec_u(sum) + lbm_dec_as_u64(v)); break;
364
        case LBM_TYPE_U32: sum = lbm_enc_u32(lbm_dec_u32(sum) + lbm_dec_as_u32(v)); break;
365
        case LBM_TYPE_I32: sum = lbm_enc_i32(lbm_dec_i32(sum) + lbm_dec_as_i32(v)); break;
366
        case LBM_TYPE_FLOAT: sum = lbm_enc_float(lbm_dec_float(sum) + lbm_dec_as_float(v)); break;
367
#else
368
24695192
        case LBM_TYPE_I: sum = lbm_enc_i(lbm_dec_i(sum) + lbm_dec_as_i32(v)); break;
369
616
        case LBM_TYPE_U: sum = lbm_enc_u(lbm_dec_u(sum) + lbm_dec_as_u32(v)); break;
370
3362190
        case LBM_TYPE_U32:
371
3362190
          sum = lbm_enc_u32(lbm_dec_u32(sum) + lbm_dec_as_u32(v));
372
3362190
          if (lbm_is_symbol(sum)) goto add_end;
373
3361820
          break;
374
2806280
        case LBM_TYPE_I32:
375
2806280
          sum = lbm_enc_i32(lbm_dec_i32(sum) + lbm_dec_as_i32(v));
376
2806280
          if (lbm_is_symbol(sum)) goto add_end;
377
2804894
          break;
378
162579186
        case LBM_TYPE_FLOAT:
379
162579186
          sum = lbm_enc_float(lbm_dec_float(sum) + lbm_dec_as_float(v));
380
162579186
          if (lbm_is_symbol(sum)) goto add_end;
381
162483912
          break;
382
#endif
383
3364626
        case LBM_TYPE_U64:
384
3364626
          sum = lbm_enc_u64(lbm_dec_u64(sum) + lbm_dec_as_u64(v));
385
3364626
          if (lbm_is_symbol(sum)) goto add_end;
386
3363096
          break;
387
4486452
        case LBM_TYPE_I64:
388
4486452
          sum = lbm_enc_i64(lbm_dec_i64(sum) + lbm_dec_as_i64(v));
389
4486452
          if (lbm_is_symbol(sum)) goto add_end;
390
4483556
          break;
391
561564
        case LBM_TYPE_DOUBLE:
392
561564
          sum = lbm_enc_double(lbm_dec_double(sum) + lbm_dec_as_double(v));
393
561564
          if (lbm_is_symbol(sum)) goto add_end;
394
561040
          break;
395
        }
396
201754406
    } else {
397
196
      lbm_set_error_suspect(v);
398
196
      sum = ENC_SYM_TERROR;
399
196
      break; // out of loop
400
    }
401
    }
402
77808296
 add_end:
403
77910472
  return sum;
404
}
405
406
26803774
static lbm_value fundamental_sub(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
407
  (void) ctx;
408
409
  lbm_uint res;
410
411

26803774
  switch (nargs) {
412
28
  case 0:
413
28
    res = lbm_enc_char(0);
414
28
    break;
415
416
476
  case 1:
417
476
    res = sub2(lbm_enc_char(0),args[0]);
418
476
    break;
419
420
26803214
  case 2:
421
26803214
    res = sub2(args[0], args[1]);
422
26803214
    break;
423
424
56
  default:
425
56
    res = args[0];
426
196
    for (lbm_uint i = 1; i < nargs; i ++) {
427
168
      res = sub2(res, args[i]);
428
168
      if (lbm_type_of(res) == LBM_TYPE_SYMBOL)
429
28
        break;
430
    }
431
56
    break;
432
  }
433
26803774
  return res;
434
}
435
436
33931022
static lbm_value fundamental_mul(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
437
  (void) ctx;
438
439
33931022
  lbm_uint prod = lbm_enc_char(1);
440
103959126
  for (lbm_uint i = 0; i < nargs; i ++) {
441
70076634
    prod = mul2(prod, args[i]);
442
70076634
    if (lbm_type_of(prod) == LBM_TYPE_SYMBOL) {
443
48530
      break;
444
    }
445
  }
446
33931022
  return prod;
447
}
448
449
1176
static lbm_value fundamental_div(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
450
  (void) ctx;
451
452
1176
  lbm_uint res = args[0];
453
454
1176
  if (nargs >= 2) {
455
1736
    for (lbm_uint i = 1; i < nargs; i ++) {
456
1176
      res = div2(res, args[i]);
457
1176
      if (lbm_type_of(res) == LBM_TYPE_SYMBOL) {
458
560
        break;
459
      }
460
    }
461
  } else {
462
56
    res = ENC_SYM_EERROR;
463
  }
464
1176
  return res;
465
}
466
467
8840
static lbm_value fundamental_mod(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
468
  (void) ctx;
469
8840
  if (nargs == 2) {
470
8784
    return mod2(args[0], args[1]);
471
  }
472
56
  lbm_set_error_reason((char*)lbm_error_str_num_args);
473
56
  return  ENC_SYM_EERROR;
474
}
475
476
80400
static lbm_value fundamental_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
477
  (void) ctx;
478
80400
  lbm_uint a = args[0];
479
136944
  for (lbm_uint i = 1; i < nargs; i ++) {
480
80568
    lbm_uint b = args[i];
481
80568
    if (!struct_eq(a, b)) return ENC_SYM_NIL;
482
  }
483
56376
  return ENC_SYM_TRUE;
484
}
485
486
280
static lbm_value fundamental_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
487
280
  lbm_value r = fundamental_eq(args, nargs, ctx);
488
280
  return r ? ENC_SYM_NIL : ENC_SYM_TRUE; // Works because ENC_SYM_NIL == 0 and ENC_SYM_TRUE is != 0
489
}
490
491
492
32097779
static lbm_value fundamental_numeq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
493
  (void) ctx;
494
495
32097779
  lbm_uint a = args[0];
496
32097779
  lbm_value res = ENC_SYM_TERROR;
497
498
32097779
  if (IS_NUMBER(a)) {
499
32097723
    res = ENC_SYM_TRUE;
500
37157634
    for (lbm_uint i = 1; i < nargs; i ++) {
501
32098311
      lbm_uint b = args[i];
502
32098311
      if (!IS_NUMBER(b)) {
503
56
        res = ENC_SYM_TERROR;
504
56
        break;
505
      }
506
32098255
      if (!compare_num(a, b) == 0) {
507
27038344
        res = ENC_SYM_NIL;
508
27038344
        break;
509
      }
510
    }
511
  }
512
32097779
  return res;
513
}
514
515
560336
static lbm_value fundamental_num_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
516
560336
  lbm_value r = fundamental_numeq(args, nargs, ctx);
517
  // Needs the more expensive check as r can be ENC_SYM_TERROR.
518
560336
  if (r == ENC_SYM_NIL) {
519
140
    r = ENC_SYM_TRUE;
520
560196
  } else if (r == ENC_SYM_TRUE) {
521
560140
    r = ENC_SYM_NIL;
522
  }
523
560336
  return r;
524
}
525
526
42389556
static lbm_value fundamental_leq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
527
  (void) ctx;
528
529
42389556
  lbm_uint a = args[0];
530
42389556
  bool r = true;
531
532
42389556
  if (IS_NUMBER(a)) {
533
84778944
    for (lbm_uint i = 1; i < nargs; i ++) {
534
42389500
      lbm_uint b = args[i];
535
42389500
      if (IS_NUMBER(b)) {
536

42389444
	r = r && (compare_num(a, b) <= 0);
537
      } else {
538
56
	lbm_set_error_suspect(b);
539
56
	goto leq_type_error;
540
      }
541
    }
542
  } else {
543
56
    lbm_set_error_suspect(a);
544
56
    goto leq_type_error;
545
  }
546
42389444
  if (r) {
547
5099752
    return ENC_SYM_TRUE;
548
  } else {
549
37289692
    return ENC_SYM_NIL;
550
  }
551
112
 leq_type_error:
552
112
  return ENC_SYM_TERROR;
553
}
554
555
1271944
static lbm_value fundamental_geq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
556
  (void) ctx;
557
558
1271944
  lbm_uint a = args[0];
559
1271944
  bool r = true;
560
561
1271944
  if (IS_NUMBER(a)) {
562
2543720
    for (lbm_uint i = 1; i < nargs; i ++) {
563
1271888
      lbm_uint b = args[i];
564
1271888
      if (IS_NUMBER(b)) {
565

1271832
	r = r && (compare_num(a, b) >= 0);
566
      } else {
567
56
	lbm_set_error_suspect(b);
568
56
	goto geq_type_error;
569
      }
570
    }
571
  } else {
572
56
    lbm_set_error_suspect(a);
573
56
    goto geq_type_error;
574
  }
575
1271832
  if (r) {
576
10440
    return ENC_SYM_TRUE;
577
  } else {
578
1261392
    return ENC_SYM_NIL;
579
  }
580
112
 geq_type_error:
581
112
  return ENC_SYM_TERROR;
582
}
583
584
1271496
static lbm_value fundamental_lt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
585
1271496
  lbm_value r = fundamental_geq(args, nargs, ctx);
586
1271496
  if (r == ENC_SYM_NIL) r = ENC_SYM_TRUE;
587
10160
  else if (r == ENC_SYM_TRUE) r = ENC_SYM_NIL;
588
1271496
  return r;
589
}
590
591
42388072
static lbm_value fundamental_gt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
592
42388072
  lbm_value r = fundamental_leq(args, nargs, ctx);
593
42388072
  if (r == ENC_SYM_NIL) r = ENC_SYM_TRUE;
594
5098576
  else if (r == ENC_SYM_TRUE) r = ENC_SYM_NIL;
595
42388072
  return r;
596
}
597
598
1988
static lbm_value fundamental_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
599
  (void) ctx;
600
1988
  if (nargs == 1) {
601
1932
    return args[0] ? ENC_SYM_NIL : ENC_SYM_TRUE;
602
  }
603
56
  return ENC_SYM_EERROR;
604
}
605
606
13244
static lbm_value fundamental_gc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
607
  (void) args;
608
  (void) nargs;
609
  (void) ctx;
610
13244
  lbm_perform_gc();
611
13244
  return ENC_SYM_TRUE;
612
}
613
614
3444
static lbm_value fundamental_self(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
615
  (void) args;
616
  (void) nargs;
617
  (void) ctx;
618
3444
  return lbm_enc_i(ctx->id);
619
}
620
621
224
static lbm_value fundamental_set_mailbox_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
622
224
  lbm_value r = ENC_SYM_EERROR;
623
224
  if (nargs == 1) {
624
168
    if (IS_NUMBER(args[0])) {
625
140
      uint32_t s = lbm_dec_as_u32(args[0]);
626
140
      if (lbm_mailbox_change_size(ctx, s)) {
627
112
        r = ENC_SYM_TRUE;
628
      } else {
629
28
        r = ENC_SYM_NIL;
630
      }
631
    } else {
632
28
      r = ENC_SYM_TERROR;
633
    }
634
  }
635
224
  return r;
636
}
637
638
5601846
static lbm_value fundamental_cons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
639
  (void) ctx;
640
5601846
  lbm_value r = ENC_SYM_EERROR;
641
5601846
  if (nargs == 2) {
642
5601762
    lbm_uint a = args[0];
643
5601762
    lbm_uint b = args[1];
644
5601762
    r = lbm_cons(a,b);
645
  }
646
5601846
  return r;
647
}
648
649
18004
static lbm_value fundamental_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
650
  (void) ctx;
651
18004
  lbm_value r = ENC_SYM_EERROR;
652
18004
  if (nargs == 1) {
653
17948
    if (lbm_is_cons(args[0])) {
654
17416
      lbm_cons_t *cell = lbm_ref_cell(args[0]);
655
17416
      r =  cell->car;
656
532
    } else if (lbm_is_symbol_nil(args[0])) {
657
448
      r = ENC_SYM_NIL;
658
    } else {
659
84
      r = ENC_SYM_TERROR;
660
    }
661
  }
662
18004
  return r;
663
}
664
665
23240
static lbm_value fundamental_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
666
  (void) ctx;
667
23240
  lbm_value r = ENC_SYM_EERROR;
668
23240
  if (nargs == 1) {
669
23184
    if (lbm_is_cons(args[0])) {
670
22652
      lbm_cons_t *cell = lbm_ref_cell(args[0]);
671
22652
      r = cell->cdr;
672
532
    } else if (lbm_is_symbol_nil(args[0])) {
673
448
      r = ENC_SYM_NIL;
674
    } else {
675
84
      r = ENC_SYM_TERROR;
676
    }
677
  }
678
23240
  return r;
679
}
680
681
88480
static lbm_value fundamental_list(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
682
  (void) ctx;
683
88480
  lbm_value result = ENC_SYM_NIL;
684
220972
  for (lbm_uint i = 1; i <= nargs; i ++) {
685
132556
    result = lbm_cons(args[nargs-i], result);
686
    // This check may be a mostly useless optimisation.
687
    // Only triggers in case of running out of heap here.
688
132556
    if (lbm_type_of(result) == LBM_TYPE_SYMBOL)
689
64
      break;
690
  }
691
88480
  return result;
692
}
693
694
48718
static lbm_value fundamental_append(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
695
  (void) ctx;
696
48718
  if (nargs == 0) return ENC_SYM_NIL;
697

48690
  if (nargs == 1 && !lbm_is_list(args[0])) {
698
28
      lbm_set_error_suspect(args[0]);
699
28
    return ENC_SYM_TERROR;
700
  }
701
48662
  lbm_value res = args[nargs-1];
702
110568
  for (int i = (int)nargs -2; i >= 0; i --) {
703
61934
    lbm_value curr = args[i];
704
61934
    if (!lbm_is_list(curr)) {
705
28
      lbm_set_error_suspect(curr);
706
28
      return ENC_SYM_TERROR;
707
    }
708
61906
    int n = 0;
709
136018
    while (lbm_type_of_functional(curr) == LBM_TYPE_CONS) {
710
74112
      n++;
711
74112
      curr = lbm_cdr(curr);
712
    }
713
61906
    curr = args[i];
714
136018
    for (int j = n-1; j >= 0; j --) {
715
74112
      res = lbm_cons(lbm_index_list(curr,j),res);
716
    }
717
  }
718
48634
  return(res);
719
}
720
721
1680224
static lbm_value fundamental_undefine(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
722
  (void) ctx;
723
1680224
  lbm_value *global_env = lbm_get_global_env();
724

1680224
  if (nargs == 1 && lbm_is_symbol(args[0])) {
725
1680168
    lbm_value key = args[0];
726
1680168
    lbm_uint ix_key = lbm_dec_sym(key) & GLOBAL_ENV_MASK;
727
1680168
    lbm_value env = global_env[ix_key];
728
1680168
    lbm_value res = lbm_env_drop_binding(env, key);
729
1680168
    if (res == ENC_SYM_NOT_FOUND) {
730
28
      return ENC_SYM_NIL;
731
    }
732
1680140
    global_env[ix_key] = res;
733
1680140
    return ENC_SYM_TRUE;
734

56
  } else if (nargs == 1 && lbm_is_cons(args[0])) {
735
56
    lbm_value curr = args[0];
736
168
    while (lbm_type_of(curr) == LBM_TYPE_CONS) {
737
112
      lbm_value key = lbm_car(curr);
738
112
      lbm_uint ix_key = lbm_dec_sym(key) & GLOBAL_ENV_MASK;
739
112
      lbm_value env = global_env[ix_key];
740
112
      lbm_value res = lbm_env_drop_binding(env, key);
741
112
      if (res != ENC_SYM_NOT_FOUND) {
742
56
        global_env[ix_key] = res;
743
      }
744
112
      curr = lbm_cdr(curr);
745
    }
746
56
    return ENC_SYM_TRUE;
747
  }
748
  return ENC_SYM_TERROR;
749
}
750
751
80114
static lbm_value fundamental_buf_create(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
752
  (void) ctx;
753
80114
  lbm_value result = ENC_SYM_EERROR;
754

80114
  if (nargs == 1 && IS_NUMBER(args[0])) {
755
24030
    lbm_heap_allocate_array(&result, lbm_dec_as_u32(args[0]));
756

56084
  } else if (nargs == 2 && IS_NUMBER(args[1]) && lbm_type_of(args[0]) == LBM_TYPE_DEFRAG_MEM) {
757
56000
    lbm_uint *dm = (lbm_uint*)lbm_car(args[0]);
758
56000
    return lbm_defrag_mem_alloc(dm, lbm_dec_as_uint(args[1]));
759
  }
760
24114
  return result;
761
}
762
763
112
static lbm_value fundamental_symbol_to_string(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
764
  (void) ctx;
765
112
  lbm_value res = ENC_SYM_EERROR;
766
112
  if (nargs == 1) {
767
84
    if (lbm_type_of_functional(args[0]) == LBM_TYPE_SYMBOL) {
768
56
      lbm_value sym = args[0];
769
56
      const char *sym_str = lbm_get_name_by_symbol(lbm_dec_sym(sym));
770
56
      if (sym_str == NULL) return ENC_SYM_NIL;
771
56
      size_t len = strlen(sym_str);
772
      lbm_value v;
773
56
      if (lbm_heap_allocate_array(&v, len+1)) {
774
56
        lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(v);
775
56
        memset(arr->data,0,len+1);
776
56
        memcpy(arr->data,sym_str,len);
777
56
        res = v;
778
      } else {
779
        res = ENC_SYM_MERROR;
780
      }
781
    } else {
782
28
      res = ENC_SYM_TERROR;
783
    }
784
  }
785
112
  return res;
786
}
787
788
112
static lbm_value fundamental_string_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
789
  (void) ctx;
790
112
  lbm_value result = ENC_SYM_EERROR;
791
112
  if (nargs == 1) {
792
84
    result = ENC_SYM_TERROR;
793
84
    lbm_array_header_t *arr = lbm_dec_array_r(args[0]);
794
84
    if (arr) {
795
      // TODO: String to symbol, string should be in LBM_memory..
796
      // Some better sanity check is possible here.
797
      // Check that array points into lbm_memory.
798
      // Additionally check that it is a zero-terminated string.
799
56
      char *str = (char *)arr->data;
800
56
      lbm_uint sym = ENC_SYM_NIL;
801
56
      lbm_str_to_symbol(str,&sym);
802
56
      result = lbm_enc_sym(sym);
803
    }
804
  }
805
112
  return result;
806
}
807
808
140
static lbm_value fundamental_symbol_to_uint(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
809
  (void) ctx;
810
140
  if (nargs < 1) return ENC_SYM_EERROR;
811
112
  lbm_value s = args[0];
812
112
  if (lbm_is_symbol(s))
813
84
    return lbm_enc_u(lbm_dec_sym(s));
814
815
28
  lbm_set_error_suspect(s);
816
28
  return ENC_SYM_TERROR;
817
}
818
819
112
static lbm_value fundamental_uint_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
820
  (void) ctx;
821
112
  if (nargs < 1) return ENC_SYM_EERROR;
822
84
  lbm_value s = args[0];
823
84
  if (lbm_type_of_functional(s) == LBM_TYPE_U)
824
56
    return lbm_enc_sym(lbm_dec_u(s));
825
826
28
  lbm_set_error_suspect(s);
827
28
  return ENC_SYM_TERROR;
828
}
829
830
112
static lbm_value fundamental_set_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
831
  (void) ctx;
832
112
  lbm_value res = ENC_SYM_EERROR;
833
112
  if (nargs == 2) {
834
112
    res = lbm_set_car(args[0], args[1]) ? ENC_SYM_TRUE : ENC_SYM_NIL;
835
  }
836
112
  return res;
837
}
838
839
112
static lbm_value fundamental_set_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
840
  (void) ctx;
841
112
  lbm_value res = ENC_SYM_EERROR;
842
112
  if (nargs == 2) {
843
112
    res = lbm_set_cdr(args[0],args[1]) ? ENC_SYM_TRUE : ENC_SYM_NIL;
844
  }
845
112
  return res;
846
}
847
848
561736
static lbm_value fundamental_set_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
849
  (void) ctx;
850
561736
  lbm_value result = ENC_SYM_TERROR;
851

561736
  if (nargs == 3 && IS_NUMBER(args[1])) {
852
561736
    if (lbm_is_list_rw(args[0])) {
853
112
      lbm_value curr = args[0];
854
112
      lbm_uint i = 0;
855
112
      lbm_int ix_pre = lbm_dec_as_i32(args[1]);
856
112
      if (ix_pre < 0) {
857
        lbm_int len = (lbm_int)lbm_list_length(args[0]);
858
        ix_pre = len + ix_pre;
859
      }
860
112
      lbm_uint ix = (lbm_uint)ix_pre;
861
448
      while (lbm_is_cons_rw(curr)) { // rw as we are going to modify
862
448
        lbm_value next = lbm_cdr(curr);
863
448
        if (i == ix) {
864
84
          lbm_set_car(curr, args[2]);
865
84
          result = args[0]; // Acts as true and as itself.
866
84
          break;
867
364
        } else if (lbm_is_symbol_nil(next)) {
868
28
          result = ENC_SYM_NIL; // index out of bounds, no update.
869
28
          break;
870
        }
871
336
        curr = next;
872
336
        i++;
873
      }
874
561624
    } else if (lbm_is_lisp_array_rw(args[0])) {
875
561624
      int32_t index = lbm_dec_as_i32(args[1]);
876
561624
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
877
561624
      lbm_value *arrdata = (lbm_value*)header->data;
878
561624
      lbm_uint size = header->size / sizeof(lbm_value);
879
561624
      if (index < 0) index = (int32_t)size + index;
880
561624
      if ((uint32_t)index < size) {
881
561624
        arrdata[index] = args[2]; // value
882
561624
        result = args[0];
883
      }  // index out of range will be eval error.
884
    }
885
  }
886
561736
  return result;
887
}
888
889
420
static lbm_value fundamental_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
890
  (void) ctx;
891
420
  lbm_value result = ENC_SYM_EERROR;
892
420
  if (nargs == 2) {
893
392
    if (lbm_is_cons(args[0])) {
894
336
      lbm_value r = assoc_lookup(args[1], args[0]);
895

336
      if (lbm_is_symbol(r) &&
896
          r == ENC_SYM_NO_MATCH) {
897
28
        result = ENC_SYM_NIL;
898
      } else {
899
308
        result = r;
900
      }
901
56
    } else if (lbm_is_symbol(args[0]) &&
902
56
               args[0] == ENC_SYM_NIL) {
903
28
      result = args[0]; /* nil */
904
    } /* else error */
905
  }
906
420
  return result;
907
}
908
909
130076
static lbm_value fundamental_acons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
910
  (void) ctx;
911
130076
  lbm_value result = ENC_SYM_TERROR;
912
130076
  if (nargs == 3) {
913
129992
    lbm_value keyval = lbm_cons(args[0], args[1]);
914
129992
    lbm_value new_alist = lbm_cons(keyval, args[2]);
915
916

259816
    if (lbm_is_symbol(keyval) ||
917
129824
        lbm_is_symbol(new_alist) )
918
182
      result = ENC_SYM_MERROR;
919
    else
920
129810
      result = new_alist;
921
84
  } else if (nargs == 2) {
922
    result = lbm_cons(args[0], args[1]);
923
  }
924
130076
  return result;
925
}
926
927
112
static bool set_assoc(lbm_value *res, lbm_value keyval, lbm_value assocs) {
928
112
  lbm_value curr = assocs;
929
112
  lbm_value key = lbm_car(keyval);
930
252
  while (lbm_is_cons(curr)) {
931
224
    if (struct_eq(key, lbm_caar(curr))) {
932
84
      lbm_set_car(curr, keyval);
933
84
      *res = assocs;
934
84
      return true;
935
    }
936
140
    curr = lbm_cdr(curr);
937
  }
938
28
  return false;
939
}
940
941
112
static lbm_value fundamental_set_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
942
  (void)ctx;
943
112
  lbm_value result = ENC_SYM_TERROR;
944
  lbm_value keyval;
945
112
  if (nargs == 3) {
946
84
    keyval = lbm_cons(args[1], args[2]);
947
84
    if (lbm_is_symbol(keyval)) return keyval;
948

28
  } else if (nargs == 2 && lbm_is_cons(args[1])) {
949
28
    keyval = args[1];
950
  } else return result;
951
112
  if (!set_assoc(&result, keyval, args[0])) {
952
28
    result = ENC_SYM_EERROR;
953
  }
954
112
  return result;
955
}
956
957
420
static lbm_value fundamental_cossa(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
958
  (void) ctx;
959
420
  lbm_value result = ENC_SYM_EERROR;
960
420
  if (nargs == 2) {
961
392
    if (lbm_is_cons(args[0])) {
962
336
      lbm_value r = cossa_lookup(args[1], args[0]);
963

336
      if (lbm_is_symbol(r) &&
964
          r == ENC_SYM_NO_MATCH) {
965
28
        result = ENC_SYM_NIL;
966
      } else {
967
308
        result = r;
968
      }
969
56
    } else if (lbm_is_symbol(args[0]) &&
970
56
               args[0] == ENC_SYM_NIL) {
971
28
      result = args[0]; /* nil */
972
    } /* else error */
973
  }
974
420
  return result;
975
}
976
977
31716
static lbm_value fundamental_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
978
  (void) ctx;
979
31716
  lbm_value result = ENC_SYM_EERROR;
980

31716
  if (nargs == 2 && IS_NUMBER(args[1])) {
981
31716
    result = ENC_SYM_NIL;
982
31716
    if (lbm_is_list(args[0])) {
983
22820
      result = lbm_index_list(args[0], lbm_dec_as_i32(args[1]));
984
8896
    } else if (lbm_is_lisp_array_r(args[0])) {
985
8896
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
986
8896
      lbm_value *arrdata = (lbm_value*)header->data;
987
8896
      lbm_uint size = header->size / sizeof(lbm_value);
988
8896
      int32_t index = lbm_dec_as_i32(args[1]);
989
8896
      if (index < 0) index = (int32_t)size + index;
990
8896
      if ((uint32_t)index < size) {
991
8896
        result = arrdata[index];
992
      }
993
    }
994
  }
995
31716
  return result;
996
}
997
998
280
static lbm_value fundamental_to_i(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
999
  (void) ctx;
1000
280
  lbm_value result = ENC_SYM_EERROR;
1001
280
  if (nargs == 1) {
1002
252
    result = lbm_enc_i((lbm_int)lbm_dec_as_i64(args[0]));
1003
  }
1004
280
  return result;
1005
}
1006
1007
280
static lbm_value fundamental_to_i32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1008
  (void) ctx;
1009
280
  lbm_value result = ENC_SYM_EERROR;
1010
280
  if (nargs == 1) {
1011
252
    result = lbm_enc_i32(lbm_dec_as_i32(args[0]));
1012
  }
1013
280
  return result;
1014
}
1015
1016
280
static lbm_value fundamental_to_u(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1017
  (void) ctx;
1018
280
  lbm_value result = ENC_SYM_EERROR;
1019
280
  if (nargs == 1) {
1020
252
    result = lbm_enc_u((lbm_uint)lbm_dec_as_u64(args[0]));
1021
  }
1022
280
  return result;
1023
}
1024
1025
280
static lbm_value fundamental_to_u32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1026
  (void) ctx;
1027
280
  lbm_value result = ENC_SYM_EERROR;
1028
280
  if (nargs == 1) {
1029
252
    result = lbm_enc_u32(lbm_dec_as_u32(args[0]));
1030
  }
1031
280
  return result;
1032
}
1033
1034
252
static lbm_value fundamental_to_float(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1035
  (void) ctx;
1036
252
  lbm_value result = ENC_SYM_EERROR;
1037
252
  if (nargs == 1) {
1038
224
    result = lbm_enc_float(lbm_dec_as_float(args[0]));
1039
  }
1040
252
  return result;
1041
}
1042
1043
280
static lbm_value fundamental_to_i64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1044
  (void) ctx;
1045
280
  lbm_value result = ENC_SYM_EERROR;
1046
280
  if (nargs == 1) {
1047
252
    result = lbm_enc_i64(lbm_dec_as_i64(args[0]));
1048
  }
1049
280
  return result;
1050
}
1051
1052
280
static lbm_value fundamental_to_u64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1053
  (void) ctx;
1054
280
  lbm_value result = ENC_SYM_EERROR;
1055
280
  if (nargs == 1) {
1056
252
    result = lbm_enc_u64(lbm_dec_as_u64(args[0]));
1057
  }
1058
280
  return result;
1059
}
1060
1061
252
static lbm_value fundamental_to_double(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1062
  (void) ctx;
1063
252
  lbm_value result = ENC_SYM_EERROR;
1064
252
  if (nargs == 1) {
1065
224
    result = lbm_enc_double(lbm_dec_as_double(args[0]));
1066
  }
1067
252
  return result;
1068
}
1069
1070
252
static lbm_value fundamental_to_byte(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1071
  (void) ctx;
1072
252
  lbm_value result = ENC_SYM_EERROR;
1073
252
  if (nargs == 1) {
1074
224
    result = lbm_enc_char(lbm_dec_as_char(args[0]));
1075
  }
1076
252
  return result;
1077
}
1078
1079
336
static lbm_value fundamental_shl(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1080
  (void) ctx;
1081
336
  lbm_value retval = ENC_SYM_EERROR;
1082
336
  if (nargs == 2) {
1083
308
    retval = ENC_SYM_TERROR;
1084

308
    if (IS_NUMBER(args[0]) && IS_NUMBER(args[1])) {
1085

252
      switch (lbm_type_of_functional(args[0])) {
1086
56
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) << lbm_dec_as_u32(args[1])); break;
1087
28
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) << lbm_dec_as_u32(args[1])); break;
1088
28
      case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) << lbm_dec_as_u32(args[1])); break;
1089
28
      case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) << lbm_dec_as_u32(args[1])); break;
1090
28
      case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) << lbm_dec_as_u32(args[1])); break;
1091
28
      case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) << lbm_dec_as_u32(args[1])); break;
1092
      }
1093
84
    }
1094
  }
1095
336
  return retval;
1096
}
1097
1098
336
static lbm_value fundamental_shr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1099
  (void) ctx;
1100
336
  lbm_value retval = ENC_SYM_EERROR;
1101
336
  if (nargs == 2) {
1102
308
    retval = ENC_SYM_TERROR;
1103

308
    if (IS_NUMBER(args[0]) && IS_NUMBER(args[1])) {
1104

252
      switch (lbm_type_of_functional(args[0])) {
1105
56
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) >> lbm_dec_as_u32(args[1])); break;
1106
28
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) >> lbm_dec_as_u32(args[1])); break;
1107
28
      case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) >> lbm_dec_as_u32(args[1])); break;
1108
28
      case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) >> lbm_dec_as_u32(args[1])); break;
1109
28
      case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) >> lbm_dec_as_u32(args[1])); break;
1110
28
      case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) >> lbm_dec_as_u32(args[1])); break;
1111
      }
1112
84
    }
1113
  }
1114
336
  return retval;
1115
}
1116
1117
336
static lbm_value fundamental_bitwise_and(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1118
  (void) ctx;
1119
336
  lbm_value retval = ENC_SYM_EERROR;
1120
336
  if (nargs == 2) {
1121
308
    retval = ENC_SYM_TERROR;
1122

308
    if (IS_NUMBER(args[0]) && IS_NUMBER(args[1])) {
1123

252
      switch (lbm_type_of_functional(args[0])) {
1124
#ifdef LBM64
1125
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) & lbm_dec_as_i64(args[1])); break;
1126
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) & lbm_dec_as_u64(args[1])); break;
1127
#else
1128
56
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) & lbm_dec_as_i32(args[1])); break;
1129
28
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) & lbm_dec_as_u32(args[1])); break;
1130
#endif
1131
28
      case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) & lbm_dec_as_u32(args[1])); break;
1132
28
      case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) & lbm_dec_as_i32(args[1])); break;
1133
28
      case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) & lbm_dec_as_i64(args[1])); break;
1134
28
      case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) & lbm_dec_as_u64(args[1])); break;
1135
      }
1136
84
    }
1137
  }
1138
336
  return retval;
1139
}
1140
1141
336
static lbm_value fundamental_bitwise_or(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1142
  (void) ctx;
1143
336
  lbm_value retval = ENC_SYM_EERROR;
1144
336
  if (nargs == 2) {
1145
308
    retval = ENC_SYM_TERROR;
1146

308
    if (IS_NUMBER(args[0]) && IS_NUMBER(args[1])) {
1147

252
      switch (lbm_type_of_functional(args[0])) {
1148
#ifdef LBM64
1149
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) | lbm_dec_as_i64(args[1])); break;
1150
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) | lbm_dec_as_u64(args[1])); break;
1151
#else
1152
56
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) | lbm_dec_as_i32(args[1])); break;
1153
28
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) | lbm_dec_as_u32(args[1])); break;
1154
#endif
1155
28
      case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) | lbm_dec_as_u32(args[1])); break;
1156
28
      case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) | lbm_dec_as_i32(args[1])); break;
1157
28
      case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) | lbm_dec_as_i64(args[1])); break;
1158
28
      case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) | lbm_dec_as_u64(args[1])); break;
1159
      }
1160
84
    }
1161
  }
1162
336
  return retval;
1163
}
1164
1165
336
static lbm_value fundamental_bitwise_xor(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1166
  (void) ctx;
1167
336
  lbm_value retval = ENC_SYM_EERROR;
1168
336
  if (nargs == 2) {
1169
308
    retval = ENC_SYM_TERROR;
1170

308
    if (IS_NUMBER(args[0]) && IS_NUMBER(args[1])) {
1171

252
      switch (lbm_type_of_functional(args[0])) {
1172
#ifdef LBM64
1173
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) ^ lbm_dec_as_i64(args[1])); break;
1174
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) ^ lbm_dec_as_u64(args[1])); break;
1175
#else
1176
56
      case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) ^ lbm_dec_as_i32(args[1])); break;
1177
28
      case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) ^ lbm_dec_as_u32(args[1])); break;
1178
#endif
1179
28
      case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) ^ lbm_dec_as_u32(args[1])); break;
1180
28
      case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) ^ lbm_dec_as_i32(args[1])); break;
1181
28
      case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) ^ lbm_dec_as_i64(args[1])); break;
1182
28
      case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) ^ lbm_dec_as_u64(args[1])); break;
1183
      }
1184
84
    }
1185
  }
1186
336
  return retval;
1187
}
1188
1189
280
static lbm_value fundamental_bitwise_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1190
  (void) ctx;
1191
280
  lbm_value retval = ENC_SYM_EERROR;
1192
280
  if (nargs == 1) {
1193
252
    retval = ENC_SYM_TERROR;
1194
252
    if (IS_NUMBER(args[0])) {
1195

224
      switch (lbm_type_of_functional(args[0])) {
1196
28
      case LBM_TYPE_I: retval = lbm_enc_i(~lbm_dec_i(args[0])); break;
1197
28
      case LBM_TYPE_U: retval = lbm_enc_u(~lbm_dec_u(args[0])); break;
1198
28
      case LBM_TYPE_U32: retval = lbm_enc_u32(~lbm_dec_u32(args[0])); break;
1199
28
      case LBM_TYPE_I32: retval = lbm_enc_i32(~lbm_dec_i32(args[0])); break;
1200
28
      case LBM_TYPE_I64: retval = lbm_enc_i64(~lbm_dec_i64(args[0])); break;
1201
28
      case LBM_TYPE_U64: retval = lbm_enc_u64(~lbm_dec_u64(args[0])); break;
1202
      }
1203
56
    }
1204
  }
1205
280
  return retval;
1206
}
1207
1208
static lbm_value fundamental_custom_destruct(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1209
  (void) ctx;
1210
  lbm_value result = ENC_SYM_EERROR;
1211
  if (nargs == 1 && (lbm_type_of(args[0]) == LBM_TYPE_CUSTOM)) {
1212
    lbm_uint *mem_ptr = (lbm_uint*)lbm_dec_custom(args[0]);
1213
    if(!mem_ptr) return ENC_SYM_FATAL_ERROR;
1214
    lbm_custom_type_destroy(mem_ptr);
1215
    lbm_value tmp = lbm_set_ptr_type(args[0], LBM_TYPE_CONS);
1216
    lbm_set_car(tmp, ENC_SYM_NIL);
1217
    lbm_set_cdr(tmp, ENC_SYM_NIL);
1218
    // The original value will still be of type custom_ptr
1219
    result = ENC_SYM_TRUE;
1220
  }
1221
  return result;
1222
}
1223
1224
16848
static lbm_value fundamental_type_of(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1225
  (void) ctx;
1226
16848
  lbm_value res = ENC_SYM_EERROR;
1227
16848
  if (nargs == 1) {
1228
16848
    lbm_value val = args[0];
1229
16848
    lbm_type t = lbm_type_of(val);
1230
1231
16848
    if (lbm_is_ptr(val)) {
1232
      // Ignore constant or not constant.
1233
11144
      t &= LBM_PTR_TO_CONSTANT_MASK;
1234
    }
1235




16848
    switch(t) {
1236
5236
    case LBM_TYPE_CONS: res = ENC_SYM_TYPE_LIST; break;
1237
112
    case LBM_TYPE_ARRAY: res = ENC_SYM_TYPE_ARRAY; break;
1238
644
    case LBM_TYPE_I32: res = ENC_SYM_TYPE_I32; break;
1239
812
    case LBM_TYPE_U32: res = ENC_SYM_TYPE_U32; break;
1240
1792
    case LBM_TYPE_FLOAT: res = ENC_SYM_TYPE_FLOAT; break;
1241
672
    case LBM_TYPE_I64: res = ENC_SYM_TYPE_I64; break;
1242
784
    case LBM_TYPE_U64: res = ENC_SYM_TYPE_U64; break;
1243
1064
    case LBM_TYPE_DOUBLE: res = ENC_SYM_TYPE_DOUBLE; break;
1244
1148
    case LBM_TYPE_I: res = ENC_SYM_TYPE_I; break;
1245
3240
    case LBM_TYPE_U: res = ENC_SYM_TYPE_U; break;
1246
56
    case LBM_TYPE_CHAR: res = ENC_SYM_TYPE_CHAR; break;
1247
1260
    case LBM_TYPE_SYMBOL: res = ENC_SYM_TYPE_SYMBOL; break;
1248
28
    case LBM_TYPE_LISPARRAY: res = ENC_SYM_TYPE_LISPARRAY; break;
1249
    case LBM_TYPE_DEFRAG_MEM: res = ENC_SYM_TYPE_DEFRAG_MEM; break;
1250
    case LBM_TYPE_CUSTOM: res = ENC_SYM_TYPE_CUSTOM; break;
1251
    }
1252
  }
1253
16848
  return res;
1254
}
1255
1256
1344
static lbm_value fundamental_list_length(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1257
  (void) ctx;
1258
1344
  lbm_value result = ENC_SYM_EERROR;
1259
1344
  if (nargs == 1) {
1260
1316
    result = ENC_SYM_TERROR;
1261
1316
    if (lbm_is_list(args[0])) {
1262
1148
      int32_t len = (int32_t)lbm_list_length(args[0]);
1263
1148
      result = lbm_enc_i(len);
1264
168
    } else if (lbm_is_array_r(args[0])) {
1265
28
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
1266
28
      result = lbm_enc_i((int)(header->size));
1267
140
    } else if (lbm_is_lisp_array_r(args[0])) {
1268
84
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
1269
84
      result = lbm_enc_i((int)(header->size / (sizeof(lbm_uint))));
1270
    }
1271
  }
1272
1344
  return result;
1273
}
1274
1275
6090602
static lbm_value fundamental_range(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1276
  (void) ctx;
1277
6090602
  lbm_value result = ENC_SYM_EERROR;
1278
1279
  int32_t start;
1280
  int32_t end;
1281
6090602
  bool rev = false;
1282
1283

6090602
  if (nargs == 1 && IS_NUMBER(args[0])) {
1284
5801910
    start = 0;
1285
5801910
    end = lbm_dec_as_i32(args[0]);
1286

577328
  } else if (nargs == 2 &&
1287
577244
             IS_NUMBER(args[0]) &&
1288
288608
             IS_NUMBER(args[1])) {
1289
288580
    start = lbm_dec_as_i32(args[0]);
1290
288580
    end = lbm_dec_as_i32(args[1]);
1291
  } else {
1292
112
    return result;
1293
  }
1294
1295
6090490
  if (end == start) return ENC_SYM_NIL;
1296
6090462
  else if (end < start) {
1297
56
    int32_t tmp = end;
1298
56
    end = start;
1299
56
    start = tmp;
1300
56
    rev = true;
1301
  }
1302
1303
6090462
  int num = end - start;
1304
1305
6090462
  if ((unsigned int)num > lbm_heap_num_free()) {
1306
197284
    return ENC_SYM_MERROR;
1307
  }
1308
1309
5893178
  lbm_value r_list = ENC_SYM_NIL;
1310
304345561
  for (int i = end - 1; i >= start; i --) {
1311
298452383
    r_list = lbm_cons(lbm_enc_i(i), r_list);
1312
  }
1313
5893178
  return rev ? lbm_list_destructive_reverse(r_list) : r_list;
1314
}
1315
1316
280
static lbm_value fundamental_reg_event_handler(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1317
  (void) ctx;
1318
280
  lbm_value res = ENC_SYM_TERROR;
1319

280
  if (nargs == 1 && IS_NUMBER(args[0])) {
1320
224
    lbm_set_event_handler_pid((lbm_cid)lbm_dec_i(args[0]));
1321
224
    res = ENC_SYM_TRUE;
1322
  }
1323
280
  return res;
1324
}
1325
1326
34688
static lbm_value fundamental_take(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1327
  (void) ctx;
1328
34688
  lbm_value res = ENC_SYM_TERROR;
1329

34688
  if (nargs == 2 && IS_NUMBER(args[1]) && lbm_is_list(args[0])) {
1330
34604
    int len = lbm_dec_as_i32(args[1]);
1331
34604
    res = lbm_list_copy(&len, args[0]);
1332
  }
1333
34688
  return res;
1334
}
1335
1336
168
static lbm_value fundamental_drop(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1337
  (void) ctx;
1338
168
  lbm_value res = ENC_SYM_TERROR;
1339

168
  if (nargs == 2 && IS_NUMBER(args[1]) && lbm_is_list(args[0])) {
1340
84
    res = lbm_list_drop(lbm_dec_as_u32(args[1]), args[0]);
1341
  }
1342
168
  return res;
1343
}
1344
/* (mkarray size) */
1345
281704
static lbm_value fundamental_mkarray(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1346
  (void) ctx;
1347
281704
  lbm_value res = ENC_SYM_TERROR;
1348

281704
  if (nargs == 1 && IS_NUMBER(args[0])) {
1349
281704
    lbm_heap_allocate_lisp_array(&res, lbm_dec_as_u32(args[0]));
1350
  }
1351
  // No high-level arrays in defrag mem until we figure out how to do it without overhead.
1352
  //else if (nargs == 2 && IS_NUMBER(args[1]) && lbm_type_of(args[0]) == LBM_TYPE_DEFRAG_MEM) {
1353
  //  lbm_uint *dm = (lbm_uint*)lbm_car(args[0]);
1354
  //  res = lbm_defrag_mem_alloc_lisparray(dm, lbm_dec_as_u32(args[1]));
1355
  //}
1356
281704
  return res;
1357
}
1358
1359
// Create an array in a similar way to how list creates a list.
1360
static lbm_value fundamental_array(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1361
  (void) ctx;
1362
  lbm_value res = ENC_SYM_TERROR;
1363
  lbm_heap_allocate_lisp_array(&res, nargs);
1364
  if (!lbm_is_symbol_merror(res)) {
1365
    lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(res);
1366
    lbm_value *arrdata = (lbm_value*)header->data;
1367
    for (lbm_uint i = 0; i < nargs; i ++) {
1368
      arrdata[i] = args[i];
1369
    }
1370
  }
1371
  return res;
1372
}
1373
1374
168
static lbm_value fundamental_dm_create(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1375
  (void) ctx;
1376
168
  lbm_value res = ENC_SYM_TERROR;
1377

168
  if (argn == 1 && lbm_is_number(args[0])) {
1378
168
    lbm_uint n = lbm_dec_as_uint(args[0]);
1379
168
    res = lbm_defrag_mem_create(n);
1380
  }
1381
168
  return res;
1382
}
1383
1384
2184
static lbm_value fundamental_dm_alloc(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1385
  (void) ctx;
1386
2184
  lbm_value res = ENC_SYM_TERROR;
1387

2184
  if (argn == 2 && lbm_is_number(args[1])) {
1388
2184
    if (lbm_type_of(args[0]) == LBM_TYPE_DEFRAG_MEM) {
1389
2184
      lbm_uint *dm = (lbm_uint*)lbm_car(args[0]);
1390
2184
      res = lbm_defrag_mem_alloc(dm, lbm_dec_as_uint(args[1]));
1391
    }
1392
  }
1393
  // NO high level arrays in Defrag mem until we can do it without overhead in the DM representation!
1394
  //else if (argn == 3 && lbm_is_number(args[1]) && args[2] == ENC_SYM_TYPE_LISPARRAY)  {
1395
  //  if (lbm_type_of(args[0]) == LBM_TYPE_DEFRAG_MEM) {
1396
  //    lbm_uint *dm = (lbm_uint*)lbm_car(args[0]);
1397
  //    res = lbm_defrag_mem_alloc_lisparray(dm, lbm_dec_as_uint(args[1]));
1398
  //  }
1399
  //}
1400
2184
  return res;
1401
}
1402
1403
140
static lbm_value fundamental_is_list(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1404
  (void) ctx;
1405
140
  lbm_value res = ENC_SYM_TERROR;
1406
140
  if (argn == 1) {
1407
140
    res = lbm_is_list(args[0]) ? ENC_SYM_TRUE : ENC_SYM_NIL;
1408
  }
1409
140
  return res;
1410
}
1411
1412
308
static lbm_value fundamental_is_number(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1413
  (void) ctx;
1414
308
  lbm_value res = ENC_SYM_TERROR;
1415
308
  if (argn == 1) {
1416
308
    res = lbm_is_number(args[0]) ? ENC_SYM_TRUE : ENC_SYM_NIL;
1417
  }
1418
308
  return res;
1419
}
1420
1421
static lbm_value fundamental_int_div(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1422
  lbm_value res = fundamental_div(args, argn, ctx);
1423
  switch (lbm_type_of(res)) {
1424
    case LBM_TYPE_FLOAT: {
1425
      res = lbm_enc_i((lbm_int)lbm_dec_float(res));
1426
      break;
1427
    }
1428
    case LBM_TYPE_DOUBLE: {
1429
      res = lbm_enc_i((lbm_int)lbm_dec_double(res));
1430
      break;
1431
    }
1432
  }
1433
1434
  return res;
1435
}
1436
1437
56
static lbm_value fundamental_identity(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1438
  (void) ctx;
1439
56
  lbm_value res = ENC_SYM_TERROR;
1440
56
  if (argn == 1) {
1441
56
    res = args[0];
1442
  }
1443
56
  return res;
1444
}
1445
1446
static lbm_value fundamental_is_string(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1447
  (void) ctx;
1448
  lbm_value res = ENC_SYM_TERROR;
1449
  if (argn == 1) {
1450
    char *str;
1451
    res = lbm_value_is_printable_string(args[0], &str) ? ENC_SYM_TRUE : ENC_SYM_NIL;
1452
  }
1453
  return res;
1454
}
1455
1456
// Check if a value is a constant (stored in flash)
1457
// Only half true for some shared arrays.. maybe rethink that.
1458
// constant? is true for constant pointers.
1459
// atoms could be considered constant in general but are not by constant?
1460
static lbm_value fundamental_is_constant(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1461
  (void) ctx;
1462
  lbm_value res = ENC_SYM_TERROR;
1463
  if (argn == 1) {
1464
    lbm_type t = lbm_type_of(args[0]);
1465
    return (((args[0] & LBM_PTR_BIT) && (t & LBM_PTR_TO_CONSTANT_BIT)) ? ENC_SYM_TRUE : ENC_SYM_NIL);
1466
  }
1467
  return res;
1468
}
1469
1470
const fundamental_fun fundamental_table[] =
1471
  {fundamental_add,
1472
   fundamental_sub,
1473
   fundamental_mul,
1474
   fundamental_div,
1475
   fundamental_mod,
1476
   fundamental_eq,
1477
   fundamental_not_eq,
1478
   fundamental_numeq,
1479
   fundamental_num_not_eq,
1480
   fundamental_lt,
1481
   fundamental_gt,
1482
   fundamental_leq,
1483
   fundamental_geq,
1484
   fundamental_not,
1485
   fundamental_gc,
1486
   fundamental_self,
1487
   fundamental_set_mailbox_size,
1488
   fundamental_cons,
1489
   fundamental_car,
1490
   fundamental_cdr,
1491
   fundamental_list,
1492
   fundamental_append,
1493
   fundamental_undefine,
1494
   fundamental_buf_create,
1495
   fundamental_symbol_to_string,
1496
   fundamental_string_to_symbol,
1497
   fundamental_symbol_to_uint,
1498
   fundamental_uint_to_symbol,
1499
   fundamental_set_car,
1500
   fundamental_set_cdr,
1501
   fundamental_set_ix,
1502
   fundamental_assoc,
1503
   fundamental_acons,
1504
   fundamental_set_assoc,
1505
   fundamental_cossa,
1506
   fundamental_ix,
1507
   fundamental_to_i,
1508
   fundamental_to_i32,
1509
   fundamental_to_u,
1510
   fundamental_to_u32,
1511
   fundamental_to_float,
1512
   fundamental_to_i64,
1513
   fundamental_to_u64,
1514
   fundamental_to_double,
1515
   fundamental_to_byte,
1516
   fundamental_shl,
1517
   fundamental_shr,
1518
   fundamental_bitwise_and,
1519
   fundamental_bitwise_or,
1520
   fundamental_bitwise_xor,
1521
   fundamental_bitwise_not,
1522
   fundamental_custom_destruct,
1523
   fundamental_type_of,
1524
   fundamental_list_length,
1525
   fundamental_range,
1526
   fundamental_reg_event_handler,
1527
   fundamental_take,
1528
   fundamental_drop,
1529
   fundamental_mkarray,
1530
   fundamental_dm_create,
1531
   fundamental_dm_alloc,
1532
   fundamental_is_list,
1533
   fundamental_is_number,
1534
   fundamental_int_div,
1535
   fundamental_identity,
1536
   fundamental_array,
1537
   fundamental_is_string,
1538
   fundamental_is_constant
1539
  };