My hobbyist coding updates and releases as the mysterious "Mr. Tines"

Thursday 31 January 2008

Confusion of Babel

I really would like to put a functional layer in the cross-VM stack, but...

Ocamljava and F# might be code compatible, but the former has a cumbersome build and interop process (and doesn't seem to advertise call-from-Java); while Bigloo seems entirely silent on interop.

Cross-compiling Scala class bytecodes to CLR doesn't seem to be a goer -- IKVM balks at referencing CLR 2.0 assemblies. I might be able decompile the classes and rebuild them via J# -- the hiccup there is that I would have to translate the runtime .jar as well -- my simple "Hello World!" level class decompiles to invoke scala.runtime.BoxesRunTime, but that's not in any of the scalac-net assemblies. On the up-side that would remove any nagging issues about CLR 2.0 compatibility, though; on the down-side, it would mean that I need a decompiler able to handle the generated code... Jode -- which I happened to have to hand -- balked at half the classes in the runtime; Jad seemed to have dealt with them all, though with a lot of goto statements replacing things like jumps out of loops -- but leaves a lot of JVM INSTR monitorenter;...JVM INSTR monitorexit; where a synchronized{} block should be, and possibly other horrors.

Meanwhile I took another prod at scalac-net, using the magic -Ydebug flag:

>\scala-2.6.1-final\bin\scalac-net -d classes -Xassem-path JavaLayer.dll SClass.
scala  -Ydebug
[running phase parser on SClass.scala]
[running phase namer on SClass.scala]
java.lang.ClassCastException: scala.tools.nsc.symtab.Symbols$ClassSymbol cannot
be cast to scala.runtime.Nothing$
        at scala.tools.nsc.symtab.clr.TypeParser.parseClass(TypeParser.scala:77)

        at scala.tools.nsc.symtab.clr.TypeParser.parse(TypeParser.scala:58)
        at scala.tools.nsc.symtab.SymbolLoaders$MSILTypeLoader.doComplete(Symbol
Loaders.scala:263)
        at scala.tools.nsc.symtab.SymbolLoaders$SymbolLoader.complete(SymbolLoad
ers.scala:54)
...
java.io.IOException: type 'scala.Predef' is broken
(scala.tools.nsc.symtab.Symbols$ClassSymbol cannot be cast to scala.runtime.Nothing$)
...

Kudos to the scala implementors -- the line numbers match up down the stack, and show the culprit to be

      unpickler.unpickle(symtab, 0, clazz.asInstanceOf, staticModule.asInstanceOf, typ.FullName);

which looks like it's doing the right sort of thing; and there's nothing particularly odd about the scala.Predef class in the assembly; and I get the same error trying to compile some of the examples in the distro...

Next diversion, rebuilding scalac with more instrumentation, piling the tower higher.

Wednesday 30 January 2008

A tower of Babel

// JClass1.java
package com_ravnaandtines.jlayer;
public class JClass1
{
    public JClass1()
    {
    }
    public int doSomething(String arg)
    {
        System.out.println("In "+this.getClass().toString()+".doSomething(), printing "+arg);
        return arg.length();
    }
}
//SClass.scala
package com_ravnaandtines.slayer

import com_ravnaandtines.jlayer

class SClass(token: String) {
 private val in = new com_ravnaandtines.jlayer.JClass1()
 private val len = in.doSomething(token)
 Console.println(len)
}
//Python.py
import com_ravnaandtines.jlayer.JClass1

direct = com_ravnaandtines.jlayer.JClass1()
val = direct.doSomething("from Jython")
print val

import com_ravnaandtines.slayer.SClass
x = com_ravnaandtines.slayer.SClass("Hello Babel!")

Build the first into JavaLayer.jar and copy it alongside the second

\scala-2.6.1-final\bin\scalac -classpath .JavaLayer.jar -d classes SClass.scala
cd classes
"\Program Files\Java\jdk1.6.0\bin\jar.exe" -cf ..\ScalaLayer.jar .

Then run the last with the two jars and the scala runtime jar in your path

In class com_ravnaandtines.jlayer.JClass1.doSomething(), printing from Jython
11
In class com_ravnaandtines.jlayer.JClass1.doSomething(), printing Hello Babel!
12

I had hoped that I could do the same in .Net, but having built the J# JavaLayer.dll, I got

>\scala-2.6.1-final\bin\scalac-net -d classes -Xassem-path JavaLayer.dll SClass.
scala
error: error while loading Predef, type 'scala.Predef' is broken
(scala.tools.nsc.symtab.Symbols$ClassSymbol cannot be cast to scala.runtime.Noth
ing$)
one error found

so haven't yet managed to make a Scala-derived DLL for IronPython to consume. And that doesn't look like something I might obviously have done wrong.

Wednesday 23 January 2008

Steps forwards, steps back.

It would be nice to have the getX()/setX() map to a property, syntactically, in general use Jython as well, along the lines of the previous essay. Alas, that simple "X indirects to getX()" method doesn't seem to work as is. I wonder if I'm relying on things that are a more modern version than Jython yet supports. I need to investigate more.

Meanwhile, on another front, even using the invaluable vjsresgen tool, I have to have platform specific interludes to handle resources -- especially to convert from .png format to something that the back-version Java support understands.

Colour me slowpoke ... Swing on J#

I'd not caught this before:

The Microsoft Supplemental UI Library provides much of the functionality described in the Java 2 JFC Swing specification. It also adds support for much of the functionality found in the JDK 1.2 java.util package.

Version 2.0 of the Supplemental UI Library is included as part of the Visual J# Version 2.0 Redistributable Package. No additional download is required.

To access the functionality in the Supplemental UI Library, simply add a reference to VJSSupUILib.dll in your project.

Betterer and betterer…

Of course this throws a little bit of a spanner in the works of the Jythonizer effort -- I might have subclassed javax.swing.JFrame, but not the component that I get from calling its shiny new contentPane attribute delegating to getContentPane(). Oh, well. At least I might be able to get some cute tricks along the lines of some of the ideas in Swing Hacks instead.

Tuesday 22 January 2008

Making IronPython and J# more Jythonic -- Part 1

For the Nine Unknown Men who might also be attempting this sort of thing.

Persistance pays…

import dtai.gwt.GadgetFrame

def my__getattr__(self, name):
  if name.startswith("__"):
    raise AttributeError(name)
  getter = "get"+name.capitalize()
  if getter in dir(self):
    tmp = getattr(self, getter)
    return tmp()
  iser = "is"+name.capitalize()
  if iser in dir(self):
    tmp = getattr(self, iser)
    return tmp()
  raise AttributeError(name)
        
class Local:    
  def getFred(self):
    return "Fred!"
  
Local.__getattr__ = my__getattr__
   
test = Local()   
print test.fred

class WrappedGadgetFrame(dtai.gwt.GadgetFrame):
  pass

WrappedGadgetFrame.__getattr__ = my__getattr__
dtai.gwt.GadgetFrame = WrappedGadgetFrame

window =  dtai.gwt.GadgetFrame()
print window.visible

when executed, yields

C:...>PyInterop.exe
Fred!
False

which is the get() side of attributes done at the cost of a pass of subclassing. The equivalent set() shouldn't be too difficult, but automating the subclassing will be the next challenge.

Then adding the listener-based attributes; and finally, hiding it from Jython…

Monday 21 January 2008

How Jythonic can it get?

Following up from my previous post, I've been thinking that it would be nice if I could make the code there a bit more Jythonic -- wrapping Java-style bean properties and event handlers transparently in the IronPython/J# world, where the inherent properties will be the Capitalized .Net ones, and we only have the .Net delegate-style handlers.

I will need to experiment to see exactly how open the IronPython proxy classes are to extension, first.

So many projects, so little free time. And I really need to do more with F# and PowerShell, not to mention wanting to try writing a generic protocol-terminating proxy framework in Erlang, probably with SOCKS5 as an exemplar protocol.

LATER

As I suspected, setting Local.__getattr__ = my__getattr__ for a function of suitable signature works where Local is a pure IronPython class; but for an imported .Net class I get


TypeError: can't set '__getattr__' in dictproxy

even with the indirect approach of something like dtai.gwt.GadgetFrame.__dict__["__getattr__"] = my__getattr__.

So Java/J# idioms at the interface it may have to be.

Wednesday 16 January 2008

Pushing at an open door…

Compared with the travails required to shim Ruby.Net and JRuby onto a shared Java/J# code platform, doing the same for Jython (in NetBeans 5.0)/IronPython (using the DevStudio extension build for IronPython 1.1) was trivial. In fact most of the work was re-gearing my mind to Python after thinking in Ruby for some weeks.

Apart from the fact that that the IronPython build ignores any directory structure and smooshes all classes into the one assembly and considers that the package, which will impact on the broader code shape for any project, there is no shimming. Just build your assembly with references to the appropriate external files and you don't even need all the clr.AddReference to do it by hand

Doing the same as the J# and Ruby.Net — string and baling wire example, in a project that references the appropriate assemblies just requires the same Python code as a Jython build with the equivalent .jar files on the classpath

## pyinterop.py
import dtai.gwt.GadgetFrame
import java11.awt.event.WindowListener
import java.lang.System

window = dtai.gwt.GadgetFrame()
window.setSize (800, 600)
window.setTitle("Proof of Concept")

class Handler(java11.awt.event.WindowListener):
  def __init__(self, window):
    self.window = window

  def windowClosing(self, e):
    self.window.hide()

  def windowClosed(self, e):
    java.lang.System.exit(0)

  def windowActivated(self, e):
    pass

  def windowDeactivated(self, e):
    pass

  def windowDeiconified(self, e):
    pass

  def windowIconified(self, e):
    pass

  def windowOpened(self, e):
    pass

adapter = Handler(window)
window.addWindowListener(adapter)
window.show()

It still works in either case, if I simply use the WindowAdapter class and just override the methods I need. W00t! Indeed, so far it almost seem too easy!

Now I just have to keep working around the weird problems I ran into last time around this loop. Keeping Java beneath everything this time around should help.

Tuesday 15 January 2008

Ruby.Net and Ruby.Net — foiled again

A reboot (of the machine, and myself) later, I realised that the obscure "Wrong argument type String (Class expected)" was the result of a sleep-addled 'C'-drenched brain putting include 'Wizard' where require 'Wizard' was expected.

Not so good with the memory issue. After a couple of hours debugging and finally getting the code to interoperate, DevStudio was peaking at over 370Mb of memory, and still thrashing (on a 512Mb machine), while building a project with < 1000 lines of Ruby. NetBeans, by comparison has about 150Mb (if I have a lot of files open)in the IDE and and under 40Mb in the spawned application.

I've put the Interop example code -- showing how to call from shared code JRuby/Ruby.Net to shared-code Java/J# libraries. main.rb calls Wizard.rb which calls through the interop layer defined by .jsl files for Ruby.Net->J#, and Interfaces.rb plus the .java files for JRuby->Java -- on one of my sites, for those who are interested in taking this further.

Until I upgrade my hardware to something that permits more than a toy Ruby.Net layer, though, I don't think I'll be taking the ideal of a shared code/multi-VM project further with Ruby. Which sucks, because that has the best IDE support (I don't even know if the Jython add-in for NetBeans still works at 6.0).

Still a little experimentation is needed with that, and with Scala, to get to an equivalent proof of concept stage.

Monday 14 January 2008

Ruby.Net and Ruby.Net — first steps

Not a typo, alas.

I was testing calling from a Ruby.Net .exe file into a Ruby.Net .dll, to see if partitioning like that would work; though not in such a simple setup as that : I was trying to test a Ruby implementation of a wizard dialog using the GWT... So I create a Testbed.Net.exe that refers to gwt_ruby.dll (which is built from a single source file Wizard.rb).

That fails with a Key Not Found Exception, and looking at the Ruby.Net code, and ildasm-ing the assembly, I discern that it was looking for a gwt_ruby.rb file having been built into the project. So I give it one to satisfy it

require 'Wizard'
class Gwt_Ruby
end

Later...

The Ruby.Net build is being a voracious memory hog on my 3 year old machine with only 512Mb RAM -- even for only a few hundred lines of Ruby code each build and test is taking more than half an hour of thrashing madly at almost 0% CPU. And I thought that NetBeans was memory hungry -- that I can work on in realtime, with the same code in JRuby. I'm not sure that testing this is going to be practical, even without having to work around packaging quirks.

It's almost enough to drive me to Scala!