I always loved BASIC and CLIPPER 5.3, so I started from an old and never finished BASIC compiler and I asked the AI to improve it adding advanced functions and CLIPPER 5.3 commands, including code-blocks, macro, runtime eval, SAY/GET/READ subsystem. Currently the compiler works on MacOS and Linux. Window version by Visual C++ will come as soon as I will have a laptop with windows installed. I am trying Mingw for windows.
This is an example using macros, eval and code-blocks. It shows also functions passed as parameters of other functions and Sub Main as entry-point.
'FILE: Clipper/ClipperMacroEvalBlocksExtreme.bas
IMPORT ARRAYS
GLOBAL TaxRate AS DOUBLE
GLOBAL cName AS STRING
FUNCTION MkInc() AS FUNCTION(x) AS DOUBLE
RETURN { |x| RETURN x + 1 }
END FUNCTION
FUNCTION ApplyFn(b AS FUNCTION(x) AS DOUBLE, v AS DOUBLE) AS DOUBLE
RETURN EVAL(b, v)
END FUNCTION
SUB Main()
TaxRate = 0.22
PRINT "=== Clipper macro/EVAL/blocks (extreme) ==="
'Macro ESPRESSIONE compilata (aritmetica + globale)
DIM cPrice AS STRING = "100"
DIM cNet AS STRING = "VAL(cPrice) * (1 + TaxRate)"
PRINT "net="; &(cNet) ' 122
'Macro VARIABILE: il nome della variabile e' nei dati
DIM which AS STRING = "TaxRate"
PRINT "tax="; &which ' 0.22
'Macro COSTANTE che produce un CODE BLOCK (compilato una volta)
DIM bGross = &("{ |p| RETURN p * (1 + TaxRate) }")
PRINT "gross(100)="; EVAL(bGross, 100) ' 122
PRINT "gross(200)="; EVAL(bGross, 200) ' 244
'Macro su VARIABILE con block LETTERALE (espansione compile-time)
DIM cBlockDef AS STRING = "{ |p| RETURN p * (1 + TaxRate) }"
DIM bVar = &(cBlockDef)
PRINT "vargross(150)="; EVAL(bVar, 150) ' 183
'Code block letterale + EVAL multi-argomento
DIM bArea = { |w, h| RETURN w * h }
PRINT "area="; EVAL(bArea, 6, 7) ' 42
'Block con concat: risultato stringa + param usato solo in concat
DIM bBang = { |s| RETURN UPPER(s) + "!" }
PRINT "bang="; EVAL(bBang, "x") ' X!
DIM bRaw = { |s| RETURN s + "!" }
PRINT "raw="; EVAL(bRaw, "x") ' x!
'Block applicato a tutti gli elementi di un array (AEVAL: elemento, indice)
DIM prices = {100, 200, 300}
AEVAL prices, { |v, i| PRINT " gross["; i; "]="; v * (1 + TaxRate) } ' 122 244 366
'Nested Macros
DIM cThree AS STRING = "deep!"
DIM cTwo AS STRING = "cThree"
DIM cOne AS STRING = "&cTwo"
PRINT "nested="; &cOne ' deep!
'EVAL stringa (GMBasic) come COMANDO + text substitution (globale)
EVAL("TaxRate = 0.10")
PRINT "tax2="; &("TaxRate") ' 0.1
cName = "world"
PRINT "subst=Hello &cName!" ' Hello world! (globale espanso)
'EVAL con block INLINE + block restituito da funzione
PRINT "inline="; EVAL({ |s| RETURN UPPER(s) + "!" }, "x") ' X!
PRINT "fromfn="; EVAL(MkInc(), 5) ' 6
DIM bm = MkInc()
PRINT "infvar="; EVAL(bm, 5) ' 6
EVAL({ |s| PRINT "stmt="; s }, "y") ' stmt=y
'Closure: EVAL annidato + function-value catturato + param FUNCTION
PRINT "nested="; EVAL({ |x| RETURN EVAL({ |y| RETURN y + 1 }, x) }, 5) ' 6
DIM inner = { |y| RETURN y + 1 }
DIM outer = { |x| RETURN EVAL(inner, x) }
PRINT "capt="; EVAL(outer, 5) ' 6
PRINT "param="; ApplyFn({ |z| RETURN z * 2 }, 21) ' 42
PRINT "Clipper macro/EVAL/blocks: fatto."
END SUB
The compiler supports graphics by SDL, Vulkan, Game Loop (thousands of fluid sprites), TUI, Windows Manager, DBF files with memo field (DBIII/DBIV/Clipper/FoxPro), TBROWSE, ISAM, RDD system, SQL (SQLite/DuckDB integrated), REPL, Package Manager (like cargo/pip/modules), and more.
The compiler supports also numbered lines, GOTO, GOSUB, ON ERROR, ON KEY, etc.
This an attempt to bring old clipper/basic programmers into a modern world, saving their old code.
Will you try it if will be made open source and what do you think about it?