Merge pull request #345 from asarhaddon/ada.2
[jackhill/mal.git] / plpgsql / printer.sql
1 -- ---------------------------------------------------------
2 -- printer.sql
3
4 CREATE SCHEMA printer;
5
6 CREATE FUNCTION printer.pr_str_array(arr integer[],
7 sep varchar, print_readably boolean)
8 RETURNS varchar AS $$
9 DECLARE
10 i integer;
11 res varchar[];
12 BEGIN
13 IF array_length(arr, 1) > 0 THEN
14 FOR i IN array_lower(arr, 1) .. array_upper(arr, 1)
15 LOOP
16 res := array_append(res, printer.pr_str(arr[i], print_readably));
17 END LOOP;
18 RETURN array_to_string(res, sep);
19 ELSE
20 RETURN '';
21 END IF;
22 END; $$ LANGUAGE plpgsql;
23
24 CREATE FUNCTION printer.pr_str(ast integer,
25 print_readably boolean DEFAULT true)
26 RETURNS varchar AS $$
27 DECLARE
28 type integer;
29 seq integer[];
30 hash hstore;
31 cid integer;
32 vid integer;
33 pid integer;
34 str varchar;
35 BEGIN
36 -- RAISE NOTICE 'pr_str ast: %', ast;
37 SELECT type_id FROM types.value WHERE value_id = ast INTO type;
38 -- RAISE NOTICE 'pr_str type: %', type;
39 CASE
40 WHEN type = 0 THEN RETURN 'nil';
41 WHEN type = 1 THEN RETURN 'false';
42 WHEN type = 2 THEN RETURN 'true';
43 WHEN type = 3 THEN -- integer
44 RETURN CAST((SELECT val_int
45 FROM types.value WHERE value_id = ast) as varchar);
46 WHEN type = 5 THEN -- string
47 str := types._valueToString(ast);
48 IF chr(CAST(x'7f' AS integer)) = substring(str FROM 1 FOR 1) THEN
49 RETURN ':' || substring(str FROM 2 FOR (char_length(str)-1));
50 ELSIF print_readably THEN
51 str := replace(str, E'\\', '\\');
52 str := replace(str, '"', '\"');
53 str := replace(str, E'\n', '\n');
54 RETURN '"' || str || '"';
55 ELSE
56 RETURN str;
57 END IF;
58 WHEN type = 7 THEN -- symbol
59 RETURN types._valueToString(ast);
60 WHEN type = 8 THEN -- list
61 BEGIN
62 SELECT val_seq INTO seq FROM types.value WHERE value_id = ast;
63 RETURN '(' ||
64 array_to_string(array(
65 SELECT printer.pr_str(x, print_readably)
66 FROM unnest(seq) AS x), ' ') ||
67 ')';
68 END;
69 WHEN type = 9 THEN -- vector
70 BEGIN
71 SELECT val_seq INTO seq FROM types.value WHERE value_id = ast;
72 RETURN '[' ||
73 array_to_string(array(
74 SELECT printer.pr_str(x, print_readably)
75 FROM unnest(seq) AS x), ' ') ||
76 ']';
77 END;
78 WHEN type = 10 THEN -- hash-map
79 BEGIN
80 SELECT val_hash INTO hash FROM types.value WHERE value_id = ast;
81 RETURN '{' ||
82 array_to_string(array(
83 SELECT printer.pr_str(CAST(key AS integer),
84 print_readably) || ' ' ||
85 printer.pr_str(CAST(value AS integer),
86 print_readably)
87 FROM each(hash)), ' ') ||
88 '}';
89 END;
90 WHEN type = 11 THEN -- native function
91 RETURN '#<function ' ||
92 (SELECT val_string FROM types.value WHERE value_id = ast) ||
93 '>';
94 WHEN type = 12 THEN -- mal function
95 BEGIN
96 SELECT ast_id, params_id
97 INTO vid, pid
98 FROM types.value WHERE value_id = ast;
99 RETURN '(fn* ' || printer.pr_str(pid, print_readably) ||
100 ' ' || printer.pr_str(vid, print_readably) || ')';
101 END;
102 WHEN type = 13 THEN -- atom
103 BEGIN
104 SELECT val_seq[1] INTO vid
105 FROM types.value WHERE value_id = ast;
106 RETURN '(atom ' || printer.pr_str(vid, print_readably) || ')';
107 END;
108 ELSE
109 RETURN 'unknown';
110 END CASE;
111 END; $$ LANGUAGE plpgsql;