summaryrefslogtreecommitdiff
path: root/src/main/java/io/devnulllabs/openjava/mop/Metaclass.java
blob: 0be5694afb7d1d3b5d016581471aeb6045341391 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * Metaclass.java
 *
 * It is used for some conveniences in writing metaclasses.
 *
 * @author   Michiaki Tatsubori
 * @version  %VERSION% %DATE%
 * @see      java.lang.Object
 *
 * COPYRIGHT 1999 by Michiaki Tatsubori, ALL RIGHTS RESERVED.
 */
package io.devnulllabs.openjava.mop;


import io.devnulllabs.openjava.ptree.ClassDeclaration;
import io.devnulllabs.openjava.ptree.ConstructorInvocation;
import io.devnulllabs.openjava.ptree.ParseTreeException;
import io.devnulllabs.openjava.ptree.StatementList;
import io.devnulllabs.openjava.ptree.util.ClassLiteralReplacer;


/**
 * The class <code>Metaclass</code> is a metametaclass for metaclasses.
 * You can write a metaclass easily using this class.
 * <p>
 * For example,
 * <pre>
 * public class MyClass instantiates Metaclass extends OJClass
 * {
 *     convenient void f() {
 *         .. String.class ..;
 *         .. oldjavaclass.String.class ..;
 *     }
 *     void g() {
 *         .. String.class ..;
 *     }
 * }
 * </pre>
 *
 * <p>Here, you don't have to write constructors if your program don't
 * concern.  And class literal doesn't represent <b>java.lang.Class</b>
 * object but <b>io.devnulllabs.openjava.mop.OJClass</b>.
 *
 * <p>The above code is to be translated into:
 * <pre>
 * public class MyClass instantiates Metaclass extends OJClass
 * {
 *     void f() {
 *         .. io.devnulllabs.openjava.mop.OJClass.forClass( String.class ) ..;
 *         .. java.lang.String.class ..;
 *     }
 *     void g() {
 *         .. java.lang.String.class ..;
 *     }
 *     void translateDefinition() {
 *         OJClass c1 = io.devnulllabs.openjava.mop.OJClass.forClass( String.class );
 *         OJClass c2 = String.class;
 *     }
 *     public MyClass(Environment e, OJClass d, ClassDeclaration p) {
 *         super(e,d,p);
 *     }
 *     public MyClass(Class c, MetaInfo m) {
 *         super(c,m);
 *     }
 * }
 * </pre>
 *
 * @author   Michiaki Tatsubori
 * @version  1.0
 * @since    $Id: Metaclass.java,v 1.2 2003/02/19 02:55:01 tatsubori Exp $
 * @see java.lang.Object
 */
public class Metaclass extends OJClass
{
    private static final String CONVENIENT = "convenient";

    public void translateDefinition() throws MOPException {
    /* automatic constructors */
        OJConstructor src_constr = makeSrcConstr();
    try {
        getConstructor( src_constr.getParameterTypes() );
    } catch ( NoSuchMemberException e ) {
        addConstructor( src_constr );
    }
        OJConstructor byte_constr = makeByteConstr();
    try {
        getConstructor( byte_constr.getParameterTypes() );
    } catch ( NoSuchMemberException e ) {
        addConstructor( byte_constr );
    }

    /* class literal */
    OJMethod[] methods = getDeclaredMethods();
    for (int i = 0; i < methods.length; ++i) {
        if (! methods[i].getModifiers().has( CONVENIENT ))  continue;
        try {
        ClassLiteralReplacer rep
            = new ClassLiteralReplacer( methods[i].getEnvironment() );
        methods[i].getBody().accept( rep );
        } catch ( ParseTreeException e ) {
        System.err.println( e );
        }
    }
    }

    public static final boolean isRegisteredModifier( String keyword ) {
    if (keyword.equals( CONVENIENT ))  return true;
    return OJClass.isRegisteredModifier( keyword );
    }

    private OJConstructor makeSrcConstr() throws MOPException {
    OJModifier modif = OJModifier.forModifier( OJModifier.PUBLIC );
    OJClass[] paramtypes
        = new OJClass[] {
        OJClass.forClass( Environment . class ),
        OJClass.forClass( OJClass . class ),
        OJClass.forClass( ClassDeclaration . class ) };
    OJConstructor result
        = new OJConstructor( this, modif, paramtypes, null,
                 null, new StatementList() );
    ConstructorInvocation ci
        = new ConstructorInvocation( result.getParameterVariables(),
                     null );
    result.setTransference( ci );
    return result;
    }

    private OJConstructor makeByteConstr() throws MOPException {
    OJModifier modif = OJModifier.forModifier( OJModifier.PUBLIC );
    OJClass[] paramtypes
        = new OJClass[] {
        OJClass.forClass( Class . class ),
        OJClass.forClass( MetaInfo . class ) };
    OJConstructor result
        = new OJConstructor( this, modif, paramtypes, null,
                 null, new StatementList() );
    ConstructorInvocation ci
        = new ConstructorInvocation( result.getParameterVariables(),
                     null );
    result.setTransference( ci );
    return result;
    }

    public Metaclass( Environment outer_env, OJClass declarer,
             ClassDeclaration ptree ) {
    super( outer_env, declarer, ptree );
    }

    public Metaclass( Class javaclass, MetaInfo minfo ) {
    super( javaclass, minfo );
    }

}