001: /*
002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.es.parser;
030:
031: import com.caucho.es.ESException;
032: import com.caucho.es.ESId;
033:
034: import java.io.IOException;
035:
036: /**
037: * Expr is an intermediate form representing an expression.
038: */
039: class IdExpr extends Expr {
040: private static ESId ARGUMENTS = ESId.intern("arguments");
041: private Variable var;
042:
043: IdExpr(Block block, Variable var) {
044: super (block);
045:
046: this .var = var;
047: if (var.getId() == ARGUMENTS) {
048: function.setArguments();
049: function.setUseAllVariables();
050: }
051:
052: if (var.getTypeExpr() != null) {
053: type = var.getType();
054: javaType = var.getTypeExpr().getJavaClass();
055: }
056:
057: if (!var.isLocal() && !function.isGlobalScope()
058: && !var.isJavaGlobal())
059: function.setNeedsScope();
060: }
061:
062: void setType(int type) {
063: var.setType(type);
064: }
065:
066: boolean isLocal() {
067: return var.isLocal() && function.allowLocals();
068: }
069:
070: boolean isJavaLocal() {
071: return var.isJavaLocal() && function.allowLocals();
072: }
073:
074: /**
075: * Returns true if the variable is a global represented as a Java
076: * field.
077: */
078: boolean isJavaGlobal() {
079: return var.isJavaGlobal();
080: }
081:
082: void setUsed() {
083: var.setUsed();
084: }
085:
086: int getType() {
087: if (!isLocal() && !isJavaGlobal())
088: return TYPE_ES;
089: else
090: return var.getType();
091: }
092:
093: Expr getTypeExpr() {
094: if (!isLocal())
095: return null;
096: else
097: return var.getTypeExpr();
098: }
099:
100: boolean isSimple() {
101: return isJavaLocal();
102: }
103:
104: boolean isGlobalScope() {
105: return function.isGlobalScope() && !var.isScope();
106: }
107:
108: /**
109: * Returns the underlying variable.
110: */
111: Variable getVar() {
112: return var;
113: }
114:
115: boolean isUsed() {
116: return var.isUsed() || function.useAllVariables();
117: }
118:
119: void setLocal() {
120: var.setLocal();
121: }
122:
123: ESId getId() {
124: return var.getId();
125: }
126:
127: Expr delete() {
128: return new DeleteExpr(block, this );
129: }
130:
131: Expr postfix(int op) {
132: if (op == '+')
133: return new PostfixExpr(block, PostfixExpr.POSTINC, this );
134: else
135: return new PostfixExpr(block, PostfixExpr.POSTDEC, this );
136: }
137:
138: Expr prefix(int op) {
139: if (op == '+')
140: return new PostfixExpr(block, PostfixExpr.PREINC, this );
141: else
142: return new PostfixExpr(block, PostfixExpr.PREDEC, this );
143: }
144:
145: /**
146: * Assigns the identifier to a value.
147: */
148: Expr assign(Expr value) throws ESException {
149: int valueType = value.getType();
150: Expr typeExpr = value.getTypeExpr();
151: // XXX: needs to differ from getType to make type inference work
152: int type = var.type;
153:
154: if (isLocal() || isJavaGlobal()) {
155: if (valueType == TYPE_UNKNOWN)
156: valueType = TYPE_ES;
157:
158: if (typeExpr != null)
159: var.setType(TYPE_JAVA, typeExpr);
160: else if (type == TYPE_UNKNOWN)
161: var.setType(valueType);
162: else if (type == valueType) {
163: } else if ((type == TYPE_INTEGER || type == TYPE_NUMBER)
164: && (valueType == TYPE_INTEGER || valueType == TYPE_NUMBER))
165: var.setType(TYPE_NUMBER);
166: else
167: var.setType(TYPE_ES, null);
168:
169: type = var.getType();
170: Expr newTypeExpr = var.getTypeExpr();
171: if (newTypeExpr == null)
172: javaType = null;
173: else
174: javaType = newTypeExpr.getJavaClass();
175: }
176:
177: return new AssignExpr(block, this , value);
178: }
179:
180: /**
181: * Creates a call expression from this id.
182: */
183: CallExpr startCall() throws ESException {
184: var.setUsed();
185:
186: return new CallExpr(block, this , null, false);
187: }
188:
189: CallExpr startNew() throws ESException {
190: var.setUsed();
191:
192: return new CallExpr(block, this , null, true);
193: }
194:
195: void exprStatement(Function fun) throws ESException {
196: doVoid().exprStatement(fun);
197: }
198:
199: void printNumImpl() throws IOException {
200: printImpl();
201: }
202:
203: void printBooleanImpl() throws IOException {
204: printImpl();
205: }
206:
207: void printInt32Impl() throws IOException {
208: printImpl();
209: }
210:
211: void printStringImpl() throws IOException {
212: printImpl();
213: }
214:
215: void printImpl() throws IOException {
216: cl.setLine(getFilename(), getLine());
217:
218: if (isJavaLocal()) {
219: cl.print(getId());
220: } else if (isJavaGlobal()) {
221: cl.print(getId());
222: } else if (isGlobalScope()) {
223: // Need to use getGlobalVariable so an undefined variable will
224: // throw an exception
225: cl.print("_env.getGlobalVariable(");
226: printLiteral(getId());
227: cl.print(")");
228: } else {
229: cl.print("_env.getScopeProperty(");
230: printLiteral(getId());
231: cl.print(")");
232: }
233: }
234:
235: void printJavaImpl() throws IOException {
236: cl.setLine(getFilename(), getLine());
237:
238: cl.print(getId());
239: }
240:
241: public String toString() {
242: return "[IdExpr " + getId() + "]";
243: }
244: }
|