plsql: stepA basics. Fix step6 argument processing.
[jackhill/mal.git] / plsql / step2_eval.sql
CommitLineData
7836cfa3
JM
1@io.sql
2@types.sql
3@reader.sql
4@printer.sql
5
0fc03918 6CREATE OR REPLACE PACKAGE mal IS
7836cfa3 7
10cc781f 8FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer;
7836cfa3 9
0fc03918 10END mal;
7836cfa3
JM
11/
12
0fc03918 13CREATE OR REPLACE PACKAGE BODY mal IS
7836cfa3 14
10cc781f 15FUNCTION MAIN(args varchar DEFAULT '()') RETURN integer IS
0fc03918
JM
16 M mem_type;
17 TYPE env_type IS TABLE OF integer INDEX BY varchar2(100);
7836cfa3 18 repl_env env_type;
0fc03918 19 line varchar2(4000);
7836cfa3
JM
20
21 -- read
0fc03918 22 FUNCTION READ(line varchar) RETURN integer IS
7836cfa3 23 BEGIN
0fc03918 24 RETURN reader.read_str(M, line);
7836cfa3
JM
25 END;
26
27 -- eval
28
29 -- forward declarations
0fc03918
JM
30 FUNCTION EVAL(ast integer, env env_type) RETURN integer;
31 FUNCTION do_core_func(fn integer, args mal_seq_items_type)
32 RETURN integer;
7836cfa3 33
0fc03918 34 FUNCTION eval_ast(ast integer, env env_type) RETURN integer IS
7836cfa3
JM
35 i integer;
36 old_seq mal_seq_items_type;
37 new_seq mal_seq_items_type;
7836cfa3 38 BEGIN
0fc03918
JM
39 IF M(ast).type_id = 7 THEN
40 RETURN env(TREAT(M(ast) AS mal_str_type).val_str);
41 ELSIF M(ast).type_id IN (8,9) THEN
42 old_seq := TREAT(M(ast) AS mal_seq_type).val_seq;
7836cfa3
JM
43 new_seq := mal_seq_items_type();
44 new_seq.EXTEND(old_seq.COUNT);
45 FOR i IN 1..old_seq.COUNT LOOP
46 new_seq(i) := EVAL(old_seq(i), env);
47 END LOOP;
0fc03918 48 RETURN types.seq(M, M(ast).type_id, new_seq);
7836cfa3
JM
49 ELSE
50 RETURN ast;
51 END IF;
52 END;
53
0fc03918
JM
54 FUNCTION EVAL(ast integer, env env_type) RETURN integer IS
55 el integer;
56 f integer;
150011e4 57 args mal_seq_items_type;
7836cfa3 58 BEGIN
0fc03918 59 IF M(ast).type_id <> 8 THEN
7836cfa3
JM
60 RETURN eval_ast(ast, env);
61 END IF;
62
63 -- apply
64 el := eval_ast(ast, env);
0fc03918 65 f := types.first(M, el);
150011e4
JM
66 args := TREAT(M(types.slice(M, el, 1)) AS mal_seq_type).val_seq;
67 RETURN do_core_func(f, args);
7836cfa3
JM
68 END;
69
70 -- print
0fc03918 71 FUNCTION PRINT(exp integer) RETURN varchar IS
7836cfa3 72 BEGIN
0fc03918 73 RETURN printer.pr_str(M, exp);
7836cfa3
JM
74 END;
75
7836cfa3 76 -- repl
0fc03918 77 FUNCTION mal_add(args mal_seq_items_type) RETURN integer IS
7836cfa3 78 BEGIN
0fc03918
JM
79 RETURN types.int(M, TREAT(M(args(1)) AS mal_int_type).val_int +
80 TREAT(M(args(2)) AS mal_int_type).val_int);
7836cfa3
JM
81 END;
82
0fc03918 83 FUNCTION mal_subtract(args mal_seq_items_type) RETURN integer IS
7836cfa3 84 BEGIN
0fc03918
JM
85 RETURN types.int(M, TREAT(M(args(1)) AS mal_int_type).val_int -
86 TREAT(M(args(2)) AS mal_int_type).val_int);
7836cfa3
JM
87 END;
88
0fc03918 89 FUNCTION mal_multiply(args mal_seq_items_type) RETURN integer IS
7836cfa3 90 BEGIN
0fc03918
JM
91 RETURN types.int(M, TREAT(M(args(1)) AS mal_int_type).val_int *
92 TREAT(M(args(2)) AS mal_int_type).val_int);
7836cfa3
JM
93 END;
94
0fc03918 95 FUNCTION mal_divide(args mal_seq_items_type) RETURN integer IS
7836cfa3 96 BEGIN
0fc03918
JM
97 RETURN types.int(M, TREAT(M(args(1)) AS mal_int_type).val_int /
98 TREAT(M(args(2)) AS mal_int_type).val_int);
7836cfa3
JM
99 END;
100
0fc03918
JM
101 FUNCTION do_core_func(fn integer, args mal_seq_items_type)
102 RETURN integer IS
7836cfa3
JM
103 fname varchar(100);
104 BEGIN
0fc03918 105 IF M(fn).type_id <> 11 THEN
7836cfa3
JM
106 raise_application_error(-20004,
107 'Invalid function call', TRUE);
108 END IF;
109
0fc03918 110 fname := TREAT(M(fn) AS mal_str_type).val_str;
9fc524f1 111 CASE
7836cfa3
JM
112 WHEN fname = '+' THEN RETURN mal_add(args);
113 WHEN fname = '-' THEN RETURN mal_subtract(args);
114 WHEN fname = '*' THEN RETURN mal_multiply(args);
115 WHEN fname = '/' THEN RETURN mal_divide(args);
116 ELSE raise_application_error(-20004,
117 'Invalid function call', TRUE);
118 END CASE;
119 END;
120
121 FUNCTION REP(line varchar) RETURN varchar IS
122 BEGIN
123 RETURN PRINT(EVAL(READ(line), repl_env));
124 END;
125
126BEGIN
0fc03918
JM
127 M := types.mem_new();
128
129 repl_env('+') := types.func(M, '+');
130 repl_env('-') := types.func(M, '-');
131 repl_env('*') := types.func(M, '*');
132 repl_env('/') := types.func(M, '/');
7836cfa3 133
9fc524f1 134 WHILE true LOOP
7836cfa3
JM
135 BEGIN
136 line := stream_readline('user> ', 0);
0fc03918 137 IF line IS NULL THEN CONTINUE; END IF;
7836cfa3
JM
138 IF line IS NOT NULL THEN
139 stream_writeline(REP(line));
140 END IF;
141
142 EXCEPTION WHEN OTHERS THEN
150011e4 143 IF SQLCODE = -20001 THEN -- io streams closed
7836cfa3
JM
144 RETURN 0;
145 END IF;
146 stream_writeline('Error: ' || SQLERRM);
9fc524f1 147 stream_writeline(dbms_utility.format_error_backtrace);
7836cfa3
JM
148 END;
149 END LOOP;
150END;
151
0fc03918 152END mal;
7836cfa3
JM
153/
154show errors;
155
156quit;