GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/extensions/set_extensions.c Lines: 54 54 100.0 %
Date: 2024-12-05 14:36:58 Branches: 28 34 82.4 %

Line Branch Exec Source
1
/*
2
    Copyright 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 "extensions/set_extensions.h"
19
20
#include "extensions.h"
21
#include "fundamental.h"
22
23
#define ABORT_ON_MERROR(X) if ((X) == ENC_SYM_MERROR) return ENC_SYM_MERROR;
24
25
static lbm_value ext_member(lbm_value *args, lbm_uint argn);
26
static lbm_value ext_set_insert(lbm_value *args, lbm_uint argn);
27
static lbm_value ext_set_union(lbm_value *args, lbm_uint argn);
28
29
21672
void lbm_set_extensions_init(void) {
30
21672
  lbm_add_extension("member", ext_member);
31
21672
  lbm_add_extension("set-insert", ext_set_insert);
32
21672
  lbm_add_extension("set-union", ext_set_union);
33
21672
}
34
35
980
static lbm_value ext_member(lbm_value *args, lbm_uint argn) {
36
980
  lbm_value res = ENC_SYM_TERROR;
37

980
  if (argn == 2 && lbm_is_list(args[0])) {
38
868
    res = ENC_SYM_NIL;
39
868
    lbm_value curr = args[0];
40
41
2072
    while (lbm_is_cons(curr)) {
42
1904
      if (struct_eq(lbm_car(curr), args[1])) {
43
700
        res = args[0];
44
700
        break;
45
      }
46
1204
      curr = lbm_cdr(curr);
47
    }
48
  }
49
980
  return res;
50
}
51
52
420
static lbm_value set_insert(lbm_value set, lbm_value val) {
53
54
420
  lbm_value end = ENC_SYM_NIL;
55
420
  lbm_value start = ENC_SYM_NIL;
56
57
420
  lbm_value curr = set;
58
1036
  while (lbm_is_cons(curr)) {
59
700
    lbm_value h = lbm_car(curr);
60
700
    if (struct_eq(lbm_car(curr), val)) {
61
84
      return set;
62
    }
63
616
    lbm_value cell = lbm_cons(h, ENC_SYM_NIL);
64
616
    ABORT_ON_MERROR(cell);
65
616
    if (end == ENC_SYM_NIL) {
66
252
      end = cell;
67
252
      start = cell;
68
    } else {
69
364
      lbm_set_cdr(end, cell);
70
364
      end = cell;
71
    }
72
616
    curr = lbm_cdr(curr);
73
  }
74
336
  lbm_value v = lbm_cons(val, ENC_SYM_NIL);
75
336
  ABORT_ON_MERROR(v);
76
336
  if (end == ENC_SYM_NIL) {
77
84
    start = v;
78
  } else {
79
252
    lbm_set_cdr(end, v);
80
  }
81
336
  return start;
82
}
83
84
/* extends a copy of the input set with the new element. */
85
308
static lbm_value ext_set_insert(lbm_value *args, lbm_uint argn) {
86
308
  lbm_value res = ENC_SYM_TERROR;
87

308
  if (argn == 2 && lbm_is_list(args[0])) {
88
196
    res = set_insert(args[0], args[1]);
89
  }
90
308
  return res;
91
}
92
93
94
224
static lbm_value ext_set_union(lbm_value *args, lbm_uint argn) {
95
224
  lbm_value res = ENC_SYM_TERROR;
96

224
  if (argn == 2 && lbm_is_list(args[0]) && lbm_is_list(args[1])) {
97
84
    lbm_value curr = args[0];
98
84
    lbm_value set  = args[1];
99
100
308
    while (lbm_is_cons(curr)) {
101
224
      set = set_insert(set, lbm_car(curr));
102
224
      ABORT_ON_MERROR(set);
103
224
      curr = lbm_cdr(curr);
104
    }
105
84
    return set;
106
  }
107
140
  return res;
108
}