1 -- ---------------------------------------------------------
10 -- ---------------------------------------------------------
15 CREATE FUNCTION mal.
READ(line
varchar) RETURNS integer AS $$
17 RETURN reader.
read_str(line
);
18 END; $$
LANGUAGE plpgsql
;
21 CREATE FUNCTION mal.
eval_ast(ast
integer, env hstore
) RETURNS integer AS $$
33 SELECT type_id
INTO type FROM types.
value WHERE value_id
= ast
;
37 symkey
:= types.
_valueToString(ast
);
39 result := env
-> symkey
;
41 RAISE
EXCEPTION '''%'' not found', symkey
;
44 WHEN type IN (8, 9) THEN
46 SELECT val_seq
INTO seq
FROM types.
value WHERE value_id
= ast
;
47 -- Evaluate each entry creating a new sequence
48 FOR i
IN 1 ..
COALESCE(array_length(seq
, 1), 0) LOOP
49 eseq
[i
] := mal.
EVAL(seq
[i
], env
);
51 INSERT INTO types.
value (type_id
, val_seq
) VALUES (type, eseq
)
52 RETURNING value_id
INTO result;
56 SELECT val_hash
INTO hash
FROM types.
value WHERE value_id
= ast
;
57 -- Evaluate each value for every key/value
58 FOR kv
IN SELECT * FROM each(hash
) LOOP
59 e
:= mal.
EVAL(CAST(kv.
value AS integer), env
);
61 ehash
:= hstore(kv.
key, CAST(e
AS varchar));
63 ehash
:= ehash ||
hstore(kv.
key, CAST(e
AS varchar));
66 INSERT INTO types.
value (type_id
, val_hash
) VALUES (type, ehash
)
67 RETURNING value_id
INTO result;
74 END; $$
LANGUAGE plpgsql
;
76 CREATE FUNCTION mal.
EVAL(ast
integer, env hstore
) RETURNS integer AS $$
84 SELECT type_id
INTO type FROM types.
value WHERE value_id
= ast
;
86 RETURN mal.
eval_ast(ast
, env
);
88 IF types.
_count(ast
) = 0 THEN
92 el
:= mal.
eval_ast(ast
, env
);
93 SELECT val_string
INTO fname
FROM types.
value
94 WHERE value_id
= types.
_first(el
);
95 args
:= types.
_restArray(el
);
96 EXECUTE format('SELECT %s($1);', fname
) INTO result USING args
;
98 END; $$
LANGUAGE plpgsql
;
101 CREATE FUNCTION mal.
PRINT(exp integer) RETURNS varchar AS $$
103 RETURN printer.
pr_str(exp);
104 END; $$
LANGUAGE plpgsql
;
109 CREATE FUNCTION mal.
intop(op
varchar, args
integer[]) RETURNS integer AS $$
110 DECLARE a
integer; b
integer; result integer;
112 SELECT val_int
INTO a
FROM types.
value WHERE value_id
= args
[1];
113 SELECT val_int
INTO b
FROM types.
value WHERE value_id
= args
[2];
114 EXECUTE format('INSERT INTO types.value (type_id, val_int)
116 RETURNING value_id;', op
) INTO result USING a
, b
;
118 END; $$
LANGUAGE plpgsql
;
120 CREATE FUNCTION mal.
add(args
integer[]) RETURNS integer AS $$
121 BEGIN RETURN mal.
intop('+', args
); END; $$
LANGUAGE plpgsql
;
122 CREATE FUNCTION mal.
subtract(args
integer[]) RETURNS integer AS $$
123 BEGIN RETURN mal.
intop('-', args
); END; $$
LANGUAGE plpgsql
;
124 CREATE FUNCTION mal.
multiply(args
integer[]) RETURNS integer AS $$
125 BEGIN RETURN mal.
intop('*', args
); END; $$
LANGUAGE plpgsql
;
126 CREATE FUNCTION mal.
divide(args
integer[]) RETURNS integer AS $$
127 BEGIN RETURN mal.
intop('/', args
); END; $$
LANGUAGE plpgsql
;
130 CREATE FUNCTION mal.
REP(env hstore
, line
varchar) RETURNS varchar AS $$
132 RETURN mal.
PRINT(mal.
EVAL(mal.
READ(line
), env
));
133 END; $$
LANGUAGE plpgsql
;
135 CREATE FUNCTION mal.
MAIN(pwd
varchar) RETURNS integer AS $$
141 repl_env
:= hstore(ARRAY[
142 '+', types.
_function('mal.add'),
143 '-', types.
_function('mal.subtract'),
144 '*', types.
_function('mal.multiply'),
145 '/', types.
_function('mal.divide')]);
148 line
:= io.
readline('user> ', 0);
153 IF line
NOT IN ('', E
'\n') THEN
154 output := mal.
REP(repl_env
, line
);
155 PERFORM io.
writeline(output);
158 EXCEPTION WHEN OTHERS THEN
159 PERFORM io.
writeline('Error: ' || SQLERRM
);
162 END; $$
LANGUAGE plpgsql
;