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 286b77dc2 Arrow functions
286b77dc2 is described below
commit 286b77dc29ab91fb7edd451bfedd20c44c84482c
Author: Josh Tynjala <[email protected]>
AuthorDate: Thu Jun 12 14:58:16 2025 -0700
Arrow functions
- Omits function keyword in favor of => arrow symbol between signature and
body
- Parentheses are optional for a single parameter that is an identifier
with no type or default value
- When parentheses are omitted, the parameter's type is not inferred and
the compiler reports a warning
- Braces are optional for a single expression (no statements)
- If braces are omitted, the single expression becomes the return value
- If braces are omitted, the return type is optional and will be inferred
(without enabling other type inference)
- 'this' is bound to the same value as the containing scope
Does not currently use JS arrow functions in the implementation. Nor does
it use
Function.prototype.bind() because that doesn't exist in SWF either. Both
SWF and
JS share a custom implementation that rewrites the arrow function like this:
```
function(context:*, func:Function):Function {
return function(...rest):* {
return func.apply(context, rest);
};
}(this, function(/* params */)/*: return_type */ {
/* body */
});
```
That doesn't mean that we can't use real JS arrow functions in the future.
Just
starting out with something that all works for SWF, and we can refine them
as
needed later.
---
.../royale/compiler/config/Configuration.java | 22 ++
.../apache/royale/compiler/parsing/IASToken.java | 3 +-
.../royale/compiler/projects/ICompilerProject.java | 5 +
.../royale/compiler/tree/as/IFunctionNode.java | 7 +
.../royale/compiler/clients/JSConfiguration.java | 1 +
.../codegen/js/royale/JSRoyaleDocEmitter.java | 16 ++
.../royale/compiler/internal/parsing/as/ASParser.g | 115 +++++++-
.../internal/definitions/FunctionDefinition.java | 26 +-
.../compiler/internal/parsing/as/ASToken.java | 2 +
.../compiler/internal/parsing/as/BaseASParser.java | 223 +++++++++++++++
.../internal/parsing/as/ConfigProcessor.java | 6 +
.../internal/parsing/as/StreamingASTokenizer.java | 1 +
.../compiler/internal/projects/ASCProject.java | 6 +
.../compiler/internal/projects/RoyaleProject.java | 15 +
.../projects/RoyaleProjectConfigurator.java | 1 +
.../semantics/MethodBodySemanticChecker.java | 13 +-
.../compiler/internal/semantics/SemanticUtils.java | 41 ++-
.../compiler/internal/tree/as/FunctionNode.java | 13 +
.../internal/parsing/as/RawASTokenizer.lex | 6 +
.../src/test/java/as/ASArrowFunctionTests.java | 305 +++++++++++++++++++++
...This_withAllowArrowFunctionsEnabled_swfdump.xml | 267 ++++++++++++++++++
...eses_withAllowArrowFunctionsEnabled_swfdump.xml | 237 ++++++++++++++++
...aces_withAllowArrowFunctionsEnabled_swfdump.xml | 232 ++++++++++++++++
...Type_withAllowArrowFunctionsEnabled_swfdump.xml | 235 ++++++++++++++++
...turn_withAllowArrowFunctionsEnabled_swfdump.xml | 232 ++++++++++++++++
25 files changed, 2012 insertions(+), 18 deletions(-)
diff --git
a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
index 206ad4851..04512f3a0 100644
---
a/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
+++
b/compiler-common/src/main/java/org/apache/royale/compiler/config/Configuration.java
@@ -1593,6 +1593,28 @@ public class Configuration
this.allowPrivateConstructors = allow;
}
+ //
+ // 'compiler.allow-arrow-functions' option
+ //
+
+ private boolean allowArrowFunctions = false;
+
+ public boolean getCompilerAllowArrowFunctions()
+ {
+ return allowArrowFunctions;
+ }
+
+ /**
+ * Whether the compiler will allow => arrow functions.
+ */
+ @Config
+ @Mapping({ "compiler", "allow-arrow-functions" })
+ @RoyaleOnly
+ public void setCompilerAllowArrowFunctions(ConfigurationValue cv, boolean
allow)
+ {
+ this.allowArrowFunctions = allow;
+ }
+
//
// 'compiler.strict-flex-css' option
//
diff --git
a/compiler-common/src/main/java/org/apache/royale/compiler/parsing/IASToken.java
b/compiler-common/src/main/java/org/apache/royale/compiler/parsing/IASToken.java
index c41d3ed8c..fa1cac8ad 100644
---
a/compiler-common/src/main/java/org/apache/royale/compiler/parsing/IASToken.java
+++
b/compiler-common/src/main/java/org/apache/royale/compiler/parsing/IASToken.java
@@ -61,7 +61,8 @@ public interface IASToken extends ICMToken, ISourceLocation
DEFAULT_XML_STATEMENT,
UNKNOWN,
INCLUDE,
- VERBATIM_STRING
+ VERBATIM_STRING,
+ ARROW
}
/**
diff --git
a/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
b/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
index 72bbf334d..c4b8a5168 100644
---
a/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
+++
b/compiler-common/src/main/java/org/apache/royale/compiler/projects/ICompilerProject.java
@@ -282,6 +282,11 @@ public interface ICompilerProject
*/
boolean getAllowPrivateConstructors();
+ /**
+ * @return True if => arrow functions are allowed.
+ */
+ boolean getAllowArrowFunctions();
+
/**
* @return True if strict function types are allowed and enforced.
*/
diff --git
a/compiler-common/src/main/java/org/apache/royale/compiler/tree/as/IFunctionNode.java
b/compiler-common/src/main/java/org/apache/royale/compiler/tree/as/IFunctionNode.java
index 64755fd16..340825fca 100644
---
a/compiler-common/src/main/java/org/apache/royale/compiler/tree/as/IFunctionNode.java
+++
b/compiler-common/src/main/java/org/apache/royale/compiler/tree/as/IFunctionNode.java
@@ -127,6 +127,13 @@ public interface IFunctionNode extends
IScopedDefinitionNode, IDocumentableDefin
*/
boolean isCastFunction();
+ /**
+ * Is this an arrow function?
+ *
+ * @return true if the member is an arrow function
+ */
+ boolean isArrowFunction();
+
/**
* Get the classification for this function (local, argument, class member,
* etc)
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
index 23e4d9340..303635ecd 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/clients/JSConfiguration.java
@@ -70,6 +70,7 @@ public class JSConfiguration extends Configuration
setCompilerAllowImportAliases(null, true);
setCompilerStrictIdentifierNames(null, false);
setCompilerStrictFlexCSS(null, false);
+ setCompilerAllowArrowFunctions(null, true);
}
//
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
index 3bd510755..4227d1b31 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
@@ -401,6 +401,14 @@ public class JSRoyaleDocEmitter extends JSDocEmitter
implements IJSRoyaleDocEmit
{
// @return
String returnType = node.getReturnType();
+ if (node.isArrowFunction() && (returnType == null ||
returnType.isEmpty()))
+ {
+ ITypeDefinition resolvedTypeDef =
SemanticUtils.resolveArrowFunctionInferredReturnType(node, project);
+ if (resolvedTypeDef != null)
+ {
+ returnType = resolvedTypeDef.getQualifiedName();
+ }
+ }
if (project.getInferTypes() && (returnType == null ||
returnType.isEmpty()))
{
ITypeDefinition resolvedTypeDef =
SemanticUtils.resolveFunctionInferredReturnType(node, project);
@@ -770,6 +778,14 @@ public class JSRoyaleDocEmitter extends JSDocEmitter
implements IJSRoyaleDocEmit
public void emitReturn(IFunctionNode node, String packageName,
ICompilerProject project)
{
String rtype = node.getReturnType();
+ if (node.isArrowFunction() && (rtype == null || rtype.isEmpty()))
+ {
+ ITypeDefinition resolvedTypeDef =
SemanticUtils.resolveArrowFunctionInferredReturnType(node, project);
+ if (resolvedTypeDef != null)
+ {
+ rtype = resolvedTypeDef.getQualifiedName();
+ }
+ }
if (project.getInferTypes() && (rtype == null || rtype.isEmpty()))
{
ITypeDefinition resolvedTypeDef =
SemanticUtils.resolveFunctionInferredReturnType(node, project);
diff --git
a/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
b/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
index 3abdabf9d..7996c3c46 100644
---
a/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
+++
b/compiler/src/main/antlr/org/apache/royale/compiler/internal/parsing/as/ASParser.g
@@ -41,6 +41,7 @@ import
org.apache.royale.compiler.asdoc.IASParserASDocDelegate;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.problems.*;
+import org.apache.royale.compiler.internal.tree.as.parts.FunctionContentsPart;
}
@@ -363,7 +364,7 @@ configConditionOfDefinition returns [boolean result]
groupDirectiveWithConfigVariable [ContainerNode c, int endToken]
{
boolean b;
- ConfigConditionBlockNode block;
+ ConfigConditionBlockNode block = null;
final Token lt = LT(1);
}
: b=configCondition
@@ -987,7 +988,108 @@ classOrInterfaceBlock[BlockNode b]
endContainerAtError(ex, b);
}
}
-
+
+/**
+ * Matches an arrow function (=>) with parenthesis, which may contain zero or
+ * more parameters and an optional return type.
+ */
+arrowFunctionExpression returns [ExpressionNodeBase n]
+{
+ n = null;
+ FunctionObjectNode funcObj = null;
+ IdentifierNode paramId = null;
+ BlockNode b = null;
+ IdentifierNode functionName = null;
+ FunctionContentsPart contentsPart = new FunctionContentsPart();
+ FunctionNode f = null;
+ ContainerNode params = null;
+ ExpressionNodeBase body = null;
+}
+ : (
+ paramId=identifier
+ {
+ functionName = new IdentifierNode("");
+ functionName.startAfter(paramId);
+ functionName.endAfter(paramId);
+
functionName.setSourcePath(paramId.getSourcePath());
+
+ contentsPart = new FunctionContentsPart();
+ params = contentsPart.getParametersNode();
+ params.startBefore(paramId);
+ params.addItem(new ParameterNode(paramId));
+ f = new FunctionNode(functionName,
contentsPart);
+ f.startBefore(paramId);
+ f.setArrowFunction(true);
+ }
+ | (
+ lpT:TOKEN_PAREN_OPEN
+ {
+ functionName =
IdentifierNode.createEmptyIdentifierNodeAfterToken(lpT);
+ contentsPart = new
FunctionContentsPart();
+ f = new FunctionNode(functionName,
contentsPart);
+ f.startBefore(lpT);
+ f.setArrowFunction(true);
+ params =
contentsPart.getParametersNode();
+ params.startBefore(lpT);
+ }
+ formalParameters[params]
+ rpT:TOKEN_PAREN_CLOSE
+ { params.endAfter(rpT); }
+ (resultType[f])?
+ )
+ )
+ arrowT:TOKEN_ARROW
+ {
+ IASNode prevNode = f.getReturnTypeNode();
+ if (prevNode == null)
+ {
+ prevNode = params;
+ }
+ if (arrowT.getLine() != prevNode.getEndLine())
+ {
+ reportUnexpectedTokenProblem((ASToken)arrowT);
+ }
+
+ ASToken funcKeywordToken = new
ASToken(TOKEN_KEYWORD_FUNCTION, -1, -1, -1, -1, "function");
+ KeywordNode funcKeywordNode = new
KeywordNode(funcKeywordToken);
+ funcKeywordNode.startBefore(arrowT);
+ funcKeywordNode.endAfter(arrowT);
+ contentsPart.setKeywordNode(funcKeywordNode);
+ funcObj = new FunctionObjectNode(f);
+ funcObj.startBefore(lpT);
+ n = funcObj;
+ b = f.getScopedNode();
+ }
+
+ // non-optional function body
+ (
+ (
+ // with braces
+ lbT:TOKEN_BLOCK_OPEN
+ { b.startAfter(lbT);}
+ functionBlock[f, (ASToken)lbT]
+ {
+ f.endAfter(b);
+ funcObj.endAfter(b);
+ }
+ )
+ | body=expression
+ {
+ // without braces
+ b.setContainerType(IContainerNode.ContainerType.BRACES);
+ ReturnNode r = new ReturnNode((IASToken)arrowT);
+ r.setStatementExpression(body);
+ b.addItem(r);
+ f.endAfter(b);
+ funcObj.endAfter(b);
+ }
+ )
+ { n=bindArrowFunction(funcObj, (ASToken)arrowT); }
+ ;
+ exception catch [RecognitionException ex] {
+ handleParsingError(ex);
+ }
+
/**
* Matches an anonymous function (function closure).
*/
@@ -1096,6 +1198,8 @@ functionDefinition[ContainerNode c,
INamespaceDecorationNode namespace, List<Mod
{
IdentifierNode name=null;
disableSemicolonInsertion();
+ FunctionNode n = null;
+ ContainerNode parameters = null;
}
: ( functionT:TOKEN_KEYWORD_FUNCTION
@@ -1115,7 +1219,6 @@ functionDefinition[ContainerNode c,
INamespaceDecorationNode namespace, List<Mod
exception catch [RecognitionException ex] { name =
handleMissingIdentifier(ex); }
)
{
- final FunctionNode n ;
if (getT != null)
n = new GetterNode((ASToken)functionT,
(ASToken)getT, name);
else if (setT != null)
@@ -1130,7 +1233,7 @@ functionDefinition[ContainerNode c,
INamespaceDecorationNode namespace, List<Mod
// function signature:
lpT:TOKEN_PAREN_OPEN
{
- final ContainerNode parameters =
n.getParametersContainerNode();
+ parameters = n.getParametersContainerNode();
parameters.startBefore(lpT);
}
formalParameters[parameters]
@@ -2038,6 +2141,7 @@ restrictedName returns [ExpressionNodeBase nameExpression]
IdentifierNode placeHolderRightNode = null;
ASToken opToken = null;
ExpressionNodeBase part = null;
+ ExpressionNodeBase nameLeft = null;
}
: nameExpression=restrictedNamePart
@@ -2055,7 +2159,7 @@ restrictedName returns [ExpressionNodeBase nameExpression]
// FullNameNode.
placeHolderRightNode =
IdentifierNode.createEmptyIdentifierNodeAfterToken(opToken);
- final ExpressionNodeBase nameLeft = nameExpression;
+ nameLeft = nameExpression;
}
( TOKEN_OPERATOR_MEMBER_ACCESS
{ nameExpression = new FullNameNode(nameLeft, opToken,
placeHolderRightNode); }
@@ -2965,6 +3069,7 @@ lhsExpr returns [ExpressionNodeBase n]
n = null;
}
: ( n=newExpression
+ | { isArrowFunction() }? n=arrowFunctionExpression
| n=parenExpression
| n=nameExpression
| n=primaryExpression
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java
index 1defdfe32..70f2a93c9 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/definitions/FunctionDefinition.java
@@ -37,6 +37,7 @@ import
org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
import org.apache.royale.compiler.definitions.references.IReference;
import org.apache.royale.compiler.definitions.references.ReferenceFactory;
import org.apache.royale.compiler.internal.definitions.metadata.MetaTag;
+import
org.apache.royale.compiler.internal.definitions.references.ResolvedReference;
import org.apache.royale.compiler.internal.projects.CompilerProject;
import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.problems.ConflictingDefinitionProblem;
@@ -196,18 +197,25 @@ public class FunctionDefinition extends
ScopedDefinitionBase implements IFunctio
return null;
}
- if (project.getInferTypes() && getReturnTypeReference() == null)
+ IReference returnTypeReference = getReturnTypeReference();
+ if (returnTypeReference == null)
{
IFunctionNode funcNode = (IFunctionNode) getNode();
- if (funcNode != null)
+ ITypeDefinition inferredReturnType = null;
+ if (funcNode.isArrowFunction())
{
- ITypeDefinition inferredReturnType =
SemanticUtils.resolveFunctionInferredReturnType(funcNode, project);
- if (inferredReturnType != null)
- {
-
setReturnTypeReference(ReferenceFactory.resolvedReference(inferredReturnType));
- DependencyType dt = DependencyType.SIGNATURE;
- return resolveType(returnTypeReference, project, dt);
- }
+ inferredReturnType =
SemanticUtils.resolveArrowFunctionInferredReturnType(funcNode, project);
+ }
+ if (project.getInferTypes() && inferredReturnType == null)
+ {
+ inferredReturnType =
SemanticUtils.resolveFunctionInferredReturnType(funcNode, project);
+ }
+ if (inferredReturnType != null)
+ {
+ IReference resolvedRef =
ReferenceFactory.resolvedReference(inferredReturnType);
+
setReturnTypeReference(ReferenceFactory.resolvedReference(inferredReturnType));
+ DependencyType dt = DependencyType.SIGNATURE;
+ return resolveType(resolvedRef, project, dt);
}
}
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
index 11df97b41..3d783ef33 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ASToken.java
@@ -986,6 +986,8 @@ public class ASToken extends TokenBase implements IASToken,
ASTokenTypes
return ASTokenKind.OPERATOR;
case TOKEN_KEYWORD_INCLUDE:
return ASTokenKind.INCLUDE;
+ case TOKEN_ARROW:
+ return ASTokenKind.ARROW;
default:
if (isKeywordOrContextualReservedWord())
return ASTokenKind.KEYWORD;
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
index 0b58fe660..f3785b8ce 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/BaseASParser.java
@@ -43,6 +43,7 @@ import
org.apache.royale.compiler.parsing.IASToken.ASTokenKind;
import org.apache.royale.compiler.problems.InvalidConfigLocationProblem;
import org.apache.royale.compiler.problems.NonConstConfigVarProblem;
import org.apache.royale.compiler.problems.ShadowedConfigNamespaceProblem;
+import org.apache.royale.compiler.tree.as.IContainerNode;
import org.apache.commons.io.IOUtils;
@@ -91,6 +92,7 @@ import
org.apache.royale.compiler.internal.tree.as.FunctionNode;
import org.apache.royale.compiler.internal.tree.as.FunctionObjectNode;
import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
import org.apache.royale.compiler.internal.tree.as.ImportNode;
+import org.apache.royale.compiler.internal.tree.as.LanguageIdentifierNode;
import org.apache.royale.compiler.internal.tree.as.LiteralNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.ModifierNode;
@@ -98,12 +100,15 @@ import
org.apache.royale.compiler.internal.tree.as.NamespaceAccessExpressionNode
import org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
import org.apache.royale.compiler.internal.tree.as.NamespaceNode;
import org.apache.royale.compiler.internal.tree.as.NodeBase;
+import org.apache.royale.compiler.internal.tree.as.ParameterNode;
import
org.apache.royale.compiler.internal.tree.as.QualifiedNamespaceExpressionNode;
+import org.apache.royale.compiler.internal.tree.as.ReturnNode;
import org.apache.royale.compiler.internal.tree.as.ScopedBlockNode;
import org.apache.royale.compiler.internal.tree.as.TernaryOperatorNode;
import org.apache.royale.compiler.internal.tree.as.UnaryOperatorNodeBase;
import org.apache.royale.compiler.internal.tree.as.VariableNode;
import org.apache.royale.compiler.internal.tree.as.metadata.MetaTagsNode;
+import org.apache.royale.compiler.internal.tree.as.parts.FunctionContentsPart;
import org.apache.royale.compiler.internal.workspaces.Workspace;
import org.apache.royale.compiler.mxml.IMXMLTextData;
import
org.apache.royale.compiler.problems.AttributesNotAllowedOnPackageDefinitionProblem;
@@ -2095,6 +2100,7 @@ abstract class BaseASParser extends LLkParser implements
IProblemReporter
private static final ImmutableMap<Integer, Integer> BINARY_PRECEDENCE =
new ImmutableMap.Builder<Integer, Integer>()
.put(TOKEN_COMMA, 1)
+ .put(TOKEN_ARROW, 2)
.put(TOKEN_OPERATOR_ASSIGNMENT, 2)
.put(TOKEN_OPERATOR_LOGICAL_AND_ASSIGNMENT, 2)
.put(TOKEN_OPERATOR_LOGICAL_OR_ASSIGNMENT, 2)
@@ -2607,6 +2613,223 @@ abstract class BaseASParser extends LLkParser
implements IProblemReporter
fileNodeAccumulator.addDeferredFunctionNode(functionNode);
}
+ protected final boolean isArrowFunction()
+ {
+ int lookahead = 1;
+ if (LA(lookahead) == TOKEN_PAREN_OPEN)
+ {
+ lookahead++;
+ // skip the content between the parentheses, even if it's not
+ // technically valid. we're only checking for a => token.
+ for (int depth = 0; depth > 0 || LA(lookahead) !=
TOKEN_PAREN_CLOSE; lookahead++)
+ {
+ ASToken token = LT(lookahead);
+
+ switch (token.getType())
+ {
+ case TOKEN_PAREN_OPEN:
+ depth++;
+ break;
+ case TOKEN_PAREN_CLOSE:
+ depth--;
+ break;
+ case EOF:
+ return false;
+ }
+ }
+ lookahead++;
+
+ // a colon may indicate a return type
+ if (LA(lookahead) == TOKEN_COLON)
+ {
+ lookahead++;
+ int nextToken = LA(lookahead);
+ if (nextToken == TOKEN_OPERATOR_STAR)
+ {
+ // special case where * is not considered an operator
+ lookahead++;
+ }
+ else if (nextToken == TOKEN_KEYWORD_VOID)
+ {
+ lookahead++;
+ }
+ else
+ {
+ while (true)
+ {
+ switch (LA(lookahead))
+ {
+ case TOKEN_ARROW:
+ // see comment below about operator precedence
+ if (precedence(LT(0)) >
precedence(LT(lookahead)))
+ {
+
reportUnexpectedTokenProblem(LT(lookahead));
+ }
+ return true;
+ case TOKEN_TYPED_COLLECTION_OPEN:
+ case TOKEN_TYPED_COLLECTION_CLOSE:
+ case TOKEN_IDENTIFIER:
+ case TOKEN_NAMESPACE_NAME:
+ case TOKEN_OPERATOR_NS_QUALIFIER:
+ case TOKEN_OPERATOR_MEMBER_ACCESS:
+ break;
+ default:
+ // token cannot appear in a return type
+ return false;
+ }
+ lookahead++;
+ }
+ }
+ }
+ }
+ else if (LA(1) == TOKEN_IDENTIFIER)
+ {
+ // if there are no parentheses, only a single identifier with no
+ // type annoation may appear before the => arrow token.
+ lookahead++;
+ }
+ else
+ {
+ // defintely not the start of an arrow function
+ return false;
+ }
+ if (LA(lookahead) == TOKEN_ARROW)
+ {
+ // while the arrow token is not actually an operator, it still
+ // is affected by the operator precedence rules. it has higher
+ // precedence than comma, equal to assignment, and lower than
+ // logical.
+ // if the previous operator has higher precedence, the arrow
+ // function cannot be parsed unless it is wrapped in parentheses.
+ if (precedence(LT(0)) > precedence(LT(lookahead)))
+ {
+ reportUnexpectedTokenProblem(LT(lookahead));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private FunctionObjectNode createInnerBindFunction(String funcName, String
contextName, ISourceLocation sourceLocation)
+ {
+ FunctionContentsPart contentsPart = new FunctionContentsPart();
+
+ // some tokens and nodes must have a valid location
+ // just place them before the source location
+ int start = sourceLocation.getAbsoluteStart();
+ int end = start;
+ int line = sourceLocation.getLine();
+ int column = sourceLocation.getColumn();
+
+ // ...rest parameter
+ ContainerNode paramsContainerNode = contentsPart.getParametersNode();
+ IdentifierNode restNameNode = new
IdentifierNode(IASLanguageConstants.REST_IDENTIFIER);
+ ParameterNode restParamNode = new ParameterNode(restNameNode);
+ restParamNode.setIsRestParameter(true);
+ paramsContainerNode.addChild(restParamNode);
+
+ IdentifierNode functionNameNode = new IdentifierNode("");
+ functionNameNode.startBefore(sourceLocation);
+ functionNameNode.endBefore(sourceLocation);
+ FunctionNode functionNode = new FunctionNode(functionNameNode,
contentsPart);
+
+ // * return type
+ ASToken starToken = new ASToken(ASTokenTypes.TOKEN_OPERATOR_STAR,
start, end, line, column, IASLanguageConstants.ANY_TYPE);
+ LanguageIdentifierNode anyTypeNode =
LanguageIdentifierNode.buildAnyType(starToken);
+ ASToken colonToken = new ASToken(ASTokenTypes.TOKEN_COLON, start, end,
line, column, ":");
+ functionNode.setType(colonToken, anyTypeNode);
+
+ BlockNode body = functionNode.getScopedNode();
+ body.setContainerType(IContainerNode.ContainerType.BRACES);
+
+ // funcName.apply(context, rest)
+ ASToken memberAccessToken = new
ASToken(ASTokenTypes.TOKEN_OPERATOR_MEMBER_ACCESS, start, end, line, column,
".");
+ IdentifierNode funcNameNode = new IdentifierNode(funcName);
+ IdentifierNode applyNameNode = new IdentifierNode("apply");
+ MemberAccessExpressionNode memberAccessNode = new
MemberAccessExpressionNode(funcNameNode, memberAccessToken, applyNameNode);
+ FunctionCallNode functionCallNode = new
FunctionCallNode(memberAccessNode);
+ ContainerNode args = functionCallNode.getArgumentsNode();
+ args.addItem(new IdentifierNode(contextName));
+ args.addItem(new IdentifierNode(IASLanguageConstants.REST_IDENTIFIER));
+
+ // return funcName.apply(context, rest)
+ ASToken returnToken = new ASToken(ASTokenTypes.TOKEN_KEYWORD_RETURN,
start, end, line, column, IASKeywordConstants.RETURN);
+ ReturnNode returnNode = new ReturnNode(returnToken);
+ returnNode.setStatementExpression(functionCallNode);
+ body.addItem(returnNode);
+
+ return new FunctionObjectNode(functionNode);
+ }
+
+ private FunctionObjectNode createOuterBindFunction(ISourceLocation
sourceLocation)
+ {
+ FunctionContentsPart contentsPart = new FunctionContentsPart();
+
+ // some tokens and nodes must have a valid location
+ // just place them before the source location
+ int start = sourceLocation.getAbsoluteStart();
+ int end = start;
+ int line = sourceLocation.getLine();
+ int column = sourceLocation.getColumn();
+
+ ContainerNode paramsContainerNode = contentsPart.getParametersNode();
+
+ // context:* parameter
+ IdentifierNode contextNameNode = new IdentifierNode("context");
+ ParameterNode contextParamNode = new ParameterNode(contextNameNode);
+ ASToken contextColonToken = new ASToken(ASTokenTypes.TOKEN_COLON,
start, end, line, column, ":");
+ ASToken starToken = new ASToken(ASTokenTypes.TOKEN_OPERATOR_STAR,
start, end, line, column, IASLanguageConstants.ANY_TYPE);
+ LanguageIdentifierNode starTypeNode =
LanguageIdentifierNode.buildAnyType(starToken);
+ contextParamNode.setType(contextColonToken, starTypeNode);
+ paramsContainerNode.addChild(contextParamNode);
+
+ // func:Function parameter
+ ASToken funcColonToken = new ASToken(ASTokenTypes.TOKEN_COLON, start,
end, line, column, ":");
+ IdentifierNode funcNameNode = new IdentifierNode("func");
+ ParameterNode funcParamNode = new ParameterNode(funcNameNode);
+ IdentifierNode funcTypeNode = new IdentifierNode("Function");
+ funcParamNode.setType(funcColonToken, funcTypeNode);
+ paramsContainerNode.addChild(funcParamNode);
+
+ IdentifierNode functionNameNode = new IdentifierNode("");
+ functionNameNode.startBefore(sourceLocation);
+ functionNameNode.endBefore(sourceLocation);
+ FunctionNode functionNode = new FunctionNode(functionNameNode,
contentsPart);
+
+ // Function return type
+ ASToken colonToken = new ASToken(ASTokenTypes.TOKEN_COLON, start, end,
line, column, ":");
+ IdentifierNode funcReturnTypeNode = new IdentifierNode("Function");
+ functionNode.setType(colonToken, funcReturnTypeNode);
+
+ BlockNode body = functionNode.getScopedNode();
+ body.setContainerType(IContainerNode.ContainerType.BRACES);
+
+ FunctionObjectNode innerBindFunction = createInnerBindFunction("func",
"context", sourceLocation);
+
+ // return funcName.apply(context, rest)
+ ASToken returnToken = new ASToken(ASTokenTypes.TOKEN_KEYWORD_RETURN,
start, end, line, column, IASKeywordConstants.RETURN);
+ ReturnNode returnNode = new ReturnNode(returnToken);
+ returnNode.setStatementExpression(innerBindFunction);
+ body.addItem(returnNode);
+
+ return new FunctionObjectNode(functionNode);
+ }
+
+ protected ExpressionNodeBase bindArrowFunction(FunctionObjectNode
arrowFunction, ASToken arrowT)
+ {
+ FunctionObjectNode bindFunction =
createOuterBindFunction(arrowFunction);
+
+ FunctionCallNode callNode = new FunctionCallNode(bindFunction);
+ callNode.span(arrowFunction);
+
+ ContainerNode args = callNode.getArgumentsNode();
+ args.addItem(LanguageIdentifierNode.buildThis());
+ args.addItem(arrowFunction);
+ args.span(arrowFunction);
+
+ return callNode;
+ }
+
/**
* Optimization: cache function body text if there's no include processing.
*
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
index b7b993b5a..c13f48d90 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/ConfigProcessor.java
@@ -177,6 +177,12 @@ public class ConfigProcessor
return false;
}
+ @Override
+ public boolean getAllowArrowFunctions() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
@Override
public boolean getAllowStrictFunctionTypes() {
// TODO Auto-generated method stub
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
index 2fb5ead78..5290befae 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/parsing/as/StreamingASTokenizer.java
@@ -1209,6 +1209,7 @@ public class StreamingASTokenizer implements
ASTokenTypes, IASTokenizer, Closeab
case TOKEN_BLOCK_OPEN:
case TOKEN_BLOCK_CLOSE:
case TOKEN_KEYWORD_FUNCTION:
+ case TOKEN_ARROW:
return retVal;
case HIDDEN_TOKEN_MULTI_LINE_COMMENT:
case HIDDEN_TOKEN_SINGLE_LINE_COMMENT:
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
index a41b7588a..2b56ade64 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/ASCProject.java
@@ -99,6 +99,12 @@ public class ASCProject extends CompilerProject implements
IASCProject
return false;
}
+ @Override
+ public boolean getAllowArrowFunctions() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
@Override
public boolean getAllowStrictFunctionTypes() {
// TODO Auto-generated method stub
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
index 638f35bc1..dd3428603 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
@@ -2526,6 +2526,21 @@ public class RoyaleProject extends ASProject implements
IRoyaleProject, ICompile
allowPrivateConstructors = allow;
}
+ private boolean allowArrowFunctions = false;
+
+ /**
+ * Indicates if => arrow functions are allowed.
+ */
+ @Override
+ public boolean getAllowArrowFunctions()
+ {
+ return allowArrowFunctions;
+ }
+ public void setAllowArrowFunctions(boolean allow)
+ {
+ allowArrowFunctions = allow;
+ }
+
private boolean allowStrictFunctionTypes = false;
/**
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
index 6cbe7cb00..1bdb4c1e6 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
@@ -271,6 +271,7 @@ public class RoyaleProjectConfigurator extends Configurator
project.setAllowImportAliases(configuration.getCompilerAllowImportAliases());
project.setAllowAbstractClasses(configuration.getCompilerAllowAbstractClasses());
project.setAllowPrivateConstructors(configuration.getCompilerAllowPrivateConstructors());
+
project.setAllowArrowFunctions(configuration.getCompilerAllowArrowFunctions());
project.setAllowStrictFunctionTypes(configuration.getAllowStrictFunctionTypes());
project.setStrictIdentifierNames(configuration.getCompilerStrictIdentifierNames());
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java
index 7f9a0073a..051838c80 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/MethodBodySemanticChecker.java
@@ -1111,7 +1111,9 @@ public class MethodBodySemanticChecker
{
FunctionNode func = (FunctionNode)iNode;
- if (SemanticUtils.isFunctionClosure(func))
+ if (project.getAllowArrowFunctions()
+ && !func.isArrowFunction()
+ && SemanticUtils.isFunctionClosure(func))
{
for (IASNode thisNode : findThisIdentifierNodes(func))
{
@@ -1358,6 +1360,15 @@ public class MethodBodySemanticChecker
SemanticUtils.checkReturnValueHasNoTypeDeclaration(this.currentScope,
iNode, def);
SemanticUtils.checkParametersHaveNoTypeDeclaration(this.currentScope,
iNode, def);
SemanticUtils.checkParametersHaveUniqueNames(this.currentScope, iNode,
def);
+
+ if (!project.getAllowArrowFunctions())
+ {
+ if (iNode.isArrowFunction())
+ {
+ //arrow functions need to be enabled
+ addProblem(new SyntaxProblem(iNode, "=>"));
+ }
+ }
if (SemanticUtils.isInFunction(iNode))
{
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
index 71ef9d4c7..0889b6392 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
@@ -94,6 +94,7 @@ import
org.apache.royale.compiler.internal.tree.as.LiteralNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.NamespaceNode;
import org.apache.royale.compiler.internal.tree.as.NodeBase;
+import org.apache.royale.compiler.internal.tree.as.ScopedBlockNode;
import org.apache.royale.compiler.internal.tree.as.TypedExpressionNode;
import org.apache.royale.compiler.internal.tree.as.UnaryOperatorAtNode;
import org.apache.royale.compiler.internal.tree.as.UnaryOperatorNodeBase;
@@ -2831,11 +2832,20 @@ public class SemanticUtils
if (node.getStart() == node.getEnd())
return;
+ ICompilerProject project = scope.getProject();
+
IExpressionNode returnType = node.getReturnTypeNode();
ITypeDefinition inferredReturnTypeDef = null;
- if (scope.getProject().getInferTypes() && returnType == null && func
!= null)
+ if (returnType == null && func != null)
{
- inferredReturnTypeDef =
SemanticUtils.resolveFunctionInferredReturnType(node, scope.getProject());
+ if (node.isArrowFunction())
+ {
+ inferredReturnTypeDef =
SemanticUtils.resolveArrowFunctionInferredReturnType(node, project);
+ }
+ if (project.getInferTypes() && inferredReturnTypeDef == null)
+ {
+ inferredReturnTypeDef =
SemanticUtils.resolveFunctionInferredReturnType(node, project);
+ }
}
// check for return type declaration
@@ -3426,6 +3436,33 @@ public class SemanticUtils
return resolvedType;
}
+ /**
+ * Infers the return type from an arrow function without braces. If the
+ * function has braces, returns null.
+ */
+ public static ITypeDefinition
resolveArrowFunctionInferredReturnType(IFunctionNode iNode, ICompilerProject
project)
+ {
+ if (!iNode.isArrowFunction())
+ {
+ return null;
+ }
+ IScopedNode scopedNode = iNode.getScopedNode();
+ if (scopedNode instanceof ScopedBlockNode)
+ {
+ ScopedBlockNode scopedBlockNode = (ScopedBlockNode) scopedNode;
+ if (scopedBlockNode.getChildCount() == 1)
+ {
+ IASNode childNode = scopedBlockNode.getChild(0);
+ if (childNode instanceof IReturnNode)
+ {
+ IReturnNode returnNode = (IReturnNode) childNode;
+ return returnNode.resolveType(project);
+ }
+ }
+ }
+ return null;
+ }
+
public static ITypeDefinition
resolveFunctionInferredReturnType(IFunctionNode iNode, ICompilerProject project)
{
if (iNode.hasModifier(ASModifier.OVERRIDE))
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/FunctionNode.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/FunctionNode.java
index 6ed897051..51751d73c 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/FunctionNode.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/FunctionNode.java
@@ -174,6 +174,8 @@ public class FunctionNode extends BaseTypedDefinitionNode
implements IFunctionNo
* function yet (if a parent function even exists in the first place) -JT
*/
private boolean isRemembered = false;
+
+ private boolean arrowFunction = false;
//
// NodeBase overrides
@@ -585,6 +587,17 @@ public class FunctionNode extends BaseTypedDefinitionNode
implements IFunctionNo
return false;
}
+
+ @Override
+ public boolean isArrowFunction()
+ {
+ return arrowFunction;
+ }
+
+ public void setArrowFunction(boolean isArrow)
+ {
+ arrowFunction = isArrow;
+ }
@Override
public ContainerNode getParametersContainerNode()
diff --git
a/compiler/src/main/jflex/org/apache/royale/compiler/internal/parsing/as/RawASTokenizer.lex
b/compiler/src/main/jflex/org/apache/royale/compiler/internal/parsing/as/RawASTokenizer.lex
index ff925c878..868964a48 100644
---
a/compiler/src/main/jflex/org/apache/royale/compiler/internal/parsing/as/RawASTokenizer.lex
+++
b/compiler/src/main/jflex/org/apache/royale/compiler/internal/parsing/as/RawASTokenizer.lex
@@ -472,6 +472,12 @@ REGEX_CLASS="[" ({REGEX_ESCAPE}|[^\n\r\]\\])* "]"
return buildToken(TOKEN_TYPED_COLLECTION_OPEN, ".<");
}
+// Arrow functions
+<YYINITIAL> "=>"
+{
+ return buildToken(TOKEN_ARROW, "=>");
+}
+
//
// Other operators
//
diff --git a/compiler/src/test/java/as/ASArrowFunctionTests.java
b/compiler/src/test/java/as/ASArrowFunctionTests.java
new file mode 100644
index 000000000..07d9e7dc3
--- /dev/null
+++ b/compiler/src/test/java/as/ASArrowFunctionTests.java
@@ -0,0 +1,305 @@
+/*
+ *
+ * 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 as;
+
+import java.io.File;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ASArrowFunctionTests extends ASFeatureTestsBase
+{
+ @Test
+ public void
testArrowFunctionNotAllowedError_withAllowArrowFunctionsDisabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ // error because arrow functions have not been enabled
+ "var f:Function = (name:String) => 'Hi, ' + name;"
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=false"
+ };
+ compileAndExpectErrors(source, false,false,false, options,
+ "'=>' is not allowed here\n");
+ }
+
+ @Test
+ public void testCallArrowFunctionNoBraces_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var f:Function = (name:String) => 'Hi, ' + name;",
+ "assertEqual('arrow function call', f('Royale'), 'Hi,
Royale');",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndRun(source, false, false, false, options);
+ }
+
+ @Test
+ public void
testCallArrowFunctionWithBracesAndReturnType_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var f:Function = (name:String):String => {",
+ " var result:String = 'Hi, ' + name;\n",
+ " return result;\n",
+ "}",
+ "assertEqual('arrow function call', f('Royale'), 'Hi,
Royale');",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndRun(source, false, false, false, options);
+ }
+
+ @Test
+ public void
testCallArrowFunctionWithBracesNoReturn_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var f:Function = (name:String) => {",
+ " 'Hi, ' + name;\n",
+ "}",
+ "assertEqual('arrow function call', f('Royale'),
undefined);",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndRun(source, false, false, false, options);
+ }
+
+ @Test
+ public void testArrowFunctionThis_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var self:Object = this;",
+ "var f:Function = () => this;",
+ "assertEqual('arrow function this value', this, self);",
+ // ensure that it's the class 'this' and not global 'this'
+ "var f2:Function = (function():Object {return this;});",
+ "assertEqual('arrow function this value', this !==
f2(), true);",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndRun(source, false, false, false, options);
+ }
+
+ @Test
+ public void
testArrowFunctionNoBracesVoidReturn_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var f:Function = ():void => 123.4;",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndExpectErrors(source, false,false,false, options,
+ "A return value is not allowed because the return type of this
function is 'void'.\n");
+ }
+
+ @Test
+ public void
testArrowFunctionWithReturnKeyword_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ // error because statements aren't allowed
+ "var f:Function = () => return 'Royale';",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndExpectErrors(source, false,false,false, options,
+ "'return' is not allowed here\n" +
+ "return value for function '' has no type declaration.\n" +
+ "Function does not have a body.\n" +
+ "Access of possibly undefined property return.\n");
+ }
+
+ @Test
+ public void
testArrowFunctionNewLineBeforeArrow_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var f:Function = ()\n",
+ " => this;",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndExpectErrors(source, false,false,false, options,
+ "'=>' is not allowed here\n");
+ }
+
+ @Test
+ public void
testArrowFunctionWithOperatorOfHigherPrecendent_NoParentheses_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var f:Function;\n",
+ "f = f || () => this;",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndExpectErrors(source, false,false,false, options,
+ "'=>' is not allowed here\n");
+ }
+
+ @Test
+ public void
testArrowFunctionWithOperatorOfHigherPrecendent_WithParentheses_withAllowArrowFunctionsEnabled()
+ {
+ String[] imports = new String[]
+ {
+ };
+ String[] declarations = new String[]
+ {
+ };
+ String[] testCode = new String[]
+ {
+ "var f:Function;\n",
+ "f = f || (() => this);\n",
+ "assertEqual('arrow function operator precedence', f(),
this);",
+ };
+ String[] extra = new String[]
+ {
+ };
+ String source = getAS(imports, declarations, testCode, extra);
+
+ String[] options = new String[]
+ {
+ "-allow-arrow-functions=true"
+ };
+ compileAndRun(source, false, false, false, options);
+ }
+}
diff --git
a/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testArrowFunctionThis_withAllowArrowFunctionsEnabled_swfdump.xml
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testArrowFunctionThis_withAllowArrowFunctionsEnabled_swfdump.xml
new file mode 100644
index 000000000..d81d8e483
--- /dev/null
+++
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testArrowFunctionThis_withAllowArrowFunctionsEnabled_swfdump.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<!-- Parsing swf
file:/Users/joshtynjala/Development/apache/royale-compiler/compiler/target/junit-temp/%0.swf
-->
+<swf xmlns="http://macromedia/2003/swfx" version="14" framerate="24.0"
size="10000x7500" compressed="true" >
+ <!-- framecount=1 length=1243 -->
+ <FileAttributes useDirectBlit="false" useGPU="false" hasMetadata="true"
actionScript3="true" suppressCrossDomainCaching="false" swfRelativeUrls="false"
useNetwork="true"/>
+ <Metadata>
+ <![CDATA[<?xml version="1.0" ?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1"
xmlns:asc="http://ns.adobe.com/asc/2012">
+ <dc:format>application/x-shockwave-flash</dc:format>
+ <asc:compiler name="Apache Royale Compiler" version="0.9.13"
build="0"/>
+ </rdf:Description>
+</rdf:RDF>
+]]>
+ </Metadata>
+ <SetBackgroundColor color="#FFFFFF"/>
+ <ScriptLimits scriptRecursionLimit="1000" scriptTimeLimit="60"/>
+ <DoABC>
+// script 0
+
+// class_id=0 slot_id=0
+public class %0 extends Object
+{
+
+ // method_id=7
+ public function %0():*
+ {
+ // derivedName %0
+ // method_info 7
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 1
+ // code_length 6
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getlocal0
+ 3 constructsuper 0
+ 4 returnvoid
+ }
+
+ private function initHandler(Object):void
+ {
+ // derivedName initHandler
+ // method_info 1
+ // max_stack 5
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 2
+ // code_length 67
+ activation_traits {
+
+ internal var e:Object
+
+ internal var self:Object
+
+ internal var f:Function
+
+ internal var f2:Function
+ }
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 newactivation
+ 3 dup
+ 4 setlocal2
+ 5 pushscope
+ 6 findpropstrict e
+ 7 getlocal1
+ 8 setproperty e
+ 9 getlocal0
+ 10 coerce Object
+ 11 getlocal2
+ 12 swap
+ 13 setslot 2
+ 14 newfunction
+ 15 getlocal0
+ 16 getlocal0
+ 17 newfunction
+ 18 call 2
+ 19 coerce Function
+ 20 getlocal2
+ 21 swap
+ 22 setslot 3
+ 23 findpropstrict assertEqual
+ 24 pushstring "arrow function this value"
+ 25 getlocal0
+ 26 getlex self
+ 27 callpropvoid
+ 28 newfunction
+ 29 coerce Function
+ 30 getlocal2
+ 31 swap
+ 32 setslot 4
+ 33 findpropstrict assertEqual
+ 34 pushstring "arrow function this value"
+ 35 getlocal0
+ 36 getlex f2
+ 37 getglobalscope
+ 38 call 0
+ 39 strictequals
+ 40 not
+ 41 pushtrue
+ 42 callpropvoid
+ 43 returnvoid
+ }
+
+ private function assertEqual(String,*,*):void
+ {
+ // derivedName assertEqual
+ // method_info 6
+ // max_stack 1
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 1
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+
+ public static function %0$():*
+ {
+ // derivedName null
+ // method_info 8
+ // max_stack 0
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+}
+
+function script0$init():*
+{
+ // derivedName null
+ // method_info 0
+ // max_stack 3
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 2
+ // code_length 14
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getscopeobject 0
+ 3 getlex Object
+ 4 dup
+ 5 pushscope
+ 6 newclass
+ 7 popscope
+ 8 initproperty %0
+ 9 returnvoid
+}
+
+
+// 2 %0.as$0:anonymous
+function (*,Function):Function
+{
+ // derivedName %0.as$0:anonymous
+ // method_info 2
+ // max_stack 2
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 1
+ // code_length 15
+ activation_traits {
+
+ internal var context:*
+
+ internal var func:Function
+ }
+ bb0
+ succs=[]
+ 0 newactivation
+ 1 pushscope
+ 2 findpropstrict context
+ 3 getlocal1
+ 4 setproperty context
+ 5 findpropstrict func
+ 6 getlocal2
+ 7 setproperty func
+ 8 newfunction
+ 9 returnvalue
+}
+
+// 3 %0.as$1:anonymous
+function ():*
+{
+ // derivedName %0.as$1:anonymous
+ // method_info 3
+ // max_stack 3
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 0
+ // code_length 9
+ bb0
+ succs=[]
+ 0 getlex func
+ 1 getlex context
+ 2 getlocal1
+ 3 callproperty
+ 4 returnvalue
+}
+
+// 4 %0.as$2:anonymous
+function ():*
+{
+ // derivedName %0.as$2:anonymous
+ // method_info 4
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 2
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 returnvalue
+}
+
+// 5 %0.as$3:anonymous
+function ():Object
+{
+ // derivedName %0.as$3:anonymous
+ // method_info 5
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 2
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 returnvalue
+}
+ </DoABC>
+ <SymbolClass>
+ <Symbol idref="0" className="%0" />
+ </SymbolClass>
+ <ShowFrame/>
+</swf>
diff --git
a/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testArrowFunctionWithOperatorOfHigherPrecendent_WithParentheses_withAllowArrowFunctionsEnabled_swfdump.xml
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testArrowFunctionWithOperatorOfHigherPrecendent_WithParentheses_withAllowArrowFunctionsEnabled_swfdump.xml
new file mode 100644
index 000000000..0529ef06e
--- /dev/null
+++
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testArrowFunctionWithOperatorOfHigherPrecendent_WithParentheses_withAllowArrowFunctionsEnabled_swfdump.xml
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<!-- Parsing swf
file:/Users/joshtynjala/Development/apache/royale-compiler/compiler/target/junit-temp/%0.swf
-->
+<swf xmlns="http://macromedia/2003/swfx" version="14" framerate="24.0"
size="10000x7500" compressed="true" >
+ <!-- framecount=1 length=1240 -->
+ <FileAttributes useDirectBlit="false" useGPU="false" hasMetadata="true"
actionScript3="true" suppressCrossDomainCaching="false" swfRelativeUrls="false"
useNetwork="true"/>
+ <Metadata>
+ <![CDATA[<?xml version="1.0" ?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1"
xmlns:asc="http://ns.adobe.com/asc/2012">
+ <dc:format>application/x-shockwave-flash</dc:format>
+ <asc:compiler name="Apache Royale Compiler" version="0.9.13"
build="0"/>
+ </rdf:Description>
+</rdf:RDF>
+]]>
+ </Metadata>
+ <SetBackgroundColor color="#FFFFFF"/>
+ <ScriptLimits scriptRecursionLimit="1000" scriptTimeLimit="60"/>
+ <DoABC>
+// script 0
+
+// class_id=0 slot_id=0
+public class %0 extends Object
+{
+
+ // method_id=6
+ public function %0():*
+ {
+ // derivedName %0
+ // method_info 6
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 1
+ // code_length 6
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getlocal0
+ 3 constructsuper 0
+ 4 returnvoid
+ }
+
+ private function initHandler(Object):void
+ {
+ // derivedName initHandler
+ // method_info 1
+ // max_stack 4
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 2
+ // code_length 47
+ activation_traits {
+
+ internal var e:Object
+
+ internal var f:Function
+ }
+ bb0
+ succs=[bb1,bb2]
+ 0 getlocal0
+ 1 pushscope
+ 2 newactivation
+ 3 dup
+ 4 setlocal2
+ 5 pushscope
+ 6 findpropstrict e
+ 7 getlocal1
+ 8 setproperty e
+ 9 getlex f
+ 10 dup
+ 11 iftrue bb2
+ bb1
+ succs=[bb2]
+ 12 pop
+ 13 newfunction
+ 14 getlocal0
+ 15 getlocal0
+ 16 newfunction
+ 17 call 2
+ bb2
+ succs=[]
+ 18 coerce Function
+ 19 getlocal2
+ 20 swap
+ 21 setslot 2
+ 22 findpropstrict assertEqual
+ 23 pushstring "arrow function operator precedence"
+ 24 getlex f
+ 25 getglobalscope
+ 26 call 0
+ 27 getlocal0
+ 28 callpropvoid
+ 29 returnvoid
+ }
+
+ private function assertEqual(String,*,*):void
+ {
+ // derivedName assertEqual
+ // method_info 5
+ // max_stack 1
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 1
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+
+ public static function %0$():*
+ {
+ // derivedName null
+ // method_info 7
+ // max_stack 0
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+}
+
+function script0$init():*
+{
+ // derivedName null
+ // method_info 0
+ // max_stack 3
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 2
+ // code_length 14
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getscopeobject 0
+ 3 getlex Object
+ 4 dup
+ 5 pushscope
+ 6 newclass
+ 7 popscope
+ 8 initproperty %0
+ 9 returnvoid
+}
+
+
+// 2 %0.as$0:anonymous
+function (*,Function):Function
+{
+ // derivedName %0.as$0:anonymous
+ // method_info 2
+ // max_stack 2
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 1
+ // code_length 15
+ activation_traits {
+
+ internal var context:*
+
+ internal var func:Function
+ }
+ bb0
+ succs=[]
+ 0 newactivation
+ 1 pushscope
+ 2 findpropstrict context
+ 3 getlocal1
+ 4 setproperty context
+ 5 findpropstrict func
+ 6 getlocal2
+ 7 setproperty func
+ 8 newfunction
+ 9 returnvalue
+}
+
+// 3 %0.as$1:anonymous
+function ():*
+{
+ // derivedName %0.as$1:anonymous
+ // method_info 3
+ // max_stack 3
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 0
+ // code_length 9
+ bb0
+ succs=[]
+ 0 getlex func
+ 1 getlex context
+ 2 getlocal1
+ 3 callproperty
+ 4 returnvalue
+}
+
+// 4 %0.as$2:anonymous
+function ():*
+{
+ // derivedName %0.as$2:anonymous
+ // method_info 4
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 2
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 returnvalue
+}
+ </DoABC>
+ <SymbolClass>
+ <Symbol idref="0" className="%0" />
+ </SymbolClass>
+ <ShowFrame/>
+</swf>
diff --git
a/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionNoBraces_withAllowArrowFunctionsEnabled_swfdump.xml
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionNoBraces_withAllowArrowFunctionsEnabled_swfdump.xml
new file mode 100644
index 000000000..ba7ca7a97
--- /dev/null
+++
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionNoBraces_withAllowArrowFunctionsEnabled_swfdump.xml
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<!-- Parsing swf
file:/Users/joshtynjala/Development/apache/royale-compiler/compiler/target/junit-temp/%0.swf
-->
+<swf xmlns="http://macromedia/2003/swfx" version="14" framerate="24.0"
size="10000x7500" compressed="true" >
+ <!-- framecount=1 length=1140 -->
+ <FileAttributes useDirectBlit="false" useGPU="false" hasMetadata="true"
actionScript3="true" suppressCrossDomainCaching="false" swfRelativeUrls="false"
useNetwork="true"/>
+ <Metadata>
+ <![CDATA[<?xml version="1.0" ?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1"
xmlns:asc="http://ns.adobe.com/asc/2012">
+ <dc:format>application/x-shockwave-flash</dc:format>
+ <asc:compiler name="Apache Royale Compiler" version="0.9.13"
build="0"/>
+ </rdf:Description>
+</rdf:RDF>
+]]>
+ </Metadata>
+ <SetBackgroundColor color="#FFFFFF"/>
+ <ScriptLimits scriptRecursionLimit="1000" scriptTimeLimit="60"/>
+ <DoABC>
+// script 0
+
+// class_id=0 slot_id=0
+public class %0 extends Object
+{
+
+ // method_id=6
+ public function %0():*
+ {
+ // derivedName %0
+ // method_info 6
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 1
+ // code_length 6
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getlocal0
+ 3 constructsuper 0
+ 4 returnvoid
+ }
+
+ private function initHandler(Object):void
+ {
+ // derivedName initHandler
+ // method_info 1
+ // max_stack 5
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 2
+ // code_length 42
+ activation_traits {
+
+ internal var e:Object
+
+ internal var f:Function
+ }
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 newactivation
+ 3 dup
+ 4 setlocal2
+ 5 pushscope
+ 6 findpropstrict e
+ 7 getlocal1
+ 8 setproperty e
+ 9 newfunction
+ 10 getlocal0
+ 11 getlocal0
+ 12 newfunction
+ 13 call 2
+ 14 coerce Function
+ 15 getlocal2
+ 16 swap
+ 17 setslot 2
+ 18 findpropstrict assertEqual
+ 19 pushstring "arrow function call"
+ 20 getlex f
+ 21 getglobalscope
+ 22 pushstring "Royale"
+ 23 call 1
+ 24 pushstring "Hi, Royale"
+ 25 callpropvoid
+ 26 returnvoid
+ }
+
+ private function assertEqual(String,*,*):void
+ {
+ // derivedName assertEqual
+ // method_info 5
+ // max_stack 1
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 1
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+
+ public static function %0$():*
+ {
+ // derivedName null
+ // method_info 7
+ // max_stack 0
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+}
+
+function script0$init():*
+{
+ // derivedName null
+ // method_info 0
+ // max_stack 3
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 2
+ // code_length 14
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getscopeobject 0
+ 3 getlex Object
+ 4 dup
+ 5 pushscope
+ 6 newclass
+ 7 popscope
+ 8 initproperty %0
+ 9 returnvoid
+}
+
+
+// 2 %0.as$0:anonymous
+function (*,Function):Function
+{
+ // derivedName %0.as$0:anonymous
+ // method_info 2
+ // max_stack 2
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 1
+ // code_length 15
+ activation_traits {
+
+ internal var context:*
+
+ internal var func:Function
+ }
+ bb0
+ succs=[]
+ 0 newactivation
+ 1 pushscope
+ 2 findpropstrict context
+ 3 getlocal1
+ 4 setproperty context
+ 5 findpropstrict func
+ 6 getlocal2
+ 7 setproperty func
+ 8 newfunction
+ 9 returnvalue
+}
+
+// 3 %0.as$1:anonymous
+function ():*
+{
+ // derivedName %0.as$1:anonymous
+ // method_info 3
+ // max_stack 3
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 0
+ // code_length 9
+ bb0
+ succs=[]
+ 0 getlex func
+ 1 getlex context
+ 2 getlocal1
+ 3 callproperty
+ 4 returnvalue
+}
+
+// 4 %0.as$2:anonymous
+function (String):*
+{
+ // derivedName %0.as$2:anonymous
+ // method_info 4
+ // max_stack 2
+ // max_regs 2
+ // scope_depth 0
+ // max_scope 0
+ // code_length 5
+ bb0
+ succs=[]
+ 0 pushstring "Hi, "
+ 1 getlocal1
+ 2 add
+ 3 returnvalue
+}
+ </DoABC>
+ <SymbolClass>
+ <Symbol idref="0" className="%0" />
+ </SymbolClass>
+ <ShowFrame/>
+</swf>
diff --git
a/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionWithBracesAndReturnType_withAllowArrowFunctionsEnabled_swfdump.xml
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionWithBracesAndReturnType_withAllowArrowFunctionsEnabled_swfdump.xml
new file mode 100644
index 000000000..e95c41190
--- /dev/null
+++
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionWithBracesAndReturnType_withAllowArrowFunctionsEnabled_swfdump.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<!-- Parsing swf
file:/Users/joshtynjala/Development/apache/royale-compiler/compiler/target/junit-temp/%0.swf
-->
+<swf xmlns="http://macromedia/2003/swfx" version="14" framerate="24.0"
size="10000x7500" compressed="true" >
+ <!-- framecount=1 length=1148 -->
+ <FileAttributes useDirectBlit="false" useGPU="false" hasMetadata="true"
actionScript3="true" suppressCrossDomainCaching="false" swfRelativeUrls="false"
useNetwork="true"/>
+ <Metadata>
+ <![CDATA[<?xml version="1.0" ?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1"
xmlns:asc="http://ns.adobe.com/asc/2012">
+ <dc:format>application/x-shockwave-flash</dc:format>
+ <asc:compiler name="Apache Royale Compiler" version="0.9.13"
build="0"/>
+ </rdf:Description>
+</rdf:RDF>
+]]>
+ </Metadata>
+ <SetBackgroundColor color="#FFFFFF"/>
+ <ScriptLimits scriptRecursionLimit="1000" scriptTimeLimit="60"/>
+ <DoABC>
+// script 0
+
+// class_id=0 slot_id=0
+public class %0 extends Object
+{
+
+ // method_id=6
+ public function %0():*
+ {
+ // derivedName %0
+ // method_info 6
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 1
+ // code_length 6
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getlocal0
+ 3 constructsuper 0
+ 4 returnvoid
+ }
+
+ private function initHandler(Object):void
+ {
+ // derivedName initHandler
+ // method_info 1
+ // max_stack 5
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 2
+ // code_length 42
+ activation_traits {
+
+ internal var e:Object
+
+ internal var f:Function
+ }
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 newactivation
+ 3 dup
+ 4 setlocal2
+ 5 pushscope
+ 6 findpropstrict e
+ 7 getlocal1
+ 8 setproperty e
+ 9 newfunction
+ 10 getlocal0
+ 11 getlocal0
+ 12 newfunction
+ 13 call 2
+ 14 coerce Function
+ 15 getlocal2
+ 16 swap
+ 17 setslot 2
+ 18 findpropstrict assertEqual
+ 19 pushstring "arrow function call"
+ 20 getlex f
+ 21 getglobalscope
+ 22 pushstring "Royale"
+ 23 call 1
+ 24 pushstring "Hi, Royale"
+ 25 callpropvoid
+ 26 returnvoid
+ }
+
+ private function assertEqual(String,*,*):void
+ {
+ // derivedName assertEqual
+ // method_info 5
+ // max_stack 1
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 1
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+
+ public static function %0$():*
+ {
+ // derivedName null
+ // method_info 7
+ // max_stack 0
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+}
+
+function script0$init():*
+{
+ // derivedName null
+ // method_info 0
+ // max_stack 3
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 2
+ // code_length 14
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getscopeobject 0
+ 3 getlex Object
+ 4 dup
+ 5 pushscope
+ 6 newclass
+ 7 popscope
+ 8 initproperty %0
+ 9 returnvoid
+}
+
+
+// 2 %0.as$0:anonymous
+function (*,Function):Function
+{
+ // derivedName %0.as$0:anonymous
+ // method_info 2
+ // max_stack 2
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 1
+ // code_length 15
+ activation_traits {
+
+ internal var context:*
+
+ internal var func:Function
+ }
+ bb0
+ succs=[]
+ 0 newactivation
+ 1 pushscope
+ 2 findpropstrict context
+ 3 getlocal1
+ 4 setproperty context
+ 5 findpropstrict func
+ 6 getlocal2
+ 7 setproperty func
+ 8 newfunction
+ 9 returnvalue
+}
+
+// 3 %0.as$1:anonymous
+function ():*
+{
+ // derivedName %0.as$1:anonymous
+ // method_info 3
+ // max_stack 3
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 0
+ // code_length 9
+ bb0
+ succs=[]
+ 0 getlex func
+ 1 getlex context
+ 2 getlocal1
+ 3 callproperty
+ 4 returnvalue
+}
+
+// 4 %0.as$2:anonymous
+function (String):String
+{
+ // derivedName %0.as$2:anonymous
+ // method_info 4
+ // max_stack 2
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 0
+ // code_length 8
+ bb0
+ succs=[]
+ 0 pushstring "Hi, "
+ 1 getlocal1
+ 2 add
+ 3 coerce_s
+ 4 setlocal2
+ 5 getlocal2
+ 6 returnvalue
+}
+ </DoABC>
+ <SymbolClass>
+ <Symbol idref="0" className="%0" />
+ </SymbolClass>
+ <ShowFrame/>
+</swf>
diff --git
a/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionWithBracesNoReturn_withAllowArrowFunctionsEnabled_swfdump.xml
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionWithBracesNoReturn_withAllowArrowFunctionsEnabled_swfdump.xml
new file mode 100644
index 000000000..c92b5299c
--- /dev/null
+++
b/compiler/src/test/resources/swfdumps/as_ASArrowFunctionTests_testCallArrowFunctionWithBracesNoReturn_withAllowArrowFunctionsEnabled_swfdump.xml
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<!-- Parsing swf
file:/Users/joshtynjala/Development/apache/royale-compiler/compiler/target/junit-temp/%0.swf
-->
+<swf xmlns="http://macromedia/2003/swfx" version="14" framerate="24.0"
size="10000x7500" compressed="true" >
+ <!-- framecount=1 length=1123 -->
+ <FileAttributes useDirectBlit="false" useGPU="false" hasMetadata="true"
actionScript3="true" suppressCrossDomainCaching="false" swfRelativeUrls="false"
useNetwork="true"/>
+ <Metadata>
+ <![CDATA[<?xml version="1.0" ?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1"
xmlns:asc="http://ns.adobe.com/asc/2012">
+ <dc:format>application/x-shockwave-flash</dc:format>
+ <asc:compiler name="Apache Royale Compiler" version="0.9.13"
build="0"/>
+ </rdf:Description>
+</rdf:RDF>
+]]>
+ </Metadata>
+ <SetBackgroundColor color="#FFFFFF"/>
+ <ScriptLimits scriptRecursionLimit="1000" scriptTimeLimit="60"/>
+ <DoABC>
+// script 0
+
+// class_id=0 slot_id=0
+public class %0 extends Object
+{
+
+ // method_id=6
+ public function %0():*
+ {
+ // derivedName %0
+ // method_info 6
+ // max_stack 1
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 1
+ // code_length 6
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getlocal0
+ 3 constructsuper 0
+ 4 returnvoid
+ }
+
+ private function initHandler(Object):void
+ {
+ // derivedName initHandler
+ // method_info 1
+ // max_stack 5
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 2
+ // code_length 41
+ activation_traits {
+
+ internal var e:Object
+
+ internal var f:Function
+ }
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 newactivation
+ 3 dup
+ 4 setlocal2
+ 5 pushscope
+ 6 findpropstrict e
+ 7 getlocal1
+ 8 setproperty e
+ 9 newfunction
+ 10 getlocal0
+ 11 getlocal0
+ 12 newfunction
+ 13 call 2
+ 14 coerce Function
+ 15 getlocal2
+ 16 swap
+ 17 setslot 2
+ 18 findpropstrict assertEqual
+ 19 pushstring "arrow function call"
+ 20 getlex f
+ 21 getglobalscope
+ 22 pushstring "Royale"
+ 23 call 1
+ 24 pushundefined
+ 25 callpropvoid
+ 26 returnvoid
+ }
+
+ private function assertEqual(String,*,*):void
+ {
+ // derivedName assertEqual
+ // method_info 5
+ // max_stack 1
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 1
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+
+ public static function %0$():*
+ {
+ // derivedName null
+ // method_info 7
+ // max_stack 0
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 0
+ // code_length 1
+ bb0
+ succs=[]
+ 0 returnvoid
+ }
+}
+
+function script0$init():*
+{
+ // derivedName null
+ // method_info 0
+ // max_stack 3
+ // max_regs 1
+ // scope_depth 0
+ // max_scope 2
+ // code_length 14
+ bb0
+ succs=[]
+ 0 getlocal0
+ 1 pushscope
+ 2 getscopeobject 0
+ 3 getlex Object
+ 4 dup
+ 5 pushscope
+ 6 newclass
+ 7 popscope
+ 8 initproperty %0
+ 9 returnvoid
+}
+
+
+// 2 %0.as$0:anonymous
+function (*,Function):Function
+{
+ // derivedName %0.as$0:anonymous
+ // method_info 2
+ // max_stack 2
+ // max_regs 3
+ // scope_depth 0
+ // max_scope 1
+ // code_length 15
+ activation_traits {
+
+ internal var context:*
+
+ internal var func:Function
+ }
+ bb0
+ succs=[]
+ 0 newactivation
+ 1 pushscope
+ 2 findpropstrict context
+ 3 getlocal1
+ 4 setproperty context
+ 5 findpropstrict func
+ 6 getlocal2
+ 7 setproperty func
+ 8 newfunction
+ 9 returnvalue
+}
+
+// 3 %0.as$1:anonymous
+function ():*
+{
+ // derivedName %0.as$1:anonymous
+ // method_info 3
+ // max_stack 3
+ // max_regs 4
+ // scope_depth 0
+ // max_scope 0
+ // code_length 9
+ bb0
+ succs=[]
+ 0 getlex func
+ 1 getlex context
+ 2 getlocal1
+ 3 callproperty
+ 4 returnvalue
+}
+
+// 4 %0.as$2:anonymous
+function (String):*
+{
+ // derivedName %0.as$2:anonymous
+ // method_info 4
+ // max_stack 2
+ // max_regs 2
+ // scope_depth 0
+ // max_scope 0
+ // code_length 5
+ bb0
+ succs=[]
+ 0 pushstring "Hi, "
+ 1 getlocal1
+ 2 add
+ 3 returnvoid
+}
+ </DoABC>
+ <SymbolClass>
+ <Symbol idref="0" className="%0" />
+ </SymbolClass>
+ <ShowFrame/>
+</swf>