▶️ #CTRAN: A drop-in FOSS replacement for CTRAN.EXE, the #Psion SIBO/EPOC16 OO C preprocessor on #DOS. Almost feature complete, but still work to do!
▶️ #ObjectPascal with #FreePascal: Used for CTRAN for easy development and portability. Honestly, I'm really enjoying it; it fits my needs and makes my brain happy.
▶️ RAM upgrade for 3mx to 4MB: Trying to source old DRAM isn't easy.
▶️ RAM upgrade for 5mx: Got the DRAM. Just need to solder it in place.
Just tried compiling Wari, a game written in #Psion OO C. The project uses #Borland Make 3.6.
Got it to compile first time with my SIBO SDK setup - all good!
However... Borland Make uses 16-bit DPMI, and its extender won't load 32-bit DPMI binaries. If I pre-load the 32-bit extender, it won't load 16-bit DPMI binaries, so Make won't run!
TL;DR: I can't use the new #ctran with Borland Make 3.6.
Looks like I'll be converting that Makefile to GNU Make or a #TopSpeed project.
Why can't I recompile #ctran for 16-bit #DOS? Because many of #FreePascal's libraries are too big to fit into 64 KiB data blocks, and won't compile no matter which memory model I use.
There is a chance I'll rewrite ctran in the future. #FreeVision (the #Borland#TurboVision "clone") with #ObjectPascal is certainly an option. I could also rewrite the lot in C or C++.
But today is not that day. For now, I'd rather just rewrite a Makefile.
Done a lot of work on #ctran tonight. In fact, I think we might have a working parser! I definitely need to check over what I've done, but it's looking promising.
I need to add more checks to make sure that tokens don't appear in files that aren't meant to have them (e.g. DECLARE should only be in .EXT files). Then I need to test that the tree is being built the way I think it is.
After that, it's time to do something with EXTERNALs and REQUIREs to make MANY trees.
⬜ Move a load of "testing" code to a separate class, inheriting the main class.
⬜ Remove the old public token-grabbing methods. They were for the old parser, so aren't needed.
The first one should be relatively simple (I think). I've not tried inheritance in #ObjectPascal classes yet, so we'll see how things go. Hopefully it doesn't make me want to refactor everything as one or more interfaces.
I'm starting to wonder if there's any point in having the lexer and parser as two separate classes.
Other than testing, the lexer is only ever going to be called by the parser, and only once during the process.
It might be better to just have a lexer-parser class that grabs a file, tokenises it, then (if it's happy with the file it's tokenised) immediately turns it into a tree.
Is there a really good reason why they should be separate classes?
Been thinking about #ctran and ASTs today. I've realised that I might be approaching this wrong.
#Psion OO C files are definition files. They're glorified mark-up, wrapping around snippets of C code that just gets copied to new files. There's no logic in them at all.
I basically need two arrays per file: a list of "classes" and their contents, and a list of "includes" and how they're, uh, included (EXTERNAL, INCLUDE, or REQUIRE).
It's still a tree, but it's got two distinct parts. Wonky tree.
Actually, I wonder if variant records would be useful for building a tree, or at least an array containing elements of different types? Need to read up on them.
Interesting... I'd assumed that #FreePascal's 16-bit #DOS cross-compiler was just ignoring the memory model I was setting. Turns out it wasn't, and I hadn't been reading the error messages properly. They're all failing for different reasons!
Surely I must be doing something wrong?
I'm struggling to find any information on issues like this, largely because hardly anyone uses it.
I might end up switching to the 32-bit DOS compiler, just to get something working.
So, I've got two relatively big problems to solve.
Ripping out TStringList() so that I can remove the Classes unit. I'm going to switch to per-character parsing anyway, so that's fine.
How do I build an AST in #ObjectPascal? More to the point, how do I build it without any nice-to-have libraries that will probably be too big to fit in 64K?
I think I build it with the nice stuff first so I understand what it's doing, and then rebuild the nice stuff from scratch, or build it better without.
The Apple Macintosh has turned 40. Originally, it was a #Pascal machine, and #ObjectPascal has been developed to evolve its revolutionary operating system.
#CTRAN currently has a lot of repetitive code in the #tokeniser. I really want to refactor it so that it's both tidier and more readable. I also know that I'm going to need to reuse a lot of the tokeniser code to process #Psion's .EXT files, which are a sort of cut-down version of the class/category files.
I'm in a position where the tokeniser works well, so I think I can afford to shift things around. I think it's time to put the tokeniser in a class.
Well, the tokeniser is now in a class and still works! Procedures and functions have been pulled in and simplified, and private things are strict private. Tidying the code will now be much easier.
Have a look at the code so far on GitHub. Feel free to critique - I know there's much to be improved, but I could have missed something.
Thank you to @rvr for sending me this. I've had a quick read through and it looks to be exactly what I need. Especially the section "7.2. Containers (lists, dictionaries) using generics".
#FreePascal compiles for almost everything (See the picture), including 16-bit DOS.
It's also still maintained, with an active community.
Using #ObjectPascal (which is basically what Free Pascal is), I can get the logic written for a lexer, an AST, and then a few code generators, without worrying about how I'm going to allocate memory for an array, let alone an entire tree.
The TIOBE Programming Community index is an indicator of the popularity of programming languages. This ranking is organized according to their popularity as of Sep 2023:
(1) Python
(2) C
(3) C++
(4) Java
(5) C#
(6) JavaScript
(7) Visual Basic
(8) PHP
(9) Assembly Language
(10) SQL
(11) Fortran
(12) Go
(13) MATLAB
(14) Scratch
(15) Delphi/Object Pascal
(16) Swift
(17) Rust
(18) R
(19) Ruby
(20) Kotlin