markvangulik
Note that embedding PROGRAMMAR inside Lisp is exactly the kind of thing we’re doing with Avail… it’s just that the base metarules are more articulate for that sort of thing.
PROGRAMMAR rewritten today in Avail wouldn’t look at all like Lisp — thank goodness. But if you implemented that language via a compiler, you would have the limitations of the compiler technology constantly getting in the way of the linguistic forms you’re trying to express. For example, having to decide on a linear ranking of precedence levels for every operation, even if they couldn’t ever appear next to each other due to type or linguistic constraints.
Even C++ requires custom lexing tweaks because of spurious “>>” tokens in nested templates… and special backtracking rules to distinguish function definitions from stack object creation. But those bypasses aren’t readily usable in the available parsing tools. Avail’s compiling scheme is decades beyond that.
If you want Avail to include all of C, you define C language capability in an Avail module and subtract the rest. Then your C program is also an Avail program, so you have the same tool chain you had with core Avail (still lacking, but getting there), you have dynamic optimizing compilation to JVM (and eventually native, perhaps), and you have a program that not only interoperates with programs written in other dialects, but allows direct connection between them. Like if you want Avail exceptions with your C code, you import exceptions and just use them. You don’t build them over and over again for each language. And if you want to support closures in your C, you’d probably just remove the limitation that treated the closures of Avail as contextless C functions. Similarly for backtracking, universal serialization, and sensible module dependencies (maybe call it #import, versus the horrible textual #include mess of C).
And finally, if you want your existing vanilla C code to be able to call “out” efficiently to some FORTRAN or Python code, you no longer have an impedance mismatch. Define those dialects as Avail, and you’ll have real garbage collection, multiplexed lightweight threads (fibers), dynamic optimization, and objects and functions that are reasonably compatible between these dialects.
Almost all of these monstrosities are caused by the “object purity” mindset that kept the designers from including first-class functions in the language. Avail attempts to include a large set of paradigms instead of trying to “axiomatize” the exposed surface (although we do axiomatize the construction of these constructs).
But yes. There’s a lot of deeply evil things that can be done in Avail, right down to the lexical scanning. Like forbidding certain variable names, or manufacturing a run of tokens every time a certain emoji is encountered. There are also a lot of safeties, like sealing methods to prevent someone overriding “_+_” for [3’s type, 4’s type]->9’s type.
Oh, and writing “x = x + 1;” as a statement will be flagged as a syntax error, because it would produce a Boolean value which is not allowed to be silently discarded like in Java or C. “Discard:_” makes these rarely needed situations absolutely obvious.
Cheesy, closed languages like C forgot that exponentiation was even a thing, or complex numbers. If you shift over to using C++’s “clevernesses”, you still don’t get exponentiation, because the traditional caret symbol is already used for exclusive-or, which has no sensible ASCII punctuation.
As for someone’s distant comment that Lisp has been used to create languages for years... sure, if the language you wanted was parenthesized lists with keywords inside the left parenthesis. Which is just Lisp with a few more operations and macros. Yuck.
Languages like Java (and many more) fail to even have a top type, which leads to kludgey add-ons to the type system — boxed, @Nullable, erased generics, annotations, dependency injection, purity annotations, etc., all of which should have been part of a single type system.
I guess they won’t ever add decades overdue Unicode support after all, since ad revenue will be zero pretty soon.
However, I'm close to completing the macro mechanism that will allow the same flexibility of syntax present in method names (keywords/operator tokens, argument positions, guillemet-enclosed repeated argument groups, etc), but for constructs that run at compile time with parse trees instead of values. The actual macro mechanisms have been working for some time, but were disabled until we were able to represent the ~dozen syntactic constructs of Avail purely as macros. Then any new syntax wouldn't be in conflict with existing syntax. When that's working we'll toss the existing compiler (the one that knows anything about Avail's current syntax, like statements and functions and variable declarations), and use the compiler that knows nothing about Avail – just how to parse methods and macros. Then we'll be able to support arbitrary evaluation orders, declaration syntax, treating some expressions as lazy, alternative scoping models, etc.
As for custom types, we're investigating ideas about carrying purity annotations through user-defined control structures. Kind of hard to describe in this forum, though.
https://www.availlang.org/about-avail/documentation/stacks/l...
There is also a strong beginning of a "cookbook" of expressions here:
https://www.availlang.org/about-avail/documentation/expressi...
There's also coverage of a sizable chunk of Avail's type system here:
https://www.availlang.org/about-avail/documentation/type-sys...
Method "_plus_" is [ a : number, b : number | a + b ]:number;
Print: 5 plus 6;
The entire language is built this way.
https://www.availlang.org/about-avail/documentation/faq.html...