I presented a simple language that I wrote an interpreter for back in 2022 - 2024. It started as a very simple version of the BASIC language and it and then transitioned to a less BASIC like language. It has some limitations at this point such as it does not support strings as function parameters but it is a language that can be used for simple scripts.
Creating an interpreter is complex and this is around 1200 lines of PL/SQL at the moment. This interpreter does not execute machine code in the VM it executes my simple language directly as a one pass lexer / parser / executor. I have many prepared articles on the design of this interpreter and I will be releasing those soon as well as the articles on my VM / ASM and also a compiler that creates assembly language for my VM from a simple language. I will also be demoing how to embed a scripting language in an existing PL/SQL application and I have two more areas I might include. I have a part written C compiler written in PL/SQL to generate my assembly language or even direct to machine code (the back end is not written yet).
Would it be great to extend PL/SQL applications using C as the scripting language?
One further area I have been looking at is transpilers also written in PL/SQL of course using the same trend / ideas to add features to a language such as PL/SQL in similar way to how I added pseudo ASM instructions to my assembler but not the VM. An example is that I added a SETSP op code, mnemonic to the assembly language to make dynamic allocation of the stack easier. The assembler converts the SETSP op code to MOV instructions. In a similar way it might be good to extend PL/SQL to have extra features such as lv_var++; or #define from the C world. I know PL/SQL has some level of this. The idea with a transpiler is to allow extra syntax and transpile it into native PL/SQL. So lv_var++; becomes transpiled into lv_var:=lv_var+1; and so on.
There are also other tools that i may write, or may not. I am thinking to add a debugger interface to the VM so that an assembly program that is running in the VM can be stepped through or breakpoints set etc. This also then means the debugger interface could be used at the source level of the high level language as an interface to a source level debugger
In this blog I want to talk about how I have written an interpreter for my simple language. The language is defined in the header for the PL/SQL package as follows (included in the PL/SQL source code):
--
-- ============================================================
-- PFCLScript BNF (derived from pfclscript package body v1.15)
-- ============================================================
-- A complete program
--::= { } "END"
-- One statement (the unit dispatched by DoCommand)
--::=
I implemented the interpreter in PL/SQL. The package has two public procedures. Init() is used to set up the interpreter and also to control trace. Yes, it has trace built in to aid debugging. The VM also had trace as did the Assembler. The second public function of the interpreter is run() which simply runs a provided program written in my simple language. An example 30 line program, well its 29 but 30 sounded better in the comment and print statements is here:
declare
lv_prog varchar2(32767) := q'[
REM "PFCLScript 30-line demo: recursion and nested calls"
FUN fact(n)
IF n<2 THEN
LET fact=1
ELSE
LET fact=n*fact(n-1)
FI
NUF
FUN pow(b;e)
IF e=0 THEN
LET pow=1
ELSE
LET pow=b*pow(b;e-1)
FI
NUF
FUN max(a;b)
IF a>b THEN
LET max=a
ELSE
LET max=b
FI
NUF
REM "--- Main ---"
PRINT "PFCLScript 30-line demo"
PRINT "fact(5) = ";fact(5)
PRINT "pow(2;10) = ";pow(2;10)
PRINT "max(fact(4);pow(3;3)) = ";max(fact(4);pow(3;3))
LET r=pow(fact(2);3)+fact(4)/2
PRINT "pow(fact(2);3)+fact(4)/2 = ";r
END
]';
begin
pfclscript.init(true, 1);
pfclscript.run(lv_prog);
end;
/
sho err
--l
This program exercises quite a few of the language features; it uses recursive function calls, nested function calls, IF THEN / ELSE / FI, most of the arithmetic and comparison of the expression parser as well as comments and LET to assign variables. It does not use GOTO or labels and does not include a loop but we also have these in the language. We do not support FOR... or DO ... WHILE or WHILE ... but all of these constructs can be added with just LOOP ... EXIT ... POOL and in fact adding these syntaxes would be a good use for a pre-compiler or transpiler.
Running the example shows:
SQL> declare
2 lv_prog varchar2(32767) := q'[
3 REM "PFCLScript 30-line demo: recursion and nested calls"
4 FUN fact(n)
5 IF n<2 THEN
6 LET fact=1
7 ELSE
8 LET fact=n*fact(n-1)
9 FI
10 NUF
11 FUN pow(b;e)
12 IF e=0 THEN
13 LET pow=1
14 ELSE
15 LET pow=b*pow(b;e-1)
16 FI
17 NUF
18 FUN max(a;b)
19 IF a>b THEN
20 LET max=a
21 ELSE
22 LET max=b
23 FI
24 NUF
25 REM "--- Main ---"
26 PRINT "PFCLScript 30-line demo"
27 PRINT "fact(5) = ";fact(5)
28 PRINT "pow(2;10) = ";pow(2;10)
29 PRINT "max(fact(4);pow(3;3)) = ";max(fact(4);pow(3;3))
30 LET r=pow(fact(2);3)+fact(4)/2
31 PRINT "pow(fact(2);3)+fact(4)/2 = ";r
32 END
33 ]';
34 begin
35 pfclscript.init(true, 1);
36 pfclscript.run(lv_prog);
37 end;
38 /
PFCLScript 30-line demo
fact(5) = 120
pow(2;10) = 1024
max(fact(4);pow(3;3)) = 27
pow(fact(2);3)+fact(4)/2 = 20
PFCLScript Execution Time (Seconds) : +000000 00:00:00.013464000
SQL> sho err
No errors.
SQL>
This is a good demo to show the usefulness of the simple language. It is not C or C++ but its a good simple script language and shows how PL/SQL can be exercised with some effort
#oracleace #oracleacepo #sym_42 #extreme #plsql #interpreter #vm #assembler #compiler #scripting #language

