1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 01:57:09 +03:00

plsql: self-hosting. Long strings, refactor io.

This commit is contained in:
Joel Martin 2016-05-03 00:28:33 -05:00
parent 6a08510367
commit 02936b429a
19 changed files with 200 additions and 155 deletions

View File

@ -82,12 +82,18 @@ FUNCTION read_string(M IN OUT NOCOPY mem_type,
H IN OUT NOCOPY types.map_entry_table,
args mal_seq_items_type) RETURN integer IS
BEGIN
RETURN reader.read_str(M, H, TREAT(M(args(1)) AS mal_str_type).val_str);
IF M(args(1)).type_id = 5 THEN
RETURN reader.read_str(M, H,
TREAT(M(args(1)) AS mal_str_type).val_str);
ELSE
RETURN reader.read_str(M, H,
TREAT(M(args(1)) AS mal_long_str_type).val_long_str);
END IF;
END;
FUNCTION readline(M IN OUT NOCOPY mem_type,
prompt integer) RETURN integer IS
input varchar2(4000);
input CLOB;
BEGIN
input := stream_readline(TREAT(M(prompt) AS mal_str_type).val_str, 0);
RETURN types.string(M, input);
@ -101,10 +107,9 @@ END;
FUNCTION slurp(M IN OUT NOCOPY mem_type,
args mal_seq_items_type) RETURN integer IS
content varchar2(4000);
content CLOB;
BEGIN
-- stream_writeline('here1: ' || TREAT(args(1) AS mal_str_type).val_str);
content := file_open_and_read(TREAT(M(args(1)) AS mal_str_type).val_str);
content := io.file_open_and_read(TREAT(M(args(1)) AS mal_str_type).val_str);
content := REPLACE(content, '\n', chr(10));
RETURN types.string(M, content);
END;
@ -398,7 +403,7 @@ FUNCTION seq(M IN OUT NOCOPY mem_type,
val integer) RETURN integer IS
type_id integer;
new_val integer;
str varchar2(4000);
str CLOB;
str_items mal_seq_items_type;
BEGIN
type_id := M(val).type_id;
@ -466,7 +471,7 @@ FUNCTION do_core_func(M IN OUT NOCOPY mem_type,
H IN OUT NOCOPY types.map_entry_table,
fn integer,
a mal_seq_items_type) RETURN integer IS
fname varchar(100);
fname varchar(256);
idx integer;
BEGIN
IF M(fn).type_id <> 11 THEN

View File

@ -4,7 +4,7 @@
PROMPT "env.sql start";
CREATE OR REPLACE TYPE env_item FORCE AS OBJECT (
key varchar2(100),
key varchar2(256),
val integer
) FINAL;
/
@ -113,7 +113,7 @@ CREATE OR REPLACE PACKAGE BODY env_pkg IS
eeT env_entry_table,
eidx integer,
key integer) RETURN integer IS
k varchar2(100);
k varchar2(256);
cnt integer;
BEGIN
k := TREAT(M(key) AS mal_str_type).val_str;
@ -131,7 +131,7 @@ CREATE OR REPLACE PACKAGE BODY env_pkg IS
eidx integer,
key integer) RETURN integer IS
found integer;
k varchar2(100);
k varchar2(256);
BEGIN
found := env_find(M, eeT, eidx, key);
k := TREAT(M(key) AS mal_str_type).val_str;

View File

@ -7,9 +7,9 @@ END;
CREATE TABLE stream (
stream_id integer,
open number(1,0), -- stream open (1) or closed (0)
data varchar2(4000), -- queued stream data
rl_prompt varchar2(4000) -- prompt for readline input
open number(1,0), -- stream open (1) or closed (0)
data CLOB, -- queued stream data
rl_prompt varchar2(256) -- prompt for readline input
);
-- stdin
@ -30,14 +30,30 @@ END;
CREATE TABLE file_io (
path varchar2(1024), -- file to read/write
data varchar2(4000), -- file data
data CLOB, -- file data
error varchar2(1024), -- any errors during read
in_or_out varchar2(4) -- input ('in') or output ('out')
);
-- ---------------------------------------------------------
CREATE OR REPLACE PROCEDURE stream_open(sid integer) AS
CREATE OR REPLACE PACKAGE io IS
PROCEDURE open(sid integer);
PROCEDURE close(sid integer);
FUNCTION read(sid integer DEFAULT 0) RETURN CLOB;
FUNCTION readline(prompt varchar, sid integer DEFAULT 0) RETURN CLOB;
PROCEDURE write(input CLOB, sid integer DEFAULT 1);
PROCEDURE writeline(data CLOB, sid integer DEFAULT 1);
FUNCTION wait_rl_prompt(sid integer DEFAULT 0) RETURN varchar;
PROCEDURE wait_flushed(sid integer DEFAULT 1);
FUNCTION file_open_and_read(path varchar) RETURN varchar;
END io;
/
show errors;
CREATE OR REPLACE PACKAGE BODY io AS
PROCEDURE open(sid integer) AS
BEGIN
-- DBMS_OUTPUT.PUT_LINE('stream_open(' || sid || ') start');
UPDATE stream SET data = '', rl_prompt = '', open = 1
@ -45,9 +61,8 @@ BEGIN
COMMIT;
-- DBMS_OUTPUT.PUT_LINE('stream_open(' || sid || ') done');
END;
/
CREATE OR REPLACE PROCEDURE stream_close(sid integer) AS
PROCEDURE close(sid integer) AS
BEGIN
-- DBMS_OUTPUT.PUT_LINE('stream_close(' || sid || ') start');
UPDATE stream SET rl_prompt = '', open = 0
@ -55,16 +70,14 @@ BEGIN
COMMIT;
-- DBMS_OUTPUT.PUT_LINE('stream_close(' || sid || ') done');
END;
/
-- stream_read:
-- read from stream stream_id in stream table. Waits until there is
-- either data to return or the stream closes (NULL data). Returns
-- NULL when stream is closed.
CREATE OR REPLACE FUNCTION stream_read(sid integer DEFAULT 0)
RETURN varchar IS
FUNCTION read(sid integer DEFAULT 0) RETURN CLOB IS
PRAGMA AUTONOMOUS_TRANSACTION;
input varchar(4000);
input CLOB;
isopen integer;
sleep real;
BEGIN
@ -93,12 +106,10 @@ BEGIN
END IF;
END LOOP;
END;
/
-- stream_readline:
-- readline:
-- set prompt and wait for readline style input on the stream
CREATE OR REPLACE FUNCTION stream_readline(prompt varchar, sid integer DEFAULT 0)
RETURN varchar IS
FUNCTION readline(prompt varchar, sid integer DEFAULT 0) RETURN CLOB IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
-- set prompt / request readline style input
@ -106,36 +117,32 @@ BEGIN
UPDATE stream SET rl_prompt = prompt WHERE stream_id = sid;
COMMIT;
RETURN stream_read(sid);
RETURN read(sid);
END;
/
CREATE OR REPLACE PROCEDURE stream_write(input varchar, sid integer DEFAULT 1) AS
PROCEDURE write(input CLOB, sid integer DEFAULT 1) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
-- LOCK TABLE stream IN EXCLUSIVE MODE;
UPDATE stream SET data = data || input WHERE stream_id = sid;
COMMIT;
END;
/
CREATE OR REPLACE PROCEDURE stream_writeline(data varchar, sid integer DEFAULT 1) AS
PROCEDURE writeline(data CLOB, sid integer DEFAULT 1) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
stream_write(data || chr(10), sid);
write(data || TO_CLOB(chr(10)), sid);
END;
/
-- ---------------------------------------------------------
-- wait_rl_prompt:
-- wait for rl_prompt to be set on the given stream and return the
-- rl_prompt value. Errors if stream is already closed.
CREATE OR REPLACE FUNCTION stream_wait_rl_prompt(sid integer DEFAULT 0)
RETURN varchar IS
FUNCTION wait_rl_prompt(sid integer DEFAULT 0) RETURN varchar IS
PRAGMA AUTONOMOUS_TRANSACTION;
isopen integer;
prompt varchar(4000);
prompt CLOB;
sleep real;
datas integer;
BEGIN
@ -145,7 +152,7 @@ BEGIN
LOCK TABLE stream IN EXCLUSIVE MODE;
SELECT open, rl_prompt INTO isopen, prompt
FROM stream WHERE stream_id = sid;
SELECT count(data) INTO datas FROM stream WHERE data IS NOT NULL;
SELECT count(*) INTO datas FROM stream WHERE data IS NOT NULL;
IF isopen = 0 THEN
raise_application_error(-20001,
@ -168,9 +175,8 @@ BEGIN
END IF;
END LOOP;
END;
/
CREATE OR REPLACE PROCEDURE stream_wait_flushed(sid integer DEFAULT 1) AS
PROCEDURE wait_flushed(sid integer DEFAULT 1) AS
PRAGMA AUTONOMOUS_TRANSACTION;
pending integer;
sleep real;
@ -178,8 +184,8 @@ BEGIN
sleep := 0.05;
WHILE true
LOOP
SELECT count(data) INTO pending FROM stream
WHERE stream_id = sid AND data IS NOT NULL AND data <> '';
SELECT count(*) INTO pending FROM stream
WHERE stream_id = sid AND data IS NOT NULL;
IF pending = 0 THEN RETURN; END IF;
DBMS_LOCK.SLEEP(sleep);
IF sleep < 0.5 THEN
@ -187,15 +193,13 @@ BEGIN
END IF;
END LOOP;
END;
/
-- ---------------------------------------------------------
CREATE OR REPLACE FUNCTION file_open_and_read(path varchar)
RETURN varchar IS
FUNCTION file_open_and_read(path varchar) RETURN varchar IS
PRAGMA AUTONOMOUS_TRANSACTION;
sleep real;
content varchar2(4000);
sleep real;
content CLOB;
error_msg varchar2(1024);
BEGIN
sleep := 0.05;
@ -227,12 +231,13 @@ BEGIN
END IF;
END LOOP;
END;
/
CREATE OR REPLACE PROCEDURE file_read_response(path varchar, data varchar) AS
PROCEDURE file_read_response(path varchar, data varchar) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE file_io SET data = data WHERE path = path;
END;
/
END io;
/
show errors;

View File

@ -17,5 +17,9 @@ SET DEFINE OFF;
-- Print DBMS_OUTPUT.PUT_LINE debugcommands
SET SERVEROUTPUT ON SIZE 30000;
-- Do not truncate or wrap CLOB output
SET LONG 32767;
SET LONGCHUNKSIZE 32767;
-- PROMPT 'Finish login.sql';

View File

@ -22,7 +22,7 @@ FUNCTION pr_str_seq(M IN OUT NOCOPY mem_type,
seq mal_seq_items_type, sep varchar2,
print_readably boolean DEFAULT TRUE) RETURN varchar IS
first integer := 1;
str varchar2(4000) := '';
str CLOB;
BEGIN
FOR i IN 1..seq.COUNT LOOP
IF first = 1 THEN
@ -41,7 +41,7 @@ FUNCTION pr_str_map(M IN OUT NOCOPY mem_type,
print_readably boolean DEFAULT TRUE) RETURN varchar IS
key varchar2(256);
first integer := 1;
str varchar2(4000) := '';
str CLOB;
BEGIN
key := H(midx).FIRST();
WHILE key IS NOT NULL LOOP
@ -65,7 +65,7 @@ FUNCTION pr_str(M IN OUT NOCOPY mem_type,
type_id integer;
first integer := 1;
i integer;
str varchar2(4000);
str CLOB;
malfn malfunc_type;
BEGIN
type_id := M(ast).type_id;
@ -76,8 +76,12 @@ BEGIN
WHEN type_id = 2 THEN RETURN 'true';
WHEN type_id = 3 THEN -- integer
RETURN CAST(TREAT(M(ast) AS mal_int_type).val_int as varchar);
WHEN type_id = 5 THEN -- string
str := TREAT(M(ast) as mal_str_type).val_str;
WHEN type_id IN (5,6) THEN -- string
IF type_id = 5 THEN
str := TREAT(M(ast) as mal_str_type).val_str;
ELSE
str := TREAT(M(ast) as mal_long_str_type).val_long_str;
END IF;
IF chr(127) = SUBSTR(str, 1, 1) THEN
RETURN ':' || SUBSTR(str, 2, LENGTH(str)-1);
ELSIF print_readably THEN

View File

@ -3,7 +3,7 @@
PROMPT "reader.sql start";
CREATE OR REPLACE TYPE tokens FORCE AS TABLE OF varchar2(4000);
CREATE OR REPLACE TYPE tokens FORCE AS TABLE OF CLOB;
/
CREATE OR REPLACE TYPE readerT FORCE AS OBJECT (
@ -44,7 +44,7 @@ CREATE OR REPLACE PACKAGE BODY reader AS
FUNCTION tokenize(str varchar) RETURN tokens IS
re varchar2(100) := '[[:space:] ,]*(~@|[][{}()''`~@]|"(([\].|[^\"])*)"|;[^' || chr(10) || ']*|[^][[:space:] {}()''"`~@,;]*)';
tok varchar2(4000);
tok CLOB;
toks tokens := tokens();
cnt integer;
BEGIN
@ -66,8 +66,9 @@ END;
FUNCTION read_atom(M IN OUT NOCOPY mem_type,
rdr IN OUT NOCOPY readerT) RETURN integer IS
str_id integer;
str varchar2(4000);
token varchar2(4000);
str CLOB;
token CLOB;
istr varchar2(256);
result integer;
BEGIN
token := rdr.next();
@ -79,7 +80,8 @@ BEGIN
ELSIF token = 'true' THEN -- true
result := 3;
ELSIF REGEXP_LIKE(token, '^-?[0-9][0-9]*$') THEN -- integer
result := types.int(M, CAST(token AS integer));
istr := token;
result := types.int(M, CAST(istr AS integer));
ELSIF REGEXP_LIKE(token, '^".*"') THEN -- string
-- string
str := SUBSTR(token, 2, LENGTH(token)-2);
@ -110,7 +112,7 @@ FUNCTION read_seq(M IN OUT NOCOPY mem_type,
rdr IN OUT NOCOPY readerT, type_id integer,
first varchar, last varchar)
RETURN integer IS
token varchar2(4000);
token CLOB;
items mal_seq_items_type;
BEGIN
token := rdr.next();
@ -143,7 +145,7 @@ END;
FUNCTION read_form(M IN OUT NOCOPY mem_type,
H IN OUT NOCOPY types.map_entry_table,
rdr IN OUT NOCOPY readerT) RETURN integer IS
token varchar2(4000);
token CLOB;
meta integer;
midx integer;
BEGIN

View File

@ -11,7 +11,7 @@ END mal;
CREATE OR REPLACE PACKAGE BODY mal IS
FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
line varchar2(4000);
line CLOB;
-- read
FUNCTION READ(line varchar) RETURN varchar IS
@ -40,18 +40,18 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -15,7 +15,7 @@ CREATE OR REPLACE PACKAGE BODY mal IS
FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
M mem_type; -- general mal value memory pool
H types.map_entry_table; -- hashmap memory pool
line varchar2(4000);
line CLOB;
-- read
FUNCTION READ(line varchar) RETURN integer IS
@ -48,18 +48,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -17,7 +17,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
H types.map_entry_table; -- hashmap memory pool
TYPE env_type IS TABLE OF integer INDEX BY varchar2(100);
repl_env env_type;
line varchar2(4000);
line CLOB;
-- read
FUNCTION READ(line varchar) RETURN integer IS
@ -119,7 +119,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
FUNCTION do_core_func(fn integer, args mal_seq_items_type)
RETURN integer IS
fname varchar(100);
fname varchar(256);
BEGIN
IF M(fn).type_id <> 11 THEN
raise_application_error(-20004,
@ -154,18 +154,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -19,7 +19,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
-- read
FUNCTION READ(line varchar) RETURN integer IS
@ -72,7 +72,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
FUNCTION EVAL(ast integer, env integer) RETURN integer IS
el integer;
a0 integer;
a0sym varchar2(100);
a0sym varchar2(256);
seq mal_seq_items_type;
let_env integer;
i integer;
@ -150,7 +150,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
FUNCTION do_core_func(fn integer, args mal_seq_items_type)
RETURN integer IS
fname varchar(100);
fname varchar(256);
BEGIN
IF M(fn).type_id <> 11 THEN
raise_application_error(-20004,
@ -191,18 +191,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -20,7 +20,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
core_ns core_ns_type;
cidx integer;
@ -179,18 +179,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -20,7 +20,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
core_ns core_ns_type;
cidx integer;
@ -186,18 +186,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -20,7 +20,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
core_ns core_ns_type;
cidx integer;
argv mal_seq_items_type;
@ -243,18 +243,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -20,7 +20,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
core_ns core_ns_type;
cidx integer;
argv mal_seq_items_type;
@ -278,18 +278,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -20,7 +20,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
core_ns core_ns_type;
cidx integer;
argv mal_seq_items_type;
@ -337,18 +337,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -20,7 +20,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
core_ns core_ns_type;
cidx integer;
argv mal_seq_items_type;
@ -423,18 +423,18 @@ BEGIN
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -20,7 +20,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
E env_pkg.env_entry_table; -- mal env memory pool
repl_env integer;
x integer;
line varchar2(4000);
line CLOB;
core_ns core_ns_type;
cidx integer;
argv mal_seq_items_type;
@ -162,7 +162,7 @@ FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
args mal_seq_items_type;
BEGIN
WHILE TRUE LOOP
-- stream_writeline('EVAL: ' || printer.pr_str(M, H, ast));
-- io.writeline('EVAL: ' || printer.pr_str(M, H, ast));
IF M(ast).type_id <> 8 THEN
RETURN eval_ast(ast, env);
END IF;
@ -427,18 +427,18 @@ BEGIN
line := REP('(println (str "Mal [" *host-language* "]"))');
WHILE true LOOP
BEGIN
line := stream_readline('user> ', 0);
IF line IS NULL THEN CONTINUE; END IF;
line := io.readline('user> ', 0);
IF line IS NULL OR line = EMPTY_CLOB() THEN CONTINUE; END IF;
IF line IS NOT NULL THEN
stream_writeline(REP(line));
io.writeline(REP(line));
END IF;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -20001 THEN -- io streams closed
RETURN 0;
END IF;
stream_writeline('Error: ' || SQLERRM);
stream_writeline(dbms_utility.format_error_backtrace);
io.writeline('Error: ' || SQLERRM);
io.writeline(dbms_utility.format_error_backtrace);
END;
END LOOP;
END;

View File

@ -17,7 +17,7 @@ END;
-- 3: integer
-- 4: float
-- 5: string
-- 6: keyword (not used, uses prefixed string)
-- 6: long string (CLOB)
-- 7: symbol
-- 8: list
-- 9: vector
@ -38,11 +38,17 @@ CREATE OR REPLACE TYPE mal_int_type FORCE UNDER mal_type (
) FINAL;
/
-- string/keyword (5), symbol (7)
-- string/keyword (5,6), symbol (7)
CREATE OR REPLACE TYPE mal_str_type FORCE UNDER mal_type (
val_str varchar2(4000)
) NOT FINAL;
/
CREATE OR REPLACE TYPE mal_long_str_type FORCE UNDER mal_str_type (
val_long_str CLOB -- long character object (for larger than 4000 chars)
) FINAL;
/
show errors;
-- list (8), vector (9)
CREATE OR REPLACE TYPE mal_seq_items_type FORCE AS TABLE OF integer;
@ -216,7 +222,7 @@ BEGIN
WHEN atyp = 3 THEN
RETURN TREAT(M(a) AS mal_int_type).val_int =
TREAT(M(b) AS mal_int_type).val_int;
WHEN atyp IN (5,7) THEN
WHEN atyp IN (5,6,7) THEN
IF TREAT(M(a) AS mal_str_type).val_str IS NULL AND
TREAT(M(b) AS mal_str_type).val_str IS NULL THEN
RETURN TRUE;
@ -317,16 +323,26 @@ END;
FUNCTION string(M IN OUT NOCOPY mem_type, name varchar) RETURN integer IS
BEGIN
M.EXTEND();
M(M.COUNT()) := mal_str_type(5, name);
IF LENGTH(name) <= 4000 THEN
M(M.COUNT()) := mal_str_type(5, name);
ELSE
M(M.COUNT()) := mal_long_str_type(6, NULL, name);
END IF;
RETURN M.COUNT();
END;
FUNCTION string_Q(M IN OUT NOCOPY mem_type, val integer) RETURN boolean IS
str varchar2(4000);
str CLOB;
BEGIN
IF M(val).type_id = 5 THEN
str := TREAT(M(val) AS mal_str_type).val_str;
IF str IS NULL OR SUBSTR(str, 1, 1) <> chr(127) THEN
IF M(val).type_id IN (5,6) THEN
IF M(val).type_id = 5 THEN
str := TREAT(M(val) AS mal_str_type).val_str;
ELSE
str := TREAT(M(val) AS mal_long_str_type).val_long_str;
END IF;
IF str IS NULL OR
str = EMPTY_CLOB() OR
SUBSTR(str, 1, 1) <> chr(127) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
@ -351,7 +367,7 @@ BEGIN
END;
FUNCTION keyword_Q(M IN OUT NOCOPY mem_type, val integer) RETURN boolean IS
str varchar2(4000);
str CLOB;
BEGIN
IF M(val).type_id = 5 THEN
str := TREAT(M(val) AS mal_str_type).val_str;

View File

@ -28,15 +28,15 @@ if [ -z "${SKIP_INIT}" ]; then
fi
# open I/O streams
echo -e "BEGIN stream_open(0); stream_open(1); END;\n/" \
echo -e "BEGIN io.open(0); io.open(1); END;\n/" \
| ${SQLPLUS} >/dev/null
# Stream from table to stdout
(
while true; do
out="$(echo "SELECT stream_read(1) FROM dual;" \
out="$(echo "SELECT io.read(1) FROM dual;" \
| ${SQLPLUS} 2>/dev/null)" || break
#echo "out: [${out}]"
#echo "out: [${out}] (${#out})"
echo "${out}"
done
) &
@ -45,7 +45,7 @@ done
(
[ -r ${RL_HISTORY_FILE} ] && history -r ${RL_HISTORY_FILE}
while true; do
prompt=$(echo "SELECT stream_wait_rl_prompt(0) FROM dual;" \
prompt=$(echo "SELECT io.wait_rl_prompt(0) FROM dual;" \
| ${SQLPLUS} 2>/dev/null) || break
# Prompt is returned single-quoted because sqlplus trims trailing
# whitespace. Remove the single quotes from the beginning and end:
@ -62,11 +62,11 @@ while true; do
# Escape (double) single quotes per SQL norm
line=${line//\'/\'\'}
#echo "line: [${line}]"
( echo -n "BEGIN stream_writeline('${line}', 0); END;";
( echo -n "BEGIN io.writeline('${line}', 0); END;";
echo -en "\n/" ) \
| ${SQLPLUS} >/dev/null || break
done
echo -e "BEGIN stream_close(0); stream_close(1); END;\n/" \
echo -e "BEGIN io.close(0); io.close(1); END;\n/" \
| ${SQLPLUS} > /dev/null
) <&0 >&1 &
@ -78,18 +78,25 @@ while true; do
| ${SQLPLUS} 2>/dev/null \
| grep -v "^no rows selected")" || break
for f in ${files}; do
if [ -r ${f} ]; then
IFS= read -rd '' content < "${f}"
content=${content//\'/\'\'}
content=${content//$'\n'/\\n}
#content=$(printf "%q" "$(cat ${f})")
#content="${content#$}" # strip bash leading $
echo "UPDATE file_io SET data = '${content}' WHERE path = '${f}' AND in_or_out = 'in';" \
| ${SQLPLUS} >/dev/null
else
if [ ! -r ${f} ]; then
echo "UPDATE file_io SET error = 'Cannot read ''${f}''' WHERE path = '${f}' AND in_or_out = 'in';" \
| ${SQLPLUS} >/dev/null
continue;
fi
IFS= read -rd '' content < "${f}"
# sqlplus limits lines to 2499 characters so split the update
# into chunks of the file ORed together over multiple lines
query="UPDATE file_io SET data = TO_CLOB('')"
while [ -n "${content}" ]; do
chunk="${content:0:2000}"
content="${content:${#chunk}}"
chunk="${chunk//\'/\'\'}"
chunk="${chunk//$'\n'/\\n}"
query="${query}"$'\n'" || TO_CLOB('${chunk}')"
done
query="${query}"$'\n'" WHERE path = '${f}' AND in_or_out = 'in';"
echo "${query}" | ${SQLPLUS} > /dev/null
#echo "file read: ${f}: ${?}"
done
sleep 1
done
@ -112,6 +119,8 @@ else
| ${SQLPLUS} > /dev/null
res=$?
fi
echo -e "BEGIN stream_close(0); stream_close(1); END;\n/" \
# TODO: fix this
sleep 2
echo -e "BEGIN io.close(0); io.close(1); END;\n/" \
| ${SQLPLUS} > /dev/null
exit ${res}