1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xalan.internal.xsltc.compiler;
23
24import com.sun.org.apache.bcel.internal.generic.ALOAD;
25import com.sun.org.apache.bcel.internal.generic.ASTORE;
26import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
27import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
28import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
29import com.sun.org.apache.bcel.internal.generic.InstructionList;
30import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
31import com.sun.org.apache.bcel.internal.generic.NEW;
32import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
33import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
34import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeType;
35import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
36import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
37import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
38
39/**
40 * @author Jacek Ambroziak
41 * @author Santiago Pericas-Geertsen
42 */
43final class AbsoluteLocationPath extends Expression {
44    private Expression _path;   // may be null
45
46    public AbsoluteLocationPath() {
47        _path = null;
48    }
49
50    public AbsoluteLocationPath(Expression path) {
51        _path = path;
52        if (path != null) {
53            _path.setParent(this);
54        }
55    }
56
57    public void setParser(Parser parser) {
58        super.setParser(parser);
59        if (_path != null) {
60            _path.setParser(parser);
61        }
62    }
63
64    public Expression getPath() {
65        return(_path);
66    }
67
68    public String toString() {
69        return "AbsoluteLocationPath(" +
70            (_path != null ? _path.toString() : "null") + ')';
71    }
72
73    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
74        if (_path != null) {
75            final Type ptype = _path.typeCheck(stable);
76            if (ptype instanceof NodeType) {            // promote to node-set
77                _path = new CastExpr(_path, Type.NodeSet);
78            }
79        }
80        return _type = Type.NodeSet;
81    }
82
83    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
84        final ConstantPoolGen cpg = classGen.getConstantPool();
85        final InstructionList il = methodGen.getInstructionList();
86        if (_path != null) {
87            final int initAI = cpg.addMethodref(ABSOLUTE_ITERATOR,
88                                                "<init>",
89                                                "("
90                                                + NODE_ITERATOR_SIG
91                                                + ")V");
92
93            // Compile relative path iterator(s)
94            //
95            // Backwards branches are prohibited if an uninitialized object is
96            // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed.
97            // We don't know whether this code might contain backwards branches,
98            // so we mustn't create the new object until after we've created
99            // this argument to its constructor.  Instead we calculate the
100            // value of the argument to the constructor first, store it in
101            // a temporary variable, create the object and reload the argument
102            // from the temporary to avoid the problem.
103            _path.translate(classGen, methodGen);
104            LocalVariableGen relPathIterator
105                    = methodGen.addLocalVariable("abs_location_path_tmp",
106                                       Util.getJCRefType(NODE_ITERATOR_SIG),
107                                       null, null);
108            relPathIterator.setStart(
109                    il.append(new ASTORE(relPathIterator.getIndex())));
110
111            // Create new AbsoluteIterator
112            il.append(new NEW(cpg.addClass(ABSOLUTE_ITERATOR)));
113            il.append(DUP);
114            relPathIterator.setEnd(
115                    il.append(new ALOAD(relPathIterator.getIndex())));
116
117            // Initialize AbsoluteIterator with iterator from the stack
118            il.append(new INVOKESPECIAL(initAI));
119        }
120        else {
121            final int gitr = cpg.addInterfaceMethodref(DOM_INTF,
122                                                       "getIterator",
123                                                       "()"+NODE_ITERATOR_SIG);
124            il.append(methodGen.loadDOM());
125            il.append(new INVOKEINTERFACE(gitr, 1));
126        }
127    }
128}
129