-- Leo's gemini proxy

-- Connecting to republic.circumlunar.space:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

Oberon FFI


There haven't been many updates lately both because of "Real Life", and the fact that Easy-ISLisp is now quite stable.


Easy-ISLisp


An aim of Sasagawa-san's, which I agree with, is that the interpreter be simple and easy to read. This puts a limit on performance, but that's fine, you can rewrite "hot" code in a faster programming language. C is a very popular choice for this, but I wanted to explore the memory-safe alternative Oberon which should be almost as fast.


Oberon Dialects


Go and Rust are popular languages in this space now, but back in the 1990s there were other choices: Turbo Pascal was the most popular, followed by Modula-2 and Oberon. Oberon is the only one I learned much about. It's also much simpler/more minimal than Go or Rust.


I used a "to-C" transpiler, obnc. This implements the Oberon-07 dialect (there isn't a massive difference between them). The steps follow.


OBNC Home Page


Target Code


This is the Oberon code you want to call.


MODULE Hello;
   IMPORT Out;
   PROCEDURE World*();
   BEGIN Out.String("Hello World!"); Out.Ln;
   END World;
END Hello.

FFI Glue Code


This is the glue code to call from the interpreter (tested on macOS).


(c-include "\".obnc/Hello.c\"")
(c-option "-I/Users/me/include /Users/me/lib/obnc/Out.o /Users/me/lib/obnc/OBNC.o -L/opt/homebrew/lib -lgc")

(defun hello-world ()
   (c-lang "OBNC_Init(0, NULL);")
   (c-lang "Out__Init();")
   (c-lang "res = NIL; Hello__World_();"))

Notes:


You have to replace "/Users/me" with the PREFIX that you used when installing obnc.

The fact that Out.o must be linked is because of "IMPORT Out" in the Oberon code

The two initialisation calls before the main call to "Hello__World_" (and even the name of Hello__World_ itself) were got by running obnc-compile with the "-e" flag once and reading .obnc/Hello.c just to see what's required for a standalone executable. But note that in normal operation you would omit this flag.


Compilation


obnc-compile Hello.Mod
eisl -c
(compile-file "oberon.lsp")
(load "oberon.o")
(hello-world)

And that's it. It's only slightly more complicated than the C interface, but personally I much prefer the safety of Oberon. It's a nice path to improve performance, if you've confirmed that that is a problem.


If I won the lottery :-) it might be nice to port the whole interpreter to Oberon, with just a few minor changes:


Rely on the Oberon garbage collector, just allocate all cells using "NEW"

Use a proper class hierarchy and type-bound procedures for "Cell" instead of the "tag" field


Back to my gemlog

-- Response ended

-- Page fetched on Wed May 1 21:51:50 2024