This is the mail archive of the
kawa@sources.redhat.com
mailing list for the Kawa project.
RE: Compiling procedures questions
- From: "Crystal, Mayer" <mayer dot crystal at gs dot com>
- To: 'Per Bothner' <per at bothner dot com>
- Cc: "'kawa at sources dot redhat dot com'" <kawa at sources dot redhat dot com>
- Date: Tue, 28 Sep 2004 01:15:23 -0400
- Subject: RE: Compiling procedures questions
Per,
Thanks for the quick response. I apologize for the snippet of code which
was unclear (due to cut and paste). Regarding the following snippet:
>>
>> 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 rule that I was referring to was really the the cached version of the
compiled proc (or, as you've pointed out, ModuleBody).
>> 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())
The mechanism that you described can be used for string rules. However, for
performance reasons, I would like to use a pre-compiled procedure (or
ModuleBody). The ClassCastException that I was referring to in the previous
email was received when trying to execute the equivalent of:
((Boolean)moduleBody.apply0()).booleanValue()
Where moduleBody is the result of the call to the compileRule() method
described in my previous email. It is this exception that I am puzzled by -
why is the return value of the apply0() call an instance of my proc1 class
as opposed to the result of the boolean or operations described by the
actual scheme code that is being evaluated?
In other words, my code looks something like:
1. String rule = "(or proc1? (or proc2? proc3?))";
2. Procedure moduleBody = compileRule( rule );
3. return ((Boolean)moduleBody.apply0()).booleanValue();
I don't understand why the result of moduleBody.apply0() is not a Boolean
but is instead an instance of my proc1 class. If this is the correct
behavior, is there a way to compile the rule and have a function simply
return the final boolean result?
Thanks again,
Mayer
-----Original Message-----
From: Per Bothner [mailto:per@bothner.com]
Sent: Monday, September 27, 2004 8:24 PM
To: Crystal, Mayer
Cc: 'kawa@sources.redhat.com'
Subject: Re: Compiling procedures questions
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/