1/*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License.  Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15
16package javassist.compiler.ast;
17
18import javassist.compiler.CompileError;
19
20/**
21 * A linked list.
22 * The right subtree must be an ASTList object or null.
23 */
24public class ASTList extends ASTree {
25    private ASTree left;
26    private ASTList right;
27
28    public ASTList(ASTree _head, ASTList _tail) {
29        left = _head;
30        right = _tail;
31    }
32
33    public ASTList(ASTree _head) {
34        left = _head;
35        right = null;
36    }
37
38    public static ASTList make(ASTree e1, ASTree e2, ASTree e3) {
39        return new ASTList(e1, new ASTList(e2, new ASTList(e3)));
40    }
41
42    public ASTree getLeft() { return left; }
43
44    public ASTree getRight() { return right; }
45
46    public void setLeft(ASTree _left) { left = _left; }
47
48    public void setRight(ASTree _right) {
49        right = (ASTList)_right;
50    }
51
52    /**
53     * Returns the car part of the list.
54     */
55    public ASTree head() { return left; }
56
57    public void setHead(ASTree _head) {
58        left = _head;
59    }
60
61    /**
62     * Returns the cdr part of the list.
63     */
64    public ASTList tail() { return right; }
65
66    public void setTail(ASTList _tail) {
67        right = _tail;
68    }
69
70    public void accept(Visitor v) throws CompileError { v.atASTList(this); }
71
72    public String toString() {
73        StringBuffer sbuf = new StringBuffer();
74        sbuf.append("(<");
75        sbuf.append(getTag());
76        sbuf.append('>');
77        ASTList list = this;
78        while (list != null) {
79            sbuf.append(' ');
80            ASTree a = list.left;
81            sbuf.append(a == null ? "<null>" : a.toString());
82            list = list.right;
83        }
84
85        sbuf.append(')');
86        return sbuf.toString();
87    }
88
89    /**
90     * Returns the number of the elements in this list.
91     */
92    public int length() {
93        return length(this);
94    }
95
96    public static int length(ASTList list) {
97        if (list == null)
98            return 0;
99
100        int n = 0;
101        while (list != null) {
102            list = list.right;
103            ++n;
104        }
105
106        return n;
107    }
108
109    /**
110     * Returns a sub list of the list.  The sub list begins with the
111     * n-th element of the list.
112     *
113     * @param nth       zero or more than zero.
114     */
115    public ASTList sublist(int nth) {
116        ASTList list = this;
117        while (nth-- > 0)
118            list = list.right;
119
120        return list;
121    }
122
123    /**
124     * Substitutes <code>newObj</code> for <code>oldObj</code> in the
125     * list.
126     */
127    public boolean subst(ASTree newObj, ASTree oldObj) {
128        for (ASTList list = this; list != null; list = list.right)
129            if (list.left == oldObj) {
130                list.left = newObj;
131                return true;
132            }
133
134        return false;
135    }
136
137    /**
138     * Appends an object to a list.
139     */
140    public static ASTList append(ASTList a, ASTree b) {
141        return concat(a, new ASTList(b));
142    }
143
144    /**
145     * Concatenates two lists.
146     */
147    public static ASTList concat(ASTList a, ASTList b) {
148        if (a == null)
149            return b;
150        else {
151            ASTList list = a;
152            while (list.right != null)
153                list = list.right;
154
155            list.right = b;
156            return a;
157        }
158    }
159}
160