2 * Copyright (c) 2016 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include <jeffpc/sexpr.h>
27 struct val
*(*f
)(struct val
*args
,
28 struct val
*(*lookup
)(struct str
*name
, void *private),
32 #define __REDUCE(fname, alloc, t, valmember, ident, op) \
33 static struct val *fname(struct val *args, \
34 struct val *(*lookup)(struct str *, void *), \
42 struct val *el = sexpr_car(val_getref(args)); \
43 struct val *next = sexpr_cdr(args); \
45 while (el && (el->type == VT_CONS || el->type == VT_SYM)) \
46 el = sexpr_eval(el, lookup, private); \
49 ASSERT3U(el->type, ==, t); \
51 ret->valmember = ret->valmember op el->valmember; \
60 #define BOOL_REDUCE(fname, ident, op) \
61 __REDUCE(fname, VAL_ALLOC_BOOL, VT_BOOL, b, ident, op)
63 BOOL_REDUCE(fxn_or
, false, ||)
64 BOOL_REDUCE(fxn_and
, true, &&)
66 #define INT_REDUCE(fname, ident, op) \
67 __REDUCE(fname, VAL_ALLOC_INT, VT_INT, i, ident, op)
69 INT_REDUCE(fxn_add
, 0, +)
70 INT_REDUCE(fxn_mult
, 1, *)
72 static struct val
*fxn_quote(struct val
*args
,
73 struct val
*(*lookup
)(struct str
*name
, void *private),
76 return sexpr_car(args
);
79 static struct val
*fxn_equal(struct val
*args
,
80 struct val
*(*lookup
)(struct str
*name
, void *private),
85 VERIFY3U(sexpr_length(val_getref(args
)), == ,2);
87 a
= sexpr_eval(sexpr_nth(val_getref(args
), 1), lookup
, private);
88 b
= sexpr_eval(sexpr_nth(args
, 2), lookup
, private);
90 return VAL_ALLOC_BOOL(sexpr_equal(a
, b
));
93 static struct builtin_fxn builtins
[] = {
100 { "quote", fxn_quote
, },
102 { "==", fxn_equal
, },
106 static struct val
*eval_cons(struct val
*expr
,
107 struct val
*(*lookup
)(struct str
*, void *),
114 op
= sexpr_car(val_getref(expr
));
115 args
= sexpr_cdr(val_getref(expr
));
118 ASSERT3U(op
->type
, ==, VT_SYM
);
120 for (i
= 0; builtins
[i
].name
; i
++)
121 if (!strcmp(builtins
[i
].name
, str_cstr(op
->str
)))
122 return builtins
[i
].f(args
, lookup
, private);
124 panic("unknown builtin function '%s'", str_cstr(op
->str
));
127 struct val
*sexpr_eval(struct val
*expr
,
128 struct val
*(*lookup
)(struct str
*, void *),
134 switch (expr
->type
) {
143 panic("VT_SYM requires non-NULL lookup "
144 "function passed to sexpr_eval");
146 name
= str_getref(expr
->str
);
149 return sexpr_eval(lookup(name
, private), lookup
, private);
152 return eval_cons(expr
, lookup
, private);
155 panic("impossible!");