mirror of
https://github.com/kanaka/mal.git
synced 2024-11-14 00:09:01 +03:00
4facce82c4
- Use COPY FROM PROGRAM to invoke sed to double backslashes before reading into the table.
110 lines
3.7 KiB
PL/PgSQL
110 lines
3.7 KiB
PL/PgSQL
-- ---------------------------------------------------------
|
|
-- printer.sql
|
|
|
|
CREATE FUNCTION
|
|
pr_str_array(arr integer[], sep varchar, print_readably boolean)
|
|
RETURNS varchar AS $$
|
|
DECLARE
|
|
i integer;
|
|
res varchar[];
|
|
BEGIN
|
|
IF array_length(arr, 1) > 0 THEN
|
|
FOR i IN array_lower(arr, 1) .. array_upper(arr, 1)
|
|
LOOP
|
|
res := array_append(res, pr_str(arr[i], print_readably));
|
|
END LOOP;
|
|
RETURN array_to_string(res, sep);
|
|
ELSE
|
|
RETURN '';
|
|
END IF;
|
|
END; $$ LANGUAGE plpgsql;
|
|
|
|
CREATE FUNCTION
|
|
pr_str(ast integer, print_readably boolean DEFAULT true)
|
|
RETURNS varchar AS $$
|
|
DECLARE
|
|
re varchar = E'[[:space:] ,]*(~@|[\\[\\]{}()\'`~@]|"(?:[\\\\].|[^\\\\"])*"|;.*|[^\\s \\[\\]{}()\'"`~@,;]*)';
|
|
type integer;
|
|
seq integer[];
|
|
hash hstore;
|
|
cid integer;
|
|
vid integer;
|
|
pid integer;
|
|
str varchar;
|
|
BEGIN
|
|
-- RAISE NOTICE 'pr_str ast: %', ast;
|
|
SELECT type_id FROM value WHERE value_id = ast INTO type;
|
|
-- RAISE NOTICE 'pr_str type: %', type;
|
|
CASE
|
|
WHEN type = 0 THEN RETURN 'nil';
|
|
WHEN type = 1 THEN RETURN 'false';
|
|
WHEN type = 2 THEN RETURN 'true';
|
|
WHEN type = 3 THEN -- integer
|
|
RETURN CAST((SELECT val_int
|
|
FROM value WHERE value_id = ast) as varchar);
|
|
WHEN type = 5 THEN -- string
|
|
str := _valueToString(ast);
|
|
IF chr(CAST(x'29e' AS integer)) = substring(str FROM 1 FOR 1) THEN
|
|
RETURN ':' || substring(str FROM 2 FOR (char_length(str)-1));
|
|
ELSIF print_readably THEN
|
|
str := replace(str, E'\\', '\\');
|
|
str := replace(str, '"', '\"');
|
|
str := replace(str, E'\n', '\n');
|
|
RETURN '"' || str || '"';
|
|
ELSE
|
|
RETURN str;
|
|
END IF;
|
|
WHEN type = 7 THEN -- symbol
|
|
RETURN _valueToString(ast);
|
|
WHEN type = 8 THEN -- list
|
|
BEGIN
|
|
SELECT val_seq INTO seq FROM value WHERE value_id = ast;
|
|
RETURN '(' ||
|
|
array_to_string(array(
|
|
SELECT pr_str(x, print_readably)
|
|
FROM unnest(seq) AS x), ' ') ||
|
|
')';
|
|
END;
|
|
WHEN type = 9 THEN -- vector
|
|
BEGIN
|
|
SELECT val_seq INTO seq FROM value WHERE value_id = ast;
|
|
RETURN '[' ||
|
|
array_to_string(array(
|
|
SELECT pr_str(x, print_readably)
|
|
FROM unnest(seq) AS x), ' ') ||
|
|
']';
|
|
END;
|
|
WHEN type = 10 THEN -- hash-map
|
|
BEGIN
|
|
SELECT val_hash INTO hash FROM value WHERE value_id = ast;
|
|
RETURN '{' ||
|
|
array_to_string(array(
|
|
SELECT pr_str(CAST(key AS integer), print_readably) ||
|
|
' ' ||
|
|
pr_str(CAST(value AS integer), print_readably)
|
|
FROM each(hash)), ' ') ||
|
|
'}';
|
|
END;
|
|
WHEN type = 11 THEN -- native function
|
|
RETURN '#<function ' ||
|
|
(SELECT val_string FROM value WHERE value_id = ast) ||
|
|
'>';
|
|
WHEN type = 12 THEN -- mal function
|
|
BEGIN
|
|
SELECT ast_id, params_id
|
|
INTO vid, pid
|
|
FROM value WHERE value_id = ast;
|
|
RETURN '(fn* ' || pr_str(pid, print_readably) ||
|
|
' ' || pr_str(vid, print_readably) || ')';
|
|
END;
|
|
WHEN type = 13 THEN -- atom
|
|
BEGIN
|
|
SELECT val_seq[1] INTO vid
|
|
FROM value WHERE value_id = ast;
|
|
RETURN '(atom ' || pr_str(vid, print_readably) || ')';
|
|
END;
|
|
ELSE
|
|
RETURN 'unknown';
|
|
END CASE;
|
|
END; $$ LANGUAGE plpgsql;
|