BCFJ (as it is now known) draws some aspects and inspirations from Forth, which is a TIL. I want "introspection", dynamic redefinitions and flexible object code generation.
But FORTH has a big problem. Well, several but let's focus on this one : the stack with a single type of data (usually a word-wide integer). Hence why I have started to define a typing system in 9. Typing (for realz).
But that's just one part of the story. I want to replace the way the whole language is structured, in fact I'd love to "structure FORTH" and "Pascalise" it. I want to make a well-defined interface for functions, just like you do in C/Pascal/Ada/VHDL so what is a function and how do you define it ?
At first glance, a function is first defined by a name (a string type) and a pointer to the code, or address. You can associate some source code and a few ad hoc metaproperties. FORTH gets along with it because the ABI and the callee/caller interface is just the stack, with as much implicitness as possible "to shave layers and get more performance", at the cost that we know:
- No accountability
- No explicit interface : you have to run the actual code to know what it actually does and it hits the halting problem (if you ever dare to try formal-proofing Forth code).
- Type confusion
Hence why I steer toward the strong typing world. Whenever a language tries to be "smart" and attempts to guess what the user wants, you get WAT-level madness. You can try to explain it away but the layers of semantic and other cruft can't go away.
So a function is also an interface : Pascal/Ada/VHDL strictly define it, what goes in and what goes out. The interface is a list of input parameters and results/outputs. They both reside on the data/call stack (the function's context), as well as temporary data.
So here comes the "brilliant idea" that currently drives my research:
A function can be defined as a name associated to the bundle of 3 structures (the input, the temporary, and the output data). This is of course a high-level, unoptimised view but this is a great guide for the design of a language, as it creates a uniform, simplified picture. All you have to do is define a flexible, convenient, effective typing system, and you get your functions easily, without having to deal with early optimisations (looking at you, Ada).
When you see things like this, implementation and debugging become simpler than usual compiled languages, without falling into crazy semantic traps as with Scheme/Haskell/JavaScript...
The "tri-structure" that defines a function is quite easy to turn into a directed-data-depency-graph and it is not difficult to process & optimise, for example to eliminate duplicates or infer copies... Which will be a lower-level view at the generated code, while the original code can remain straight-forward to examine/debug.
You can imagine a function that is declared as:
function some_processing( u8 a, u16 b, u32 c) returns (u8 d, *u16 e) is u8 t, v; begin ... ... some code ... end;
This means that the "bundle" is actually a higher-level struct with 3 elements, such as
struct struct_some_function is struct arguments is u8 a, u16 b, u32 c end argument, struct locals is u8 t, v end locals struct results is u8 d, *u16 e end results end struct;
I hope you get the idea.
I don't know of a language that does this transform, can anyone comment on this ?
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.