001: /*
002: * $Id: AbstractAssignmentNode.java,v 1.15 2002/09/16 08:05:04 jkl Exp $
003: *
004: * Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
005: *
006: * Use is subject to license terms, as defined in
007: * Anvil Sofware License, Version 1.1. See LICENSE
008: * file, or http://njet.org/license-1.1.txt
009: */
010: package anvil.script.expression;
011:
012: import anvil.ErrorListener;
013: import anvil.Location;
014: import anvil.core.Any;
015: import anvil.core.Array;
016: import anvil.codec.Code;
017: import anvil.script.compiler.ByteCompiler;
018: import anvil.script.Context;
019: import java.io.IOException;
020: import java.util.Enumeration;
021:
022: /**
023: * class AbstractAssignmentNode
024: *
025: * @author: Jani Lehtimäki
026: */
027: public abstract class AbstractAssignmentNode extends MultiParent {
028:
029: protected Location _location;
030:
031: public AbstractAssignmentNode(Location location, int childs) {
032: super (childs);
033: _location = location;
034: }
035:
036: public AbstractAssignmentNode(Parent parent) {
037: super (parent);
038: }
039:
040: public boolean isConstant() {
041: return false;
042: }
043:
044: public void check(ErrorListener context) {
045: super .check(context);
046: int type = typeOf();
047: switch (type) {
048: case EXPR_ASSIGN: {
049: final int n = childs() - 1;
050: for (int i = 0; i < n; i++) {
051: if (!getChild(i).isAssignable()) {
052: context.error(_location, "Left side expression #"
053: + (i + 1)
054: + " of assignment is not assignable");
055: }
056: }
057: }
058: break;
059:
060: case EXPR_ASSIGN_INIT:
061: case EXPR_ASSIGN_ADD:
062: case EXPR_ASSIGN_SUBTRACT:
063: case EXPR_ASSIGN_MULTIPLY:
064: case EXPR_ASSIGN_CONCAT:
065: case EXPR_ASSIGN_MODULO:
066: case EXPR_ASSIGN_DIVIDE: {
067: final int n = childs() - 1;
068: for (int i = 0; i < n; i++) {
069: if (!getChild(i).isUpdatable()) {
070: context
071: .error(
072: _location,
073: "Left side expression #"
074: + (i + 1)
075: + " of augmented assignment is not updatable");
076: }
077: }
078: }
079: break;
080: }
081: }
082:
083: public abstract String getOperator();
084:
085: protected abstract String getAssignmentMethod();
086:
087: protected void compileOperation(ByteCompiler context,
088: final Node left, final Node right) {
089: left.compile(context, new Node() {
090: public void compile(ByteCompiler context, int operation) {
091: left.compile(context, GET);
092: right.compile(context, GET);
093: Code code = context.getCode();
094: code
095: .invokestatic(code
096: .getPool()
097: .addMethodRef(context.TYPE_ANY_OP,
098: getAssignmentMethod(),
099: "(Lanvil/core/Any;Lanvil/core/Any;)Lanvil/core/Any;"));
100: }
101: });
102: }
103:
104: public void compile(ByteCompiler context, Node left, Node right) {
105: Code code = context.getCode();
106: switch (left.typeOf()) {
107: case EXPR_VARIABLE:
108: case EXPR_CONSTANT_VARIABLE:
109: compileOperation(context, left, right);
110: break;
111:
112: case EXPR_ATTRIBUTE:
113: right.compile(context, GET);
114: AttributeNode attr = (AttributeNode) left;
115: attr.getChild().compile(context, GET);
116: code.astring(attr.getAttribute());
117: code.aload_first();
118: code
119: .invokestatic(code
120: .getPool()
121: .addMethodRef(
122: context.TYPE_CONTEXT,
123: getAssignmentMethod(),
124: "(Lanvil/core/Any;Lanvil/core/Any;Ljava/lang/String;Lanvil/script/Context;)Lanvil/core/Any;"));
125: break;
126:
127: case Node.EXPR_REFERENCE:
128: right.compile(context, GET);
129: ReferenceNode ref = (ReferenceNode) left;
130: ref.getChild(0).compile(context, GET);
131: ref.getChild(1).compile(context, GET);
132: code.aload_first();
133: code
134: .invokestatic(code
135: .getPool()
136: .addMethodRef(
137: context.TYPE_CONTEXT,
138: getAssignmentMethod(),
139: "(Lanvil/core/Any;Lanvil/core/Any;Lanvil/core/Any;Lanvil/script/Context;)Lanvil/core/Any;"));
140: break;
141:
142: case Node.EXPR_EMPTY_REFERENCE:
143: left.compile(context, right);
144: }
145: }
146:
147: public void compile(ByteCompiler context, Node child) {
148: compile(context, getChild(0), child);
149: }
150:
151: public void compile(ByteCompiler context, int operation) {
152: final Code code = context.getCode();
153: int n = childs() - 1;
154: if (n == 1) {
155: compile(context, getChild(0), getChild(1));
156: } else {
157: final int tmp = code.addLocal();
158: getChild(n).compile(context, GET);
159: code.astore(tmp);
160: final int nth = code.getPool().addMethodRef(
161: context.TYPE_CONTEXT, "nth",
162: "(Lanvil/core/Any;I)Lanvil/core/Any;");
163: for (int i = 0; i < n; i++) {
164: final int c = i;
165: compile(context, getChild(i), new Node() {
166: public void compile(ByteCompiler context,
167: int operation) {
168: code.aload_first();
169: code.aload(tmp);
170: code.iconst(c);
171: code.invokevirtual(nth);
172: }
173: });
174: code.pop();
175: }
176: code.aload(tmp);
177: code.endLocal(tmp);
178: }
179: if (operation == GET_BOOLEAN) {
180: context.any2boolean();
181: }
182: }
183:
184: }
|