GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/fundamental.c Lines: 833 861 96.7 %
Date: 2025-01-19 11:10:47 Branches: 571 641 89.1 %

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
21204244
static lbm_uint sub2(lbm_uint a, lbm_uint b) {
183
21204244
  lbm_uint retval = ENC_SYM_TERROR;
184

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


21204048
    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
20922922
    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
168
    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
21204048
  } else {
204
196
    lbm_set_error_suspect(IS_NUMBER(a) ? b : a);
205
  }
206
21204244
  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
10136
  bool res = false;
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
  if ((a_ && b_) && a_->size == b_->size) {
218
9968
    res = (memcmp((char*)a_->data, (char*)b_->data, a_->size) == 0);
219
  }
220
10136
  return res;
221
}
222
223
// a and b must be arrays!
224
196
static bool array_struct_equality(lbm_value a, lbm_value b) {
225
196
  lbm_array_header_t *a_ = (lbm_array_header_t*)lbm_car(a);
226
196
  lbm_array_header_t *b_ = (lbm_array_header_t*)lbm_car(b);
227
196
  bool res = false;
228

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



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

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


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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

252
    switch (lbm_type_of_functional(args[0])) {
1067
56
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) << lbm_dec_as_u32(args[1])); break;
1068
28
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) << lbm_dec_as_u32(args[1])); break;
1069
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) << lbm_dec_as_u32(args[1])); break;
1070
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) << lbm_dec_as_u32(args[1])); break;
1071
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) << lbm_dec_as_u32(args[1])); break;
1072
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) << lbm_dec_as_u32(args[1])); break;
1073
    }
1074
28
  }
1075
280
  return retval;
1076
}
1077
1078
336
static lbm_value fundamental_shr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1079
  (void) ctx;
1080
336
  lbm_value retval = ENC_SYM_EERROR;
1081
336
  if (nargs == 2) {
1082
308
    retval = ENC_SYM_TERROR;
1083

308
    if (!(IS_NUMBER(args[0]) && IS_NUMBER(args[1]))) {
1084
56
      return retval;
1085
    }
1086

252
    switch (lbm_type_of_functional(args[0])) {
1087
56
    case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) >> lbm_dec_as_u32(args[1])); break;
1088
28
    case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) >> lbm_dec_as_u32(args[1])); break;
1089
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) >> lbm_dec_as_u32(args[1])); break;
1090
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) >> lbm_dec_as_u32(args[1])); break;
1091
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) >> lbm_dec_as_u32(args[1])); break;
1092
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) >> lbm_dec_as_u32(args[1])); break;
1093
    }
1094
28
  }
1095
280
  return retval;
1096
}
1097
1098
336
static lbm_value fundamental_bitwise_and(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
56
      return retval;
1105
    }
1106

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

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

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

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

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

224
    switch (lbm_type_of_functional(args[0])) {
1182
28
    case LBM_TYPE_I: retval = lbm_enc_i(~lbm_dec_i(args[0])); break;
1183
28
    case LBM_TYPE_U: retval = lbm_enc_u(~lbm_dec_u(args[0])); break;
1184
28
    case LBM_TYPE_U32: retval = lbm_enc_u32(~lbm_dec_u32(args[0])); break;
1185
28
    case LBM_TYPE_I32: retval = lbm_enc_i32(~lbm_dec_i32(args[0])); break;
1186
28
    case LBM_TYPE_I64: retval = lbm_enc_i64(~lbm_dec_i64(args[0])); break;
1187
28
    case LBM_TYPE_U64: retval = lbm_enc_u64(~lbm_dec_u64(args[0])); break;
1188
    }
1189
28
  }
1190
252
  return retval;
1191
}
1192
1193
static lbm_value fundamental_custom_destruct(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1194
  (void) ctx;
1195
  lbm_value result = ENC_SYM_EERROR;
1196
  if (nargs == 1 && (lbm_type_of(args[0]) == LBM_TYPE_CUSTOM)) {
1197
    lbm_uint *mem_ptr = (lbm_uint*)lbm_dec_custom(args[0]);
1198
    if(!mem_ptr) return ENC_SYM_FATAL_ERROR;
1199
    lbm_custom_type_destroy(mem_ptr);
1200
    lbm_value tmp = lbm_set_ptr_type(args[0], LBM_TYPE_CONS);
1201
    lbm_set_car(tmp, ENC_SYM_NIL);
1202
    lbm_set_cdr(tmp, ENC_SYM_NIL);
1203
      /* The original value will still be of type custom_ptr */
1204
    result = ENC_SYM_TRUE;
1205
  }
1206
  return result;
1207
}
1208
1209
14448
static lbm_value fundamental_type_of(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) {
1210
  (void) ctx;
1211
14448
  lbm_value res = ENC_SYM_EERROR;
1212
14448
  if (nargs == 1) {
1213
14448
    lbm_value val = args[0];
1214
14448
    lbm_type t = lbm_type_of(val);
1215
1216
14448
    if (lbm_is_ptr(val)) {
1217
      // Ignore constant or not constant.
1218
11144
      t &= LBM_PTR_TO_CONSTANT_MASK;
1219
    }
1220




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

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

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

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

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

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

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

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

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

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

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