This is an automated email from the ASF dual-hosted git repository.
joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
The following commit(s) were added to refs/heads/develop by this push:
new 0158f0099 UnaryOperatorEmitter, BinaryOperatorEmitter: followup to
adding JSDynamicOverride metadata, adding a new setMethodReversed attribute to
optionally reverse key and value parameters
0158f0099 is described below
commit 0158f0099d0dd1a0e85667da1b6ab016d8989a16
Author: Josh Tynjala <[email protected]>
AuthorDate: Wed Aug 12 14:24:27 2026 -0700
UnaryOperatorEmitter, BinaryOperatorEmitter: followup to adding
JSDynamicOverride metadata, adding a new setMethodReversed attribute to
optionally reverse key and value parameters
May be set to true or false. If true, the key and value parameters are
reversed so that the value is first. By default, the key is first, followed by
the value.
Followup to commits 308d8867b923c0edff4bf814fa89a175123dcf37 and
b939a18ed7d101a505eda9c1aba5ec7b746d63d2
---
.../constants/IJSMetaAttributeConstants.java | 1 +
.../codegen/js/jx/BinaryOperatorEmitter.java | 164 ++++++++++++---------
.../codegen/js/jx/UnaryOperatorEmitter.java | 116 ++++++++++-----
.../js/royale/TestRoyaleJSDynamicOverrides.java | 24 ++-
4 files changed, 189 insertions(+), 116 deletions(-)
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
index ecbb3a81f..87463fcad 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/constants/IJSMetaAttributeConstants.java
@@ -27,6 +27,7 @@ public interface IJSMetaAttributeConstants
static final String NAME_DYNAMIC_OVERRIDE_SET_METHOD = "setMethod";
static final String NAME_DYNAMIC_OVERRIDE_DELETE_METHOD = "deleteMethod";
static final String NAME_DYNAMIC_OVERRIDE_IN_METHOD = "inMethod";
+ static final String NAME_DYNAMIC_OVERRIDE_SET_METHOD_REVERSED =
"setMethodReversed";
// [JSForInOverride]
static final String ATTRIBUTE_FOR_IN_OVERRIDE = "JSForInOverride";
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index 0096ae5bf..4e93c37d6 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -716,8 +716,6 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
}
else
{
- boolean dynamicAssignmentOverride = false;
- boolean dynamicInOverride = false;
if (isAssignment
&& (getProject() instanceof
RoyaleJSProject && ((RoyaleJSProject) getProject()).config != null &&
((RoyaleJSProject) getProject()).config.getJsVectorEmulationClass() == null)
&& node.getLeftOperandNode() instanceof
MemberAccessExpressionNode
@@ -751,40 +749,34 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
else if (isAssignment && node.getLeftOperandNode()
instanceof IDynamicAccessNode)
{
IDynamicAccessNode dynamicAccessNode =
(IDynamicAccessNode) node.getLeftOperandNode();
- String setMethod =
getDynamicAccessSetOverride(dynamicAccessNode);
- if (setMethod != null)
+ IExpressionNode dynamicLeftOperandNode =
dynamicAccessNode.getLeftOperandNode();
+ IMetaTag dynamicOverrideMeta =
getDynamicAccessOverride(dynamicLeftOperandNode);
+ if (dynamicOverrideMeta != null)
{
- dynamicAssignmentOverride = true;
-
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(setMethod);
- write(ASEmitterTokens.PAREN_OPEN);
-
getWalker().walk(dynamicAccessNode.getRightOperandNode());
- write(ASEmitterTokens.COMMA);
- }
- else
- {
- // normal dynamic access
-
getWalker().walk(node.getLeftOperandNode());
+ String setMethod =
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD);
+ if (setMethod != null)
+ {
+
emitAssignmentWithDynamicAccessOverride(node, dynamicAccessNode, setMethod,
dynamicOverrideMeta);
+ return;
+ }
}
+ // normal dynamic access
+ getWalker().walk(node.getLeftOperandNode());
}
else if (id == ASTNodeID.Op_InID)
{
- String inMethod =
getDynamicAccessInOverride(node.getRightOperandNode());
- if (inMethod != null)
+ IMetaTag dynamicOverrideMeta =
getDynamicAccessOverride(node.getRightOperandNode());
+ if (dynamicOverrideMeta != null)
{
- dynamicInOverride = true;
-
getWalker().walk(node.getRightOperandNode());
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(inMethod);
- write(ASEmitterTokens.PAREN_OPEN);
-
getWalker().walk(node.getLeftOperandNode());
- }
- else
- {
- // normal in operator
-
getWalker().walk(node.getLeftOperandNode());
+ String inMethod =
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_IN_METHOD);
+ if (inMethod != null)
+ {
+
emitInWithDynamicAccessOverride(node, inMethod);
+ return;
+ }
}
+ // normal in operator
+ getWalker().walk(node.getLeftOperandNode());
}
else getWalker().walk(node.getLeftOperandNode());
startMapping(node, node.getLeftOperandNode());
@@ -793,7 +785,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
//we need to use 'plus' method instead of '+'
xmlAdd = true;
}
- if (id != ASTNodeID.Op_CommaID && !xmlAdd &&
!dynamicAssignmentOverride && !dynamicInOverride)
+ if (id != ASTNodeID.Op_CommaID && !xmlAdd)
write(ASEmitterTokens.SPACE);
// (erikdebruin) rewrite 'a &&= b' to 'a = a && b'
@@ -814,7 +806,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
: ASEmitterTokens.LOGICAL_OR);
write(ASEmitterTokens.SPACE);
}
- else if (!dynamicAssignmentOverride && !dynamicInOverride)
+ else
{
if (xmlAdd) {
write(".plus(");
@@ -830,7 +822,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
{
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(),
node.getLeftOperandNode().resolveType(getProject()));
}
- else if (!dynamicInOverride)
+ else
{
getWalker().walk(node.getRightOperandNode());
@@ -846,7 +838,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
write(".propertyNames()");
}
}
- if (xmlAdd || dynamicAssignmentOverride ||
dynamicInOverride) {
+ if (xmlAdd) {
write(")");
}
}
@@ -855,57 +847,23 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
write(ASEmitterTokens.PAREN_CLOSE);
}
- private String getDynamicAccessSetOverride(IASNode leftSide)
+ private IMetaTag getDynamicAccessOverride(IExpressionNode context)
{
- if (!(leftSide instanceof DynamicAccessNode))
- {
- return null;
- }
-
- IDynamicAccessNode dynamicAccessNode = (IDynamicAccessNode)
leftSide;
- IExpressionNode dynamicLeftOperandNode =
dynamicAccessNode.getLeftOperandNode();
- ITypeDefinition dynamicLeftType =
dynamicLeftOperandNode.resolveType(getProject());
- if (dynamicLeftType == null)
+ ITypeDefinition contextType = context.resolveType(getProject());
+ if (contextType == null)
{
return null;
}
IMetaTag dynamicOverrideMeta = null;
- for (ITypeDefinition currentType :
dynamicLeftType.typeIteratable(getProject(), false))
+ for (ITypeDefinition currentType :
contextType.typeIteratable(getProject(), false))
{
dynamicOverrideMeta =
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
if (dynamicOverrideMeta != null)
{
- break;
+ return dynamicOverrideMeta;
}
}
- if (dynamicOverrideMeta == null)
- {
- return null;
- }
- return
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD);
- }
-
- private String getDynamicAccessInOverride(IExpressionNode rightSideOfIn)
- {
- ITypeDefinition typeDef =
rightSideOfIn.resolveType(getProject());
- if (typeDef == null)
- {
- return null;
- }
- IMetaTag dynamicOverrideMeta = null;
- for (ITypeDefinition currentType :
typeDef.typeIteratable(getProject(), false))
- {
- dynamicOverrideMeta =
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
- if (dynamicOverrideMeta != null)
- {
- break;
- }
- }
- if (dynamicOverrideMeta == null)
- {
- return null;
- }
- return
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_IN_METHOD);
+ return null;
}
public static enum DatePropertiesGetters
@@ -1063,4 +1021,64 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
write(ASEmitterTokens.PAREN_CLOSE);
}
}
+
+ private void
emitAssignmentWithDynamicAccessOverride(IBinaryOperatorNode node,
IDynamicAccessNode dynamicAccessNode, String setMethod, IMetaTag
dynamicOverrideMeta)
+ {
+ boolean reversed = false;
+ String reversedValue =
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD_REVERSED);
+ if (reversedValue != null)
+ {
+ switch (reversedValue)
+ {
+ case "true":
+ reversed = true;
+ break;
+ // anything except true is treated as false
+ }
+ }
+
+ getWalker().walk(dynamicAccessNode.getLeftOperandNode());
+ startMapping(node);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(setMethod);
+ write(ASEmitterTokens.PAREN_OPEN);
+ endMapping(node);
+ if (!reversed)
+ {
+
getWalker().walk(dynamicAccessNode.getRightOperandNode());
+ }
+ else
+ {
+
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(),
node.getLeftOperandNode().resolveType(getProject()));
+ }
+ startMapping(node);
+ write(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SPACE);
+ endMapping(node);
+ if (!reversed)
+ {
+
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(),
node.getLeftOperandNode().resolveType(getProject()));
+ }
+ else
+ {
+
getWalker().walk(dynamicAccessNode.getRightOperandNode());
+ }
+ startMapping(node);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(node);
+ }
+
+ private void emitInWithDynamicAccessOverride(IBinaryOperatorNode node,
String inMethod)
+ {
+ getWalker().walk(node.getRightOperandNode());
+ startMapping(node);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(inMethod);
+ write(ASEmitterTokens.PAREN_OPEN);
+ endMapping(node);
+ getWalker().walk(node.getLeftOperandNode());
+ startMapping(node);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(node);
+ }
}
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
index 8de4c800c..5a374c4c7 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
@@ -113,46 +113,7 @@ public class UnaryOperatorEmitter extends JSSubEmitter
implements
{
// BEFORE: abc[xyz]++
// AFTER: abc.set(xyz, abc.get(xyz) + 1)
-
-
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
- startMapping(node);
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(setMethod);
- write(ASEmitterTokens.PAREN_OPEN);
- endMapping(node);
-
getWalker().walk(dynamicAccessNode.getRightOperandNode());
- writeToken(ASEmitterTokens.COMMA);
-
-
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
- startMapping(node);
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(getMethod);
- write(ASEmitterTokens.PAREN_OPEN);
- endMapping(node);
-
getWalker().walk(dynamicAccessNode.getRightOperandNode());
- startMapping(node);
- write(ASEmitterTokens.PAREN_CLOSE);
- endMapping(node);
- startMapping(node, dynamicAccessNode);
- if (node.getNodeID() == ASTNodeID.Op_PreIncrID
- || node.getNodeID() == ASTNodeID.Op_PostIncrID)
- {
- write(ASEmitterTokens.SPACE);
- write(OperatorType.PLUS.getOperatorText());
- write(ASEmitterTokens.SPACE);
- write("1");
- }
- else // decrement
- {
- write(ASEmitterTokens.SPACE);
- write(OperatorType.MINUS.getOperatorText());
- write(ASEmitterTokens.SPACE);
- write("1");
- }
- endMapping(node);
- startMapping(node);
- write(ASEmitterTokens.PAREN_CLOSE);
- endMapping(node);
+ emitAssignmentWithDynamicAccessOverride(node,
dynamicAccessNode, getMethod, setMethod, dynamicOverrideMeta);
return;
}
}
@@ -269,4 +230,79 @@ public class UnaryOperatorEmitter extends JSSubEmitter
implements
write(ASEmitterTokens.PAREN_CLOSE);
endMapping(node);
}
+
+ private void emitAssignmentWithDynamicAccessOverride(IUnaryOperatorNode
node, IDynamicAccessNode dynamicAccessNode, String getMethod, String setMethod,
IMetaTag dynamicOverrideMeta)
+ {
+ boolean reversed = false;
+ String reversedValue =
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_SET_METHOD_REVERSED);
+ if (reversedValue != null)
+ {
+ switch (reversedValue)
+ {
+ case "true":
+ reversed = true;
+ break;
+ // anything except true is treated as false
+ }
+ }
+
+ getWalker().walk(dynamicAccessNode.getLeftOperandNode());
+ startMapping(node);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(setMethod);
+ write(ASEmitterTokens.PAREN_OPEN);
+ endMapping(node);
+ if (!reversed)
+ {
+ getWalker().walk(dynamicAccessNode.getRightOperandNode());
+ }
+ else
+ {
+ emitDynamicAccessOverrideValue(node, dynamicAccessNode, getMethod,
setMethod);
+ }
+ writeToken(ASEmitterTokens.COMMA);
+
+ if (!reversed)
+ {
+ emitDynamicAccessOverrideValue(node, dynamicAccessNode, getMethod,
setMethod);
+ }
+ else
+ {
+ getWalker().walk(dynamicAccessNode.getRightOperandNode());
+ }
+ }
+
+ private void emitDynamicAccessOverrideValue(IUnaryOperatorNode node,
IDynamicAccessNode dynamicAccessNode, String getMethod, String setMethod)
+ {
+ getWalker().walk(dynamicAccessNode.getLeftOperandNode());
+ startMapping(node);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(getMethod);
+ write(ASEmitterTokens.PAREN_OPEN);
+ endMapping(node);
+ getWalker().walk(dynamicAccessNode.getRightOperandNode());
+ startMapping(node);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(node);
+ startMapping(node, dynamicAccessNode);
+ if (node.getNodeID() == ASTNodeID.Op_PreIncrID
+ || node.getNodeID() == ASTNodeID.Op_PostIncrID)
+ {
+ write(ASEmitterTokens.SPACE);
+ write(OperatorType.PLUS.getOperatorText());
+ write(ASEmitterTokens.SPACE);
+ write("1");
+ }
+ else // decrement
+ {
+ write(ASEmitterTokens.SPACE);
+ write(OperatorType.MINUS.getOperatorText());
+ write(ASEmitterTokens.SPACE);
+ write("1");
+ }
+ endMapping(node);
+ startMapping(node);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ endMapping(node);
+ }
}
diff --git
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
index 217296030..d41965656 100644
---
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
+++
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
@@ -71,7 +71,25 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
IClassNode node = (IClassNode)
getNode("[JSDynamicOverride(setMethod=\"set\")] class A { public function A() {
this[0] = 123.4; } }",
IClassNode.class, WRAP_LEVEL_NONE);
asBlockWalker.visitClass(node);
- assertOut("/**\n * @constructor\n */\nA = function() {\n
this.set(0,123.4);\n};");
+ assertOut("/**\n * @constructor\n */\nA = function() {\n this.set(0,
123.4);\n};");
+ }
+
+ @Test
+ public void testDynamicOverride_setMethod_reversedTrue()
+ {
+ IClassNode node = (IClassNode)
getNode("[JSDynamicOverride(setMethod=\"set\",setMethodReversed=\"true\")]
class A { public function A() { this[0] = 123.4; } }",
+ IClassNode.class, WRAP_LEVEL_NONE);
+ asBlockWalker.visitClass(node);
+ assertOut("/**\n * @constructor\n */\nA = function() {\n
this.set(123.4, 0);\n};");
+ }
+
+ @Test
+ public void testDynamicOverride_setMethod_reversedFalse()
+ {
+ IClassNode node = (IClassNode)
getNode("[JSDynamicOverride(setMethod=\"set\",setMethodReversed=\"false\")]
class A { public function A() { this[0] = 123.4; } }",
+ IClassNode.class, WRAP_LEVEL_NONE);
+ asBlockWalker.visitClass(node);
+ assertOut("/**\n * @constructor\n */\nA = function() {\n this.set(0,
123.4);\n};");
}
@Test
@@ -80,7 +98,7 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
IClassNode node = (IClassNode) getNode("public class B extends A {
public function B() { this[0] = 123.4; } };
[JSDynamicOverride(setMethod=\"set\")] public class A { public function A() {}
}",
IClassNode.class, WRAP_LEVEL_PACKAGE);
asBlockWalker.visitClass(node);
- assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function()
{\n B.base(this, 'constructor');\n this.set(0,123.4);\n};\ngoog.inherits(B,
A);");
+ assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function()
{\n B.base(this, 'constructor');\n this.set(0, 123.4);\n};\ngoog.inherits(B,
A);");
}
@Test
@@ -89,7 +107,7 @@ public class TestRoyaleJSDynamicOverrides extends ASTestBase
IClassNode node = (IClassNode) getNode("public class B implements A {
public function B() { this[0] = 123.4; } };
[JSDynamicOverride(setMethod=\"set\")] public interface A { }",
IClassNode.class, WRAP_LEVEL_PACKAGE);
asBlockWalker.visitClass(node);
- assertOut("/**\n * @constructor\n * @implements {A}\n */\nB =
function() {\n this.set(0,123.4);\n};");
+ assertOut("/**\n * @constructor\n * @implements {A}\n */\nB =
function() {\n this.set(0, 123.4);\n};");
}
@Test