Tuesday, March 20, 2018

Dots to colons

I changed the dot in `System.nil` into a colon, so now it's `System:nil`. The good part, `.` is now function composition. The bad part, `:` might interfere with CVS, comma separated files, which, despite being called comma separated, often use a colon.

I might change it again. `#`? `$`? I am out of ideas.

Monday, March 19, 2018


What's a language without a semicolon? Since Egel has strict semantics but combinators may be side-effecting, it makes sense to add statements, a bit of a trivial extension, to at least give users the possibility to easily define input/output behavior. For example,

printLine "What's your name?"; let X = readLine in print "Hello, " X "!"

Which is a bit shorter than

let _ = printLine "What's your name?" in let X = readLine in print "Hello, " X "!"

But I guess that'll pay off for longer routines. The easiest manner of generating code for semicolons is therefor a let. But lijero on freenode pointed out that you can also employ a 'semicolon' combinator.

[ X _ -> X ] (let X = readLine in print "Hello, " X "!") (printLine "What's your name?")

So, there are some tradeoffs. The let sugar means I'll generate one combinator for each semicolon, the semicolon combinator needs to be added to the runtime -which I don't like- but you could, for instance, then fold that semicolon over a list.

Then, should the semicolon combinator be a built-in or generated on the fly? I don't know yet. If I had some kind of optimizing compiler, the compiler would need to know about its definition. A C++ defined combinator is a bit faster but also more a bit work.

Looks like I'll go the whole principled way of going for an explicit AST node for a statement, a transform do desugarize that, and built-in C++ combinator.

For a semicolon.

Sunday, March 18, 2018

Eight Reasons Egel is Slow

I checked the program `foldl (+) 0 {0,..,1000000}` against GHC and it's about 16 seconds for the Egel interpreter versus maybe at most 300ms for ghci. Because Egel is a term rewriter it turns out `foldl` and `foldr` have roughly the same performance. That in comparison to an old report on GHC behavior.

The odd thing is that it seems to take more time in the IRC bot, a dynamic library seems slower than the compiled interpreter. It's 16 seconds for the console application versus roughly a minute in the bot.

I am two or three orders off. That roughly corresponds to 2^8 to 2^10, so there are in the neighborhood of at least eight reasons why Egel is slower.
  1. The Egel interpreter is a vannila term rewriter.
  2. The interpreter doesn't optimize.
  3. The language is untyped.
  4. The interpreter uses idiomatic C++ and classes from the standard library.
  5. Thread safe reference counting.
  6. No standard arithmetic primitives.
  7. The bytecode generated is dumb.
  8. The overhead of exceptions.
But not bad for a simplistic robust interpreter. Not bad at all.

I love back-of-an-envelope reasoning.

Changes to the Syntax

Well, I tried to be smart and that didn't pan out. I thought using a comma would shave off some characters from pattern definitions because

[ cons X XX, cons Y YY -> .. ]
[ (cons X XX) (cons Y YY) -> .. ]
That is one comma versus four parentheses.

But, as it turns out, the prelude is exactly as large for both alternatives and the standard manner of writing things made the Conway's Game of Life program a tiny bit shorter.

I changed the syntax to the standard manner because people seemed to like that more.

Wednesday, October 4, 2017


I am still a bit dumbfounded how to get something useful out of the Commonmark bindings. One manner of making it useful, as others showcased, is to add Yaml meta-information and a template system to a processor so I looked at the various Yaml C/C++ implementations but shied a bit away of yet another binding.

The other manner is to use Egel for metainformation or even post-processing rules. Egel-enabled Commonmark where the language plays a similar role as Javascript plays for HTML.

And, of course, that idea is somewhat neat but.. Caveats, unclear how to implement that, etc.

For one, Egel constructs are of course far more verbose than Yaml specification which is designed to be terse. Then, Egel is pure; well, mostly. How do you insert information, or even processing instructions into a document when everything is supposed to be pure? And it seems clear I need some form of `eval` but in the interpreter, so far, the evaluator makes use of a module system which in turn makes use of the runtime system. If the runtime needs to know of the evaluator I suddenly got cyclic dependencies.

This actually needs far more thought than I imagined.