<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to Methods</title><link>https://sourceforge.net/p/classmaker/wiki/Methods/</link><description>Recent changes to Methods</description><atom:link href="https://sourceforge.net/p/classmaker/wiki/Methods/feed" rel="self"/><language>en</language><lastBuildDate>Mon, 01 Oct 2012 00:17:54 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/classmaker/wiki/Methods/feed" rel="self" type="application/rss+xml"/><item><title>WikiPage Methods modified by Donald Strong</title><link>https://sourceforge.net/p/classmaker/wiki/Methods/</link><description>[Home]

----

Language Features
=================

Methods
-------

_Declaring methods_

Methods are declared in !ClassMaker using the following methods.

&lt;pre&gt;
    public void Method(String methodName, Class returnType, int methodModifiers) throws ClassMakerException
    public void Method(String methodName, Type returnType, int methodModifiers) throws ClassMakerException
    public void Begin() throws ClassMakerException
    public void End() throws ClassMakerException
&lt;/pre&gt;

There are two versions of &lt;code&gt;Method&lt;/code&gt; and &lt;code&gt;Declare&lt;/code&gt;.
Most of the time you will use the version that takes a java reflection &lt;code&gt;Class&lt;/code&gt;.
The version that takes a !ClassMaker &lt;code&gt;Type&lt;/code&gt; is only necessary when you are passing a class
that you are generating at runtime.

&lt;table border="1" width="100%"&gt;
&lt;tr&gt;&lt;td&gt;Java code&lt;/td&gt;&lt;td&gt;ClassMaker code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
&amp;nbsp;
    String name;
&amp;nbsp;          
    public void exec()
    {
        name = "Hello World";
    }
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
&amp;nbsp;
    Declare("name", String.class, ACC_PUBLIC);
&amp;nbsp;
    Method("exec", void.class, ACC_PUBLIC);
    Begin();
        Eval(Set(This(), "name", Literal("Hello World")));
    End();
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

Valid bitmasks for the &lt;code&gt;methodModifiers&lt;/code&gt; of a &lt;code&gt;Method&lt;/code&gt; call include &lt;code&gt;ACC_PUBLIC&lt;/code&gt;,
&lt;code&gt;ACC_PROTECTED&lt;/code&gt; or &lt;code&gt;ACC_PRIVATE&lt;/code&gt;. The modifiers may be bitwise &lt;code&gt;OR&lt;/code&gt;ed with
&lt;code&gt;ACC_STATIC&lt;/code&gt; and &lt;code&gt;ACC_FINAL&lt;/code&gt;, as appropriate.
Provide a zero (0) value if there are no modifiers.

_Formal Parameters_

Formal parameters are declared in &lt;code&gt;ClassMaker&lt;/code&gt; using the following methods.

&lt;pre&gt;
    public void Declare(String name, Class javaClass, int modifiers) throws ClassMakerException
    public void Declare(String name, String typeName, int modifiers) throws ClassMakerException
    public void Declare(String name, Type type, int modifiers) throws ClassMakerException
&lt;/pre&gt;

&lt;table border="1" width="100%"&gt;
&lt;tr&gt;&lt;td&gt;Java code&lt;/td&gt;&lt;td&gt;ClassMaker code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
&amp;nbsp;
    public void setName(String name)
    {
        this.name = name;
    }
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
&amp;nbsp;
    Method("setName", void.class, ACC_PUBLIC);
    Declare("name", String.class, 0);
    Begin();
        Eval(Set(This(), "name", Get("name")));
    End();
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

The only valid values for the &lt;code&gt;modifiers&lt;/code&gt; of a &lt;code&gt;Declare&lt;/code&gt; call when used to declare a
formal parameter are &lt;code&gt;ACC_FINAL&lt;/code&gt; or zero (0).

_Returning values_

These methods are used in &lt;code&gt;ClassMaker&lt;/code&gt; to return from a method.

&lt;pre&gt;
    public void Return() throws ClassMakerException
    public void Return(Type type) throws ClassMakerException
&lt;/pre&gt;

The former method must be used for &lt;code&gt;void&lt;/code&gt; methods and the latter for any method that returns a value.

A call to &lt;code&gt;Return&lt;/code&gt; may be required as the last statement of a method, even if that call is unreachable.

&lt;table border="1" width="100%"&gt;
&lt;tr&gt;&lt;td&gt;Java code&lt;/td&gt;&lt;td&gt;ClassMaker code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
&amp;nbsp;
    String name;
&amp;nbsp;
    public String getName()
    {
        return name;
    }
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
    &amp;nbsp;
    Method("getName", String.class, ACC_PUBLIC);    
    Begin();
        Return(Get(This(), "name"));
    End();
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
    &amp;nbsp;
    protected int add(int a, int b)
    {
        return a + b;
    }
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
    &amp;nbsp;
    maker.Method("add", int.class, ACC_PROTECTED);
    maker.Declare("a", int.class, 0);
    maker.Declare("b", int.class, 0);
    maker.Begin();
        maker.Return(maker.Add(maker.Get("a"), maker.Get("b")));    
    maker.End();
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

_Calling methods_

&lt;code&gt;ClassMaker&lt;/code&gt; provides the following methods to perform methods calls.

&lt;pre&gt;
    // Calls to non-static methods
    public Type Call(Type type, String methodName, CallStack actualParameters) throws ClassMakerException
    // Calls to static methods
    public Type Call(Class javaClass, String methodName, CallStack actualParameters) throws ClassMakerException
    public Type Call(String className, String methodName, CallStack actualParameters) throws ClassMakerException
&lt;/pre&gt;

The first version of &lt;code&gt;Call&lt;/code&gt; is the one you will use most of the time. The other methods are used to generate calls
to static methods.

&lt;table border="1" width="100%"&gt;
&lt;tr&gt;&lt;td&gt;Java code&lt;/td&gt;&lt;td&gt;ClassMaker code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
    run();
    obj.run();
    obj = ExampleMethodsTest.getInstance();    
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
    Eval(Call(This(), "run", null));
    Eval(Call(Get(This(), "obj"), "run", null));
    Eval(Set(This(), "obj", Call(ExampleMethodsTest.class, "getInstance", null)));        
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

_Calling methods with parameters_

All of the &lt;code&gt;Call&lt;/code&gt; methods above take a &lt;code&gt;CallStack&lt;/code&gt; as their third parameter.
&lt;code&gt;ClassMaker&lt;/code&gt; provides the following methods to create a call stack.

&lt;pre&gt;
    public CallStack Push() throws ClassMakerException;
    public CallStack Push(Type param) throws ClassMakerException;
    public class CallStack
    {
        public CallStack Push(Type param) throws ClassMakerException;
    }
&lt;/pre&gt;

These methods can be daisy-chained together to create a call stack of actual parameters.
The &lt;code&gt;Types&lt;/code&gt; on the call stack will be used by the method resolver to determine
which method to call.

&lt;pre&gt;
    Push( &lt;value1&gt; ).Push( &lt;value2&gt; ).Push( &lt;value3&gt; );
&lt;/pre&gt;

&lt;table border="1" width="100%"&gt;
&lt;tr&gt;&lt;td&gt;Java code&lt;/td&gt;&lt;td&gt;ClassMaker code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
&amp;nbsp;
    x = add(1, 2);
    y = obj.add(x, 3);
    ExampleMethodsTest.setInstance(this);    
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
&amp;nbsp;
    Eval(Set(This(), "x", Call(This(), "add", Push(Literal(1)).Push(Literal(2)))));
    Eval(Set(This(), "y", Call(Get(This(), "obj"), "add", Push(Get(This(), "x")).Push(Literal(3)))));    
    Eval(Call(ExampleMethodsTest.class, "setInstance", Push(This())));
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

Note that &lt;code&gt;Push()&lt;/code&gt; provides an empty &lt;code&gt;CallStack&lt;/code&gt;. An empty &lt;code&gt;CallStack&lt;/code&gt; will be created if
the &lt;code&gt;callStack&lt;/code&gt; parameter is &lt;code&gt;null&lt;/code&gt;.

_Constructors_

Two special methods are provided to assist with creating constructor methods.

&lt;pre&gt;
    public void Init(ClassType classType, CallStack actualParameters) throws ClassMakerException
    public ClassType Super() throws ClassMakerException
&lt;/pre&gt;

The &lt;code&gt;Init&lt;/code&gt; method is used to invoke a constructor method. The &lt;code&gt;Super()&lt;/code&gt; method
pushes a reference to the current instance onto the stack. It differs from &lt;code&gt;This()&lt;/code&gt;
in that it returns the type of the parent class.

Every class you generate must have at least one constructor. A typical
constructor looks like this.

&lt;pre&gt;
    Method("&lt;init&gt;", void.class, ACC_PUBLIC);
    Begin();
        Init(Super(), null);
        Return();
    End();
&lt;/pre&gt;

You can provide your constructor either in the &lt;code&gt;code()&lt;/code&gt; method
of &lt;code&gt;ClassMakerBase&lt;/code&gt; or by overriding the special &lt;code&gt;defaultConstructor()&lt;/code&gt; method.
&lt;code&gt;ClassMakerBase&lt;/code&gt; will provide a default constructor if you don't.

A constructor method must be called &lt;code&gt;"&lt;init&gt;"&lt;/code&gt; and must include a call to a
constructor in the super class with an appropriate &lt;code&gt;CallStack&lt;/code&gt;.

&lt;pre&gt;
    Init(Super(), ... );
&lt;/pre&gt;

_Abstract methods_

Interface methods and abstract methods do not have a body.
This is indicated in !ClassMaker using the &lt;code&gt;Forward&lt;/code&gt; method.
This method is used instead of providing a body for the method being generated.

&lt;pre&gt;
    public void Forward() throws ClassMakerException
&lt;/pre&gt;

An abstract method in an abstract class must be declared as such using the &lt;code&gt;ClassMaker.ACC_ABSTRACT&lt;/code&gt; bit mask.
All methods in an interface are implicitly abstract so the &lt;code&gt;ACC_ABSTRACT&lt;/code&gt; bit mask is optional. 

&lt;table border="1" width="100%"&gt;
&lt;tr&gt;&lt;td&gt;Java code&lt;/td&gt;&lt;td&gt;ClassMaker code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
    &amp;nbsp;
    public abstract int getId();
    &amp;nbsp;
    public abstract void setId(int value);
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
    &amp;nbsp;
    Method("getId", int.class, ACC_PUBLIC | ACC_ABSTRACT);
    Forward();
    &amp;nbsp;
    Method("setId", void.class, ACC_PUBLIC | ACC_ABSTRACT);
    Declare("value", int.class, 0);
    Forward();
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;


_Forward declarations_

&lt;code&gt;ClassMaker&lt;/code&gt; is a single pass byte-code generator by default. This means that
a method cannot be used until it has been declared. This creates a problem if two
methods mutually call each other. &lt;code&gt;ClassMaker&lt;/code&gt; resolves this issue by allowing
methods to be forward declared using the &lt;code&gt;Forward&lt;/code&gt; method.

&lt;pre&gt;
    public void Forward() throws ClassMakerException
&lt;/pre&gt;

Methods that are used before they are declared must be declared twice. The
first time the method is declared without a body using the &lt;code&gt;Forward&lt;/code&gt; method.
This declaration must occur before the method is first used.
The second declaration of the method, which provides the body of the method,
may be declared anywhere after the forward declaration. 
Both the forward declaration and the actual declaration of the method must 
have the same parameters otherwise the generator will complain.

&lt;pre&gt;
    maker.Method("add", int.class, ClassMaker.ACC_PRIVATE);
    maker.Declare("a", int.class, 0);
    maker.Declare("b", int.class, 0);
    maker.Forward();
    &amp;nbsp;
    maker.Method("eval", int.class, ClassMaker.ACC_PUBLIC);
    maker.Begin();
        maker.Return(maker.Call(maker.This(), "add", maker.Push(maker.Literal(1)).Push(maker.Literal(2))));
    maker.End();
    &amp;nbsp;
    maker.Method("add", int.class, ClassMaker.ACC_PRIVATE);
    maker.Declare("a", int.class, 0);
    maker.Declare("b", int.class, 0);
    maker.Begin();
        maker.Return(maker.Add(maker.Get("a"), maker.Get("b")));
    maker.End();
&lt;/pre&gt;

In this example the &lt;code&gt;add&lt;/code&gt; method is forward declared and then called in the &lt;code&gt;eval&lt;/code&gt; method.
The actual declaration of the &lt;code&gt;add&lt;/code&gt; method occurs after it is first used.

There is no equivalent in java of a forward declaration, however there is forward declaration
in C and C++ which are the predecessors of java and upon which the java syntax is based. The
original Kernigan and Richie (K&amp;R) C also had a style of declaring formal parameters similar to that
used in &lt;code&gt;ClassMaker&lt;/code&gt;.

Note that &lt;code&gt;ClassMaker&lt;/code&gt; may be configured to be a two pass code generator, in which case it is
not necessary to forward declare methods.

_Recursive data structures_

There are times when a class needs to refer to itself, such as when building recursive data structures
like linked lists and binary trees. 
This method returns the &lt;code&gt;Type&lt;/code&gt; of the class currently being generated.

&lt;pre&gt;
    public ClassType getClassType()
&lt;/pre&gt;

The following example shows how one might recursively search through a linked list.

&lt;table border="1" width="100%"&gt;
&lt;tr&gt;&lt;td&gt;Java code&lt;/td&gt;&lt;td&gt;ClassMaker code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre&gt;
    String name;
    Link   next;
    &amp;nbsp;
    public Link find(String target)
    {
        if (target.equals(name))
            return this;
        else
            return next.find(target);
    }
&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;
    Declare("name", String.class, 0);
    Declare("next", getClassType(), 0);
    &amp;nbsp;
    Method("find", getClassType(), ACC_PUBLIC);
    Declare("target", String.class, 0);
    Begin();
        If(Call(Get("target"), "equals", Push(Get(This(), "name"))));
            Return(This());
        Else();
            Return(Call(Get(This(), "next"), "find", Push(Get("target"))));
        EndIf();
    End();
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

----

[Home]
</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Donald Strong</dc:creator><pubDate>Mon, 01 Oct 2012 00:17:54 -0000</pubDate><guid>https://sourceforge.netaaf34493b839c96ac0cd0d6f506a8920b3e79016</guid></item></channel></rss>