This is the mail archive of the
kawa@sources.redhat.com
mailing list for the Kawa project.
Re: Compiling procedures questions
- From: Per Bothner <per at bothner dot com>
- To: "Crystal, Mayer" <mayer dot crystal at gs dot com>
- Cc: "'kawa at sources dot redhat dot com'" <kawa at sources dot redhat dot com>
- Date: Mon, 27 Sep 2004 17:23:48 -0700
- Subject: Re: Compiling procedures questions
- References: <7F7603A85B0C674D9834EC479BE4F884067712D3@gsnmp27es.ny.fw.gs.com>
Crystal, Mayer wrote:
I'm relatively new to kawa (and scheme for that matter) and have a question
about compiling procedures into bytecode and using them in a java program.
The scenario I am coding is as follows:
You've done a good job of figuring out APIs that aren't realy documented
or designed for end-users, so it's understandable you got some things
wrong.
- I have created three procedures (which extend Procedure0) and they all
return Boolean.TRUE or Boolean.FALSE.
- I have written a rule of the following form: (or proc1? (or proc2?
proc3?))
- I compile the rule into a procedure using the following code:
/**
* A helper method to compile a String rule into a Procedure.
*
* @param rule The string representation of the rule
*/
private static final Procedure compileRule( String rule ) throws
Exception {
Scheme scheme = new Scheme( Scheme.builtin() );
Leave out the 'Scheme.builtin()':
Scheme scheme = new Scheme();
scheme.eval( "(load \" + MyProcs.class.getName() + ".class\")"
);
Loading a class file by name isn't really recommended. The meaning of
that is hard to nail down. On the other hand require is better:
(require <MyProcs>)
InPort port = new InPort( new CharArrayInPort( rule ) );
SourceMessages messages = new SourceMessages();
Compilation comp = scheme.parseFile( port, true, messages );
Class cl = ModuleExp.evalToClass( comp );
if ( messages.getErrorCount() > 0 ) {
StringBuffer sb = new StringBuffer();
sb.append( "Failed compiling: " );
sb.append( messages.toString( messages.getErrorCount() ) );
throw new Exception( sb.toString() );
}
Procedure p = null;
try {
p = (Procedure) cl.newInstance();
}
catch ( Exception e ) {
throw new Exception( "Could not create new instance of rule:
" + rule );
}
return p;
}
The 'p' which is an instance of 'cl' is a ModuleBody. It's not a
normal procedure, but the top-level forms of the module.
- The compilation succeeds and is cached.
- I evaluate the rule using the following code:
return ((Boolean)rule.apply0()).booleanValue();
Not sure where 'rule' is coming from. The only one in your
program is the parameter to compileRule, which is a String.
The evaluation throws a ClassCastException reporting that I am attempting to
cast my proc1 class to a Boolean. Did I miss something in the compilation
step? How do a compile the procedure (and any references it may have to
other procedures) such that after compilation I can call an apply() method
and retrieve the final boolean result?
One machanism is:
(Boolean) (((Procedure) scheme.eval("rule")).apply0())
--
--Per Bothner
per@bothner.com http://per.bothner.com/