GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/fundamental.c Lines: 839 856 98.0 %
Date: 2024-12-05 14:36:58 Branches: 568 631 90.0 %

Line Branch Exec Source
1
/*
2
    Copyright 2019, 2021 - 2024      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
30
#include <stdio.h>
31
#include <math.h>
32
33
/* Type promotion ranks
34
35
   32bit LBM:
36
   byte < i < u < i32 < u32 < i64 < u64 < float < double
37
38
   64bit LBM:
39
   byte < i32 < u32 < i < u < i64 < u64 < float < double
40
 */
41
42
// PROMOTE_SWAP is for commutative operations
43
// PROMOTE is for non-commutative operations
44
45
#ifndef LBM64
46
#define PROMOTE_SWAP(t, a, b)                                  \
47
  if (lbm_type_of_functional(a) < lbm_type_of_functional(b)) { \
48
    lbm_value tmp = a;                                         \
49
    a = b;                                                     \
50
    b = tmp;                                                   \
51
  }                                                            \
52
  t = lbm_type_of_functional(a);
53
#else
54
#define PROMOTE_SWAP(t, a, b)                                           \
55
  if (lbm_type_of_functional(b) == LBM_TYPE_FLOAT && (lbm_type_of_functional(a) < LBM_TYPE_DOUBLE)) { \
56
      lbm_value tmp = a;                                                \
57
      a = b;                                                            \
58
      b = tmp;                                                          \
59
  } if (lbm_type_of_functional(a) == LBM_TYPE_FLOAT && (lbm_type_of_functional(b) < LBM_TYPE_DOUBLE)) { \
60
    /* DO NOTHING */                                                    \
61
  } else if (lbm_type_of_functional(a) < lbm_type_of_functional(b)) {   \
62
    lbm_value tmp = a;                                                  \
63
    a = b;                                                              \
64
    b = tmp;                                                            \
65
  }                                                                     \
66
  t = lbm_type_of_functional(a);
67
#endif
68
69
#ifndef LBM64
70
#define PROMOTE(t, a, b)                                                \
71
  t = lbm_type_of_functional(a);                                        \
72
  lbm_uint t_b = lbm_type_of_functional(b);                             \
73
  if (t < t_b) {                                                        \
74
    t  = t_b;                                                           \
75
  }
76
77
#else
78
#define PROMOTE(t, a, b)                                                \
79
  if (lbm_type_of_functional(b) == LBM_TYPE_FLOAT) {                    \
80
    if (lbm_type_of_functional(a) < LBM_TYPE_DOUBLE) {                  \
81
      t = LBM_TYPE_FLOAT;                                               \
82
    } else {                                                            \
83
      t = lbm_type_of_functional(a);                                    \
84
    }                                                                   \
85
  }  else if (lbm_type_of_functional(a) < lbm_type_of_functional(b)) {  \
86
    t = lbm_type_of_functional(b);                                      \
87
  } else {                                                              \
88
    t = lbm_type_of_functional(a);                                      \
89
  }
90
#endif
91
92
93
#define IS_NUMBER lbm_is_number
94
95
// Todo: It may be possible perform some of these operations
96
//       on encoded values followed by a "correction" of the result values
97
//       type bits.
98
//       But the checks required to figure out if it is possible to apply the
99
//       operation in this way has a cost too...
100
101
2805236
static lbm_uint mul2(lbm_uint a, lbm_uint b) {
102
2805236
  lbm_uint retval = ENC_SYM_TERROR;
103

2805236
  if (IS_NUMBER(a) && IS_NUMBER(b)) {
104
    lbm_type t;
105
2805068
    PROMOTE_SWAP(t, a, b);
106


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

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


1064
    switch (t) {
134
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;
135
#ifdef LBM64
136
    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;
137
    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;
138
#else
139
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;
140
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;
141
#endif
142
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;
143
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;
144

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;
145
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;
146
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;
147

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;
148
    }
149
616
  } else {
150
112
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
151
  }
152
728
  return retval;
153
}
154
155
784
static lbm_uint mod2(lbm_uint a, lbm_uint b) {
156
784
  lbm_uint retval = ENC_SYM_TERROR;
157

784
  if (IS_NUMBER(a) && IS_NUMBER(b)) {
158
    lbm_type t;
159
672
    PROMOTE(t, a, b);
160


672
    switch (t) {
161
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;
162
#ifdef LBM64
163
    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;
164
    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;
165
#else
166
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;
167
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;
168
#endif
169
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;
170
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;
171

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;
172
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;
173
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;
174

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;
175
    }
176
392
  } else {
177
112
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
178
  }
179
504
  return retval;
180
}
181
182
21204954
static lbm_uint sub2(lbm_uint a, lbm_uint b) {
183
21204954
  lbm_uint retval = ENC_SYM_TERROR;
184

21204954
  if (IS_NUMBER(a) && IS_NUMBER(b)) {
185
    lbm_uint t;
186
21204758
    PROMOTE(t, a, b);
187


21204758
    switch (t) {
188
56
    case LBM_TYPE_BYTE: retval = lbm_enc_char((uint8_t)(lbm_dec_char(a) - lbm_dec_char(b))); break;
189
#ifdef LBM64
190
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_as_i64(a) - lbm_dec_as_i64(b)); break;
191
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_as_u64(a) - lbm_dec_as_u64(b)); break;
192
#else
193
20923548
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_as_i32(a) - lbm_dec_as_i32(b)); break;
194
56
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_as_u32(a) - lbm_dec_as_u32(b)); break;
195
#endif
196
280566
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_as_u32(a) - lbm_dec_as_u32(b)); break;
197
84
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_as_i32(a) - lbm_dec_as_i32(b)); break;
198
252
    case LBM_TYPE_FLOAT: retval = lbm_enc_float(lbm_dec_as_float(a) - lbm_dec_as_float(b)); break;
199
56
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_as_u64(a) - lbm_dec_as_u64(b)); break;
200
84
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_as_i64(a) - lbm_dec_as_i64(b)); break;
201
56
    case LBM_TYPE_DOUBLE: retval = lbm_enc_double(lbm_dec_as_double(a) - lbm_dec_as_double(b)); break;
202
    }
203
21204758
  } else {
204
196
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
205
  }
206
21204954
  return retval;
207
}
208
209
// a and b must be bytearrays!
210
10136
static bool bytearray_equality(lbm_value a, lbm_value b) {
211
10136
  lbm_array_header_t *a_ = (lbm_array_header_t*)lbm_car(a);
212
10136
  lbm_array_header_t *b_ = (lbm_array_header_t*)lbm_car(b);
213
214
  // A NULL array arriving here should be impossible.
215
  // if the a and b are not valid arrays at this point, the data
216
  // is most likely nonsense - corrupted by cosmic radiation.
217
10136
  bool res = a_->size == b_->size;
218
10136
  if (res) {
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
196
static bool array_struct_equality(lbm_value a, lbm_value b) {
226
196
  lbm_array_header_t *a_ = (lbm_array_header_t*)lbm_car(a);
227
196
  lbm_array_header_t *b_ = (lbm_array_header_t*)lbm_car(b);
228
196
  lbm_value *adata = (lbm_value*)a_->data;
229
196
  lbm_value *bdata = (lbm_value*)b_->data;
230
196
  bool res =  a_->size == b_->size;
231
196
  if (res) {
232
168
    lbm_uint size = (lbm_uint)a_->size / (lbm_uint)sizeof(lbm_value);
233
588
    for (lbm_uint i = 0; i < size; i ++ ) {
234
448
      res = struct_eq(adata[i], bdata[i]);
235
448
      if (!res) break;
236
    }
237
  }
238
196
  return res;
239
}
240
241
231632
bool struct_eq(lbm_value a, lbm_value b) {
242
243
231632
  bool res = false;
244
231632
  lbm_type ta = lbm_type_of_functional(a);
245
231632
  lbm_type tb = lbm_type_of_functional(b);
246
247
231632
  if (ta == tb) {
248



215504
    switch(ta){
249
59828
    case LBM_TYPE_SYMBOL:
250
59828
      res = (lbm_dec_sym(a) == lbm_dec_sym(b)); break;
251
51924
    case LBM_TYPE_I:
252
51924
      res =  (lbm_dec_i(a) == lbm_dec_i(b)); break;
253
588
    case LBM_TYPE_U:
254
588
      res = (lbm_dec_u(a) == lbm_dec_u(b)); break;
255
4592
    case LBM_TYPE_CHAR:
256
4592
      res = (lbm_dec_char(a) == lbm_dec_char(b)); break;
257
74044
    case LBM_TYPE_CONS:
258

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


33436212
  switch (t) {
292
28
  case LBM_TYPE_CHAR: retval = CMP(lbm_dec_char(a), lbm_dec_char(b)); break;
293
#ifdef LBM64
294
  case LBM_TYPE_I: retval = CMP(lbm_dec_as_i64(a), lbm_dec_as_i64(b)); break;
295
  case LBM_TYPE_U: retval = CMP(lbm_dec_as_u64(a), lbm_dec_as_u64(b)); break;
296
#else
297
31754084
  case LBM_TYPE_I: retval = CMP(lbm_dec_as_i32(a), lbm_dec_as_i32(b)); break;
298
84
  case LBM_TYPE_U: retval = CMP(lbm_dec_as_u32(a), lbm_dec_as_u32(b)); break;
299
#endif
300
560728
  case LBM_TYPE_U32: retval = CMP(lbm_dec_as_u32(a), lbm_dec_as_u32(b)); break;
301
280056
  case LBM_TYPE_I32: retval = CMP(lbm_dec_as_i32(a), lbm_dec_as_i32(b)); break;
302
896
  case LBM_TYPE_FLOAT: retval = CMP(lbm_dec_as_float(a), lbm_dec_as_float(b)); break;
303
280084
  case LBM_TYPE_U64: retval = CMP(lbm_dec_as_u64(a), lbm_dec_as_u64(b)); break;
304
560084
  case LBM_TYPE_I64: retval = CMP(lbm_dec_as_i64(a), lbm_dec_as_i64(b)); break;
305
168
  case LBM_TYPE_DOUBLE: retval = CMP(lbm_dec_as_double(a), lbm_dec_as_double(b)); break;
306
  }
307
33436212
  return retval;
308
}
309
310
/* (array-create size) */
311
24130
static void array_create(lbm_value *args, lbm_uint nargs, lbm_value *result) {
312
24130
  *result = ENC_SYM_EERROR;
313

24130
  if (nargs == 1 && IS_NUMBER(args[0])) {
314
24046
    lbm_heap_allocate_array(result, lbm_dec_as_u32(args[0]));
315
  }
316
24130
}
317
318
364
static lbm_value assoc_lookup(lbm_value key, lbm_value assoc) {
319
364
  lbm_value curr = assoc;
320
364
  lbm_value res = ENC_SYM_NO_MATCH;
321
840
  while (lbm_is_cons(curr)) {
322
812
    lbm_value c = lbm_ref_cell(curr)->car;
323
812
    if (lbm_is_cons(c)) {
324
784
      if (struct_eq(lbm_ref_cell(c)->car, key)) {
325
308
        res = lbm_ref_cell(c)->cdr;
326
308
        break;
327
      }
328
    } else {
329
28
      res = ENC_SYM_EERROR;
330
28
      break;
331
    }
332
476
    curr = lbm_ref_cell(curr)->cdr;
333
  }
334
364
  return res;
335
}
336
337
336
static lbm_value cossa_lookup(lbm_value key, lbm_value assoc) {
338
336
  lbm_value curr = assoc;
339
840
  while (lbm_is_cons(curr)) {
340
812
    lbm_value c = lbm_ref_cell(curr)->car;
341
812
    if (lbm_is_cons(c)) {
342
784
      if (struct_eq(lbm_ref_cell(c)->cdr, key)) {
343
280
        return lbm_ref_cell(c)->car;
344
      }
345
    } else {
346
28
      return ENC_SYM_EERROR;
347
    }
348
504
    curr = lbm_ref_cell(curr)->cdr;
349
  }
350
28
  return ENC_SYM_NO_MATCH;
351
}
352
353
354
355
/***************************************************/
356
/* Fundamental operations                          */
357
358
7495106
static lbm_value fundamental_add(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
359
  (void) ctx;
360
7495106
  lbm_uint sum = lbm_enc_char(0);
361
46146730
  for (lbm_uint i = 0; i < nargs; i ++) {
362
38656850
    lbm_value v = args[i];
363
38656850
    if (IS_NUMBER(v)) { // inlining add2 explicitly removes one condition.
364
        lbm_type t;
365
38656654
        PROMOTE_SWAP(t, sum, v);
366


38656654
        switch (t) {
367
280
        case LBM_TYPE_BYTE: sum = lbm_enc_char((uint8_t)(lbm_dec_char(sum) + lbm_dec_char(v))); break;
368
#ifdef LBM64
369
        case LBM_TYPE_I: sum = lbm_enc_i(lbm_dec_i(sum) + lbm_dec_as_i64(v)); break;
370
        case LBM_TYPE_U: sum = lbm_enc_u(lbm_dec_u(sum) + lbm_dec_as_u64(v)); break;
371
#else
372
24054728
        case LBM_TYPE_I: sum = lbm_enc_i(lbm_dec_i(sum) + lbm_dec_as_i32(v)); break;
373
616
        case LBM_TYPE_U: sum = lbm_enc_u(lbm_dec_u(sum) + lbm_dec_as_u32(v)); break;
374
#endif
375
3364152
        case LBM_TYPE_U32: sum = lbm_enc_u32(lbm_dec_u32(sum) + lbm_dec_as_u32(v)); break;
376
2814532
        case LBM_TYPE_I32: sum = lbm_enc_i32(lbm_dec_i32(sum) + lbm_dec_as_i32(v)); break;
377
1876
        case LBM_TYPE_FLOAT: sum = lbm_enc_float(lbm_dec_float(sum) + lbm_dec_as_float(v)); break;
378
          // extra check only in the cases that require it. (on 32bit, some wasted cycles on 64 bit)
379
3368402
        case LBM_TYPE_U64:
380
3368402
          sum = lbm_enc_u64(lbm_dec_u64(sum) + lbm_dec_as_u64(v));
381
3368402
          if (lbm_is_symbol_merror(sum)) goto add_end;
382
3366836
          break;
383
4490244
        case LBM_TYPE_I64:
384
4490244
          sum = lbm_enc_i64(lbm_dec_i64(sum) + lbm_dec_as_i64(v));
385
4490244
          if (lbm_is_symbol_merror(sum)) goto add_end;
386
4487304
          break;
387
561824
        case LBM_TYPE_DOUBLE:
388
561824
          sum = lbm_enc_double(lbm_dec_double(sum) + lbm_dec_as_double(v));
389
561824
          if (lbm_is_symbol_merror(sum)) goto add_end;
390
561300
          break;
391
        }
392
38651624
    } else {
393
196
      lbm_set_error_suspect(v);
394
196
      sum = ENC_SYM_TERROR;
395
196
      break; // out of loop
396
    }
397
  }
398
7489880
 add_end:
399
7495106
  return sum;
400
}
401
402
21204870
static lbm_value fundamental_sub(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
403
  (void) ctx;
404
405
  lbm_uint res;
406
407

21204870
  switch (nargs) {
408
28
  case 0:
409
28
    res = lbm_enc_char(0);
410
28
    break;
411
412
476
  case 1:
413
476
    res = sub2(lbm_enc_char(0),args[0]);
414
476
    break;
415
416
21204310
  case 2:
417
21204310
    res = sub2(args[0], args[1]);
418
21204310
    break;
419
420
56
  default:
421
56
    res = args[0];
422
196
    for (lbm_uint i = 1; i < nargs; i ++) {
423
168
      res = sub2(res, args[i]);
424
168
      if (lbm_type_of(res) == LBM_TYPE_SYMBOL)
425
28
        break;
426
    }
427
56
    break;
428
  }
429
21204870
  return res;
430
}
431
432
282660
static lbm_value fundamental_mul(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
433
  (void) ctx;
434
435
282660
  lbm_uint prod = lbm_enc_char(1);
436
3087728
  for (lbm_uint i = 0; i < nargs; i ++) {
437
2805236
    prod = mul2(prod, args[i]);
438
2805236
    if (lbm_type_of(prod) == LBM_TYPE_SYMBOL) {
439
168
      break;
440
    }
441
  }
442
282660
  return prod;
443
}
444
445
1176
static lbm_value fundamental_div(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
446
  (void) ctx;
447
448
1176
  lbm_uint res = args[0];
449
450
1176
  if (nargs >= 2) {
451
1736
    for (lbm_uint i = 1; i < nargs; i ++) {
452
1176
      res = div2(res, args[i]);
453
1176
      if (lbm_type_of(res) == LBM_TYPE_SYMBOL) {
454
560
        break;
455
      }
456
    }
457
  } else {
458
56
    res = ENC_SYM_EERROR;
459
  }
460
1176
  return res;
461
}
462
463
840
static lbm_value fundamental_mod(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
464
  (void) ctx;
465
840
  if (nargs != 2) {
466
56
    lbm_set_error_reason((char*)lbm_error_str_num_args);
467
56
    return ENC_SYM_EERROR;
468
  }
469
784
  lbm_value res = args[0];
470
784
  lbm_value arg2 = args[1];
471
784
  res = mod2(res, arg2);
472
784
  return res;
473
}
474
475
75984
static lbm_value fundamental_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
476
  (void) ctx;
477
478
75984
  lbm_uint a = args[0];
479
75984
  bool r = true;
480
481
129484
  for (lbm_uint i = 1; i < nargs; i ++) {
482
76152
    lbm_uint b = args[i];
483

76152
    r = r && struct_eq(a, b);
484
76152
    if (!r) break;
485
  }
486
75984
  return r ? ENC_SYM_TRUE : ENC_SYM_NIL;
487
}
488
489
280
static lbm_value fundamental_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
490
280
  lbm_value r = fundamental_eq(args, nargs, ctx);
491
280
  return r ? ENC_SYM_NIL : ENC_SYM_TRUE; // Works because ENC_SYM_NIL == 0 and ENC_SYM_TRUE is != 0
492
}
493
494
495
23698820
static lbm_value fundamental_numeq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
496
  (void) ctx;
497
498
23698820
  lbm_uint a = args[0];
499
23698820
  lbm_value res = ENC_SYM_TERROR;
500
501
23698820
  if (IS_NUMBER(a)) {
502
23698764
    res = ENC_SYM_TRUE;
503
25958398
    for (lbm_uint i = 1; i < nargs; i ++) {
504
23699352
      lbm_uint b = args[i];
505
23699352
      if (!IS_NUMBER(b)) {
506
56
        res = ENC_SYM_TERROR;
507
56
        break;
508
      }
509
23699296
      if (!compare_num(a, b) == 0) {
510
21439662
        res = ENC_SYM_NIL;
511
21439662
        break;
512
      }
513
    }
514
  }
515
23698820
  return res;
516
}
517
518
560336
static lbm_value fundamental_num_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
519
560336
  lbm_value r = fundamental_numeq(args, nargs, ctx);
520
560336
  if (r == ENC_SYM_NIL) {
521
140
    r = ENC_SYM_TRUE;
522
560196
  } else if (r == ENC_SYM_TRUE) {
523
560140
    r = ENC_SYM_NIL;
524
  }
525
560336
  return r;
526
}
527
528
8784384
static lbm_value fundamental_leq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
529
  (void) ctx;
530
531
8784384
  lbm_uint a = args[0];
532
8784384
  lbm_uint b = ENC_SYM_NIL;
533
8784384
  bool r = true;
534
8784384
  bool ok = true;
535
536
8784384
  if (!IS_NUMBER(a)) {
537
56
    lbm_set_error_suspect(a);
538
56
    return ENC_SYM_TERROR;
539
  }
540
17568600
  for (lbm_uint i = 1; i < nargs; i ++) {
541
8784328
    b = args[i];
542
8784328
    if (!IS_NUMBER(b)) {
543
56
      ok = false;
544
56
      break;
545
    }
546

8784272
    r = r && (compare_num(a, b) <= 0);
547
  }
548
8784328
  if (ok) {
549
8784272
    if (r) {
550
5099752
      return ENC_SYM_TRUE;
551
    } else {
552
3684520
      return ENC_SYM_NIL;
553
    }
554
  }
555
56
  lbm_set_error_suspect(b);
556
56
  return ENC_SYM_TERROR;
557
}
558
559
952756
static lbm_value fundamental_geq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
560
  (void) ctx;
561
562
952756
  lbm_uint a = args[0];
563
952756
  lbm_uint b = ENC_SYM_NIL;
564
952756
  bool r = true;
565
952756
  bool ok = true;
566
567
952756
  if (!IS_NUMBER(a)) {
568
56
    lbm_set_error_suspect(a);
569
56
    return ENC_SYM_TERROR;
570
  }
571
1905344
  for (lbm_uint i = 1; i < nargs; i ++) {
572
952700
    b = args[i];
573
952700
    if (!IS_NUMBER(b)) {
574
56
      ok = false;
575
56
      break;
576
    }
577

952644
    r = r && (compare_num(a, b) >= 0);
578
  }
579
952700
  if (ok) {
580
952644
    if (r) {
581
9996
      return ENC_SYM_TRUE;
582
    } else {
583
942648
      return ENC_SYM_NIL;
584
    }
585
  }
586
56
  lbm_set_error_suspect(b);
587
56
  return ENC_SYM_TERROR;
588
}
589
590
952616
static lbm_value fundamental_lt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
591
952616
  lbm_value r = fundamental_geq(args, nargs, ctx);
592
952616
  if (r == ENC_SYM_NIL) r = ENC_SYM_TRUE;
593
9996
  else if (r == ENC_SYM_TRUE) r = ENC_SYM_NIL;
594
952616
  return r;
595
}
596
597
8782900
static lbm_value fundamental_gt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
598
8782900
  lbm_value r = fundamental_leq(args, nargs, ctx);
599
8782900
  if (r == ENC_SYM_NIL) r = ENC_SYM_TRUE;
600
5098576
  else if (r == ENC_SYM_TRUE) r = ENC_SYM_NIL;
601
8782900
  return r;
602
}
603
604
1960
static lbm_value fundamental_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
605
  (void) ctx;
606
1960
  lbm_value r = ENC_SYM_EERROR;
607
1960
  if (nargs == 1) {
608
1904
    r = args[0] ? ENC_SYM_NIL : ENC_SYM_TRUE;
609
  }
610
1960
  return r;
611
}
612
613
13160
static lbm_value fundamental_gc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
614
  (void) args;
615
  (void) nargs;
616
  (void) ctx;
617
13160
  lbm_perform_gc();
618
13160
  return ENC_SYM_TRUE;
619
}
620
621
3444
static lbm_value fundamental_self(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
622
  (void) args;
623
  (void) nargs;
624
  (void) ctx;
625
3444
  return lbm_enc_i(ctx->id);
626
}
627
628
224
static lbm_value fundamental_set_mailbox_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
629
224
  lbm_value r = ENC_SYM_EERROR;
630
224
  if (nargs == 1) {
631
168
    if (IS_NUMBER(args[0])) {
632
140
      uint32_t s = lbm_dec_as_u32(args[0]);
633
140
      if (lbm_mailbox_change_size(ctx, s)) {
634
112
        r = ENC_SYM_TRUE;
635
      } else {
636
28
        r = ENC_SYM_NIL;
637
      }
638
    } else {
639
28
      r = ENC_SYM_TERROR;
640
    }
641
  }
642
224
  return r;
643
}
644
645
2801762
static lbm_value fundamental_cons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
646
  (void) ctx;
647
2801762
  lbm_value r = ENC_SYM_EERROR;
648
2801762
  if (nargs == 2) {
649
2801678
    lbm_uint a = args[0];
650
2801678
    lbm_uint b = args[1];
651
2801678
    r = lbm_cons(a,b);
652
  }
653
2801762
  return r;
654
}
655
656
16016
static lbm_value fundamental_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
657
  (void) ctx;
658
16016
  lbm_value r = ENC_SYM_EERROR;
659
16016
  if (nargs == 1) {
660
15960
    if (lbm_is_cons(args[0])) {
661
15848
      lbm_cons_t *cell = lbm_ref_cell(args[0]);
662
15848
      r =  cell->car;
663
112
    } else if (lbm_is_symbol_nil(args[0])) {
664
28
      r = ENC_SYM_NIL;
665
    } else {
666
84
      r = ENC_SYM_TERROR;
667
    }
668
  }
669
16016
  return r;
670
}
671
672
21504
static lbm_value fundamental_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
673
  (void) ctx;
674
21504
  lbm_value r = ENC_SYM_EERROR;
675
21504
  if (nargs == 1) {
676
21448
    if (lbm_is_cons(args[0])) {
677
21336
      lbm_cons_t *cell = lbm_ref_cell(args[0]);
678
21336
      r = cell->cdr;
679
112
    } else if (lbm_is_symbol_nil(args[0])) {
680
28
      r = ENC_SYM_NIL;
681
    } else {
682
84
      r = ENC_SYM_TERROR;
683
    }
684
  }
685
21504
  return r;
686
}
687
688
78372
static lbm_value fundamental_list(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
689
  (void) ctx;
690
78372
  lbm_value result = ENC_SYM_NIL;
691
190138
  for (lbm_uint i = 1; i <= nargs; i ++) {
692
111822
    result = lbm_cons(args[nargs-i], result);
693
111822
    if (lbm_type_of(result) == LBM_TYPE_SYMBOL)
694
56
      break;
695
  }
696
78372
  return result;
697
}
698
699
47702
static lbm_value fundamental_append(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
700
  (void) ctx;
701
47702
  if (nargs == 0) return ENC_SYM_NIL;
702

47674
  if (nargs == 1 && !lbm_is_list(args[0])) {
703
28
      lbm_set_error_suspect(args[0]);
704
28
    return ENC_SYM_TERROR;
705
  }
706
47646
  lbm_value res = args[nargs-1];
707
107584
  for (int i = (int)nargs -2; i >= 0; i --) {
708
59966
    lbm_value curr = args[i];
709
59966
    if (!lbm_is_list(curr)) {
710
28
      lbm_set_error_suspect(curr);
711
28
      return ENC_SYM_TERROR;
712
    }
713
59938
    int n = 0;
714
132046
    while (lbm_type_of_functional(curr) == LBM_TYPE_CONS) {
715
72108
      n++;
716
72108
      curr = lbm_cdr(curr);
717
    }
718
59938
    curr = args[i];
719
132046
    for (int j = n-1; j >= 0; j --) {
720
72108
      res = lbm_cons(lbm_index_list(curr,j),res);
721
    }
722
  }
723
47618
  return(res);
724
}
725
726
1680224
static lbm_value fundamental_undefine(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
727
  (void) ctx;
728
1680224
  lbm_value *global_env = lbm_get_global_env();
729

1680224
  if (nargs == 1 && lbm_is_symbol(args[0])) {
730
1680168
    lbm_value key = args[0];
731
1680168
    lbm_uint ix_key = lbm_dec_sym(key) & GLOBAL_ENV_MASK;
732
1680168
    lbm_value env = global_env[ix_key];
733
1680168
    lbm_value res = lbm_env_drop_binding(env, key);
734
1680168
    if (res == ENC_SYM_NOT_FOUND) {
735
28
      return ENC_SYM_NIL;
736
    }
737
1680140
    global_env[ix_key] = res;
738
1680140
    return ENC_SYM_TRUE;
739

56
  } else if (nargs == 1 && lbm_is_cons(args[0])) {
740
56
    lbm_value curr = args[0];
741
168
    while (lbm_type_of(curr) == LBM_TYPE_CONS) {
742
112
      lbm_value key = lbm_car(curr);
743
112
      lbm_uint ix_key = lbm_dec_sym(key) & GLOBAL_ENV_MASK;
744
112
      lbm_value env = global_env[ix_key];
745
112
      lbm_value res = lbm_env_drop_binding(env, key);
746
112
      if (res != ENC_SYM_NOT_FOUND) {
747
56
        global_env[ix_key] = res;
748
      }
749
112
      curr = lbm_cdr(curr);
750
    }
751
56
    return ENC_SYM_TRUE;
752
  }
753
  return ENC_SYM_TERROR;
754
}
755
756
24130
static lbm_value fundamental_buf_create(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
757
  (void) ctx;
758
24130
  lbm_value result = ENC_SYM_EERROR;
759
24130
  array_create(args, nargs, &result);
760
24130
  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
    if (lbm_is_array_r(args[0])) {
794
56
      lbm_array_header_t *arr = (lbm_array_header_t *)lbm_car(args[0]);
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_type_of_functional(s) == LBM_TYPE_SYMBOL)
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
280
static lbm_value fundamental_set_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
849
  (void) ctx;
850
280
  lbm_value result = ENC_SYM_TERROR;
851

280
  if (nargs == 3 && IS_NUMBER(args[1])) {
852
280
    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
168
    } else if (lbm_is_lisp_array_rw(args[0])) {
875
168
      lbm_value index = lbm_dec_as_u32(args[1]);
876
168
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
877
168
      lbm_value *arrdata = (lbm_value*)header->data;
878
168
      lbm_uint size = header->size / sizeof(lbm_value);
879
168
      if (index < size) {
880
168
        arrdata[index] = args[2]; // value
881
168
        result = args[0];
882
      }  // index out of range will be eval error.
883
    }
884
  }
885
280
  return result;
886
}
887
888
448
static lbm_value fundamental_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
889
  (void) ctx;
890
448
  lbm_value result = ENC_SYM_EERROR;
891
448
  if (nargs == 2) {
892
420
    if (lbm_is_cons(args[0])) {
893
364
      lbm_value r = assoc_lookup(args[1], args[0]);
894

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

259816
    if (lbm_is_symbol(keyval) ||
916
129824
        lbm_is_symbol(new_alist) )
917
182
      result = ENC_SYM_MERROR;
918
    else
919
129810
      result = new_alist;
920
84
  } else if (nargs == 2) {
921
    result = lbm_cons(args[0], args[1]);
922
  }
923
130076
  return result;
924
}
925
926
112
static lbm_value fundamental_set_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
927
  (void) ctx;
928
112
  lbm_value result = ENC_SYM_EERROR;
929
112
  if (nargs == 3) {
930
84
    result = lbm_env_set_functional(args[0], args[1], args[2]);
931

28
  } else if (nargs == 2 && lbm_is_cons(args[1])) {
932
28
    lbm_value x = lbm_car(args[1]);
933
28
    lbm_value xs = lbm_cdr(args[1]);
934
28
    result = lbm_env_set(args[0], x, xs);
935
  }
936
112
  return result;
937
}
938
939
420
static lbm_value fundamental_cossa(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
940
  (void) ctx;
941
420
  lbm_value result = ENC_SYM_EERROR;
942
420
  if (nargs == 2) {
943
392
    if (lbm_is_cons(args[0])) {
944
336
      lbm_value r = cossa_lookup(args[1], args[0]);
945

336
      if (lbm_is_symbol(r) &&
946
          r == ENC_SYM_NO_MATCH) {
947
28
        result = ENC_SYM_NIL;
948
      } else {
949
308
        result = r;
950
      }
951
56
    } else if (lbm_is_symbol(args[0]) &&
952
56
               args[0] == ENC_SYM_NIL) {
953
28
      result = args[0]; /* nil */
954
    } /* else error */
955
  }
956
420
  return result;
957
}
958
959
22988
static lbm_value fundamental_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
960
  (void) ctx;
961
22988
  lbm_value result = ENC_SYM_EERROR;
962

22988
  if (nargs == 2 && IS_NUMBER(args[1])) {
963
22988
    if (lbm_is_list(args[0])) {
964
22820
      result = lbm_index_list(args[0], lbm_dec_as_i32(args[1]));
965
168
    } else if (lbm_is_lisp_array_r(args[0])) {
966
168
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
967
168
      lbm_value *arrdata = (lbm_value*)header->data;
968
168
      lbm_uint size = header->size / sizeof(lbm_value);
969
168
      lbm_uint index = lbm_dec_as_u32(args[1]);
970
168
      if (index < size) {
971
168
        result = arrdata[index];
972
      }  // index out of range will be eval error.
973
    }
974
  }
975
22988
  return result;
976
}
977
978
280
static lbm_value fundamental_to_i(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
979
  (void) ctx;
980
280
  lbm_value result = ENC_SYM_EERROR;
981
280
  if (nargs == 1) {
982
252
    result = lbm_enc_i((lbm_int)lbm_dec_as_i64(args[0]));
983
  }
984
280
  return result;
985
}
986
987
280
static lbm_value fundamental_to_i32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
988
  (void) ctx;
989
280
  lbm_value result = ENC_SYM_EERROR;
990
280
  if (nargs == 1) {
991
252
    result = lbm_enc_i32(lbm_dec_as_i32(args[0]));
992
  }
993
280
  return result;
994
}
995
996
280
static lbm_value fundamental_to_u(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
997
  (void) ctx;
998
280
  lbm_value result = ENC_SYM_EERROR;
999
280
  if (nargs == 1) {
1000
252
    result = lbm_enc_u((lbm_uint)lbm_dec_as_u64(args[0]));
1001
  }
1002
280
  return result;
1003
}
1004
1005
280
static lbm_value fundamental_to_u32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1006
  (void) ctx;
1007
280
  lbm_value result = ENC_SYM_EERROR;
1008
280
  if (nargs == 1) {
1009
252
    result = lbm_enc_u32(lbm_dec_as_u32(args[0]));
1010
  }
1011
280
  return result;
1012
}
1013
1014
252
static lbm_value fundamental_to_float(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1015
  (void) ctx;
1016
252
  lbm_value result = ENC_SYM_EERROR;
1017
252
  if (nargs == 1) {
1018
224
    result = lbm_enc_float(lbm_dec_as_float(args[0]));
1019
  }
1020
252
  return result;
1021
}
1022
1023
280
static lbm_value fundamental_to_i64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1024
  (void) ctx;
1025
280
  lbm_value result = ENC_SYM_EERROR;
1026
280
  if (nargs == 1) {
1027
252
    result = lbm_enc_i64(lbm_dec_as_i64(args[0]));
1028
  }
1029
280
  return result;
1030
}
1031
1032
280
static lbm_value fundamental_to_u64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1033
  (void) ctx;
1034
280
  lbm_value result = ENC_SYM_EERROR;
1035
280
  if (nargs == 1) {
1036
252
    result = lbm_enc_u64(lbm_dec_as_u64(args[0]));
1037
  }
1038
280
  return result;
1039
}
1040
1041
252
static lbm_value fundamental_to_double(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1042
  (void) ctx;
1043
252
  lbm_value result = ENC_SYM_EERROR;
1044
252
  if (nargs == 1) {
1045
224
    result = lbm_enc_double(lbm_dec_as_double(args[0]));
1046
  }
1047
252
  return result;
1048
}
1049
1050
252
static lbm_value fundamental_to_byte(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1051
  (void) ctx;
1052
252
  lbm_value result = ENC_SYM_EERROR;
1053
252
  if (nargs == 1) {
1054
224
    result = lbm_enc_char(lbm_dec_as_char(args[0]));
1055
  }
1056
252
  return result;
1057
}
1058
1059
336
static lbm_value fundamental_shl(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1060
  (void) ctx;
1061
336
  lbm_value retval = ENC_SYM_EERROR;
1062
336
  if (nargs == 2) {
1063
308
    retval = ENC_SYM_TERROR;
1064

308
    if (!(IS_NUMBER(args[0]) && IS_NUMBER(args[1]))) {
1065
56
      return retval;
1066
    }
1067

252
    switch (lbm_type_of_functional(args[0])) {
1068
56
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) << lbm_dec_as_u32(args[1])); break;
1069
28
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) << lbm_dec_as_u32(args[1])); break;
1070
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) << lbm_dec_as_u32(args[1])); break;
1071
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) << lbm_dec_as_u32(args[1])); break;
1072
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) << lbm_dec_as_u32(args[1])); break;
1073
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) << lbm_dec_as_u32(args[1])); break;
1074
    }
1075
28
  }
1076
280
  return retval;
1077
}
1078
1079
336
static lbm_value fundamental_shr(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
56
      return retval;
1086
    }
1087

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

308
    if (!(IS_NUMBER(args[0]) && IS_NUMBER(args[1]))) {
1105
56
      return retval;
1106
    }
1107

252
    switch (lbm_type_of_functional(args[0])) {
1108
#ifdef LBM64
1109
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) & lbm_dec_as_i64(args[1])); break;
1110
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) & lbm_dec_as_u64(args[1])); break;
1111
#else
1112
56
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) & lbm_dec_as_i32(args[1])); break;
1113
28
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) & lbm_dec_as_u32(args[1])); break;
1114
#endif
1115
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) & lbm_dec_as_u32(args[1])); break;
1116
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) & lbm_dec_as_i32(args[1])); break;
1117
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) & lbm_dec_as_i64(args[1])); break;
1118
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) & lbm_dec_as_u64(args[1])); break;
1119
    }
1120
28
  }
1121
280
  return retval;
1122
}
1123
1124
336
static lbm_value fundamental_bitwise_or(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1125
  (void) ctx;
1126
336
  lbm_value retval = ENC_SYM_EERROR;
1127
336
  if (nargs == 2) {
1128
308
    retval = ENC_SYM_TERROR;
1129

308
    if (!(IS_NUMBER(args[0]) && IS_NUMBER(args[1]))) {
1130
56
      return retval;
1131
    }
1132

252
    switch (lbm_type_of_functional(args[0])) {
1133
#ifdef LBM64
1134
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) | lbm_dec_as_i64(args[1])); break;
1135
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) | lbm_dec_as_u64(args[1])); break;
1136
#else
1137
56
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) | lbm_dec_as_i32(args[1])); break;
1138
28
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) | lbm_dec_as_u32(args[1])); break;
1139
#endif
1140
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) | lbm_dec_as_u32(args[1])); break;
1141
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) | lbm_dec_as_i32(args[1])); break;
1142
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) | lbm_dec_as_i64(args[1])); break;
1143
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) | lbm_dec_as_u64(args[1])); break;
1144
    }
1145
28
  }
1146
280
  return retval;
1147
}
1148
1149
336
static lbm_value fundamental_bitwise_xor(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1150
  (void) ctx;
1151
336
  lbm_value retval = ENC_SYM_EERROR;
1152
336
  if (nargs == 2) {
1153
308
    retval = ENC_SYM_TERROR;
1154

308
    if (!(IS_NUMBER(args[0]) && IS_NUMBER(args[1]))) {
1155
56
      return retval;
1156
    }
1157

252
    switch (lbm_type_of_functional(args[0])) {
1158
#ifdef LBM64
1159
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) ^ lbm_dec_as_i64(args[1])); break;
1160
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) ^ lbm_dec_as_u64(args[1])); break;
1161
#else
1162
56
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) ^ lbm_dec_as_i32(args[1])); break;
1163
28
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) ^ lbm_dec_as_u32(args[1])); break;
1164
#endif
1165
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) ^ lbm_dec_as_u32(args[1])); break;
1166
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) ^ lbm_dec_as_i32(args[1])); break;
1167
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) ^ lbm_dec_as_i64(args[1])); break;
1168
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) ^ lbm_dec_as_u64(args[1])); break;
1169
    }
1170
28
  }
1171
280
  return retval;
1172
}
1173
1174
280
static lbm_value fundamental_bitwise_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1175
  (void) ctx;
1176
280
  lbm_value retval = ENC_SYM_EERROR;
1177
280
  if (nargs == 1) {
1178
252
    retval = ENC_SYM_TERROR;
1179
252
    if (!(IS_NUMBER(args[0]))) {
1180
28
      return retval;
1181
    }
1182

224
    switch (lbm_type_of_functional(args[0])) {
1183
28
    case LBM_TYPE_I: retval = lbm_enc_i(~lbm_dec_i(args[0])); break;
1184
28
    case LBM_TYPE_U: retval = lbm_enc_u(~lbm_dec_u(args[0])); break;
1185
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(~lbm_dec_u32(args[0])); break;
1186
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(~lbm_dec_i32(args[0])); break;
1187
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(~lbm_dec_i64(args[0])); break;
1188
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(~lbm_dec_u64(args[0])); break;
1189
    }
1190
28
  }
1191
252
  return retval;
1192
}
1193
1194
28
static lbm_value fundamental_custom_destruct(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1195
  (void) ctx;
1196
28
  lbm_value result = ENC_SYM_EERROR;
1197

28
  if (nargs == 1 && (lbm_type_of(args[0]) == LBM_TYPE_CUSTOM)) {
1198
28
    lbm_uint *mem_ptr = (lbm_uint*)lbm_dec_custom(args[0]);
1199
28
    if(!mem_ptr) return ENC_SYM_FATAL_ERROR;
1200
28
    lbm_custom_type_destroy(mem_ptr);
1201
28
    lbm_value tmp = lbm_set_ptr_type(args[0], LBM_TYPE_CONS);
1202
28
    lbm_set_car(tmp, ENC_SYM_NIL);
1203
28
    lbm_set_cdr(tmp, ENC_SYM_NIL);
1204
      /* The original value will still be of type custom_ptr */
1205
28
    result = ENC_SYM_TRUE;
1206
  }
1207
28
  return result;
1208
}
1209
1210
14448
static lbm_value fundamental_type_of(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1211
  (void) ctx;
1212
14448
  lbm_value res = ENC_SYM_EERROR;
1213
14448
  if (nargs == 1) {
1214
14448
    lbm_value val = args[0];
1215
14448
    lbm_type t = lbm_type_of(val);
1216
1217
14448
    if (lbm_is_ptr(val)) {
1218
      // Ignore constant or not constant.
1219
11144
      t &= LBM_PTR_TO_CONSTANT_MASK;
1220
    }
1221




14448
    switch(t) {
1222
5236
    case LBM_TYPE_CONS: res = ENC_SYM_TYPE_LIST; break;
1223
112
    case LBM_TYPE_ARRAY: res = ENC_SYM_TYPE_ARRAY; break;
1224
644
    case LBM_TYPE_I32: res = ENC_SYM_TYPE_I32; break;
1225
812
    case LBM_TYPE_U32: res = ENC_SYM_TYPE_U32; break;
1226
1792
    case LBM_TYPE_FLOAT: res = ENC_SYM_TYPE_FLOAT; break;
1227
672
    case LBM_TYPE_I64: res = ENC_SYM_TYPE_I64; break;
1228
784
    case LBM_TYPE_U64: res = ENC_SYM_TYPE_U64; break;
1229
1064
    case LBM_TYPE_DOUBLE: res = ENC_SYM_TYPE_DOUBLE; break;
1230
1148
    case LBM_TYPE_I: res = ENC_SYM_TYPE_I; break;
1231
840
    case LBM_TYPE_U: res = ENC_SYM_TYPE_U; break;
1232
56
    case LBM_TYPE_CHAR: res = ENC_SYM_TYPE_CHAR; break;
1233
1260
    case LBM_TYPE_SYMBOL: res = ENC_SYM_TYPE_SYMBOL; break;
1234
28
    case LBM_TYPE_LISPARRAY: res = ENC_SYM_TYPE_LISPARRAY; break;
1235
    case LBM_TYPE_DEFRAG_MEM: res = ENC_SYM_TYPE_DEFRAG_MEM; break;
1236
    case LBM_TYPE_CUSTOM: res = ENC_SYM_TYPE_CUSTOM; break;
1237
    }
1238
  }
1239
14448
  return res;
1240
}
1241
1242
812
static lbm_value fundamental_list_length(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1243
  (void) ctx;
1244
812
  lbm_value result = ENC_SYM_EERROR;
1245
812
  if (nargs == 1) {
1246
784
    result = ENC_SYM_TERROR;
1247
784
    if (lbm_is_list(args[0])) {
1248
672
      int32_t len = (int32_t)lbm_list_length(args[0]);
1249
672
      result = lbm_enc_i(len);
1250
112
    } else if (lbm_is_array_r(args[0])) {
1251
28
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
1252
28
      result = lbm_enc_i((int)(header->size));
1253
84
    } else if (lbm_is_lisp_array_r(args[0])) {
1254
56
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
1255
56
      result = lbm_enc_i((int)(header->size / (sizeof(lbm_uint))));
1256
    }
1257
  }
1258
812
  return result;
1259
}
1260
1261
6092116
static lbm_value fundamental_range(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1262
  (void) ctx;
1263
6092116
  lbm_value result = ENC_SYM_EERROR;
1264
1265
  int32_t start;
1266
  int32_t end;
1267
6092116
  bool rev = false;
1268
1269

6092116
  if (nargs == 1 && IS_NUMBER(args[0])) {
1270
5801910
    start = 0;
1271
5801910
    end = lbm_dec_as_i32(args[0]);
1272

580356
  } else if (nargs == 2 &&
1273
580272
             IS_NUMBER(args[0]) &&
1274
290122
             IS_NUMBER(args[1])) {
1275
290094
    start = lbm_dec_as_i32(args[0]);
1276
290094
    end = lbm_dec_as_i32(args[1]);
1277
  } else {
1278
112
    return result;
1279
  }
1280
1281
6092004
  if (end == start) return ENC_SYM_NIL;
1282
6091976
  else if (end < start) {
1283
56
    int32_t tmp = end;
1284
56
    end = start;
1285
56
    start = tmp;
1286
56
    rev = true;
1287
  }
1288
1289
6091976
  int num = end - start;
1290
1291
6091976
  if ((unsigned int)num > lbm_heap_num_free()) {
1292
197471
    return ENC_SYM_MERROR;
1293
  }
1294
1295
5894505
  lbm_value r_list = ENC_SYM_NIL;
1296
304687731
  for (int i = end - 1; i >= start; i --) {
1297
298793226
    r_list = lbm_cons(lbm_enc_i(i), r_list);
1298
  }
1299
5894505
  return rev ? lbm_list_destructive_reverse(r_list) : r_list;
1300
}
1301
1302
280
static lbm_value fundamental_reg_event_handler(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1303
  (void) ctx;
1304
280
  lbm_value res = ENC_SYM_TERROR;
1305

280
  if (nargs == 1 && IS_NUMBER(args[0])) {
1306
224
    lbm_set_event_handler_pid((lbm_cid)lbm_dec_i(args[0]));
1307
224
    res = ENC_SYM_TRUE;
1308
  }
1309
280
  return res;
1310
}
1311
1312
34532
static lbm_value fundamental_take(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1313
  (void) ctx;
1314
34532
  lbm_value res = ENC_SYM_TERROR;
1315

34532
  if (nargs == 2 && IS_NUMBER(args[1]) && lbm_is_list(args[0])) {
1316
34448
    int len = lbm_dec_as_i32(args[1]);
1317
34448
    res = lbm_list_copy(&len, args[0]);
1318
  }
1319
34532
  return res;
1320
}
1321
1322
168
static lbm_value fundamental_drop(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1323
  (void) ctx;
1324
168
  lbm_value res = ENC_SYM_TERROR;
1325

168
  if (nargs == 2 && IS_NUMBER(args[1]) && lbm_is_list(args[0])) {
1326
84
    res = lbm_list_drop(lbm_dec_as_u32(args[1]), args[0]);
1327
  }
1328
168
  return res;
1329
}
1330
/* (mkarray size) */
1331
112
static lbm_value fundamental_mkarray(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1332
  (void) ctx;
1333
112
  lbm_value res = ENC_SYM_TERROR;
1334

112
  if (nargs == 1 && IS_NUMBER(args[0])) {
1335
112
    lbm_heap_allocate_lisp_array(&res, lbm_dec_as_u32(args[0]));
1336
  }
1337
112
  return res;
1338
}
1339
1340
28
static lbm_value fundamental_array_to_list(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1341
  (void) ctx;
1342
28
  lbm_value res = ENC_SYM_TERROR;
1343

28
  if (nargs == 1 && lbm_is_lisp_array_r(args[0])) {
1344
28
    lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(args[0]);
1345
28
    lbm_value *arrdata = (lbm_value*)header->data;
1346
28
    lbm_uint size = (header->size / sizeof(lbm_uint));
1347
28
    res = lbm_heap_allocate_list(size);
1348
28
    if (lbm_is_symbol(res)) return res;
1349
28
    lbm_value curr = res;
1350
28
    lbm_uint ix = 0;
1351
308
    while (lbm_is_cons(curr)) {
1352
280
      lbm_set_car(curr, arrdata[ix]);
1353
280
      ix ++;
1354
280
      curr = lbm_cdr(curr);
1355
    }
1356
  }
1357
28
  return res;
1358
}
1359
1360
476
static lbm_value fundamental_list_to_array(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1361
  (void) ctx;
1362
476
  lbm_value res = ENC_SYM_TERROR;
1363

476
  if (nargs == 1 && lbm_is_list(args[0])) {
1364
420
    lbm_int len = (lbm_int)lbm_list_length(args[0]);
1365
420
    if ( len > 0 ) {
1366
392
      lbm_heap_allocate_lisp_array(&res, (lbm_uint)len);
1367
392
      if (lbm_is_symbol(res)) return res;
1368
392
      lbm_value curr = args[0];
1369
392
      int ix = 0;
1370
392
      lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(res);
1371
392
      lbm_value *arrdata = (lbm_value*)header->data;
1372
1736
      while (lbm_is_cons(curr)) {
1373
1344
        arrdata[ix] = lbm_car(curr);
1374
1344
        ix ++;
1375
1344
        curr = lbm_cdr(curr);
1376
      }
1377
    } else {
1378
28
      res = ENC_SYM_NIL; // could be a unique array-empty symbol
1379
    }
1380
  }
1381
476
  return res;
1382
}
1383
1384
140
static lbm_value fundamental_dm_create(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1385
  (void) ctx;
1386
140
  lbm_value res = ENC_SYM_TERROR;
1387

140
  if (argn == 1 && lbm_is_number(args[0])) {
1388
140
    lbm_uint n = lbm_dec_as_uint(args[0]);
1389
140
    res = lbm_defrag_mem_create(n);
1390
  }
1391
140
  return res;
1392
}
1393
1394
2184
static lbm_value fundamental_dm_alloc(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1395
  (void) ctx;
1396
2184
  lbm_value res = ENC_SYM_TERROR;
1397

2184
  if (argn == 2 && lbm_is_number(args[1])) {
1398
2184
    if (lbm_type_of(args[0]) == LBM_TYPE_DEFRAG_MEM) {
1399
2184
      lbm_uint *dm = (lbm_uint*)lbm_car(args[0]);
1400
2184
      res = lbm_defrag_mem_alloc(dm, lbm_dec_as_uint(args[1]));
1401
    }
1402
  }
1403
2184
  return res;
1404
}
1405
1406
140
static lbm_value fundamental_is_list(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1407
  (void) ctx;
1408
140
  lbm_value res = ENC_SYM_TERROR;
1409
140
  if (argn == 1) {
1410
140
    res = lbm_is_list_rw(args[0]) ? ENC_SYM_TRUE : ENC_SYM_NIL;
1411
  }
1412
140
  return res;
1413
}
1414
1415
308
static lbm_value fundamental_is_number(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1416
  (void) ctx;
1417
308
  lbm_value res = ENC_SYM_TERROR;
1418
308
  if (argn == 1) {
1419
308
    res = lbm_is_number(args[0]) ? ENC_SYM_TRUE : ENC_SYM_NIL;
1420
  }
1421
308
  return res;
1422
}
1423
1424
static lbm_value fundamental_int_div(lbm_value *args, lbm_uint argn, eval_context_t *ctx) {
1425
  lbm_value res = fundamental_div(args, argn, ctx);
1426
  switch (lbm_type_of(res)) {
1427
    case LBM_TYPE_FLOAT: {
1428
      res = lbm_enc_i((lbm_int)lbm_dec_float(res));
1429
      break;
1430
    }
1431
    case LBM_TYPE_DOUBLE: {
1432
      res = lbm_enc_i((lbm_int)lbm_dec_double(res));
1433
      break;
1434
    }
1435
  }
1436
1437
  return res;
1438
}
1439
1440
const fundamental_fun fundamental_table[] =
1441
  {fundamental_add,
1442
   fundamental_sub,
1443
   fundamental_mul,
1444
   fundamental_div,
1445
   fundamental_mod,
1446
   fundamental_eq,
1447
   fundamental_not_eq,
1448
   fundamental_numeq,
1449
   fundamental_num_not_eq,
1450
   fundamental_lt,
1451
   fundamental_gt,
1452
   fundamental_leq,
1453
   fundamental_geq,
1454
   fundamental_not,
1455
   fundamental_gc,
1456
   fundamental_self,
1457
   fundamental_set_mailbox_size,
1458
   fundamental_cons,
1459
   fundamental_car,
1460
   fundamental_cdr,
1461
   fundamental_list,
1462
   fundamental_append,
1463
   fundamental_undefine,
1464
   fundamental_buf_create,
1465
   fundamental_symbol_to_string,
1466
   fundamental_string_to_symbol,
1467
   fundamental_symbol_to_uint,
1468
   fundamental_uint_to_symbol,
1469
   fundamental_set_car,
1470
   fundamental_set_cdr,
1471
   fundamental_set_ix,
1472
   fundamental_assoc,
1473
   fundamental_acons,
1474
   fundamental_set_assoc,
1475
   fundamental_cossa,
1476
   fundamental_ix,
1477
   fundamental_to_i,
1478
   fundamental_to_i32,
1479
   fundamental_to_u,
1480
   fundamental_to_u32,
1481
   fundamental_to_float,
1482
   fundamental_to_i64,
1483
   fundamental_to_u64,
1484
   fundamental_to_double,
1485
   fundamental_to_byte,
1486
   fundamental_shl,
1487
   fundamental_shr,
1488
   fundamental_bitwise_and,
1489
   fundamental_bitwise_or,
1490
   fundamental_bitwise_xor,
1491
   fundamental_bitwise_not,
1492
   fundamental_custom_destruct,
1493
   fundamental_type_of,
1494
   fundamental_list_length,
1495
   fundamental_range,
1496
   fundamental_reg_event_handler,
1497
   fundamental_take,
1498
   fundamental_drop,
1499
   fundamental_mkarray,
1500
   fundamental_array_to_list,
1501
   fundamental_list_to_array,
1502
   fundamental_dm_create,
1503
   fundamental_dm_alloc,
1504
   fundamental_is_list,
1505
   fundamental_is_number,
1506
   fundamental_int_div,
1507
  };