After some major refactoring, I reverted it back to use vanilla Arc 3.1.
Now, Arc/Nu has a rudimentary "multiple language" feature. When using the "arc" executable, you can now specify the "--lang" property.
For instance, when using "arc --lang foo", it will look for a folder called "foo" in the "lang" subdirectory. This folder should contain a file called "main" which should be written in Racket. Using this file, you can implement custom languages using the Arc/Nu compiler.
Currently, only two languages are supported: "arc/nu" and "arc/3.1"
As you can see, "nu.nu" is quite sparse at the moment, but it does load correctly if you use "arc --lang arc/nu". With some more refactoring, I'll be able to make it so that arc/nu and arc/3.1 can use libraries written in the other language.
Now multiple languages are fully supported. The way it works is that, within a file, you can use "w/lang" to temporarily change the language. For instance, suppose you had the following "arc/3.1" program:
(w/lang arc/nu
(var foo 1))
(= bar (+ foo 2))
Within the "w/lang" block, it's using "arc/nu", but outside, it's using "arc/3.1"! Using this, it's easy to import libraries written in "arc/nu":
(w/lang arc/nu
(import foo))
And vice versa, if you're writing a program in "arc/nu", you can use "w/lang" to import things from "arc/3.1":
(w/lang arc/3.1
(import foo))
By the way, because all of this is using boxes at compile-time, there's zero runtime cost. The only downside is that if you use two languages at once, it has to load both of them, which increases the startup time.
Well! I just learned something new! Racket's "procedure-rename" is ridiculously slow. In case you don't know what I'm talking about, it's just a function that lets you rename functions:
(procedure-rename (lambda () 1) 'foo)
Anyways, here's the timing tests I did for Arc/Nu using "procedure-rename":
What a ginormous difference. Removing it doubled the speed of Arc/Nu! Given that the sole purpose of "procedure-rename" is to, well, rename functions, I wouldn't expect it to have such a huge runtime performance penalty, but apparently it does...
Sounds like a good topic, and I'd be interested in hearing to hear your thoughts on this. I've been thinking about the same kind of thing, but I'm looking to use it in a weakly typed subset of a statically typed language. My motivation is mostly to see if we can make it convenient to externally manage the memory needs of otherwise encapsulated programs.
This is probably a discussion for another thread. ^_^;
I wonder if the compiler can't see through a 'procedure-rename call to realize it can still apply optimizations to the code. Like, maybe it can optimize ((lambda (x) ...) 2) but not ((procedure-rename (lambda (x) ...) 'foo) 2).