blob: e55ed3243f4d8bc5edf51bdcafe17bfba1238c7c [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.IFunctionDefinition;
import org.apache.royale.compiler.definitions.IFunctionDefinition.FunctionClassification;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.definitions.IVariableDefinition;
import org.apache.royale.compiler.definitions.IVariableDefinition.VariableClassification;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
import org.apache.royale.compiler.internal.definitions.AppliedVectorDefinition;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
import org.apache.royale.compiler.tree.as.IClassNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IIdentifierNode;
import org.apache.royale.compiler.utils.ASNodeUtils;
public class BinaryOperatorEmitter extends JSSubEmitter implements
ISubEmitter<IBinaryOperatorNode>
{
public BinaryOperatorEmitter(IJSEmitter emitter)
{
super(emitter);
}
@Override
public void emit(IBinaryOperatorNode node)
{
// TODO (mschmalle) will remove this cast as more things get abstracted
JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
String op = node.getOperator().getOperatorText();
boolean isAssignment = op.contains("=")
&& !op.contains("==")
&& !(op.startsWith("<") || op.startsWith(">") || op
.startsWith("!"));
ASTNodeID id = node.getNodeID();
/*
if (id == ASTNodeID.Op_InID
|| id == ASTNodeID.Op_LogicalAndAssignID
|| id == ASTNodeID.Op_LogicalOrAssignID)
{
super.emitBinaryOperator(node);
}
else */if (id == ASTNodeID.Op_IsID || id == ASTNodeID.Op_AsID)
{
fjs.emitIsAs(node, node.getLeftOperandNode(), node.getRightOperandNode(),
id, false);
}
else if (id == ASTNodeID.Op_InstanceOfID)
{
getWalker().walk(node.getLeftOperandNode());
startMapping(node, node.getLeftOperandNode());
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.INSTANCEOF);
endMapping(node);
IDefinition dnode = (node.getRightOperandNode())
.resolve(getProject());
if (dnode != null)
{
String dnodeQname = dnode.getQualifiedName();
boolean isPackageOrFileMember = false;
if (dnode instanceof IVariableDefinition)
{
IVariableDefinition variable = (IVariableDefinition) dnode;
VariableClassification classification = variable.getVariableClassification();
if (classification == VariableClassification.PACKAGE_MEMBER ||
classification == VariableClassification.FILE_MEMBER)
{
isPackageOrFileMember = true;
}
}
else if (dnode instanceof IFunctionDefinition)
{
IFunctionDefinition func = (IFunctionDefinition) dnode;
FunctionClassification classification = func.getFunctionClassification();
if (classification == FunctionClassification.PACKAGE_MEMBER ||
classification == FunctionClassification.FILE_MEMBER)
{
isPackageOrFileMember = true;
}
}
else if(dnode instanceof ITypeDefinition)
{
isPackageOrFileMember = true;
}
if(isPackageOrFileMember)
{
dnodeQname = getEmitter().formatQualifiedName(dnodeQname);
}
write(dnodeQname);
}
else
{
getWalker().walk(node.getRightOperandNode());
}
}
else
{
IExpressionNode leftSide = node.getLeftOperandNode();
IDefinition leftDef = leftSide.resolveType(getWalker().getProject());
if (leftSide.getNodeID() == ASTNodeID.MemberAccessExpressionID)
{
IASNode lnode = leftSide.getChild(0);
IASNode rnode = leftSide.getChild(1);
IDefinition rnodeDef = (rnode instanceof IIdentifierNode) ?
((IIdentifierNode) rnode).resolve(getWalker().getProject()) :
null;
boolean isDynamicAccess = rnode instanceof DynamicAccessNode;
if (lnode.getNodeID() == ASTNodeID.SuperID
&& rnodeDef instanceof AccessorDefinition)
{
if (isAssignment)
{
IClassNode cnode = (IClassNode) node
.getAncestorOfType(IClassNode.class);
if (cnode != null)
write(getEmitter().formatQualifiedName(
cnode.getQualifiedName()));
else
write(getEmitter().formatQualifiedName(
getModel().getCurrentClass().getQualifiedName()));
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSGoogEmitterTokens.SUPERCLASS);
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSRoyaleEmitterTokens.SETTER_PREFIX);
write(rnodeDef.getBaseName());
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSEmitterTokens.APPLY);
write(ASEmitterTokens.PAREN_OPEN);
write(ASEmitterTokens.THIS);
writeToken(ASEmitterTokens.COMMA);
writeToken(ASEmitterTokens.SQUARE_OPEN);
if (op.length() > 1) // += and things like that
{
write(getEmitter().formatQualifiedName(
cnode.getQualifiedName()));
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSGoogEmitterTokens.SUPERCLASS);
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSRoyaleEmitterTokens.GETTER_PREFIX);
write(rnodeDef.getBaseName());
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSEmitterTokens.APPLY);
write(ASEmitterTokens.PAREN_OPEN);
write(ASEmitterTokens.THIS);
write(ASEmitterTokens.PAREN_CLOSE);
write(op.substring(0, 1));
}
getWalker().walk(node.getRightOperandNode());
writeToken(ASEmitterTokens.SQUARE_CLOSE);
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
}
else if (((JSRoyaleEmitter)getEmitter()).isXMLList((MemberAccessExpressionNode)leftSide))
{
MemberAccessExpressionNode xmlNode = (MemberAccessExpressionNode)leftSide;
if (node.getNodeID() == ASTNodeID.Op_AssignId)
{
getWalker().walk(xmlNode.getLeftOperandNode());
IExpressionNode rightSide = xmlNode.getRightOperandNode();
if (rightSide instanceof UnaryOperatorAtNode)
{
write(".setAttribute('");
getWalker().walk(((UnaryOperatorAtNode)rightSide).getChild(0));
}
else
{
write(".setChild('");
getWalker().walk(rightSide);
}
write("', ");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
else if (node.getNodeID() == ASTNodeID.Op_AddAssignID)
{
getWalker().walk(xmlNode.getLeftOperandNode());
IExpressionNode rightSide = xmlNode.getRightOperandNode();
if (rightSide instanceof UnaryOperatorAtNode)
{
write(".setAttribute('");
getWalker().walk(((UnaryOperatorAtNode)rightSide).getChild(0));
}
else
{
write(".setChild('");
getWalker().walk(rightSide);
}
write("', ");
getWalker().walk(node.getLeftOperandNode());
write(".plus(");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
else if (node.getNodeID() == ASTNodeID.Op_AddID)
{
getWalker().walk(xmlNode);
write(".plus(");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
}
else if (isDynamicAccess && ((JSRoyaleEmitter)getEmitter()).isXML((IExpressionNode)lnode))
{
DynamicAccessNode dyn = (DynamicAccessNode)rnode;
ITypeDefinition type = dyn.getRightOperandNode().resolveType(getProject());
if (type.isInstanceOf("String", getProject()) || type.isInstanceOf("Object", getProject()))
{
String field;
if (node.getNodeID() == ASTNodeID.Op_AssignId)
{
getWalker().walk(lnode);
IExpressionNode dynLeft = dyn.getLeftOperandNode();
IExpressionNode dynRight = dyn.getRightOperandNode();
if (dynLeft instanceof UnaryOperatorAtNode)
{
write(".setAttribute(");
field = fjs.stringifyNode(dyn.getRightOperandNode());
}
else if (dynRight instanceof UnaryOperatorAtNode)
{
write(".setAttribute(");
field = fjs.stringifyNode(dynRight.getChild(0));
}
else
{
write(".setChild(");
field = fjs.stringifyNode(dynLeft);
}
write(field + ", ");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
else if (node.getNodeID() == ASTNodeID.Op_AddAssignID)
{
getWalker().walk(lnode);
IExpressionNode rightSide = dyn.getRightOperandNode();
if (rightSide instanceof UnaryOperatorAtNode)
{
write(".setAttribute('");
field = fjs.stringifyNode(((UnaryOperatorAtNode)rightSide).getChild(0));
field = field.replace("\"", ""); // remove wrapping double-quotes
}
else
{
write(".setChild('");
field = fjs.stringifyNode(rightSide);
field = field.replace("\"", ""); // remove wrapping double-quotes
}
write(field + "', ");
getWalker().walk(node.getLeftOperandNode());
write(".plus(");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
else if (node.getNodeID() == ASTNodeID.Op_AddID)
{
getWalker().walk(dyn);
write(".plus(");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
}
}
else if (((JSRoyaleEmitter)getEmitter()).isProxy(((MemberAccessExpressionNode)leftSide).getLeftOperandNode()) && leftDef == null)
{
MemberAccessExpressionNode proxyNode = (MemberAccessExpressionNode)leftSide;
if (node.getNodeID() == ASTNodeID.Op_AssignId)
{
getWalker().walk(proxyNode.getLeftOperandNode());
IExpressionNode rightSide = proxyNode.getRightOperandNode();
write(".setProperty('");
getWalker().walk(rightSide);
write("', ");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
else if (node.getNodeID() == ASTNodeID.Op_AddAssignID)
{
IExpressionNode rightSide = proxyNode.getRightOperandNode();
getWalker().walk(proxyNode.getLeftOperandNode());
write(".setProperty('");
getWalker().walk(rightSide);
write("', ");
getWalker().walk(proxyNode.getLeftOperandNode());
write(".getProperty(");
write(ASEmitterTokens.SINGLE_QUOTE);
getWalker().walk(rightSide);
write(ASEmitterTokens.SINGLE_QUOTE);
write(ASEmitterTokens.PAREN_CLOSE);
write(" + ");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
}
else if (((JSRoyaleEmitter)getEmitter()).isDateProperty((MemberAccessExpressionNode)leftSide, true))
{
specialCaseDate(node, (MemberAccessExpressionNode)leftSide);
return;
}
}
else if (leftSide.getNodeID() == ASTNodeID.IdentifierID)
{
if ((leftDef != null)
&& SemanticUtils.isXMLish(leftDef, getWalker().getProject()))
{
if (node.getNodeID() == ASTNodeID.Op_AddAssignID)
{
getWalker().walk(leftSide);
write(" = ");
getWalker().walk(leftSide);
write(".plus(");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
}
}
else if (leftSide.getNodeID() == ASTNodeID.ArrayIndexExpressionID) // dynamic access
{
DynamicAccessNode dyn = (DynamicAccessNode)leftSide;
IExpressionNode dynLeft = dyn.getLeftOperandNode();
ITypeDefinition type = dyn.getRightOperandNode().resolveType(getProject());
if (((JSRoyaleEmitter)getEmitter()).isXML(dynLeft) && type.isInstanceOf("String", getProject()))
{
String field;
if (node.getNodeID() == ASTNodeID.Op_AssignId)
{
getWalker().walk(dynLeft);
IExpressionNode rightSide = dyn.getRightOperandNode();
if (rightSide instanceof UnaryOperatorAtNode)
{
write(".setAttribute('");
field = fjs.stringifyNode(((UnaryOperatorAtNode)rightSide).getChild(0));
field = field.replace("\"", ""); // remove wrapping double-quotes
}
else
{
write(".setChild('");
field = fjs.stringifyNode(rightSide);
field = field.replace("\"", ""); // remove wrapping double-quotes
}
write(field + "', ");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
else if (node.getNodeID() == ASTNodeID.Op_AddAssignID)
{
getWalker().walk(dynLeft);
IExpressionNode rightSide = dyn.getRightOperandNode();
if (rightSide instanceof UnaryOperatorAtNode)
{
write(".setAttribute('");
field = fjs.stringifyNode(((UnaryOperatorAtNode)rightSide).getChild(0));
field = field.replace("\"", ""); // remove wrapping double-quotes
}
else
{
write(".setChild('");
field = fjs.stringifyNode(rightSide);
field = field.replace("\"", ""); // remove wrapping double-quotes
}
write(field + "', ");
getWalker().walk(node.getLeftOperandNode());
write(".plus(");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
else if (node.getNodeID() == ASTNodeID.Op_AddID)
{
getWalker().walk(dyn);
write(".plus(");
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
}
}
super_emitBinaryOperator(node, isAssignment);
}
}
private void super_emitBinaryOperator(IBinaryOperatorNode node, boolean isAssignment)
{
if (ASNodeUtils.hasParenOpen(node))
write(ASEmitterTokens.PAREN_OPEN);
ASTNodeID id = node.getNodeID();
if (id == ASTNodeID.Op_IsID)
{
write(ASEmitterTokens.IS);
write(ASEmitterTokens.PAREN_OPEN);
getWalker().walk(node.getLeftOperandNode());
writeToken(ASEmitterTokens.COMMA);
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
}
else if (id == ASTNodeID.Op_AsID)
{
// (is(a, b) ? a : null)
write(ASEmitterTokens.PAREN_OPEN);
write(ASEmitterTokens.IS);
write(ASEmitterTokens.PAREN_OPEN);
getWalker().walk(node.getLeftOperandNode());
writeToken(ASEmitterTokens.COMMA);
getWalker().walk(node.getRightOperandNode());
writeToken(ASEmitterTokens.PAREN_CLOSE);
writeToken(ASEmitterTokens.TERNARY);
getWalker().walk(node.getLeftOperandNode());
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.COLON);
write(ASEmitterTokens.NULL);
write(ASEmitterTokens.PAREN_CLOSE);
}
else
{
if (isAssignment
&& (getProject() instanceof RoyaleJSProject && ((RoyaleJSProject) getProject()).config != null && ((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass() == null)
&& node.getLeftOperandNode() instanceof MemberAccessExpressionNode
&& ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode() instanceof IdentifierNode
&& ((IdentifierNode) ((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode()).getName().equals("length")
&& ((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode().resolveType(getProject()) instanceof AppliedVectorDefinition)
{
//for default Vector implementation, when setting length, we need to set it on the associated 'synthType' instance which tags the native
//Array representation of the Vector. This allows running 'setter' code because it is not possible to override the native length setter on Array
//unless using a different approach, like es6 Proxy.
//this code inserts the extra access name for setting length, e.g. myVectInstance['_synthType'].length = assignedValue
//the dynamic access field name is a constant on Language, so it can be different/shorter in release build
getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getLeftOperandNode());
write(ASEmitterTokens.SQUARE_OPEN);
write(JSRoyaleEmitterTokens.LANGUAGE_QNAME.getToken());
write(ASEmitterTokens.MEMBER_ACCESS);
write(JSRoyaleEmitterTokens.ROYALE_SYNTH_TAG_FIELD_NAME);
write(ASEmitterTokens.SQUARE_CLOSE);
write(ASEmitterTokens.MEMBER_ACCESS);
getWalker().walk(((MemberAccessExpressionNode) node.getLeftOperandNode()).getRightOperandNode());
}
else getWalker().walk(node.getLeftOperandNode());
startMapping(node, node.getLeftOperandNode());
if (id != ASTNodeID.Op_CommaID)
write(ASEmitterTokens.SPACE);
// (erikdebruin) rewrite 'a &&= b' to 'a = a && b'
if (id == ASTNodeID.Op_LogicalAndAssignID
|| id == ASTNodeID.Op_LogicalOrAssignID)
{
IExpressionNode lnode = node
.getLeftOperandNode();
writeToken(ASEmitterTokens.EQUAL);
endMapping(node);
getWalker().walk(lnode);
startMapping(node, node.getLeftOperandNode());
write(ASEmitterTokens.SPACE);
write((id == ASTNodeID.Op_LogicalAndAssignID) ? ASEmitterTokens.LOGICAL_AND
: ASEmitterTokens.LOGICAL_OR);
}
else
{
write(node.getOperator().getOperatorText());
}
write(ASEmitterTokens.SPACE);
endMapping(node);
if (isAssignment)
{
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(), node.getLeftOperandNode().resolveType(getProject()));
}
else
{
getWalker().walk(node.getRightOperandNode());
if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isXML(node.getRightOperandNode()))
{
write(".elementNames()");
}
else if (node.getNodeID() == ASTNodeID.Op_InID &&
((JSRoyaleEmitter)getEmitter()).isProxy(node.getRightOperandNode()))
{
write(".propertyNames()");
}
}
}
if (ASNodeUtils.hasParenOpen(node))
write(ASEmitterTokens.PAREN_CLOSE);
}
public static enum DatePropertiesGetters
{
TIME("time", "getTime"),
FULLYEAR("fullYear", "getFullYear"),
MONTH("month", "getMonth"),
DATE("date", "getDate"),
DAY("day", "getDay"),
FULLYEARUTC("fullYearUTC", "getUTCFullYear"),
MONTHUTC("monthUTC", "getUTCMonth"),
DATEUTC("dateUTC", "getUTCDate"),
DAYUTC("dayUTC", "getUTCDay"),
HOURS("hours", "getHours"),
MINUTES("minutes", "getMinutes"),
SECONDS("seconds", "getSeconds"),
MILLISECONDS("milliseconds", "getMilliseconds"),
HOURSUTC("hoursUTC", "getUTCHours"),
MINUTESUTC("minutesUTC", "getUTCMinutes"),
SECONDSUTC("secondsUTC", "getUTCSeconds"),
MILLISECONDSUTC("millisecondsUTC", "getUTCMilliseconds"),
TIMEZONEOFFSET("timezoneOffset", "getTimezoneOffset");
DatePropertiesGetters(String value, String functionName)
{
this.value = value;
this.functionName = functionName;
}
private String value;
private String functionName;
public String getFunctionName()
{
return functionName;
}
public String getValue()
{
return value;
}
}
public static enum DatePropertiesSetters
{
TIME("time", "setTime"),
FULLYEAR("fullYear", "setFullYear"),
MONTH("month", "setMonth"),
DATE("date", "setDate"),
DAY("day", "setDay"),
FULLYEARUTC("fullYearUTC", "setUTCFullYear"),
MONTHUTC("monthUTC", "setUTCMonth"),
DATEUTC("dateUTC", "setUTCDate"),
DAYUTC("day", "setUTCDay"),
HOURS("hours", "setHours"),
MINUTES("minutes", "setMinutes"),
SECONDS("seconds", "setSeconds"),
MILLISECONDS("milliseconds", "setMilliseconds"),
HOURSUTC("hoursUTC", "setUTCHours"),
MINUTESUTC("minutesUTC", "setUTCMinutes"),
SECONDSUTC("secondsUTC", "setUTCSeconds"),
MILLISECONDSUTC("millisecondsUTC", "setUTCMilliseconds");
DatePropertiesSetters(String value, String functionName)
{
this.value = value;
this.functionName = functionName;
}
private String value;
private String functionName;
public String getFunctionName()
{
return functionName;
}
public String getValue()
{
return value;
}
}
void specialCaseDate(IBinaryOperatorNode node, MemberAccessExpressionNode leftSide)
{
MemberAccessExpressionNode dateNode = (MemberAccessExpressionNode)leftSide;
IIdentifierNode rightSide = (IIdentifierNode)dateNode.getRightOperandNode();
String op = node.getOperator().getOperatorText();
boolean isAssignment = op.contains("=")
&& !op.contains("==")
&& !(op.startsWith("<") || op.startsWith(">") || op
.startsWith("!"));
getWalker().walk(dateNode.getLeftOperandNode());
String rightName = rightSide.getName();
if (isAssignment)
{
DatePropertiesSetters prop = DatePropertiesSetters.valueOf(rightName.toUpperCase());
write(ASEmitterTokens.MEMBER_ACCESS);
write(prop.getFunctionName());
write(ASEmitterTokens.PAREN_OPEN);
if (op.length() > 1)
{
DatePropertiesGetters propGetter = DatePropertiesGetters.valueOf(rightName.toUpperCase());
getWalker().walk(dateNode.getLeftOperandNode());
write(ASEmitterTokens.MEMBER_ACCESS);
write(propGetter.getFunctionName());
write(ASEmitterTokens.PAREN_OPEN);
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.SPACE);
write(op.substring(0, 1));
write(ASEmitterTokens.SPACE);
}
getWalker().walk(node.getRightOperandNode());
write(ASEmitterTokens.PAREN_CLOSE);
}
else
{
DatePropertiesGetters propGetter = DatePropertiesGetters.valueOf(rightName.toUpperCase());
write(ASEmitterTokens.MEMBER_ACCESS);
write(propGetter.getFunctionName());
write(ASEmitterTokens.PAREN_OPEN);
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.SPACE);
write(op);
write(ASEmitterTokens.SPACE);
getWalker().walk(node.getRightOperandNode());
}
}
}