1 PROMPT
'core.sql start';
3 CREATE OR REPLACE TYPE core_ns_type
IS TABLE OF varchar2(100);
6 CREATE OR REPLACE PACKAGE core
IS
8 FUNCTION do_core_func(M
IN OUT NOCOPY mem_type
,
9 H
IN OUT NOCOPY types.map_entry_table
,
11 a mal_seq_items_type
) RETURN integer;
13 FUNCTION get_core_ns
RETURN core_ns_type
;
19 CREATE OR REPLACE PACKAGE BODY core
AS
22 FUNCTION equal_Q(M
IN OUT NOCOPY mem_type
,
23 H
IN OUT NOCOPY types.map_entry_table
,
24 args mal_seq_items_type
) RETURN integer IS
26 RETURN types.
tf(types.
equal_Q(M
, H
, args(1), args(2)));
30 FUNCTION symbol(M
IN OUT NOCOPY mem_type
,
31 val
integer) RETURN integer IS
33 RETURN types.
symbol(M
, TREAT(M(val
) AS mal_str_type
).val_str
);
36 FUNCTION keyword(M
IN OUT NOCOPY mem_type
,
37 val
integer) RETURN integer IS
39 IF types.
string_Q(M
, val
) THEN
40 RETURN types.
keyword(M
, TREAT(M(val
) AS mal_str_type
).val_str
);
41 ELSIF types.
keyword_Q(M
, val
) THEN
44 raise_application_error(-20009,
45 'invalid keyword call', TRUE);
51 FUNCTION pr_str(M
IN OUT NOCOPY mem_type
,
52 H
IN OUT NOCOPY types.map_entry_table
,
53 args mal_seq_items_type
) RETURN integer IS
55 RETURN types.
string(M
, printer.
pr_str_seq(M
, H
, args
, ' ', TRUE));
58 FUNCTION str(M
IN OUT NOCOPY mem_type
,
59 H
IN OUT NOCOPY types.map_entry_table
,
60 args mal_seq_items_type
) RETURN integer IS
62 RETURN types.
string(M
, printer.
pr_str_seq(M
, H
, args
, '', FALSE));
65 FUNCTION prn(M
IN OUT NOCOPY mem_type
,
66 H
IN OUT NOCOPY types.map_entry_table
,
67 args mal_seq_items_type
) RETURN integer IS
69 stream_writeline(printer.
pr_str_seq(M
, H
, args
, ' ', TRUE));
73 FUNCTION println(M
IN OUT NOCOPY mem_type
,
74 H
IN OUT NOCOPY types.map_entry_table
,
75 args mal_seq_items_type
) RETURN integer IS
77 stream_writeline(printer.
pr_str_seq(M
, H
, args
, ' ', FALSE));
81 FUNCTION read_string(M
IN OUT NOCOPY mem_type
,
82 H
IN OUT NOCOPY types.map_entry_table
,
83 args mal_seq_items_type
) RETURN integer IS
85 RETURN reader.
read_str(M
, H
, TREAT(M(args(1)) AS mal_str_type
).val_str
);
88 FUNCTION readline(M
IN OUT NOCOPY mem_type
,
89 prompt
integer) RETURN integer IS
92 input := stream_readline(TREAT(M(prompt
) AS mal_str_type
).val_str
, 0);
93 RETURN types.
string(M
, input);
94 EXCEPTION WHEN OTHERS THEN
95 IF SQLCODE = -20001 THEN -- io streams closed
102 FUNCTION slurp(M
IN OUT NOCOPY mem_type
,
103 args mal_seq_items_type
) RETURN integer IS
104 content varchar2(4000);
106 -- stream_writeline('here1: ' || TREAT(args(1) AS mal_str_type).val_str);
107 content := file_open_and_read(TREAT(M(args(1)) AS mal_str_type
).val_str
);
108 content := REPLACE(content, '\n', chr(10));
109 RETURN types.
string(M
, content);
114 FUNCTION lt(M
IN OUT NOCOPY mem_type
,
115 args mal_seq_items_type
) RETURN integer IS
117 RETURN types.
tf(TREAT(M(args(1)) AS mal_int_type
).val_int
<
118 TREAT(M(args(2)) AS mal_int_type
).val_int
);
121 FUNCTION lte(M
IN OUT NOCOPY mem_type
,
122 args mal_seq_items_type
) RETURN integer IS
124 RETURN types.
tf(TREAT(M(args(1)) AS mal_int_type
).val_int
<=
125 TREAT(M(args(2)) AS mal_int_type
).val_int
);
128 FUNCTION gt(M
IN OUT NOCOPY mem_type
,
129 args mal_seq_items_type
) RETURN integer IS
131 RETURN types.
tf(TREAT(M(args(1)) AS mal_int_type
).val_int
>
132 TREAT(M(args(2)) AS mal_int_type
).val_int
);
135 FUNCTION gte(M
IN OUT NOCOPY mem_type
,
136 args mal_seq_items_type
) RETURN integer IS
138 RETURN types.
tf(TREAT(M(args(1)) AS mal_int_type
).val_int
>=
139 TREAT(M(args(2)) AS mal_int_type
).val_int
);
142 FUNCTION add(M
IN OUT NOCOPY mem_type
,
143 args mal_seq_items_type
) RETURN integer IS
145 RETURN types.
int(M
, TREAT(M(args(1)) AS mal_int_type
).val_int
+
146 TREAT(M(args(2)) AS mal_int_type
).val_int
);
149 FUNCTION subtract(M
IN OUT NOCOPY mem_type
,
150 args mal_seq_items_type
) RETURN integer IS
152 RETURN types.
int(M
, TREAT(M(args(1)) AS mal_int_type
).val_int
-
153 TREAT(M(args(2)) AS mal_int_type
).val_int
);
156 FUNCTION multiply(M
IN OUT NOCOPY mem_type
,
157 args mal_seq_items_type
) RETURN integer IS
159 RETURN types.
int(M
, TREAT(M(args(1)) AS mal_int_type
).val_int
*
160 TREAT(M(args(2)) AS mal_int_type
).val_int
);
163 FUNCTION divide(M
IN OUT NOCOPY mem_type
,
164 args mal_seq_items_type
) RETURN integer IS
166 RETURN types.
int(M
, TREAT(M(args(1)) AS mal_int_type
).val_int
/
167 TREAT(M(args(2)) AS mal_int_type
).val_int
);
170 FUNCTION time_ms(M
IN OUT NOCOPY mem_type
) RETURN integer IS
173 -- SELECT (SYSDATE - TO_DATE('01-01-1970 00:00:00', 'DD-MM-YYYY HH24:MI:SS')) * 24 * 60 * 60 * 1000
174 -- INTO now FROM DUAL;
175 SELECT extract(day from(sys_extract_utc(systimestamp
) - to_timestamp('1970-01-01', 'YYYY-MM-DD'))) * 86400000 + to_number(to_char(sys_extract_utc(systimestamp
), 'SSSSSFF3'))
178 RETURN types.
int(M
, now
);
181 -- hash-map functions
182 FUNCTION assoc(M
IN OUT NOCOPY mem_type
,
183 H
IN OUT NOCOPY types.map_entry_table
,
185 kvs mal_seq_items_type
) RETURN integer IS
189 new_hm
:= types.
clone(M
, H
, hm
);
190 midx
:= TREAT(M(new_hm
) AS mal_map_type
).map_idx
;
191 -- Add the new key/values
192 midx
:= types.
assoc_BANG(M
, H
, midx
, kvs
);
196 FUNCTION dissoc(M
IN OUT NOCOPY mem_type
,
197 H
IN OUT NOCOPY types.map_entry_table
,
199 ks mal_seq_items_type
) RETURN integer IS
203 new_hm
:= types.
clone(M
, H
, hm
);
204 midx
:= TREAT(M(new_hm
) AS mal_map_type
).map_idx
;
206 midx
:= types.
dissoc_BANG(M
, H
, midx
, ks
);
211 FUNCTION get(M
IN OUT NOCOPY mem_type
,
212 H
IN OUT NOCOPY types.map_entry_table
,
213 hm
integer, key integer) RETURN integer IS
218 IF M(hm
).type_id
= 0 THEN
221 midx
:= TREAT(M(hm
) AS mal_map_type
).map_idx
;
222 k
:= TREAT(M(key) AS mal_str_type
).val_str
;
223 IF H(midx
).
EXISTS(k
) THEN
230 FUNCTION contains_Q(M
IN OUT NOCOPY mem_type
,
231 H
IN OUT NOCOPY types.map_entry_table
,
232 hm
integer, key integer) RETURN integer IS
237 midx
:= TREAT(M(hm
) AS mal_map_type
).map_idx
;
238 k
:= TREAT(M(key) AS mal_str_type
).val_str
;
239 RETURN types.
tf(H(midx
).
EXISTS(k
));
242 FUNCTION keys(M
IN OUT NOCOPY mem_type
,
243 H
IN OUT NOCOPY types.map_entry_table
,
244 hm
integer) RETURN integer IS
247 ks mal_seq_items_type
;
250 midx
:= TREAT(M(hm
) AS mal_map_type
).map_idx
;
251 ks
:= mal_seq_items_type();
253 k
:= H(midx
).
FIRST();
254 WHILE k
IS NOT NULL LOOP
256 ks(ks.
COUNT()) := types.
string(M
, k
);
257 k
:= H(midx
).
NEXT(k
);
260 RETURN types.
seq(M
, 8, ks
);
263 FUNCTION vals(M
IN OUT NOCOPY mem_type
,
264 H
IN OUT NOCOPY types.map_entry_table
,
265 hm
integer) RETURN integer IS
268 ks mal_seq_items_type
;
271 midx
:= TREAT(M(hm
) AS mal_map_type
).map_idx
;
272 ks
:= mal_seq_items_type();
274 k
:= H(midx
).
FIRST();
275 WHILE k
IS NOT NULL LOOP
277 ks(ks.
COUNT()) := H(midx
)(k
);
278 k
:= H(midx
).
NEXT(k
);
281 RETURN types.
seq(M
, 8, ks
);
285 -- sequence functions
286 FUNCTION cons(M
IN OUT NOCOPY mem_type
,
287 args mal_seq_items_type
) RETURN integer IS
288 new_items mal_seq_items_type
;
292 new_items
:= mal_seq_items_type();
293 len
:= types.
count(M
, args(2));
294 new_items.
EXTEND(len
+1);
295 new_items(1) := args(1);
297 new_items(i
+1) := TREAT(M(args(2)) AS mal_seq_type
).
val_seq(i
);
299 RETURN types.
seq(M
, 8, new_items
);
302 FUNCTION concat(M
IN OUT NOCOPY mem_type
,
303 args mal_seq_items_type
) RETURN integer IS
304 new_items mal_seq_items_type
;
310 new_items
:= mal_seq_items_type();
312 FOR i
IN 1..args.
COUNT() LOOP
313 seq_len
:= types.
count(M
, args(i
));
314 new_items.
EXTEND(seq_len
);
315 FOR j
IN 1..seq_len LOOP
316 new_items(cur_len
+ j
) := types.
nth(M
, args(i
), j
-1);
318 cur_len
:= cur_len
+ seq_len
;
320 RETURN types.
seq(M
, 8, new_items
);
324 FUNCTION nth(M
IN OUT NOCOPY mem_type
,
326 ival
integer) RETURN integer IS
329 idx
:= TREAT(M(ival
) AS mal_int_type
).val_int
;
330 RETURN types.
nth(M
, val
, idx
);
333 FUNCTION first(M
IN OUT NOCOPY mem_type
,
334 val
integer) RETURN integer IS
336 IF val
= 1 OR types.
count(M
, val
) = 0 THEN
339 RETURN types.
first(M
, val
);
343 FUNCTION rest(M
IN OUT NOCOPY mem_type
,
344 val
integer) RETURN integer IS
346 IF val
= 1 OR types.
count(M
, val
) = 0 THEN
347 RETURN types.
list(M
);
349 RETURN types.
slice(M
, val
, 1);
353 FUNCTION do_count(M
IN OUT NOCOPY mem_type
,
354 val
integer) RETURN integer IS
356 IF M(val
).type_id
= 0 THEN
357 RETURN types.
int(M
, 0);
359 RETURN types.
int(M
, types.
count(M
, val
));
364 FUNCTION conj(M
IN OUT NOCOPY mem_type
,
366 vals mal_seq_items_type
) RETURN integer IS
369 items mal_seq_items_type
;
371 type_id
:= M(seq
).type_id
;
372 slen
:= types.
count(M
, seq
);
373 items
:= mal_seq_items_type();
374 items.
EXTEND(slen
+ vals.
COUNT());
376 WHEN type_id
= 8 THEN
377 FOR i
IN 1..vals.
COUNT() LOOP
378 items(i
) := vals(vals.
COUNT + 1 - i
);
380 FOR i
IN 1..slen LOOP
381 items(vals.
COUNT() + i
) := types.
nth(M
, seq
, i
-1);
383 WHEN type_id
= 9 THEN
384 FOR i
IN 1..slen LOOP
385 items(i
) := types.
nth(M
, seq
, i
-1);
387 FOR i
IN 1..vals.
COUNT() LOOP
388 items(slen
+ i
) := vals(i
);
391 raise_application_error(-20009,
392 'conj: not supported on type ' || type_id
, TRUE);
394 RETURN types.
seq(M
, type_id
, items
);
397 FUNCTION seq(M
IN OUT NOCOPY mem_type
,
398 val
integer) RETURN integer IS
402 str_items mal_seq_items_type
;
404 type_id
:= M(val
).type_id
;
406 WHEN type_id
= 8 THEN
407 IF types.
count(M
, val
) = 0 THEN
411 WHEN type_id
= 9 THEN
412 IF types.
count(M
, val
) = 0 THEN
415 RETURN types.
seq(M
, 8, TREAT(M(val
) AS mal_seq_type
).val_seq
);
416 WHEN types.
string_Q(M
, val
) THEN
417 str
:= TREAT(M(val
) AS mal_str_type
).val_str
;
421 str_items
:= mal_seq_items_type();
422 str_items.
EXTEND(LENGTH(str
));
423 FOR i
IN 1..
LENGTH(str
) LOOP
424 str_items(i
) := types.
string(M
, SUBSTR(str
, i
, 1));
426 RETURN types.
seq(M
, 8, str_items
);
427 WHEN type_id
= 0 THEN
430 raise_application_error(-20009,
431 'seq: not supported on type ' || type_id
, TRUE);
436 FUNCTION reset_BANG(M
IN OUT NOCOPY mem_type
,
438 new_val
integer) RETURN integer IS
440 M(atm
) := mal_atom_type(13, new_val
);
444 -- metadata functions
445 FUNCTION meta(M
IN OUT NOCOPY mem_type
,
446 val
integer) RETURN integer IS
449 type_id
:= M(val
).type_id
;
450 IF type_id
IN (8,9) THEN -- list/vector
451 RETURN TREAT(M(val
) AS mal_seq_type
).meta
;
452 ELSIF type_id
= 10 THEN -- hash-map
453 RETURN TREAT(M(val
) AS mal_map_type
).meta
;
454 ELSIF type_id
= 11 THEN -- native function
456 ELSIF type_id
= 12 THEN -- mal function
457 RETURN TREAT(M(val
) AS malfunc_type
).meta
;
459 raise_application_error(-20006,
460 'meta: metadata not supported on type', TRUE);
464 -- general native function case/switch
465 FUNCTION do_core_func(M
IN OUT NOCOPY mem_type
,
466 H
IN OUT NOCOPY types.map_entry_table
,
468 a mal_seq_items_type
) RETURN integer IS
472 IF M(fn
).type_id
<> 11 THEN
473 raise_application_error(-20004,
474 'Invalid function call', TRUE);
477 fname
:= TREAT(M(fn
) AS mal_str_type
).val_str
;
480 WHEN fname
= '=' THEN RETURN equal_Q(M
, H
, a
);
482 WHEN fname
= 'nil?' THEN RETURN types.
tf(a(1) = 1);
483 WHEN fname
= 'false?' THEN RETURN types.
tf(a(1) = 2);
484 WHEN fname
= 'true?' THEN RETURN types.
tf(a(1) = 3);
485 WHEN fname
= 'string?' THEN RETURN types.
tf(types.
string_Q(M
, a(1)));
486 WHEN fname
= 'symbol' THEN RETURN symbol(M
, a(1));
487 WHEN fname
= 'symbol?' THEN RETURN types.
tf(M(a(1)).type_id
= 7);
488 WHEN fname
= 'keyword' THEN RETURN keyword(M
, a(1));
489 WHEN fname
= 'keyword?' THEN RETURN types.
tf(types.
keyword_Q(M
, a(1)));
491 WHEN fname
= 'pr-str' THEN RETURN pr_str(M
, H
, a
);
492 WHEN fname
= 'str' THEN RETURN str(M
, H
, a
);
493 WHEN fname
= 'prn' THEN RETURN prn(M
, H
, a
);
494 WHEN fname
= 'println' THEN RETURN println(M
, H
, a
);
495 WHEN fname
= 'read-string' THEN RETURN read_string(M
, H
, a
);
496 WHEN fname
= 'readline' THEN RETURN readline(M
, a(1));
497 WHEN fname
= 'slurp' THEN RETURN slurp(M
, a
);
499 WHEN fname
= '<' THEN RETURN lt(M
, a
);
500 WHEN fname
= '<=' THEN RETURN lte(M
, a
);
501 WHEN fname
= '>' THEN RETURN gt(M
, a
);
502 WHEN fname
= '>=' THEN RETURN gte(M
, a
);
503 WHEN fname
= '+' THEN RETURN add(M
, a
);
504 WHEN fname
= '-' THEN RETURN subtract(M
, a
);
505 WHEN fname
= '*' THEN RETURN multiply(M
, a
);
506 WHEN fname
= '/' THEN RETURN divide(M
, a
);
507 WHEN fname
= 'time-ms' THEN RETURN time_ms(M
);
509 WHEN fname
= 'list' THEN RETURN types.
seq(M
, 8, a
);
510 WHEN fname
= 'list?' THEN RETURN types.
tf(M(a(1)).type_id
= 8);
511 WHEN fname
= 'vector' THEN RETURN types.
seq(M
, 9, a
);
512 WHEN fname
= 'vector?' THEN RETURN types.
tf(M(a(1)).type_id
= 9);
513 WHEN fname
= 'hash-map' THEN RETURN types.
hash_map(M
, H
, a
);
514 WHEN fname
= 'assoc' THEN RETURN assoc(M
, H
, a(1), types.
islice(a
, 1));
515 WHEN fname
= 'dissoc' THEN RETURN dissoc(M
, H
, a(1), types.
islice(a
, 1));
516 WHEN fname
= 'map?' THEN RETURN types.
tf(M(a(1)).type_id
= 10);
517 WHEN fname
= 'get' THEN RETURN get(M
, H
, a(1), a(2));
518 WHEN fname
= 'contains?' THEN RETURN contains_Q(M
, H
, a(1), a(2));
519 WHEN fname
= 'keys' THEN RETURN keys(M
, H
, a(1));
520 WHEN fname
= 'vals' THEN RETURN vals(M
, H
, a(1));
522 WHEN fname
= 'sequential?' THEN RETURN types.
tf(M(a(1)).type_id
IN (8,9));
523 WHEN fname
= 'cons' THEN RETURN cons(M
, a
);
524 WHEN fname
= 'concat' THEN RETURN concat(M
, a
);
525 WHEN fname
= 'nth' THEN RETURN nth(M
, a(1), a(2));
526 WHEN fname
= 'first' THEN RETURN first(M
, a(1));
527 WHEN fname
= 'rest' THEN RETURN rest(M
, a(1));
528 WHEN fname
= 'empty?' THEN RETURN types.
tf(0 = types.
count(M
, a(1)));
529 WHEN fname
= 'count' THEN RETURN do_count(M
, a(1));
531 WHEN fname
= 'conj' THEN RETURN conj(M
, a(1), types.
islice(a
, 1));
532 WHEN fname
= 'seq' THEN RETURN seq(M
, a(1));
534 WHEN fname
= 'meta' THEN RETURN meta(M
, a(1));
535 WHEN fname
= 'with-meta' THEN RETURN types.
clone(M
, H
, a(1), a(2));
536 WHEN fname
= 'atom' THEN RETURN types.
atom_new(M
, a(1));
537 WHEN fname
= 'atom?' THEN RETURN types.
tf(M(a(1)).type_id
= 13);
538 WHEN fname
= 'deref' THEN RETURN TREAT(M(a(1)) AS mal_atom_type
).val
;
539 WHEN fname
= 'reset!' THEN RETURN reset_BANG(M
, a(1), a(2));
541 ELSE raise_application_error(-20004, 'Invalid function call', TRUE);
545 FUNCTION get_core_ns
RETURN core_ns_type
IS
599 'apply', -- defined in step do_builtin function
600 'map', -- defined in step do_builtin function
611 'swap!' -- defined in step do_builtin function
619 PROMPT
'core.sql finished';