1 -- ---------------------------------------------------------
5 EXECUTE IMMEDIATE 'DROP TYPE mal_T FORCE';
7 WHEN OTHERS THEN IF SQLCODE != -4043 THEN RAISE
; END IF;
11 -- list of types for type_id
18 -- 6: long string (CLOB)
27 -- nil (0), false (1), true (2)
28 CREATE OR REPLACE TYPE mal_T
FORCE AS OBJECT (
33 -- general nested table of mal values (integers)
34 -- used frequently for argument passing
35 CREATE OR REPLACE TYPE mal_vals
FORCE AS TABLE OF integer;
40 CREATE OR REPLACE TYPE mal_int_T
FORCE UNDER mal_T (
45 -- string/keyword (5,6), symbol (7)
46 CREATE OR REPLACE TYPE mal_str_T
FORCE UNDER mal_T (
47 val_str
varchar2(4000)
51 CREATE OR REPLACE TYPE mal_long_str_T
FORCE UNDER mal_str_T (
52 val_long_str
CLOB -- long character object (for larger than 4000 chars)
57 -- list (8), vector (9)
58 CREATE OR REPLACE TYPE mal_seq_T
FORCE UNDER mal_T (
64 CREATE OR REPLACE TYPE mal_map_T
FORCE UNDER mal_T (
65 map_idx
integer, -- index into map entry table
71 CREATE OR REPLACE TYPE mal_func_T
FORCE UNDER mal_T (
81 CREATE OR REPLACE TYPE mal_atom_T
FORCE UNDER mal_T (
82 val
integer -- index into mal_table
87 -- ---------------------------------------------------------
89 CREATE OR REPLACE PACKAGE types
IS
90 -- memory pool for mal_objects (non-hash-map)
91 TYPE mal_table
IS TABLE OF mal_T
;
93 -- memory pool for hash-map objects
94 TYPE map_entry
IS TABLE OF integer INDEX BY varchar2(256);
95 TYPE map_entry_table
IS TABLE OF map_entry
;
98 FUNCTION mem_new
RETURN mal_table
;
100 FUNCTION tf(val
boolean) RETURN integer;
101 FUNCTION equal_Q(M
IN OUT NOCOPY mal_table
,
102 H
IN OUT NOCOPY map_entry_table
,
103 a
integer, b
integer) RETURN boolean;
105 FUNCTION clone(M
IN OUT NOCOPY mal_table
,
106 H
IN OUT NOCOPY map_entry_table
,
108 meta
integer DEFAULT 1) RETURN integer;
111 FUNCTION int(M
IN OUT NOCOPY mal_table
, num
integer) RETURN integer;
112 FUNCTION string(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer;
113 FUNCTION string_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean;
114 FUNCTION symbol(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer;
115 FUNCTION keyword(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer;
116 FUNCTION keyword_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean;
117 FUNCTION number_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean;
118 FUNCTION function_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean;
119 FUNCTION macro_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean;
121 -- sequence functions
122 FUNCTION seq(M
IN OUT NOCOPY mal_table
,
125 meta
integer DEFAULT 1) RETURN integer;
126 FUNCTION list(M
IN OUT NOCOPY mal_table
) RETURN integer;
127 FUNCTION list(M
IN OUT NOCOPY mal_table
,
128 a
integer) RETURN integer;
129 FUNCTION list(M
IN OUT NOCOPY mal_table
,
130 a
integer, b
integer) RETURN integer;
131 FUNCTION list(M
IN OUT NOCOPY mal_table
,
132 a
integer, b
integer, c
integer) RETURN integer;
134 FUNCTION first(M
IN OUT NOCOPY mal_table
,
135 seq
integer) RETURN integer;
136 FUNCTION slice(M
IN OUT NOCOPY mal_table
,
139 last integer DEFAULT NULL) RETURN integer;
140 FUNCTION slice(M
IN OUT NOCOPY mal_table
,
142 idx
integer) RETURN integer;
143 FUNCTION islice(items mal_vals
,
144 idx
integer) RETURN mal_vals
;
145 FUNCTION nth(M
IN OUT NOCOPY mal_table
,
146 seq
integer, idx
integer) RETURN integer;
148 FUNCTION count(M
IN OUT NOCOPY mal_table
,
149 seq
integer) RETURN integer;
151 FUNCTION atom_new(M
IN OUT NOCOPY mal_table
,
152 val
integer) RETURN integer;
153 FUNCTION atom_reset(M
IN OUT NOCOPY mal_table
,
155 val
integer) RETURN integer;
157 -- hash-map functions
158 FUNCTION assoc_BANG(M
IN OUT NOCOPY mal_table
,
159 H
IN OUT NOCOPY map_entry_table
,
161 kvs mal_vals
) RETURN integer;
162 FUNCTION dissoc_BANG(M
IN OUT NOCOPY mal_table
,
163 H
IN OUT NOCOPY map_entry_table
,
165 ks mal_vals
) RETURN integer;
166 FUNCTION hash_map(M
IN OUT NOCOPY mal_table
,
167 H
IN OUT NOCOPY map_entry_table
,
169 meta
integer DEFAULT 1) RETURN integer;
171 -- function functions
172 FUNCTION func(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer;
173 FUNCTION malfunc(M
IN OUT NOCOPY mal_table
,
177 is_macro
integer DEFAULT 0,
178 meta
integer DEFAULT 1) RETURN integer;
184 CREATE OR REPLACE PACKAGE BODY types
IS
186 -- ---------------------------------------------------------
189 FUNCTION mem_new
RETURN mal_table
IS
191 -- initialize mal type memory pool
195 RETURN mal_table(mal_T(0), mal_T(1), mal_T(2));
198 FUNCTION tf(val
boolean) RETURN integer IS
207 FUNCTION equal_Q(M
IN OUT NOCOPY mal_table
,
208 H
IN OUT NOCOPY map_entry_table
,
209 a
integer, b
integer) RETURN boolean IS
219 atyp
:= M(a
).type_id
;
220 btyp
:= M(b
).type_id
;
221 IF NOT (atyp
= btyp
OR (atyp
IN (8,9) AND btyp
IN (8,9))) THEN
226 WHEN atyp
IN (0,1,2) THEN
229 RETURN TREAT(M(a
) AS mal_int_T
).val_int
=
230 TREAT(M(b
) AS mal_int_T
).val_int
;
231 WHEN atyp
IN (5,6,7) THEN
232 IF TREAT(M(a
) AS mal_str_T
).val_str
IS NULL AND
233 TREAT(M(b
) AS mal_str_T
).val_str
IS NULL THEN
236 RETURN TREAT(M(a
) AS mal_str_T
).val_str
=
237 TREAT(M(b
) AS mal_str_T
).val_str
;
239 WHEN atyp
IN (8,9) THEN
240 aseq
:= TREAT(M(a
) AS mal_seq_T
).val_seq
;
241 bseq
:= TREAT(M(b
) AS mal_seq_T
).val_seq
;
242 IF aseq.
COUNT <> bseq.
COUNT THEN
245 FOR i
IN 1..aseq.
COUNT LOOP
246 IF NOT equal_Q(M
, H
, aseq(i
), bseq(i
)) THEN
252 amidx
:= TREAT(M(a
) AS mal_map_T
).map_idx
;
253 bmidx
:= TREAT(M(b
) AS mal_map_T
).map_idx
;
254 IF H(amidx
).
COUNT() <> H(bmidx
).
COUNT() THEN
258 k
:= H(amidx
).
FIRST();
259 WHILE k
IS NOT NULL LOOP
260 IF H(amidx
)(k
) IS NULL OR H(bmidx
)(k
) IS NULL THEN
263 IF NOT equal_Q(M
, H
, H(amidx
)(k
), H(bmidx
)(k
)) THEN
266 k
:= H(amidx
).
NEXT(k
);
274 FUNCTION clone(M
IN OUT NOCOPY mal_table
,
275 H
IN OUT NOCOPY map_entry_table
,
277 meta
integer DEFAULT 1) RETURN integer IS
285 type_id
:= M(obj
).type_id
;
287 WHEN type_id
IN (8,9) THEN -- list/vector
288 RETURN seq(M
, type_id
,
289 TREAT(M(obj
) AS mal_seq_T
).val_seq
,
291 WHEN type_id
= 10 THEN -- hash-map
292 new_hm
:= types.
hash_map(M
, H
, mal_vals(), meta
);
293 old_midx
:= TREAT(M(obj
) AS mal_map_T
).map_idx
;
294 new_midx
:= TREAT(M(new_hm
) AS mal_map_T
).map_idx
;
296 k
:= H(old_midx
).
FIRST();
297 WHILE k
IS NOT NULL LOOP
298 H(new_midx
)(k
) := H(old_midx
)(k
);
299 k
:= H(old_midx
).
NEXT(k
);
303 WHEN type_id
= 12 THEN -- mal function
304 malfn
:= TREAT(M(obj
) AS mal_func_T
);
305 RETURN types.
malfunc(M
,
312 raise_application_error(-20008,
313 'clone not supported for type ' || type_id
, TRUE);
318 -- ---------------------------------------------------------
322 FUNCTION int(M
IN OUT NOCOPY mal_table
, num
integer) RETURN integer IS
325 M(M.
COUNT()) := mal_int_T(3, num
);
329 FUNCTION string(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer IS
332 IF LENGTH(name) <= 4000 THEN
333 M(M.
COUNT()) := mal_str_T(5, name);
335 M(M.
COUNT()) := mal_long_str_T(6, NULL, name);
340 FUNCTION string_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean IS
343 IF M(val
).type_id
IN (5,6) THEN
344 IF M(val
).type_id
= 5 THEN
345 str
:= TREAT(M(val
) AS mal_str_T
).val_str
;
347 str
:= TREAT(M(val
) AS mal_long_str_T
).val_long_str
;
350 str
= EMPTY_CLOB() OR
351 SUBSTR(str
, 1, 1) <> chr(127) THEN
361 FUNCTION symbol(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer IS
364 M(M.
COUNT()) := mal_str_T(7, name);
368 FUNCTION keyword(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer IS
371 M(M.
COUNT()) := mal_str_T(5, chr(127) ||
name);
375 FUNCTION keyword_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean IS
378 IF M(val
).type_id
= 5 THEN
379 str
:= TREAT(M(val
) AS mal_str_T
).val_str
;
380 IF LENGTH(str
) > 0 AND SUBSTR(str
, 1, 1) = chr(127) THEN
390 FUNCTION number_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean IS
393 IF M(val
).type_id
IN (3,4) THEN
400 FUNCTION function_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean IS
403 IF M(val
).type_id
= 11 THEN
405 ELSIF
M(val
).type_id
= 12 THEN
406 RETURN TREAT(M(val
) AS mal_func_T
).is_macro
= 0;
412 FUNCTION macro_Q(M
IN OUT NOCOPY mal_table
, val
integer) RETURN boolean IS
415 IF M(val
).type_id
= 12 THEN
416 RETURN TREAT(M(val
) AS mal_func_T
).is_macro
> 0;
423 -- ---------------------------------------------------------
424 -- sequence functions
426 FUNCTION seq(M
IN OUT NOCOPY mal_table
,
429 meta
integer DEFAULT 1) RETURN integer IS
432 M(M.
COUNT()) := mal_seq_T(type_id
, items
, meta
);
438 FUNCTION list(M
IN OUT NOCOPY mal_table
) RETURN integer IS
441 M(M.
COUNT()) := mal_seq_T(8, mal_vals(), 1);
445 FUNCTION list(M
IN OUT NOCOPY mal_table
,
446 a
integer) RETURN integer IS
449 M(M.
COUNT()) := mal_seq_T(8, mal_vals(a
), 1);
453 FUNCTION list(M
IN OUT NOCOPY mal_table
,
454 a
integer, b
integer) RETURN integer IS
457 M(M.
COUNT()) := mal_seq_T(8, mal_vals(a
, b
), 1);
461 FUNCTION list(M
IN OUT NOCOPY mal_table
,
462 a
integer, b
integer, c
integer) RETURN integer IS
465 M(M.
COUNT()) := mal_seq_T(8, mal_vals(a
, b
, c
), 1);
469 FUNCTION first(M
IN OUT NOCOPY mal_table
,
470 seq
integer) RETURN integer IS
472 RETURN TREAT(M(seq
) AS mal_seq_T
).
val_seq(1);
475 FUNCTION slice(M
IN OUT NOCOPY mal_table
,
478 last integer DEFAULT NULL) RETURN integer IS
484 old_items
:= TREAT(M(seq
) AS mal_seq_T
).val_seq
;
485 new_items
:= mal_vals();
487 final_idx
:= old_items.
COUNT();
489 final_idx
:= last + 1;
491 IF final_idx
> idx
THEN
492 new_items.
EXTEND(final_idx
- idx
);
493 FOR i
IN idx
+1..final_idx LOOP
494 new_items(i
-idx
) := old_items(i
);
498 M(M.
COUNT()) := mal_seq_T(8, new_items
, 1);
502 FUNCTION slice(M
IN OUT NOCOPY mal_table
,
504 idx
integer) RETURN integer IS
507 new_items
:= islice(items
, idx
);
509 M(M.
COUNT()) := mal_seq_T(8, new_items
, 1);
513 FUNCTION islice(items mal_vals
,
514 idx
integer) RETURN mal_vals
IS
518 new_items
:= mal_vals();
519 IF items.
COUNT > idx
THEN
520 new_items.
EXTEND(items.
COUNT - idx
);
521 FOR i
IN idx
+1..items.
COUNT LOOP
522 new_items(i
-idx
) := items(i
);
529 FUNCTION nth(M
IN OUT NOCOPY mal_table
,
530 seq
integer, idx
integer) RETURN integer IS
532 RETURN TREAT(M(seq
) AS mal_seq_T
).
val_seq(idx
+1);
535 FUNCTION count(M
IN OUT NOCOPY mal_table
,
536 seq
integer) RETURN integer IS
538 RETURN TREAT(M(seq
) AS mal_seq_T
).val_seq.
COUNT;
541 -- ---------------------------------------------------------
542 -- hash-map functions
544 FUNCTION assoc_BANG(M
IN OUT NOCOPY mal_table
,
545 H
IN OUT NOCOPY map_entry_table
,
547 kvs mal_vals
) RETURN integer IS
550 IF MOD(kvs.
COUNT(), 2) = 1 THEN
551 raise_application_error(-20007,
552 'odd number of arguments to assoc', TRUE);
556 WHILE i
<= kvs.
COUNT() LOOP
557 H(midx
)(TREAT(M(kvs(i
)) AS mal_str_T
).val_str
) := kvs(i
+1);
563 FUNCTION dissoc_BANG(M
IN OUT NOCOPY mal_table
,
564 H
IN OUT NOCOPY map_entry_table
,
566 ks mal_vals
) RETURN integer IS
569 FOR i
IN 1..ks.
COUNT() LOOP
570 H(midx
).
DELETE(TREAT(M(ks(i
)) AS mal_str_T
).val_str
);
575 FUNCTION hash_map(M
IN OUT NOCOPY mal_table
,
576 H
IN OUT NOCOPY map_entry_table
,
578 meta
integer DEFAULT 1) RETURN integer IS
583 midx
:= assoc_BANG(M
, H
, midx
, kvs
);
586 M(M.
COUNT()) := mal_map_T(10, midx
, meta
);
591 -- ---------------------------------------------------------
592 -- function functions
594 FUNCTION func(M
IN OUT NOCOPY mal_table
, name varchar) RETURN integer IS
597 M(M.
COUNT()) := mal_str_T(11, name);
601 FUNCTION malfunc(M
IN OUT NOCOPY mal_table
,
605 is_macro
integer DEFAULT 0,
606 meta
integer DEFAULT 1) RETURN integer IS
609 M(M.
COUNT()) := mal_func_T(12, ast
, params
, env
, is_macro
, meta
);
614 -- ---------------------------------------------------------
617 FUNCTION atom_new(M
IN OUT NOCOPY mal_table
,
618 val
integer) RETURN integer IS
622 M(M.
COUNT()) := mal_atom_T(13, val
);
626 FUNCTION atom_reset(M
IN OUT NOCOPY mal_table
,
628 val
integer) RETURN integer IS
630 M(atm
) := mal_atom_T(13, val
);