lac : 54b3831bb6847a39d31917099711f45734540dbb
1: /*
2: lac -- a lisp interpreter library
3: Copyright (C) 2010 Gianluca Guida
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 2 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 along
16: with this program; if not, write to the Free Software Foundation, Inc.,
17: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18: */
19:
20: /* Mapping functions */
21: #include "lac.h"
22: #include <gc/gc.h>
23:
24: #define ARGEVAL(_lr, _e) ((_e) == NULL ? _lr : eval((_lr), (_e)))
25: #define is_cons(lr) (lreg_raw_type(lr) == LREG_CONS)
26:
27: static lreg_t
28: map_args (lreg_t lists)
29: {
30: lreg_t args = lists;
31: lreg_t outargs = NIL, tail = NIL;
32:
33: for (; args != NIL; args = cdr (args))
34: {
35: if (!is_cons (args) || !is_cons (car (args)))
36: {
37: if (is_cons (args) && car (args) == NIL)
38: return NIL;
39: raise_exception ("Syntax Error in mapcar", args);
40: }
41:
42: if (outargs == NIL)
43: {
44: outargs = tail =
45: cons (cons (sym_quote, cons (cons (car (car (args)), NIL), NIL)),
46: NIL);
47: }
48: else
49: {
50: lreg_t tmp =
51: cons (cons (sym_quote, cons (cons (car (car (args)), NIL), NIL)),
52: NIL);
53: rplacd (tail, tmp);
54: tail = tmp;
55: }
56:
57: rplaca (args, cdr (car (args)));
58: }
59:
60: return outargs;
61: }
62:
63:
64:
65: LAC_API static lreg_t
66: proc_mapcar (lreg_t args, lenv_t * argenv, lenv_t * env)
67: {
68: _EXPECT_MIN_ARGS (args, 2);
69: lreg_t mapargs;
70: lreg_t fn, lists;
71: lreg_t outlist = NIL, tail = NIL;
72: lreg_t evd = argenv == NULL ? args : evargs (args, env);
73: fn = car (evd);
74: lists = cdr (evd);
75:
76: switch (lreg_type (fn))
77: {
78: case LREG_LAMBDA:
79: case LREG_MACRO:
80: case LREG_LLPROC:
81: break;
82: default:
83: _ERROR_AND_RET ("Syntax error in mapcar");
84: }
85:
86:
87: for (;;)
88: {
89: lreg_t outelm;
90: mapargs = map_args (lists);
91: if (mapargs == NIL)
92: break;
93: outelm = apply (fn, car (mapargs), env);
94:
95: if (outlist == NIL)
96: {
97: outlist = tail = cons (outelm, NIL);
98: }
99: else
100: {
101: lreg_t tmp = cons (outelm, NIL);
102: rplacd (tail, tmp);
103: tail = tmp;
104: }
105: }
106: return outlist;
107: }
108:
109: LAC_API static lreg_t
110: proc_reduce (lreg_t args, lenv_t * argenv, lenv_t * env)
111: {
112: _EXPECT_ARGS (args, 2);
113: lreg_t acc;
114: lreg_t fn = ARGEVAL (car (args), argenv);
115: lreg_t list = ARGEVAL (car (cdr (args)), argenv);
116:
117: if (!is_cons (list))
118: _ERROR_AND_RET ("Syntax error in reduce\n");
119:
120: acc = car (list);
121: list = cdr (list);
122:
123: for (; list != NIL; list = cdr (list))
124: acc = apply (fn, cons (acc, cons (car (list), NIL)), env);
125:
126: return acc;
127: }
128:
129: void
130: map_init (lenv_t * env)
131: {
132:
133: lac_extproc_register (env, "MAPCAR", proc_mapcar);
134: lac_extproc_register (env, "REDUCE", proc_reduce);
135: }
Generated by git2html.