KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > js > JsNormalizer


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.js;
17
18 import com.google.gwt.dev.js.ast.JsBinaryOperation;
19 import com.google.gwt.dev.js.ast.JsBinaryOperator;
20 import com.google.gwt.dev.js.ast.JsContext;
21 import com.google.gwt.dev.js.ast.JsExpression;
22 import com.google.gwt.dev.js.ast.JsModVisitor;
23 import com.google.gwt.dev.js.ast.JsPostfixOperation;
24 import com.google.gwt.dev.js.ast.JsPrefixOperation;
25 import com.google.gwt.dev.js.ast.JsProgram;
26 import com.google.gwt.dev.js.ast.JsUnaryOperation;
27 import com.google.gwt.dev.js.ast.JsUnaryOperator;
28
29 /**
30  * Fixes any semantic errors introduced by JS AST gen.
31  *
32  * <ul>
33  * <li> Creating clinit calls can put comma expressions as lvalues; the
34  * modifying operation must be moved inside the comma expression to the last
35  * argument. </li>
36  * </ul>
37  */

38 public class JsNormalizer {
39
40   /**
41    * Resolves any unresolved JsNameRefs.
42    */

43   private class JsNormalizing extends JsModVisitor {
44
45     public void endVisit(JsBinaryOperation x, JsContext ctx) {
46       maybeShuffleModifyingBinary(x, ctx);
47     }
48
49     public void endVisit(JsPostfixOperation x, JsContext ctx) {
50       maybeShuffleModifyingUnary(x, ctx);
51     }
52
53     public void endVisit(JsPrefixOperation x, JsContext ctx) {
54       maybeShuffleModifyingUnary(x, ctx);
55     }
56
57     /**
58      * Due to the way clinits are constructed, you can end up with a comma
59      * operation as the argument to a modifying operation, which is illegal.
60      * Juggle things to put the operator inside of the comma expression.
61      */

62     private void maybeShuffleModifyingBinary(JsBinaryOperation x, JsContext ctx) {
63       JsBinaryOperator myOp = x.getOperator();
64       JsExpression lhs = x.getArg1();
65       JsExpression rhs = x.getArg2();
66
67       if (myOp.isAssignment() && (lhs instanceof JsBinaryOperation)) {
68         // Find the rightmost comma operation
69
JsBinaryOperation curLhs = (JsBinaryOperation) lhs;
70         assert (curLhs.getOperator() == JsBinaryOperator.COMMA);
71         while (curLhs.getArg2() instanceof JsBinaryOperation) {
72           curLhs = (JsBinaryOperation) curLhs.getArg2();
73           assert (curLhs.getOperator() == JsBinaryOperator.COMMA);
74         }
75         // curLhs is now the rightmost comma operation; slide our operation in
76
x.setArg1(curLhs.getArg2());
77         curLhs.setArg2(x);
78         // replace myself with the comma expression
79
ctx.replaceMe(lhs);
80       }
81     }
82
83     /**
84      * Due to the way clinits are constructed, you can end up with a comma
85      * operation as the argument to a modifying operation, which is illegal.
86      * Juggle things to put the operator inside of the comma expression.
87      */

88     private void maybeShuffleModifyingUnary(JsUnaryOperation x, JsContext ctx) {
89       JsUnaryOperator myOp = x.getOperator();
90       JsExpression arg = x.getArg();
91       if (myOp.isModifying() && (arg instanceof JsBinaryOperation)) {
92         // Find the rightmost comma operation
93
JsBinaryOperation curArg = (JsBinaryOperation) arg;
94         assert (curArg.getOperator() == JsBinaryOperator.COMMA);
95         while (curArg.getArg2() instanceof JsBinaryOperation) {
96           curArg = (JsBinaryOperation) curArg.getArg2();
97           assert (curArg.getOperator() == JsBinaryOperator.COMMA);
98         }
99         // curArg is now the rightmost comma operation; slide our operation in
100
x.setArg(curArg.getArg2());
101         curArg.setArg2(x);
102         // replace myself with the comma expression
103
ctx.replaceMe(arg);
104       }
105     }
106   }
107
108   public static void exec(JsProgram program) {
109     new JsNormalizer(program).execImpl();
110   }
111
112   private final JsProgram program;
113
114   private JsNormalizer(JsProgram program) {
115     this.program = program;
116   }
117
118   private void execImpl() {
119     JsNormalizing normalizer = new JsNormalizing();
120     normalizer.accept(program);
121   }
122 }
123
Popular Tags