GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/symrepr.c Lines: 126 159 79.2 %
Date: 2024-12-05 14:36:58 Branches: 44 73 60.3 %

Line Branch Exec Source
1
/*
2
    Copyright 2018, 2021, 2022, 2024 Joel Svensson  svenssonjoel@yahoo.se
3
4
    This program is free software: you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation, either version 3 of the License, or
7
    (at your option) any later version.
8
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13
14
    You should have received a copy of the GNU General Public License
15
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
#include <stdint.h>
19
#include <stdio.h>
20
#include <string.h>
21
#include <stdlib.h>
22
#include <inttypes.h>
23
24
25
#include <lbm_memory.h>
26
#include <heap.h>
27
#include "symrepr.h"
28
#include "extensions.h"
29
#include "lbm_utils.h"
30
31
#define NUM_SPECIAL_SYMBOLS (sizeof(special_symbols) / sizeof(special_sym))
32
#define NAME   0
33
#define ID     1
34
#define NEXT   2
35
36
typedef struct {
37
  const char *name;
38
  const lbm_uint id;
39
} special_sym;
40
41
special_sym const special_symbols[] =  {
42
  {"nil"        , SYM_NIL},
43
  {"quote"      , SYM_QUOTE},
44
  {"t"          , SYM_TRUE},
45
  {"if"         , SYM_IF},
46
  {"cond"       , SYM_COND},
47
  {"lambda"     , SYM_LAMBDA},
48
  {"closure"    , SYM_CLOSURE},
49
  {"let"        , SYM_LET},
50
  {"define"     , SYM_DEFINE},
51
  {"progn"      , SYM_PROGN},
52
  {"read"       , SYM_READ},
53
  {"read-program" , SYM_READ_PROGRAM},
54
  {"read-eval-program", SYM_READ_AND_EVAL_PROGRAM},
55
  {"match"        , SYM_MATCH},
56
  {"_"            , SYM_DONTCARE},
57
  {"send"         , SYM_SEND},
58
  {"recv"         , SYM_RECEIVE},
59
  {"recv-to"      , SYM_RECEIVE_TIMEOUT},
60
  {"macro"        , SYM_MACRO},
61
  {"call-cc"      , SYM_CALLCC},
62
  {"continuation" , SYM_CONT},
63
  {"var"          , SYM_PROGN_VAR},
64
  {"timeout"      , SYM_TIMEOUT},
65
66
  {"set"          , SYM_SETVAR},
67
  {"setq"         , SYM_SETQ},
68
  {"move-to-flash", SYM_MOVE_TO_FLASH},
69
  {"exit-ok"      , SYM_EXIT_OK},
70
  {"exit-error"   , SYM_EXIT_ERROR},
71
  {"map"          , SYM_MAP},
72
  {"reverse"      , SYM_REVERSE},
73
  {"flatten"      , SYM_FLATTEN},
74
  {"unflatten"    , SYM_UNFLATTEN},
75
  {"kill"         , SYM_KILL},
76
  {"sleep"        , SYM_SLEEP},
77
  {"merge"        , SYM_MERGE},
78
  {"sort"         , SYM_SORT},
79
  {"gc"           , SYM_PERFORM_GC},
80
  {"loop"         , SYM_LOOP},
81
  {"trap"         , SYM_TRAP},
82
  {"rest-args"    , SYM_REST_ARGS},
83
  {"rotate"       , SYM_ROTATE},
84
85
  // pattern matching
86
  {"?"          , SYM_MATCH_ANY},
87
88
  // Error symbols with parsable names
89
  {"no_match"           , SYM_NO_MATCH},
90
  {"read_error"         , SYM_RERROR},
91
  {"type_error"         , SYM_TERROR},
92
  {"eval_error"         , SYM_EERROR},
93
  {"out_of_memory"      , SYM_MERROR},
94
  {"fatal_error"        , SYM_FATAL_ERROR},
95
  {"out_of_stack"       , SYM_STACK_ERROR},
96
  {"division_by_zero"   , SYM_DIVZERO},
97
  {"variable_not_bound" , SYM_NOT_FOUND},
98
  {"flash_full"         , SYM_ERROR_FLASH_HEAP_FULL},
99
100
  // Special symbols with unparsable names
101
  {"$barray"         , SYM_ARRAY_TYPE},
102
  {"$raw_i"          , SYM_RAW_I_TYPE},
103
  {"$raw_u"          , SYM_RAW_U_TYPE},
104
  {"$raw_f"          , SYM_RAW_F_TYPE},
105
  {"$ind_i"          , SYM_IND_I_TYPE},
106
  {"$ind_u"          , SYM_IND_U_TYPE},
107
  {"$ind_f"          , SYM_IND_F_TYPE},
108
  {"$channel"        , SYM_CHANNEL_TYPE},
109
  {"$recovered"      , SYM_RECOVERED},
110
  {"$placeholder"    , SYM_PLACEHOLDER},
111
  {"$custom"         , SYM_CUSTOM_TYPE},
112
  {"$array"          , SYM_LISPARRAY_TYPE},
113
  {"$nonsense"       , SYM_NONSENSE},
114
  {"$dm-array"       , SYM_DEFRAG_ARRAY_TYPE},
115
  {"$dm"             , SYM_DEFRAG_MEM_TYPE},
116
117
  // tokenizer symbols with unparsable names
118
  {"[openpar]"        , SYM_OPENPAR},
119
  {"[closepar]"       , SYM_CLOSEPAR},
120
  {"[backquote]"      , SYM_BACKQUOTE},
121
  {"[comma]"          , SYM_COMMA},
122
  {"[commaat]"        , SYM_COMMAAT},
123
  {"[dot]"            , SYM_DOT},
124
  {"[done]"           , SYM_TOKENIZER_DONE},
125
  {"[quote_it]"       , SYM_QUOTE_IT},
126
  {"[colon]"          , SYM_COLON},
127
  {"[wait]"           , SYM_TOKENIZER_WAIT},
128
  {"[openbrack]"      , SYM_OPENBRACK},
129
  {"[closebrack]"     , SYM_CLOSEBRACK},
130
  {"[rerror]"         , SYM_TOKENIZER_RERROR},
131
  {"[appcont]"        , SYM_APP_CONT},
132
133
  // special symbols with parseable names
134
  {"type-list"        , SYM_TYPE_LIST},
135
  {"type-i"           , SYM_TYPE_I},
136
  {"type-u"           , SYM_TYPE_U},
137
  {"type-float"       , SYM_TYPE_FLOAT},
138
  {"type-i32"         , SYM_TYPE_I32},
139
  {"type-u32"         , SYM_TYPE_U32},
140
  {"type-double"      , SYM_TYPE_DOUBLE},
141
  {"type-i64"         , SYM_TYPE_I64},
142
  {"type-u64"         , SYM_TYPE_U64},
143
  {"type-array"       , SYM_TYPE_ARRAY},
144
  {"type-symbol"      , SYM_TYPE_SYMBOL},
145
  {"type-char"        , SYM_TYPE_CHAR},
146
  {"type-byte"        , SYM_TYPE_BYTE},
147
  {"type-channel"     , SYM_TYPE_CHANNEL},
148
  {"type-lisparray"   , SYM_TYPE_LISPARRAY},
149
  {"type-dm"          , SYM_TYPE_DEFRAG_MEM},
150
  {"type-custom"      , SYM_TYPE_CUSTOM},
151
152
  // Fundamental operations
153
  {"+"                , SYM_ADD},
154
  {"-"                , SYM_SUB},
155
  {"*"                , SYM_MUL},
156
  {"/"                , SYM_DIV},
157
  {"//"               , SYM_INT_DIV},
158
  {"mod"              , SYM_MOD},
159
  {"="                , SYM_NUMEQ},
160
  {"!="               , SYM_NUM_NOT_EQ},
161
  {"<"                , SYM_LT},
162
  {">"                , SYM_GT},
163
  {"<="               , SYM_LEQ},
164
  {">="               , SYM_GEQ},
165
  {"eval"             , SYM_EVAL},
166
  {"eval-program"     , SYM_EVAL_PROGRAM},
167
  {"and"              , SYM_AND},
168
  {"or"               , SYM_OR},
169
  {"not"              , SYM_NOT},
170
  {"yield"            , SYM_YIELD},
171
  {"wait"             , SYM_WAIT},
172
  {"spawn"            , SYM_SPAWN},
173
  {"atomic"           , SYM_ATOMIC},
174
  {"self"             , SYM_SELF},
175
  {"spawn-trap"       , SYM_SPAWN_TRAP},
176
  {"set-mailbox-size" , SYM_SET_MAILBOX_SIZE},
177
  {"eq"               , SYM_EQ},
178
  {"not-eq"           , SYM_NOT_EQ},
179
  {"car"              , SYM_CAR},
180
  {"cdr"              , SYM_CDR},
181
  {"cons"             , SYM_CONS},
182
  {"list"             , SYM_LIST},
183
  {"append"           , SYM_APPEND},
184
  {"undefine"         , SYM_UNDEFINE},
185
  {"bufcreate"        , SYM_BYTEARRAY_CREATE},
186
  {"type-of"          , SYM_TYPE_OF},
187
  {"sym2str"          , SYM_SYMBOL_TO_STRING},
188
  {"str2sym"          , SYM_STRING_TO_SYMBOL},
189
  {"sym2u"            , SYM_SYMBOL_TO_UINT},
190
  {"u2sym"            , SYM_UINT_TO_SYMBOL},
191
  {"setcar"           , SYM_SET_CAR},
192
  {"setcdr"           , SYM_SET_CDR},
193
  {"setix"            , SYM_SET_IX},
194
  {"length"           , SYM_LIST_LENGTH},
195
  {"range"            , SYM_RANGE},
196
197
  {"assoc"          , SYM_ASSOC}, // lookup an association
198
  {"cossa"          , SYM_COSSA}, // lookup an association "backwards"
199
  {"acons"          , SYM_ACONS}, // Add to alist
200
  {"setassoc"       , SYM_SET_ASSOC}, // Change association
201
202
  {"shl"            , SYM_SHL},
203
  {"shr"            , SYM_SHR},
204
  {"bitwise-and"    , SYM_BITWISE_AND},
205
  {"bitwise-or"     , SYM_BITWISE_OR},
206
  {"bitwise-xor"    , SYM_BITWISE_XOR},
207
  {"bitwise-not"    , SYM_BITWISE_NOT},
208
209
  {"custom-destruct", SYM_CUSTOM_DESTRUCT},
210
211
  {"to-i"           , SYM_TO_I},
212
  {"to-i32"         , SYM_TO_I32},
213
  {"to-u"           , SYM_TO_U},
214
  {"to-u32"         , SYM_TO_U32},
215
  {"to-float"       , SYM_TO_FLOAT},
216
  {"to-i64"         , SYM_TO_I64},
217
  {"to-u64"         , SYM_TO_U64},
218
  {"to-double"      , SYM_TO_DOUBLE},
219
  {"to-byte"        , SYM_TO_BYTE},
220
221
  {"event-register-handler", SYM_REG_EVENT_HANDLER},
222
  {"take"           , SYM_TAKE},
223
  {"drop"           , SYM_DROP},
224
  {"mkarray"        , SYM_MKARRAY},
225
  {"array-to-list"  , SYM_ARRAY_TO_LIST},
226
  {"list-to-array"  , SYM_LIST_TO_ARRAY},
227
228
  {"dm-create"      , SYM_DM_CREATE},
229
  {"dm-alloc"       , SYM_DM_ALLOC},
230
231
  {"list?"          , SYM_IS_LIST},
232
  {"number?"        , SYM_IS_NUMBER},
233
234
  // fast access in list
235
  {"ix"             , SYM_IX},
236
237
  // aliases
238
  {"first"          , SYM_CAR},
239
  {"rest"           , SYM_CDR},
240
  {"fn"             , SYM_LAMBDA},
241
  {"def"            , SYM_DEFINE},
242
  {"true"           , SYM_TRUE},
243
  {"false"          , SYM_NIL},
244
  {"setvar"         , SYM_SETVAR},
245
  {"type-f32"       , SYM_TYPE_FLOAT},
246
  {"type-f64"       , SYM_TYPE_DOUBLE},
247
  {"array-create"   , SYM_BYTEARRAY_CREATE},
248
};
249
250
static lbm_uint *symlist = NULL;
251
static lbm_uint next_symbol_id = RUNTIME_SYMBOLS_START;
252
static lbm_uint symbol_table_size_list = 0;
253
static lbm_uint symbol_table_size_list_flash = 0;
254
static lbm_uint symbol_table_size_strings = 0;
255
static lbm_uint symbol_table_size_strings_flash = 0;
256
257
lbm_value symbol_x = ENC_SYM_NIL;
258
lbm_value symbol_y = ENC_SYM_NIL;
259
260
21672
int lbm_symrepr_init(void) {
261
21672
  symlist = NULL;
262
21672
  next_symbol_id = RUNTIME_SYMBOLS_START;
263
21672
  symbol_table_size_list = 0;
264
21672
  symbol_table_size_list_flash = 0;
265
21672
  symbol_table_size_strings = 0;
266
21672
  symbol_table_size_strings_flash = 0;
267
268
21672
  lbm_uint x = 0;
269
21672
  lbm_uint y = 0;
270
21672
  lbm_add_symbol("x", &x);
271
21672
  lbm_add_symbol("y", &y);
272
21672
  symbol_x = lbm_enc_sym(x);
273
21672
  symbol_y = lbm_enc_sym(y);
274
21672
  return 1;
275
}
276
277
void lbm_symrepr_name_iterator(symrepr_name_iterator_fun f) {
278
279
  lbm_uint *curr = symlist;
280
  while (curr) {
281
    f((const char *)curr[NAME]);
282
    curr = (lbm_uint *)curr[NEXT];
283
  }
284
}
285
286
62368
const char *lookup_symrepr_name_memory(lbm_uint id) {
287
288
62368
  lbm_uint *curr = symlist;
289
795592
  while (curr) {
290
795592
    if (id == curr[ID]) {
291
62368
      return (const char *)curr[NAME];
292
    }
293
733224
    curr = (lbm_uint*)curr[NEXT];
294
  }
295
  return NULL;
296
}
297
298
// Lookup symbol name given a symbol id
299
175075
const char *lbm_get_name_by_symbol(lbm_uint id) {
300
175075
  lbm_uint sym_kind = SYMBOL_KIND(id);
301
175075
  switch (sym_kind) {
302
112699
  case SYMBOL_KIND_SPECIAL:  /* fall through */
303
  case SYMBOL_KIND_FUNDAMENTAL:
304
  case SYMBOL_KIND_APPFUN:
305
220349
    for (unsigned int i = 0; i < NUM_SPECIAL_SYMBOLS; i ++) {
306
220349
      if (id == special_symbols[i].id) {
307
112699
        return (special_symbols[i].name);
308
      }
309
    }
310
    return NULL;
311
    break;
312
8
  case SYMBOL_KIND_EXTENSION: {
313
8
    lbm_uint ext_id = id - EXTENSION_SYMBOLS_START;
314
8
    if (ext_id < lbm_get_max_extensions()) {
315
8
      return extension_table[ext_id].name;
316
    }
317
    return NULL;
318
  } break;
319
62368
  default:
320
62368
    return lookup_symrepr_name_memory(id);
321
  }
322
}
323
324
lbm_uint *lbm_get_symbol_list_entry_by_name(char *name) {
325
  lbm_uint *curr = symlist;
326
  while (curr) {
327
    char *str = (char*)curr[NAME];
328
    if (str_eq(name, str)) {
329
      return (lbm_uint *)curr;
330
    }
331
    curr = (lbm_uint*)curr[NEXT];
332
  }
333
  return NULL;
334
}
335
336
// Lookup symbol id given symbol name
337
3701268
int lbm_get_symbol_by_name(char *name, lbm_uint* id) {
338
339
  // loop through special symbols
340
639180672
  for (unsigned int i = 0; i < NUM_SPECIAL_SYMBOLS; i ++) {
341
635797684
    if (str_eq(name, (char *)special_symbols[i].name)) {
342
318280
      *id = special_symbols[i].id;
343
318280
      return 1;
344
    }
345
   }
346
347
  // loop through extensions
348
665608860
  for (unsigned int i = 0; i < lbm_get_max_extensions(); i ++) {
349

662269748
    if (extension_table[i].name && str_eq(name, extension_table[i].name)) {
350
43876
      *id = EXTENSION_SYMBOLS_START + i;
351
43876
      return 1;
352
    }
353
  }
354
355
3339112
  lbm_uint *curr = symlist;
356
42635756
  while (curr) {
357
39783466
    char *str = (char*)curr[NAME];
358
39783466
    if (str_eq(name, str)) {
359
486822
      *id = curr[ID];
360
486822
      return 1;
361
    }
362
39296644
    curr = (lbm_uint*)curr[NEXT];
363
  }
364
2852290
  return 0;
365
}
366
367
extern lbm_flash_status lbm_write_const_array_padded(uint8_t *data, lbm_uint n, lbm_uint *res);
368
369
370
70
static bool store_symbol_name_flash(char *name, lbm_uint *res) {
371
70
  size_t n = strlen(name) + 1;
372
70
  if (n == 1) return 0; // failure if empty symbol
373
374
  lbm_uint alloc_size;
375
70
  if (n % sizeof(lbm_uint) == 0) {
376
    alloc_size = n/(sizeof(lbm_uint));
377
  } else {
378
70
    alloc_size = (n/(sizeof(lbm_uint))) + 1;
379
  }
380
381
70
  lbm_uint symbol_addr = 0;
382
70
  lbm_flash_status s = lbm_write_const_array_padded((uint8_t*)name, n, &symbol_addr);
383

70
  if (s != LBM_FLASH_WRITE_OK || symbol_addr == 0) {
384
    return false;
385
  }
386
70
  symbol_table_size_strings_flash += alloc_size;
387
70
  *res = symbol_addr;
388
70
  return true;
389
}
390
391
// Symbol table
392
// non-const name copied into symbol-table-entry:
393
// Entry
394
//   |
395
//   [name-ptr | symbol-id | next-ptr | name n-bytes]
396
//       |                             /
397
//        ------------points here -----
398
//
399
// const name referenced by symbol-table-entry:
400
// Entry
401
//   |
402
//   [name-ptr | symbol-id | next-ptr]
403
//       |
404
//        [name n-bytes]
405
//
406
143150
static bool add_symbol_to_symtab(char* name, lbm_uint id) {
407
143150
  bool r = false;
408
143150
  size_t n = strlen(name) + 1;
409

143150
  if (n > 1 && n <= 257) {
410
143150
    size_t alloc_size = n + (3 * sizeof(lbm_uint));
411
143150
    char *storage = lbm_malloc(alloc_size);
412
143150
    if (storage) {
413
143150
      memcpy(storage + (3 * sizeof(lbm_uint)), name, n);
414
143150
      lbm_uint *m = (lbm_uint*)storage;
415
416
143150
      symbol_table_size_list += 3 * sizeof(lbm_uint); // Bytes
417
143150
      symbol_table_size_strings += n; // Bytes
418
143150
      m[NAME] = (lbm_uint)&m[3];
419
143150
      m[NEXT] = (lbm_uint) symlist;
420
143150
      symlist = m;
421
143150
      m[ID] =id;
422
143150
      r = true;
423
    }
424
  }
425
143150
  return r;
426
}
427
428
70
static bool add_symbol_to_symtab_flash(lbm_uint name, lbm_uint id) {
429
  lbm_uint entry[3];
430
70
  entry[NAME] = name;
431
70
  entry[NEXT] = (lbm_uint) symlist;
432
70
  entry[ID]   = id;
433
70
  lbm_uint entry_addr = 0;
434
70
  if (lbm_write_const_raw(entry,3, &entry_addr) == LBM_FLASH_WRITE_OK) {
435
70
    symlist = (lbm_uint*)entry_addr;
436
70
    symbol_table_size_list_flash += 3;
437
70
    return true;
438
  }
439
  return false;
440
}
441
442
143220
int lbm_add_symbol_base(char *name, lbm_uint *id, bool flash) {
443
  lbm_uint symbol_name_storage;
444
143220
  if (flash) {
445
70
    if (!store_symbol_name_flash(name, &symbol_name_storage)) return 0;
446
70
    if (!add_symbol_to_symtab_flash(symbol_name_storage, next_symbol_id)) return 0;
447
  } else {
448
143150
    if (!add_symbol_to_symtab(name, next_symbol_id)) {
449
      return 0;
450
    }
451
  }
452
143220
  *id = next_symbol_id ++;
453
143220
  return 1;
454
}
455
456
106894
int lbm_add_symbol(char *name, lbm_uint* id) {
457
  lbm_uint sym_id;
458
106894
  if (!lbm_get_symbol_by_name(name, &sym_id)) {
459
43372
    return lbm_add_symbol_base(name, id, false);
460
  } else {
461
63522
    *id = sym_id;
462
63522
    return 1;
463
  }
464
  return 0;
465
}
466
467
int lbm_add_symbol_flash(char *name, lbm_uint* id) {
468
  lbm_uint sym_id;
469
  if (!lbm_get_symbol_by_name(name, &sym_id)) {
470
    return lbm_add_symbol_base(name, id, true);
471
  } else {
472
    *id = sym_id;
473
    return 1;
474
  }
475
  return 0;
476
}
477
478
411768
int lbm_add_symbol_const_base(char *name, lbm_uint* id) {
479
411768
  lbm_uint *m = lbm_memory_allocate(3);
480
411768
  if (m == NULL) return 0;
481
411768
  symbol_table_size_list += 3;
482
411768
  m[NAME] = (lbm_uint) name;
483
411768
  m[NEXT] = (lbm_uint) symlist;
484
411768
  symlist = m;
485
411768
  m[ID] = next_symbol_id;
486
411768
  *id = next_symbol_id ++;
487
411768
  return 1;
488
}
489
490
411768
int lbm_add_symbol_const(char *name, lbm_uint* id) {
491
  lbm_uint sym_id;
492
411768
  if (!lbm_get_symbol_by_name(name, &sym_id)) {
493
411768
    return lbm_add_symbol_const_base(name, id);
494
  } else {
495
    *id = sym_id;
496
    return 1;
497
  }
498
  return 0;
499
}
500
501
56
int lbm_str_to_symbol(char *name, lbm_uint *sym_id) {
502
56
  if (lbm_get_symbol_by_name(name, sym_id))
503
28
    return 1;
504
28
  else if (lbm_add_symbol(name, sym_id))
505
28
    return 1;
506
  return 0;
507
}
508
509
28
lbm_uint lbm_get_symbol_table_size(void) {
510
28
  return (symbol_table_size_list +symbol_table_size_strings);
511
}
512
513
28
lbm_uint lbm_get_symbol_table_size_flash(void) {
514
28
  return (symbol_table_size_list_flash +
515
28
          symbol_table_size_strings_flash) * sizeof(lbm_uint);
516
}
517
518
28
lbm_uint lbm_get_symbol_table_size_names(void) {
519
28
  return symbol_table_size_strings; // Bytes already
520
}
521
522
28
lbm_uint lbm_get_symbol_table_size_names_flash(void) {
523
28
  return symbol_table_size_strings_flash * sizeof(lbm_uint);
524
}
525
526
bool lbm_symbol_in_flash(char *str) {
527
  return !lbm_memory_ptr_inside((lbm_uint*)str);
528
}
529
530
bool lbm_symbol_list_entry_in_flash(char *str) {
531
  lbm_uint *entry = lbm_get_symbol_list_entry_by_name(str);
532
  return (entry == NULL || !lbm_memory_ptr_inside(entry));
533
}