LCOV - code coverage report
Current view: top level - src/flisp - table.c (source / functions) Hit Total Coverage
Test: [build process] commit ef510b1f346f4c9f9d86eaceace5ca54961a1dbc Lines: 91 121 75.2 %
Date: 2022-07-17 01:01:28 Functions: 11 15 73.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 33 52 63.5 %

           Branch data     Line data    Source code
       1                 :            : #include <stdlib.h>
       2                 :            : #include <stdio.h>
       3                 :            : #include <stdarg.h>
       4                 :            : #include <string.h>
       5                 :            : #include <assert.h>
       6                 :            : #include <sys/types.h>
       7                 :            : #include "flisp.h"
       8                 :            : #include "equalhash.h"
       9                 :            : 
      10                 :            : #ifdef __cplusplus
      11                 :            : extern "C" {
      12                 :            : #endif
      13                 :            : 
      14                 :          0 : void print_htable(fl_context_t *fl_ctx, value_t v, ios_t *f)
      15                 :            : {
      16                 :          0 :     htable_t *h = (htable_t*)cv_data((cvalue_t*)ptr(v));
      17                 :            :     size_t i;
      18                 :          0 :     int first=1;
      19                 :          0 :     fl_print_str(fl_ctx, "#table(", f);
      20         [ #  # ]:          0 :     for(i=0; i < h->size; i+=2) {
      21         [ #  # ]:          0 :         if (h->table[i+1] != HT_NOTFOUND) {
      22         [ #  # ]:          0 :             if (!first) fl_print_str(fl_ctx, "  ", f);
      23                 :          0 :             fl_print_child(fl_ctx, f, (value_t)h->table[i]);
      24                 :          0 :             fl_print_chr(fl_ctx, ' ', f);
      25                 :          0 :             fl_print_child(fl_ctx, f, (value_t)h->table[i+1]);
      26                 :          0 :             first = 0;
      27                 :            :         }
      28                 :            :     }
      29                 :          0 :     fl_print_chr(fl_ctx, ')', f);
      30                 :          0 : }
      31                 :            : 
      32                 :          0 : void print_traverse_htable(fl_context_t *fl_ctx, value_t self)
      33                 :            : {
      34                 :          0 :     htable_t *h = (htable_t*)cv_data((cvalue_t*)ptr(self));
      35                 :            :     size_t i;
      36         [ #  # ]:          0 :     for(i=0; i < h->size; i+=2) {
      37         [ #  # ]:          0 :         if (h->table[i+1] != HT_NOTFOUND) {
      38                 :          0 :             print_traverse(fl_ctx, (value_t)h->table[i]);
      39                 :          0 :             print_traverse(fl_ctx, (value_t)h->table[i+1]);
      40                 :            :         }
      41                 :            :     }
      42                 :          0 : }
      43                 :            : 
      44                 :      39816 : void free_htable(fl_context_t *fl_ctx, value_t self)
      45                 :            : {
      46                 :            :     (void)fl_ctx;
      47                 :      39816 :     htable_t *h = (htable_t*)cv_data((cvalue_t*)ptr(self));
      48                 :      39816 :     htable_free(h);
      49                 :      39816 : }
      50                 :            : 
      51                 :     155446 : void relocate_htable(fl_context_t *fl_ctx, value_t oldv, value_t newv)
      52                 :            : {
      53                 :     155446 :     htable_t *oldh = (htable_t*)cv_data((cvalue_t*)ptr(oldv));
      54                 :     155446 :     htable_t *h = (htable_t*)cv_data((cvalue_t*)ptr(newv));
      55         [ +  + ]:     155446 :     if (oldh->table == &oldh->_space[0])
      56                 :      43212 :         h->table = &h->_space[0];
      57                 :            :     size_t i;
      58         [ +  + ]:  254730000 :     for(i=0; i < h->size; i++) {
      59         [ +  + ]:  254574000 :         if (h->table[i] != HT_NOTFOUND)
      60                 :   79423800 :             h->table[i] = (void*)relocate_lispvalue(fl_ctx, (value_t)h->table[i]);
      61                 :            :     }
      62                 :     155446 : }
      63                 :            : 
      64                 :   62149000 : static int ishashtable(fl_context_t *fl_ctx, value_t v)
      65                 :            : {
      66   [ +  -  +  - ]:   62149000 :     return iscvalue(v) && cv_class((cvalue_t*)ptr(v)) == fl_ctx->tabletype;
      67                 :            : }
      68                 :            : 
      69                 :          0 : value_t fl_tablep(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
      70                 :            : {
      71                 :          0 :     argcount(fl_ctx, "table?", nargs, 1);
      72         [ #  # ]:          0 :     return ishashtable(fl_ctx, args[0]) ? fl_ctx->T : fl_ctx->F;
      73                 :            : }
      74                 :            : 
      75                 :   62149000 : static htable_t *totable(fl_context_t *fl_ctx, value_t v, char *fname)
      76                 :            : {
      77         [ -  + ]:   62149000 :     if (!ishashtable(fl_ctx, v))
      78                 :          0 :         type_error(fl_ctx, fname, "table", v);
      79                 :   62149000 :     return (htable_t*)cv_data((cvalue_t*)ptr(v));
      80                 :            : }
      81                 :            : 
      82                 :    6553940 : value_t fl_table(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
      83                 :            : {
      84                 :    6553940 :     size_t cnt = (size_t)nargs;
      85         [ -  + ]:    6553940 :     if (cnt & 1)
      86                 :          0 :         lerror(fl_ctx, fl_ctx->ArgError, "table: arguments must come in pairs");
      87                 :            :     value_t nt;
      88                 :            :     // prevent small tables from being added to finalizer list
      89         [ +  + ]:    6553940 :     if (cnt <= HT_N_INLINE) {
      90                 :    6553180 :         fl_ctx->table_vtable.finalize = NULL;
      91                 :    6553180 :         nt = cvalue(fl_ctx, fl_ctx->tabletype, sizeof(htable_t));
      92                 :    6553180 :         fl_ctx->table_vtable.finalize = free_htable;
      93                 :            :     }
      94                 :            :     else {
      95                 :        750 :         nt = cvalue(fl_ctx, fl_ctx->tabletype, 2*sizeof(void*));
      96                 :            :     }
      97                 :    6553940 :     htable_t *h = (htable_t*)cv_data((cvalue_t*)ptr(nt));
      98                 :    6553940 :     htable_new(h, cnt/2);
      99                 :            :     uint32_t i;
     100                 :    6553940 :     value_t k=fl_ctx->NIL, arg=fl_ctx->NIL;
     101         [ +  + ]:    7086140 :     FOR_ARGS(i,0,arg,args) {
     102         [ +  + ]:     532200 :         if (i&1)
     103                 :     266100 :             equalhash_put_r(h, (void*)k, (void*)arg, (void*)fl_ctx);
     104                 :            :         else
     105                 :     266100 :             k = arg;
     106                 :            :     }
     107                 :    6553940 :     return nt;
     108                 :            : }
     109                 :            : 
     110                 :            : // (put! table key value)
     111                 :    8011960 : value_t fl_table_put(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     112                 :            : {
     113                 :    8011960 :     argcount(fl_ctx, "put!", nargs, 3);
     114                 :    8011960 :     htable_t *h = totable(fl_ctx, args[0], "put!");
     115                 :    8011960 :     void **table0 = h->table;
     116                 :    8011960 :     equalhash_put_r(h, (void*)args[1], (void*)args[2], (void*)fl_ctx);
     117                 :            :     // register finalizer if we outgrew inline space
     118   [ +  +  +  + ]:    8011960 :     if (table0 == &h->_space[0] && h->table != &h->_space[0]) {
     119                 :      44778 :         cvalue_t *cv = (cvalue_t*)ptr(args[0]);
     120                 :      44778 :         add_finalizer(fl_ctx, cv);
     121                 :      44778 :         cv->len = 2*sizeof(void*);
     122                 :            :     }
     123                 :    8011960 :     return args[0];
     124                 :            : }
     125                 :            : 
     126                 :          0 : static void key_error(fl_context_t *fl_ctx, char *fname, value_t key)
     127                 :            : {
     128                 :          0 :     lerrorf(fl_ctx, fl_list2(fl_ctx, fl_ctx->KeyError, key), "%s: key not found", fname);
     129                 :            : }
     130                 :            : 
     131                 :            : // (get table key [default])
     132                 :   19172620 : value_t fl_table_get(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     133                 :            : {
     134         [ +  + ]:   19172620 :     if (nargs != 3)
     135                 :     832448 :         argcount(fl_ctx, "get", nargs, 2);
     136                 :   19172620 :     htable_t *h = totable(fl_ctx, args[0], "get");
     137                 :   19172620 :     value_t v = (value_t)equalhash_get_r(h, (void*)args[1], (void*)fl_ctx);
     138         [ +  + ]:   19172620 :     if (v == (value_t)HT_NOTFOUND) {
     139         [ +  - ]:    6757580 :         if (nargs == 3)
     140                 :    6757580 :             return args[2];
     141                 :          0 :         key_error(fl_ctx, "get", args[1]);
     142                 :            :     }
     143                 :   12415040 :     return v;
     144                 :            : }
     145                 :            : 
     146                 :            : // (has? table key)
     147                 :   33178400 : value_t fl_table_has(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     148                 :            : {
     149                 :   33178400 :     argcount(fl_ctx, "has", nargs, 2);
     150                 :   33178400 :     htable_t *h = totable(fl_ctx, args[0], "has");
     151         [ +  + ]:   33178400 :     return equalhash_has_r(h, (void*)args[1], (void*)fl_ctx) ? fl_ctx->T : fl_ctx->F;
     152                 :            : }
     153                 :            : 
     154                 :            : // (del! table key)
     155                 :      91534 : value_t fl_table_del(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     156                 :            : {
     157                 :      91534 :     argcount(fl_ctx, "del!", nargs, 2);
     158                 :      91534 :     htable_t *h = totable(fl_ctx, args[0], "del!");
     159         [ -  + ]:      91534 :     if (!equalhash_remove_r(h, (void*)args[1], (void*)fl_ctx))
     160                 :          0 :         key_error(fl_ctx, "del!", args[1]);
     161                 :      91534 :     return args[0];
     162                 :            : }
     163                 :            : 
     164                 :    1694406 : value_t fl_table_foldl(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
     165                 :            : {
     166                 :    1694406 :     argcount(fl_ctx, "table.foldl", nargs, 3);
     167                 :    1694406 :     value_t f=args[0], zero=args[1], t=args[2];
     168                 :    1694406 :     htable_t *h = totable(fl_ctx, t, "table.foldl");
     169                 :    1694406 :     size_t i, n = h->size;
     170                 :    1694406 :     void **table = h->table;
     171                 :    1694406 :     fl_gc_handle(fl_ctx, &f);
     172                 :    1694406 :     fl_gc_handle(fl_ctx, &zero);
     173                 :    1694406 :     fl_gc_handle(fl_ctx, &t);
     174         [ +  + ]:   28934600 :     for(i=0; i < n; i+=2) {
     175         [ +  + ]:   27240200 :         if (table[i+1] != HT_NOTFOUND) {
     176                 :    1794540 :             zero = fl_applyn(fl_ctx, 3, f,
     177                 :     897270 :                              (value_t)table[i],
     178                 :     897270 :                              (value_t)table[i+1],
     179                 :            :                              zero);
     180                 :            :             // reload pointer
     181                 :     897270 :             h = (htable_t*)cv_data((cvalue_t*)ptr(t));
     182         [ -  + ]:     897270 :             if (h->size != n)
     183                 :          0 :                 lerror(fl_ctx, fl_ctx->EnumerationError, "table.foldl: table modified");
     184                 :     897270 :             table = h->table;
     185                 :            :         }
     186                 :            :     }
     187                 :    1694406 :     fl_free_gc_handles(fl_ctx, 3);
     188                 :    1694406 :     return zero;
     189                 :            : }
     190                 :            : 
     191                 :            : static const builtinspec_t tablefunc_info[] = {
     192                 :            :     { "table", fl_table },
     193                 :            :     { "table?", fl_tablep },
     194                 :            :     { "put!", fl_table_put },
     195                 :            :     { "get", fl_table_get },
     196                 :            :     { "has?", fl_table_has },
     197                 :            :     { "del!", fl_table_del },
     198                 :            :     { "table.foldl", fl_table_foldl },
     199                 :            :     { NULL, NULL }
     200                 :            : };
     201                 :            : 
     202                 :         30 : void table_init(fl_context_t *fl_ctx)
     203                 :            : {
     204                 :         30 :     fl_ctx->table_vtable.print = print_htable;
     205                 :         30 :     fl_ctx->table_vtable.relocate = relocate_htable;
     206                 :         30 :     fl_ctx->table_vtable.finalize = free_htable;
     207                 :         30 :     fl_ctx->table_vtable.print_traverse = print_traverse_htable;
     208                 :            : 
     209                 :         30 :     fl_ctx->tablesym = symbol(fl_ctx, "table");
     210                 :         60 :     fl_ctx->tabletype = define_opaque_type(fl_ctx->tablesym, sizeof(htable_t),
     211                 :         30 :                                            &fl_ctx->table_vtable, NULL);
     212                 :         30 :     assign_global_builtins(fl_ctx, tablefunc_info);
     213                 :         30 : }
     214                 :            : 
     215                 :            : #ifdef __cplusplus
     216                 :            : }
     217                 :            : #endif

Generated by: LCOV version 1.14