Hi,

Just going to update this thread with a link to the repo I am asking this 
question for which I finally see fit to share 
https://github.com/sstewartgallus/jsystemf .

Mostly copypasting from a reddit post I made.

So I plan to use this as the core of a functional language similar to
the Glasgow Haskell Compiler's core but for now I don't have a higher
language made yet.

Atypically I use higher order abstract syntax for the core IR. Higher
order abstract syntax cheats for implementing things like closures by
using lambda expressions. I compile these lambdas to a point free
representation by repeatedly substituting the free variables with
pairs.

Basically Type.INT.l(x -> Type.INT.l(y -> x)) becomes rewritten to
something like curry(Type.INT.and(Type.INT).l(v -> v.second())) which
then can be reduced to simple category theory based combinators (It's
well known the lambda calculus can be compiled to closed cartesian
categories see http://conal.net/papers/compiling-to-categories/ .)
Unexpectedly I found that evaluation of the product of a thunk and a
function Category<<F<A, B>, A> can be implemented using uncurrying and
currying implements closures.

After I compile to a point-free closed cartesian category combinator
representation I then compile my types to a similar
representation. Just as lambda abstraction is curried so is universal
quantification over types. Interestingly existential quantification
plays the same role products play in compiling functions.

Still I haven't really implemented generics properly yet and I
struggle a bit because of Java's mediocre type system and also because
this is something I have mostly figured out myself.

Next I compile the CCC representation to MethodHandle. As a legacy of
an earlier much more complicated code base before I settled on the CCC
representation I use bytebuddy to spin custom closure types that
represent an environment + a method. I use invokedynamic heavily for
linking calls. I still haven't implemented supersaturated/partially
saturated callsites yet meaning that multiargument Invokers
(dynamically spun classes that fill interfaces for invoking function
values) don't really work.

I think I'm pretty confident I have a solid foundation now though and
just have to figure out the type representation at runtime. Currently
the type Type is more akin to a ClassDesc in Java than an actual live
Class value. I need to figure out how to instantiate/cache generic
types and methods. I hope that by flattening generic tuple types I can
recover a more JVM native argument passing convention as as of now
everything is boxed into pairs.

A lazy pure functional language on the JVM has been an itch I've been
trying to scratch for a while (even playing with GraalVM at times,
which proved not flexible enough) but I think I've figured out a solid
foundation with this even though I have not yet implemented tail calls
or lazy evaluation.

I thought some of you might be interested in this kind of bytecode spinning 
stuff.

On Sunday, April 26, 2020 at 9:36:07 AM UTC-7, Steven Stewart-Gallus wrote:
>
> I'm spinning a lot of classes dynamically for an interpreter.
> I'm not sure the best way to load the classes into the VM.
>
> Aside from Unsafe's defineAnonymousClass what's the best way to load 
> classes into the VM?
>
> I believe I could create a new classloader for each spun class but IIRC 
> classloaders are expensive.
>
> I believe as much as possible I'd want to reuse MethodHandle and 
> LambdaMetafactory to rely on the JVMs use of defineAnonymousClass.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/mechanical-sympathy/1d74256c-f60c-453f-98c8-0452230732b9%40googlegroups.com.

Reply via email to