/*
 *
 *  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.
 *
 */

/*
 *  Tree parsing patterns for the ASTs generated by the Royale Compiler parser.
 */

/*
 *  Directives.
 */
Pattern useNamespaceDirective
UseID(name ns_name);

Pattern importDirective
ImportID(import_name importName);

/*
 *  Declarations.
 */

//  Patterns for function variants are factored into FunctionPatterns.jbg;
//  include them with applicable modifications to the root node ID recognized
//  and the names of the generated patterns.
JBurg.include "FunctionPatterns.jbg"
JBurg.include "FunctionPatterns.jbg" FunctionID="GetterID" typelessFunction="typelessGetter" typedFunction="typedGetter"
JBurg.include "FunctionPatterns.jbg" FunctionID="SetterID" typelessFunction="typelessSetter" typedFunction="typedSetter"

//  An anonymous function closure, e.g.,
//  foo = function() { return 12; }
Pattern anonymousFunction
AnonymousFunctionID(function function_body);

//  A function closure with no type, e.g.,
//  foo = function factorial(x) { return x == 1? 1: x * factorial(x-1); }
Pattern typelessFunctionObject
FunctionObjectID(FunctionID(IdentifierID(void) function_name, parameterList plist, statement block));

//  A function closure with a return type, e.g.,
//  foo = function factorial(x):int { return x == 1? 1: x * factorial(x-1); }
Pattern typedFunctionObject
FunctionObjectID(FunctionID(IdentifierID(void) function_name, parameterList plist, return_type_name return_type, statement block));

//  Parameter declarations.

Pattern plist
ContainerID(parameter pdecl*);

Pattern requiredParameter
ArgumentID(decl_name param_name, type_name param_type);

Pattern optionalParameter
ArgumentID(decl_name param_name, type_name param_type, required_constant_value default_value);

Pattern restParameter
ArgumentRestID(decl_name param_name, type_name param_type);

//  Variable declarations.

Pattern typedVariableDecl
VariableID(decl_name var_name, type_name var_type, var_decl chained_decls*);

// variable or const decl with a non-constant initializer
// var v = func();
Pattern typedVariableDeclWithInitializer
VariableID(decl_name var_name, type_name var_type, expression var_initializer, var_decl chained_decls*);

// variable or const decl with a constant initializer
// var v = 10;
Pattern typedVariableDeclWithConstantInitializer
VariableID(decl_name var_name, type_name var_type, constant_value constant_var_initializer, var_decl chained_decls*);

Pattern typedBindableVariableDecl
BindableVariableID(decl_name var_name, type_name var_type, var_decl chained_decls*);

Pattern typedBindableVariableDeclWithInitializer
BindableVariableID(decl_name var_name, type_name var_type, expression var_initializer, var_decl chained_decls*);

Pattern variableExpression
VariableExpressionID(var_decl decls+);

Pattern typedVariableExpression
VariableExpressionID(
    VariableID( 
        decl_name var_name,
        type_name var_type
        )
    );

//  namespace NsFoo;
Pattern namespaceDeclaration
NamespaceID(name ns_name);

//  namespace NsBar = "http://foo";
Pattern namespaceDeclarationConstantInitializer
NamespaceID(name ns_name, string_constant uri);

//  namespace NsCopy = NsOrig;
//  See also CMP-268.
Pattern namespaceDeclarationInitializer
NamespaceID(name ns_name, name second_ns);

/*
 *  Statements.
 */

// { stmts; } or { }
Pattern blockStmt
BlockID(statement stmts*);

// CONFIG... { stmts; }
Pattern configBlockStmt
ConfigBlockID(statement stmts*);

//  break;
Pattern breakStmt  
BreakID(void);

//  break foo;
Pattern labeledBreakStmt
BreakID(IdentifierID(void));

//  continue;
Pattern continueStmt
ContinueID(void);

//  continue foo;
Pattern labeledContinueStmt
ContinueID(IdentifierID(void));

// goto foo;
Pattern gotoStmt
GotoID(IdentifierID(void));

//  do { body } while ( cond );
Pattern doStmt
DoWhileLoopID(statement body, expression cond);

//  for ( init; test_insns; incr ) body;
Pattern countedForStmt
ForLoopID(ContainerID( void_expression init, conditionalJump test_insns, void_expression incr ), statement body);

// for (it in base) body;
Pattern forInStmt
ForLoopID(ContainerID(Op_InID(name it, expression base)), statement body);

// for (a[it] in base) body;
Pattern forInArrayStmt
ForLoopID(ContainerID(Op_InID(ArrayIndexExpressionID(expression stem, expression index), expression base)), statement body);

// for (x.y in base) body;
Pattern forInMemberStmt
ForLoopID(ContainerID(Op_InID(MemberAccessExpressionID(expression stem, name member), expression base)), statement body);

// for (x..y in base) body;
Pattern forInDescendantStmt
ForLoopID(ContainerID(Op_InID(Op_DescendantsID(expression stem, name descendants), expression base)), statement body);

// for (super.y in base) body;
Pattern forInSuperStmt
ForLoopID(ContainerID(Op_InID(MemberAccessExpressionID(SuperID(void), name member), expression base)), statement body);

// for (super['y'] in base) body;
Pattern forInSuperBracketStmt
ForLoopID(ContainerID(Op_InID(ArrayIndexExpressionID(SuperID(void), expression index), expression base)), statement body);

// for (var x:type = "init" in base) body;
Pattern forVarDeclInStmt
ForLoopID(ContainerID(Op_InID(VariableExpressionID(var_decl single_decl), expression base)), statement body);

// for each (var x:type = "init" in base) body;
Pattern forEachVarDeclInStmt
ForEachLoopID(ContainerID(Op_InID(VariableExpressionID(var_decl single_decl), expression base)), statement body);

//  for each (it in base) body;
Pattern forEachStmt
ForEachLoopID(ContainerID(Op_InID(name it, expression base)), statement body);

// for each (a[it] in base) body;
Pattern forEachArrayStmt
ForEachLoopID(ContainerID(Op_InID(ArrayIndexExpressionID(expression stem, expression index), expression base)), statement body);

// for each (x.y in base) body;
Pattern forEachMemberStmt
ForEachLoopID(ContainerID(Op_InID(MemberAccessExpressionID(expression stem, name member), expression base)), statement body);

// for each (x..y in base) body;
Pattern forEachInDescendantStmt
ForEachLoopID(ContainerID(Op_InID(Op_DescendantsID(expression stem, name descendants), expression base)), statement body);

// for each (super.y in base) body;
Pattern forEachSuperStmt
ForEachLoopID(ContainerID(Op_InID(MemberAccessExpressionID(SuperID(void), name member), expression base)), statement body);

// for each (super['y'] in base) body;
Pattern forEachSuperBracketStmt
ForEachLoopID(ContainerID(Op_InID(ArrayIndexExpressionID(SuperID(void), expression index), expression base)), statement body);

//  if ( test ) then; else ...
Pattern ifElseIf
IfStatementID ( ConditionalID(expression test, statement then), conditionalElements if_elseif* );

//  final else following the linked chain of if/else if clauses above.
Pattern lastElse
ElseID ( statement else_clause );

//  return value;
Pattern returnValue
ReturnStatementID(expression value);

// return void 0;
Pattern returnVoidValue
ReturnStatementID(void_expression no_value);

// return void(expr);
Pattern returnVoidSideEffect
ReturnStatementID(Op_VoidID(expression expr));

// return;
Pattern returnVoid
ReturnStatementID(void);

// this handles the no semi-colon case:
// return
Pattern returnNil
ReturnStatementID(NilID(void));

//  switch ( switch_expr ) { cases }
Pattern switchStmt
SwitchID(expression switch_expr, BlockID(conditionalElements cases*));

//  case case_expr: case_actions; ...
Pattern switchCase
ConditionalID(expression case_expr, statement case_actions*);

// This is an optimization for constant conditionals such as:
//     if (true) { }
// or:
//     case 7: case_actions; ...
Pattern constantSwitchCase
ConditionalID(constant_value case_const_value, statement case_actions*);

//  default: case_actions; ...
Pattern switchDefault
DefaultID(BlockID(statement case_actions*));

//  throw tossable;
Pattern throwStmt
ThrowsStatementID(expression tossable);

//  try { try_stmt; } catch( ex1:Etype1 ) { }... finally { finally_stmt }
Pattern tryCatchFinallyStmt
TryID(statement try_stmt, FinallyID(finally_clause finally_stmt), catch_block catch_blocks+);

//  try { try_stmt; } catch( ex1:Etype1 ) { }...
Pattern tryCatchStmt
TryID(statement try_stmt, catch_block catch_blocks+);

//  try { try_stmt; } finally { finally_stmt; }
Pattern tryFinallyStmt
TryID(statement try_stmt, FinallyID(finally_clause finally_stmt));

//  catch ( ex:ExType ) { actions; }
Pattern catchBlockTyped
CatchID(ArgumentID(name var_name, type_name exception), statement action);

//  catch(ex) { actions; }
Pattern catchBlockUntyped
CatchID(ArgumentID(name var_name), statement action);

// while(cond) body;
Pattern whileStmt
WhileLoopID(expression cond, statement body);

//  with(new_scope) body;
Pattern withStmt
WithID(expression new_scope, statement body);

// label: statement;
Pattern labeledStmt
LabledStatementID(non_resolving_identifier label, statement substatement);


/*
 *  Assignment expressions.
 */

// x = <rvalue>
Pattern assignToNameExpr
Op_AssignId(name lval, expression r);

// x.rt_name.foo = <rvalue>
Pattern assignToRuntimeNameExpr 
Op_AssignId(runtime_name_expression lval, expression r);

// x.member.foo = <rvalue>
Pattern assignToMemberExpr
Op_AssignId(MemberAccessExpressionID(expression stem, name member), expression r);

// x.ns::foo = <rvalue>
Pattern assignToQualifiedMemberExpr
Op_AssignId(MemberAccessExpressionID(expression stem, NamespaceAccessExpressionID(name qualifier, name member)), expression r);

// x.ns::[foo] = <rvalue>
Pattern assignToQualifiedRuntimeMemberExpr
Op_AssignId(MemberAccessExpressionID(expression stem, NamespaceAccessExpressionID(name qualifier, expression member)), expression r);

// x.@ns::foo = <rvalue>
Pattern assignToQualifiedAttributeExpr
Op_AssignId(MemberAccessExpressionID(expression stem, Op_AtID(NamespaceAccessExpressionID(name qualifier, name attribute))), expression r);

// x.@ns::[foo] = <rvalue>
Pattern assignToQualifiedRuntimeAttributeExpr
Op_AssignId(MemberAccessExpressionID(expression stem, Op_AtID(NamespaceAccessExpressionID(name qualifier, expression attribute))), expression r);

// x.@[foo] = <rvalue>
Pattern assignToUnqualifiedRuntimeAttributeExpr
Op_AssignId(MemberAccessExpressionID(expression stem, ArrayIndexExpressionID(Op_AtID(void), expression rt_attr_name)), expression r);

// x..@[foo] = <rvalue>
Pattern assignToUnqualifiedRuntimeDescendantsAttributeExpr
Op_AssignId(Op_DescendantsID(expression stem, ArrayIndexExpressionID(Op_AtID(void), expression rt_attr_name)), expression r);

// a[i] = <rvalue>
Pattern assignToBracketExpr
Op_AssignId(ArrayIndexExpressionID(expression stem, expression index), expression r);

//  super[x] = <rvalue>
Pattern assignToSuperBracketExpr
Op_AssignId(ArrayIndexExpressionID(SuperID(void) stem, expression index), expression r);

// x..foo = <rvalue>
Pattern assignToDescendantsExpr
Op_AssignId(Op_DescendantsID(expression stem, name member), expression r);

//  lhs += rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_AddAssignID" \
    compoundAssignToName="assignPlusToNameExpr" \
    compoundAssignToMember="assignPlusToMemberExpr" \
    compoundAssignToBracket="assignPlusToBracketExpr" \
    compoundAssignToDescendants="assignPlusToDescendantsExpr" \
    compoundAssignToRuntimeName="assignPlusToRuntimeNameExpr"

// lhs -= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_SubtractAssignID" \
    compoundAssignToName="assignMinusToNameExpr" \
    compoundAssignToMember="assignMinusToMemberExpr" \
    compoundAssignToBracket="assignMinusToBracketExpr" \
    compoundAssignToDescendants="assignMinusToDescendantsExpr" \
    compoundAssignToRuntimeName="assignMinusToRuntimeNameExpr"

//  lhs |= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_BitwiseOrAssignID" \
    compoundAssignToName="assignBitwiseOrToNameExpr" \
    compoundAssignToMember="assignBitwiseOrToMemberExpr" \
    compoundAssignToBracket="assignBitwiseOrToBracketExpr" \
    compoundAssignToDescendants="assignBitwiseOrToDescendantsExpr" \
    compoundAssignToRuntimeName="assignBitwiseOrToRuntimeNameExpr"

//  lhs &= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_BitwiseAndAssignID" \
    compoundAssignToName="assignBitwiseAndToNameExpr" \
    compoundAssignToMember="assignBitwiseAndToMemberExpr" \
    compoundAssignToBracket="assignBitwiseAndToBracketExpr" \
    compoundAssignToDescendants="assignBitwiseAndToDescendantsExpr" \
    compoundAssignToRuntimeName="assignBitwiseAndToRuntimeNameExpr"

//  lhs ^= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_BitwiseXorAssignID" \
    compoundAssignToName="assignBitwiseXorToNameExpr" \
    compoundAssignToMember="assignBitwiseXorToMemberExpr" \
    compoundAssignToBracket="assignBitwiseXorToBracketExpr" \
    compoundAssignToDescendants="assignBitwiseXorToDescendantsExpr" \
    compoundAssignToRuntimeName="assignBitwiseXorToRuntimeNameExpr"

//  lhs <<= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_LeftShiftAssignID" \
    compoundAssignToName="assignLeftShiftToNameExpr" \
    compoundAssignToMember="assignLeftShiftToMemberExpr" \
    compoundAssignToBracket="assignLeftShiftToBracketExpr" \
    compoundAssignToDescendants="assignLeftShiftToDescendantsExpr" \
    compoundAssignToRuntimeName="assignLeftShiftToRuntimeNameExpr"

//  lhs >>= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_RightShiftAssignID" \
    compoundAssignToName="assignRightShiftToNameExpr" \
    compoundAssignToMember="assignRightShiftToMemberExpr" \
    compoundAssignToBracket="assignRightShiftToBracketExpr" \
    compoundAssignToDescendants="assignRightShiftToDescendantsExpr" \
    compoundAssignToRuntimeName="assignRightShiftToRuntimeNameExpr"


//  lhs >>>= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_UnsignedRightShiftAssignID" \
    compoundAssignToName="assignUnsignedRightShiftToNameExpr" \
    compoundAssignToMember="assignUnsignedRightShiftToMemberExpr" \
    compoundAssignToBracket="assignUnsignedRightShiftToBracketExpr" \
    compoundAssignToDescendants="assignUnsignedRightShiftToDescendantsExpr" \
    compoundAssignToRuntimeName="assignUnsignedRightShiftToRuntimeNameExpr"

//  lhs *= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_MultiplyAssignID" \
    compoundAssignToName="assignMultiplyToNameExpr" \
    compoundAssignToMember="assignMultiplyToMemberExpr" \
    compoundAssignToBracket="assignMultiplyToBracketExpr" \
    compoundAssignToDescendants="assignMultiplyToDescendantsExpr" \
    compoundAssignToRuntimeName="assignMultiplyToRuntimeNameExpr"

// lhs %= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_ModuloAssignID" \
    compoundAssignToName="assignModuloToNameExpr" \
    compoundAssignToMember="assignModuloToMemberExpr" \
    compoundAssignToBracket="assignModuloToBracketExpr" \
    compoundAssignToDescendants="assignModuloToDescendantsExpr" \
    compoundAssignToRuntimeName="assignModuloToRuntimeNameExpr"

// lhs /= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_DivideAssignID" \
    compoundAssignToName="assignDivideToNameExpr" \
    compoundAssignToMember="assignDivideToMemberExpr" \
    compoundAssignToBracket="assignDivideToBracketExpr" \
    compoundAssignToDescendants="assignDivideToDescendantsExpr" \
    compoundAssignToRuntimeName="assignDivideToRuntimeNameExpr"

//  lhs ||= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_LogicalOrAssignID" \
    compoundAssignToName="assignLogicalOrToNameExpr" \
    compoundAssignToMember="assignLogicalOrToMemberExpr" \
    compoundAssignToBracket="assignLogicalOrToBracketExpr" \
    compoundAssignToDescendants="assignLogicalOrToDescendantsExpr" \
    compoundAssignToRuntimeName="assignLogicalOrToRuntimeNameExpr"

//  lhs &&= rhs
JBurg.include "CompoundAssignmentPatterns.jbg" \
    Op_COMPOUND_ASSIGN="Op_LogicalAndAssignID" \
    compoundAssignToName="assignLogicalAndToNameExpr" \
    compoundAssignToMember="assignLogicalAndToMemberExpr" \
    compoundAssignToBracket="assignLogicalAndToBracketExpr" \
    compoundAssignToDescendants="assignLogicalAndToDescendantsExpr" \
    compoundAssignToRuntimeName="assignLogicalAndToRuntimeNameExpr"


/*
 * Binary expressions: relational.
 */
Pattern equalExpr
Op_EqualID(expression l, expression r);

Pattern neqExpr
Op_NotEqualID(expression l, expression r) ;

Pattern stricteqExpr
Op_StrictEqualID(expression l, expression r);

Pattern strictneqExpr
Op_StrictNotEqualID(expression l, expression r);

Pattern greaterThanExpr
Op_GreaterThanID(expression l, expression r);

Pattern greaterThanEqExpr
Op_GreaterThanEqualsID(expression l, expression r);

Pattern lessExpr
Op_LessThanID(expression l, expression r);

Pattern lessEqExpr
Op_LessThanEqualsID(expression l, expression r);

Pattern istypeExprLate
Op_IsID(expression expr, expression typename);

Pattern astypeExprLate
Op_AsID(expression expr, expression typename);

Pattern inExpr
Op_InID(expression needle, expression haystack);

Pattern instanceofExpr
Op_InstanceOfID(expression expr, expression typename);

/*
 *  Binary expressions: multiplicative.
 */
Pattern multExpr
Op_MultiplyID(expression l, expression r);

Pattern divideExpr
Op_DivideID(expression l, expression r);

Pattern moduloExpr
Op_ModuloID(expression l, expression r);

/*
 *  Binary expressions: additive.
 */
Pattern addExpr
Op_AddID(expression l, expression r);

Pattern subtractExpr
Op_SubtractID(expression l, expression r);

/*
 *  Binary expressions: bitwise.
 */
Pattern bitwiseLeftShiftExpr
Op_LeftShiftID(expression l, expression r);

Pattern bitwiseRightShiftExpr
Op_RightShiftID(expression l, expression r);

Pattern bitwiseUnsignedRightShiftExpr
Op_UnsignedRightShift(expression l, expression r);

Pattern bitwiseAndExpr
Op_BitwiseAndID(expression l, expression r);

Pattern bitwiseOrExpr
Op_BitwiseOrID(expression l, expression r);

Pattern bitwiseXorExpr
Op_BitwiseXorID(expression l, expression r);


/*
 *  Unary expressions.
 */
Pattern unaryMinusExpr
Op_SubtractID(expression e);

Pattern unaryPlusExpr
Op_AddID(expression e);

//  typeof(foo()) or typeof(foo.bar)
Pattern typeofExpr
Op_TypeOfID(expression expr);

//  typeof(n) needs to find names that
//  refer to local registers and synthesize
//  their typeof results at compile time.
Pattern typeofName
Op_TypeOfID(name n);

Pattern bitNotExpr
Op_BitwiseNotID(expression unary);

//  Increment/decrement and variants
Pattern preIncNameExpr
Op_PreIncrID(name unary);

Pattern postIncNameExpr
Op_PostIncrID(name unary);

Pattern preIncMemberExpr
Op_PreIncrID(MemberAccessExpressionID(expression stem, name field));

Pattern postIncMemberExpr
Op_PostIncrID(MemberAccessExpressionID(expression stem, name field));

Pattern preIncBracketExpr
Op_PreIncrID(ArrayIndexExpressionID(expression stem, expression index));

Pattern postIncBracketExpr
Op_PostIncrID(ArrayIndexExpressionID(expression stem, expression index));

Pattern preDecNameExpr
Op_PreDecrID(name unary);

Pattern postDecNameExpr
Op_PostDecrID(name unary);

Pattern preDecMemberExpr
Op_PreDecrID(MemberAccessExpressionID(expression stem, name field));

Pattern postDecMemberExpr
Op_PostDecrID(MemberAccessExpressionID(expression stem, name field));

Pattern preDecBracketExpr
Op_PreDecrID(ArrayIndexExpressionID(expression stem, expression index));

Pattern postDecBracketExpr
Op_PostDecrID(ArrayIndexExpressionID(expression stem, expression index));

//  foo.bar used in a context where it may be a compile-time constant.
Pattern constantDottedName
MemberAccessExpressionID(expression stem, name member);

/*
 *  Access to member, function call
 */
// a[i]
Pattern arrayIndexExpr
ArrayIndexExpressionID(expression stem, expression index);

// super[x]
Pattern superIndexExpr
ArrayIndexExpressionID(SuperID(void) stem, expression index);


// foo.bar
Pattern memberAccessExpr
MemberAccessExpressionID(expression stem, name member);

//  qualified member reference, e.g., foo.bar::baz
Pattern qualifiedMemberAccessExpr
MemberAccessExpressionID(expression stem, NamespaceAccessExpressionID(name qualifier, name member));

//  qualified member reference with runtime name, e.g. foo.ns1::[baz]
Pattern qualifiedMemberRuntimeNameExpr
MemberAccessExpressionID(expression stem, NamespaceAccessExpressionID(name qualifier, expression runtime_member));

//  qualified attribute reference, e.g. foo@bar::baz
Pattern qualifiedAttributeExpr
MemberAccessExpressionID(expression stem, Op_AtID(NamespaceAccessExpressionID(name qualifier, name member)));

//  Runtime qualified attribute, e.g. foo@bar::[baz]
Pattern qualifiedAttributeRuntimeMemberExpr
MemberAccessExpressionID(expression stem, Op_AtID(NamespaceAccessExpressionID(name qualifier, expression runtime_member)));

//  qualified descendants reference, e.g., foo..bar::baz
Pattern qualifiedDescendantsExpr
Op_DescendantsID(expression stem, NamespaceAccessExpressionID(name qualifier, name member));

//  Runtime qualified descendants, e.g. foo..bar::[baz]
Pattern qualifiedDescendantsRuntimeExpr
Op_DescendantsID(expression stem, NamespaceAccessExpressionID(name qualifier, expression runtime_member));

//  qualified descendants/attribute reference, e.g. foo..@bar::baz
Pattern qualifiedDescendantsAttributeExpr
Op_DescendantsID(expression stem, Op_AtID(NamespaceAccessExpressionID(name qualifier, name member)));

//  Runtime qualified descendants/attribute, e.g. foo..@bar::[baz]
Pattern qualifiedDescendantsRuntimeMemberExpr
Op_DescendantsID(expression stem, Op_AtID(NamespaceAccessExpressionID(name qualifier, expression runtime_member)));

//  Unqualified runtime attribute expression, e.g., foo@[bar]
Pattern unqualifiedAttributeExpr
MemberAccessExpressionID(expression stem, ArrayIndexExpressionID(Op_AtID(void), expression expr));

//  Unqualified runtime descendants/attribute expression, e.g., foo..@[bar]
Pattern unqualifiedDescendantsAttributeExpr
Op_DescendantsID(expression stem, ArrayIndexExpressionID(Op_AtID(void), expression expr));

// runtime attribute expression, e.g., @[bar]
Pattern runtimeAttributeExp
ArrayIndexExpressionID(Op_AtID(void), expression expr);

// foo()
Pattern functionCallExpr
FunctionCallID(name method_name, ContainerID(expression args*));

// new foo()
Pattern newExpr
FunctionCallID(KeywordNewID(void), new_type_name class_binding, ContainerID(expression args*));

Pattern newVectorLiteral
FunctionCallID(KeywordNewID(void), vector_literal literal, ContainerID(void) /*vestigial*/);

// new foo.bar()
Pattern newMemberProperty
FunctionCallID(KeywordNewID(void), MemberAccessExpressionID(expression stem, name member), ContainerID(expression args*));

// new (any_expression)
Pattern newAsRandomExpr
FunctionCallID(KeywordNewID(void), expression random_expr, ContainerID(expression args*));

//  foo.bar()
Pattern functionAsMemberExpr
FunctionCallID(MemberAccessExpressionID(expression stem, name method_name), ContainerID(expression args*));

//  super.foo()
Pattern functionCallOfSuperclassMethod
FunctionCallID(MemberAccessExpressionID(SuperID(void), name method_name), ContainerID(expression args*));

//  super(x).foo()
Pattern functionCallOfExplicitObjectSuperclassMethod
FunctionCallID(MemberAccessExpressionID(FunctionCallID(SuperID(void), ContainerID(expression stem)), name method_name), ContainerID(expression args*));


// a[i]()
Pattern functionAsBracketExpr
FunctionCallID(ArrayIndexExpressionID(expression stem, expression index), ContainerID(expression args*));

// super()
Pattern superCallExpr
FunctionCallID(SuperID(void), ContainerID(expression args*));

// foo()()
Pattern functionAsRandomExpr
FunctionCallID(expression random_expr, ContainerID(expression args*));

/*
 *  Delete
 */
//  delete foo
Pattern deleteNameExpr
Op_DeleteID(name n);

Pattern deleteBracketExpr
Op_DeleteID(ArrayIndexExpressionID(expression stem, expression index));

// delete p.@[foo]
Pattern deleteAtBracketExpr
Op_DeleteID(MemberAccessExpressionID(expression stem, ArrayIndexExpressionID(Op_AtID(void), expression index)));

// delete p.foo
Pattern deleteMemberExpr
Op_DeleteID(MemberAccessExpressionID(expression stem, name field));

//  delete p.ns_var::foo
Pattern deleteRuntimeNameExpr
Op_DeleteID(MemberAccessExpressionID(expression stem, runtime_name_expression rt_name));

// delete foo..bar
Pattern deleteDescendantsExpr
Op_DeleteID(Op_DescendantsID(expression stem, name field));

// delete new Object(), delete "foo", etc.
Pattern deleteAnyExprExprExpr
Op_DeleteID(expression expr);


/*
 *  Misc
 */

Pattern nilExpr
NilID(void);

/*
 *  Expressions with control flow.
 */
Pattern logicalAndExpr
Op_LogicalAndID(expression l, expression r);

Pattern logicalOrExpr
Op_LogicalOrID(expression l, expression r);

Pattern logicalNotExpr
Op_LogicalNotID(expression expr);

Pattern ternaryExpr
TernaryExpressionID(expression test, expression when_true, expression when_false);

//  Note: the IASNodeAdapter flips the trailing expression
//  to the 0th position so that the trailing n-ary args can
//  be processed as void_expressions.
Pattern commaExpr
Op_CommaID(expression payload_expr, void_expression exprs+);

/*
 *  Names and references.
 */

//  A simple reference to a name.
Pattern simpleName
IdentifierID(void);

//  A dotted name that looked like member access to the parser.
Pattern dottedName
MemberAccessExpressionID(dottedNamePart first, dottedNamePart second);

//  A dotted name that was actually resolved as a dotted name.
Pattern fullName
FullNameID(dottedNamePart first, dottedNamePart second);

// qualified namespace expression
//   use a.b.Foo;
Pattern qualifiedNamespaceName
QualifiedNamespaceExpressionID(dottedNamePart first, dottedNamePart second);

//  A namespace-qualified name.
//  For example: ns1::aVariable
Pattern namespaceAccess
NamespaceAccessExpressionID(NamespaceIdentifierID(void) qualifier, name qualified_name);

//  A namespace-qualified expression where the namespace
//  is known, but the name is a runtime expression.
//  For example: trace(ns1::[foo])
Pattern namespaceMultinameL
NamespaceAccessExpressionID(NamespaceIdentifierID(void) qualifier, expression expr);

//  A namespace-qualified expression where the name is known
//  at compile time, but the namespace is an expression.
//  For example: var rt_ns = getANamespace(); trace(rt_ns::aVariable)
Pattern namespaceRTQName
NamespaceAccessExpressionID(expression qualifier, name qualfied_name);

//  A namespace-qualified expression where the name
//  and the namespace are both runtime expressions.
//  For example: var rt_ns = getANamespace(); trace(rt_ns::[foo])
Pattern namespaceRTQNameL
NamespaceAccessExpressionID(expression qualifier, expression expr);

//  A namespace standing on its own as a name, or as a compile-time
//  qualifier to a MultinameL.
Pattern namespaceAsName
NamespaceIdentifierID(void);

//  An expression packed inside a "it's an expression" node.
Pattern runtimeNameExpression
RuntimeNameExpressionID(expression expr);

//  super-qualified name.
Pattern superAccess
MemberAccessExpressionID(SuperID(void), name qualified_name);

//  super(this).foo
//  This pattern is feasible only when IdentifierID(void) is "this" keyword. 
//  The cost function "isSuperThisForFieldAccess" validates the condition.
Pattern superThisAccess
MemberAccessExpressionID(FunctionCallID(SuperID(void), ContainerID(IdentifierID(void))), name qualified_name);

// Parameterized name in a context where
// the name alone is needed.
// For example: Vector.<String>, Vector.<*>, __AS3__.vec.Vector.<T>
Pattern parameterizedName
TypedExpressionID(name base, type_name param);

//  Parameterized name as a general expression
//  For example, getVector().<int>, Vector.<*>.foo
Pattern parameterizedTypeExpression
TypedExpressionID(expression base, type_param_expression param);

// attribute name
// For example: @foo
Pattern attributeName
Op_AtID(name attr_name);

// An EmbedNode which is constructed by the compiler when 
// it comes across embed meta data and is used as an
// initial expression for an embed variable
Pattern embedExpression
EmbedID(void);

/*
 *  Literals.
 */

Pattern nullLiteral
LiteralNullID(void);

Pattern stringLiteral
LiteralStringID(void);

Pattern numericLiteral
LiteralNumberID(void);

Pattern integerLiteral
LiteralIntegerID(void);

Pattern uintLiteral
LiteralUintID(void);

Pattern doubleLiteral
LiteralDoubleID(void);

Pattern objectLiteral
ObjectLiteralExpressionID(ContainerID(object_literal_element elements*));

Pattern objectLiteralElement
ObjectLiteralValuePairID(expression id, expression value);

Pattern nonResolvingIdentifier
NonResolvingIdentifierID(void);

Pattern booleanLiteral
LiteralBooleanID(void);

Pattern arrayLiteral
ArrayLiteralID(ContainerID(expression elements*));

Pattern vectorLiteral
VectorLiteralID(type_name type_param, ContainerID(expression elements*));

Pattern regexLiteral
LiteralRegexID(void);

//	This patern is used to match '<code>new Array()' and 'new Object()'
//  so that they are efficiently codegen'd using 'newarray' and 'newobject' opcodes.
Pattern emptyConstructor
FunctionCallID(KeywordNewID(void), IdentifierID(void), ContainerID(void));

/*
 *  E4X constructs.
 */

//  Expression-level packaging of an XML literal, e.g. <foo x="moo">bar</foo>
Pattern XMLContent
XMLContentID(ContainerID(expression exprs+));

//  XMLList literal, e.g. <><foo>bar</foo><foo>{myVar}</foo></>
Pattern XMLList
XMLListContentID(ContainerID(expression exprs*));

//  XMLList literal with all constant elements, e.g. <><foo>bar</foo><foo>baz</foo></>
Pattern XMLListConst
XMLListContentID(ContainerID(e4x_literal elements*));

//  XML literal token, e.g., <foo><bar>12</bar></foo>.
Pattern XMLLiteral
LiteralXMLID(void);

//  Filter expression, e.g. e.employee(id == 1234) 
Pattern e4xFilter
E4XFilterID(expression stem, expression filter);

//  default xml namespace
Pattern defaultXMLNamespace
DefaultXMLStatementID(expression ns_expr);

//  descendants operator
Pattern descendantsExpression
Op_DescendantsID(expression stem, name descendants);


//  TODO: On resolution of CMP-208 and CMP-209,
//  these two patterns should merge into one.

//  "void 0" idiom.
Pattern void0Literal
LiteralObjectID(void);

//  void(0)
Pattern void0Operator
Op_VoidID(void);

// void(expr)
Pattern voidOperator
Op_VoidID(expression expr);

// void("some constant")
Pattern voidConstant
Op_VoidID(constant_value value);

// void;
Pattern voidExpr
VoidID(void);

//  Special forms of void expressions.
Pattern groupedVoidExpression
ContainerID(void_expression contents+);

/*
 *  MXML constructs
 */

// An MXMLEventSpecifierNode corresponds to an MXML event attribute or event child tag.
// For example, MXML such as
//   <Button click="doThis(); doThat()"/>
// or
//   <Button>
//       <click>doThis(); doThat;</click>
//   <Button>
// creates an AST like
//   MXMLInstanceNode
//     MXMLEventSpecifierNode
//       FunctionCallNode
//         IdentifierNode=doThis
//         ContainerNode
//       FunctionCallNode
//         IdentifierNode=doTaht
//         ContainerNode

Pattern mxmlEventSpecifier
MXMLEventSpecifierID(statement stmts*);

/*
 *  Special Instruction List node - allows arbitrary instructions to be inserted
 *  where an expression is expected.  Used by some MXML processing that wants to
 *  generate code without having to create a synthetic AST to pass to the burm.
 */
Pattern instructionListExpression
InstructionListID(void);
