GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/extensions/loop_extensions.c Lines: 43 46 93.5 %
Date: 2024-12-26 17:59:19 Branches: 5 8 62.5 %

Line Branch Exec Source
1
/*
2
    Copyright 2023 Joel Svensson        svenssonjoel@yahoo.se
3
              2022 Benjamin Vedder      benjamin@vedder.se
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
19
#include <extensions.h>
20
#include <stdarg.h>
21
22
static lbm_uint sym_res;
23
static lbm_uint sym_loop;
24
static lbm_uint sym_break;
25
static lbm_uint sym_brk;
26
static lbm_uint sym_rst;
27
28
1792
static lbm_value make_list(unsigned int n, ...) {
29
  lbm_value res;
30
  va_list valist;
31
1792
  va_start(valist, n);
32
1792
  res = lbm_heap_allocate_list_init_va(n, valist);
33
1792
  va_end(valist);
34
1792
  return res;
35
}
36
37
168
static lbm_value ext_me_loopfor(lbm_value *args, lbm_uint argn) {
38
168
  if (argn != 5) {
39
140
    return ENC_SYM_EERROR;
40
  }
41
42
28
  lbm_value it = args[0];
43
28
  lbm_value start = args[1];
44
28
  lbm_value cond = args[2];
45
28
  lbm_value update = args[3];
46
28
  lbm_value body = args[4];
47
48
  // (let ((loop (lambda (it res break) (if cond (loop update body break) res)))) (call-cc (lambda (brk) (loop start nil brk))))
49
50
28
   return make_list(3,
51
                   lbm_enc_sym(SYM_LET),
52
                   make_list(1,
53
                             make_list(2,
54
                                       lbm_enc_sym(sym_loop),
55
                                       make_list(3,
56
                                                 lbm_enc_sym(SYM_LAMBDA),
57
                                                 make_list(3, it, lbm_enc_sym(sym_res), lbm_enc_sym(sym_break)),
58
                                                 make_list(4,
59
                                                           lbm_enc_sym(SYM_IF),
60
                                                           cond,
61
                                                           make_list(4, lbm_enc_sym(sym_loop), update, body, lbm_enc_sym(sym_break)),
62
                                                           lbm_enc_sym(sym_res))))),
63
                   make_list(2,
64
                             lbm_enc_sym(SYM_CALLCC),
65
                             make_list(3,
66
                                       lbm_enc_sym(SYM_LAMBDA),
67
                                       make_list(1, lbm_enc_sym(sym_brk)),
68
                                       make_list(4, lbm_enc_sym(sym_loop), start, ENC_SYM_NIL, lbm_enc_sym(sym_brk)))));
69
}
70
71
28
static lbm_value ext_me_loopwhile(lbm_value *args, lbm_uint argn) {
72
28
  if (argn != 2) {
73
    return ENC_SYM_EERROR;
74
  }
75
76
28
  lbm_value cond = args[0];
77
28
  lbm_value body = args[1];
78
79
  // (let ((loop (lambda (res break) (if cond (loop body break) res)))) (call-cc (lambda (brk) (loop nil brk))))
80
81
28
  return make_list(3,
82
                   lbm_enc_sym(SYM_LET),
83
                   make_list(1,
84
                             make_list(2,
85
                                       lbm_enc_sym(sym_loop),
86
                                       make_list(3,
87
                                                 lbm_enc_sym(SYM_LAMBDA),
88
                                                 make_list(2, lbm_enc_sym(sym_res), lbm_enc_sym(sym_break)),
89
                                                 make_list(4,
90
                                                           lbm_enc_sym(SYM_IF),
91
                                                           cond,
92
                                                           make_list(3, lbm_enc_sym(sym_loop), body, lbm_enc_sym(sym_break)),
93
                                                           lbm_enc_sym(sym_res))))),
94
                   make_list(2,
95
                             lbm_enc_sym(SYM_CALLCC),
96
                             make_list(3,
97
                                       lbm_enc_sym(SYM_LAMBDA),
98
                                       make_list(1, lbm_enc_sym(sym_brk)),
99
                                       make_list(3, lbm_enc_sym(sym_loop), ENC_SYM_NIL, lbm_enc_sym(sym_brk)))));
100
}
101
102
56
static lbm_value ext_me_looprange(lbm_value *args, lbm_uint argn) {
103
56
  if (argn != 4) {
104
    return ENC_SYM_EERROR;
105
  }
106
107
56
  lbm_value it = args[0];
108
56
  lbm_value start = args[1];
109
56
  lbm_value end = args[2];
110
56
  lbm_value body = args[3];
111
112
  // (let ((loop (lambda (it res break) (if (< it end) (loop (+ it 1) body break) res)))) (call-cc (lambda (brk) (loop start nil brk))))
113
114
56
  return make_list(3,
115
                   lbm_enc_sym(SYM_LET),
116
                   make_list(1,
117
                             make_list(2,
118
                                       lbm_enc_sym(sym_loop),
119
                                       make_list(3,
120
                                                 lbm_enc_sym(SYM_LAMBDA),
121
                                                 make_list(3, it, lbm_enc_sym(sym_res), lbm_enc_sym(sym_break)),
122
                                                 make_list(4,
123
                                                           lbm_enc_sym(SYM_IF),
124
                                                           make_list(3, lbm_enc_sym(SYM_LT), it, end),
125
                                                           make_list(4, lbm_enc_sym(sym_loop), make_list(3, lbm_enc_sym(SYM_ADD), it, lbm_enc_i(1)), body, lbm_enc_sym(sym_break)),
126
                                                           lbm_enc_sym(sym_res))))),
127
                   make_list(2,
128
                             lbm_enc_sym(SYM_CALLCC),
129
                             make_list(3,
130
                                       lbm_enc_sym(SYM_LAMBDA),
131
                                       make_list(1, lbm_enc_sym(sym_brk)),
132
                                       make_list(4, lbm_enc_sym(sym_loop), start, ENC_SYM_NIL, lbm_enc_sym(sym_brk)))));
133
}
134
135
28
static lbm_value ext_me_loopforeach(lbm_value *args, lbm_uint argn) {
136
28
  if (argn != 3) {
137
    return ENC_SYM_EERROR;
138
  }
139
140
28
  lbm_value it = args[0];
141
28
  lbm_value lst = args[1];
142
28
  lbm_value body = args[2];
143
144
  // (let ((loop (lambda (it rst res break) (if (eq it nil) res (loop (car rst) (cdr rst) body break))))) (call-cc (lambda (brk) (loop (car lst) (cdr lst) nil brk))))
145
146
28
  return make_list(3,
147
                   lbm_enc_sym(SYM_LET),
148
                   make_list(1,
149
                             make_list(2,
150
                                       lbm_enc_sym(sym_loop),
151
                                       make_list(3,
152
                                                 lbm_enc_sym(SYM_LAMBDA),
153
                                                 make_list(4, it, lbm_enc_sym(sym_rst), lbm_enc_sym(sym_res), lbm_enc_sym(sym_break)),
154
                                                 make_list(4,
155
                                                           lbm_enc_sym(SYM_IF),
156
                                                           make_list(3, lbm_enc_sym(SYM_EQ), it, ENC_SYM_NIL),
157
                                                           lbm_enc_sym(sym_res),
158
                                                           make_list(5,
159
                                                                     lbm_enc_sym(sym_loop),
160
                                                                     make_list(2, lbm_enc_sym(SYM_CAR), lbm_enc_sym(sym_rst)),
161
                                                                     make_list(2, lbm_enc_sym(SYM_CDR), lbm_enc_sym(sym_rst)),
162
                                                                     body,
163
                                                                     lbm_enc_sym(sym_break))
164
                                                           )))),
165
                   make_list(2,
166
                             lbm_enc_sym(SYM_CALLCC),
167
                             make_list(3,
168
                                       lbm_enc_sym(SYM_LAMBDA),
169
                                       make_list(1, lbm_enc_sym(sym_brk)),
170
                                       make_list(5,
171
                                                 lbm_enc_sym(sym_loop),
172
                                                 make_list(2, lbm_enc_sym(SYM_CAR), lst),
173
                                                 make_list(2, lbm_enc_sym(SYM_CDR), lst),
174
                                                 ENC_SYM_NIL,
175
                                                 lbm_enc_sym(sym_brk)))));
176
}
177
178
const char *loop_extensions_dyn_load[4] = {
179
  "(define loopfor (macro (it start cnd update body) (me-loopfor it start cnd update body)))",
180
  "(define loopwhile (macro (cnd body) (me-loopwhile cnd body)))",
181
  "(define looprange (macro (it start end body) (me-looprange it start end body)))",
182
  "(define loopforeach (macro (it lst body) (me-loopforeach it lst body)))"
183
};
184
185
21756
void lbm_loop_extensions_init(void) {
186
187
21756
  lbm_add_symbol_const("a01", &sym_res);
188
21756
  lbm_add_symbol_const("a02", &sym_loop);
189
21756
  lbm_add_symbol_const("break", &sym_break);
190
21756
  lbm_add_symbol_const("a03", &sym_brk);
191
21756
  lbm_add_symbol_const("a04", &sym_rst);
192
193
21756
  lbm_add_extension("me-loopfor", ext_me_loopfor);
194
21756
  lbm_add_extension("me-loopwhile", ext_me_loopwhile);
195
21756
  lbm_add_extension("me-looprange", ext_me_looprange);
196
21756
  lbm_add_extension("me-loopforeach", ext_me_loopforeach);
197
21756
}