summaryrefslogtreecommitdiff
path: root/src/main/java/io/devnulllabs/openjava/ptree/util/MemberAccessCorrector.java
blob: 8c1a2d8f5ba736d05ebe821a5da3e87b7eb15c86 (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
 * MemberAccessCorrector.java
 *
 * Firstly, the parser generates a temporal parse tree.
 * This class correct them.
 * <p>
 *
 * All the continuous field access are stored in a single Variable ptree
 * object.
 * [p.p.f.f].f  [p.f].m()  ([] a single Variable object)
 * FieldAccess := Variable name
 * MemberAccess := Variable name "(" .. ")"
 *
 * @author   Michiaki Tatsubori
 * @version  %VERSION% %DATE%
 * @see      java.lang.Object
 *
 * COPYRIGHT 1998 by Michiaki Tatsubori, ALL RIGHTS RESERVED.
 */
package io.devnulllabs.openjava.ptree.util;

import io.devnulllabs.openjava.mop.Environment;
import io.devnulllabs.openjava.mop.NoSuchMemberException;
import io.devnulllabs.openjava.mop.OJClass;
import io.devnulllabs.openjava.mop.OJClassNotFoundException;
import io.devnulllabs.openjava.mop.OJField;
import io.devnulllabs.openjava.ptree.Expression;
import io.devnulllabs.openjava.ptree.FieldAccess;
import io.devnulllabs.openjava.ptree.MethodCall;
import io.devnulllabs.openjava.ptree.ParseTreeException;
import io.devnulllabs.openjava.ptree.TypeName;
import io.devnulllabs.openjava.ptree.Variable;
import io.devnulllabs.openjava.tools.DebugOut;

/**
 * The class <code>MemberAccessCorrector</code>
 * <p>
 * For example
 * <pre>
 * </pre>
 * <p>
 *
 * @author   Michiaki Tatsubori
 * @version  1.0
 * @since    $Id: MemberAccessCorrector.java,v 1.2 2003/02/19 02:55:00 tatsubori Exp $
 * @see java.lang.Object
 */
public class MemberAccessCorrector extends VariableBinder {

    private String errorState = null;

    public MemberAccessCorrector(Environment env) {
        super(env);
    }

    public String getErrorState() {
        return errorState;
    }

    public Expression evaluateDown(FieldAccess ptree)
        throws ParseTreeException {
        super.evaluateDown(ptree);

        if (ptree.getReferenceType() != null)
            return ptree;

        Expression ref = ptree.getReferenceExpr();
        String field_name = ptree.getName();

        if (ref == null) {
            if (isVariable(field_name)) {
                /* this is a variable. */
                DebugOut.println("MC variable - " + field_name);
                return new Variable(field_name);
            } else if (isField(field_name)) {
                /* this is a field access */
                DebugOut.println("MC field access - " + field_name);
            } else {
                /* unknown variable or field */
                System.err.println("unknown field or variable : " + field_name);
                System.err.println(getEnvironment());
            }
        } else if (ref instanceof Variable) {
            FieldAccess fa = name2fieldaccess(ref.toString(), field_name);
            TypeName typename = fa.getReferenceType();
            Expression refexpr = fa.getReferenceExpr();
            if (typename != null) {
                ptree.setReferenceType(typename);
            } else {
                ptree.setReferenceExpr(refexpr);
            }
        }

        return ptree;
    }

    public Expression evaluateDown(MethodCall ptree)
        throws ParseTreeException {
        super.evaluateDown(ptree);

        if (ptree.getReferenceType() != null)
            return ptree;

        Expression ref = ptree.getReferenceExpr();
        if (ref == null || !(ref instanceof Variable))
            return ptree;
        String method_name = ptree.getName();

        if (ref instanceof Variable) {
            FieldAccess fa = name2fieldaccess(ref.toString(), method_name);
            TypeName typename = fa.getReferenceType();
            Expression refexpr = fa.getReferenceExpr();
            if (typename != null) {
                ptree.setReferenceType(typename);
            } else {
                ptree.setReferenceExpr(refexpr);
            }
        }
        return ptree;
    }

    private FieldAccess name2fieldaccess(String names, String field) {
        Expression result_expr;
        String first = getFirst(names);
        String rest = getRest(names);

        if (isVariable(first)) {
            /* this is a variable  */
            DebugOut.println("MC variable - " + first);
            result_expr = new Variable(first);
        } else if (isField(first)) {
            /* this is a field  */
            DebugOut.println("MC field - " + first);
            result_expr = new FieldAccess((Variable) null, first);
        } else {
            /* this is a class */
            while (rest != null && !isClass(first)) {
                first = first + "." + getFirst(rest);
                rest = getRest(rest);
            }
            while (isClass(first + "." + getFirst(rest))) {
                first = first + "." + getFirst(rest);
                rest = getRest(rest);
            }
            if (isClass(first)) {
                DebugOut.println("MC class - " + first);
            } else {
                System.err.println("unknown class : " + first);
            }

            TypeName type = new TypeName(first);
            if (rest == null) {
                /* ref is a typename */
                return new FieldAccess(type, field);
            }
            first = getFirst(rest);
            rest = getRest(rest);
            result_expr = new FieldAccess(type, first);
        }

        /* remainder is field access */
        while (rest != null) {
            first = getFirst(rest);
            rest = getRest(rest);
            result_expr = new FieldAccess(result_expr, first);
        }

        return new FieldAccess(result_expr, field);
    }

    private boolean isVariable(String name) {
        Environment env = getEnvironment();
        OJClass bindedtype = env.lookupBind(name);
        return (bindedtype != null);
    }

    private boolean isField(String name) {
        Environment env = getEnvironment();
        String qcname = env.toQualifiedName(env.currentClassName());
        OJClass declarer = env.lookupClass(qcname);
        OJField field = null;
        while (declarer != null && field == null) {
            try {
                field = declarer.getField(name, declarer);
            } catch (NoSuchMemberException e) {
            }
            declarer = declarer.getDeclaringClass();
        }
        return (field != null);
    }

    private boolean isClass(String name) {
        Environment env = getEnvironment();
        String qname = env.toQualifiedName(name);
        try {
            OJClass.forName(qname);
            return true;
        } catch (OJClassNotFoundException e) {
        }
        OJClass clazz = env.lookupClass(qname);
        return (clazz != null);
    }

    private static final String getFirst(String qname) {
        if (qname == null)
            return null;
        int dot = qname.indexOf('.');
        if (dot == -1)
            return qname;
        return qname.substring(0, dot);
    }

    private static final String getRest(String qname) {
        if (qname == null)
            return null;
        int dot = qname.indexOf('.');
        if (dot == -1)
            return null;
        return qname.substring(dot + 1);
    }

}