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.
