// buildBinaryOperatorExpression builds the CodeDOM for a binary operator. func (db *domBuilder) buildBinaryOperatorExpression(node compilergraph.GraphNode, modifier exprModifier) codedom.Expression { scope, _ := db.scopegraph.GetScope(node) operator, _ := scope.CalledOperator(db.scopegraph.TypeGraph()) if operator.IsNative() { return db.buildNativeBinaryExpression(node, operatorMap[node.Kind()]) } leftExpr := db.getExpression(node, parser.NodeBinaryExpressionLeftExpr) rightExpr := db.getExpression(node, parser.NodeBinaryExpressionRightExpr) leftScope, _ := db.scopegraph.GetScope(node.GetNode(parser.NodeBinaryExpressionLeftExpr)) parentType := leftScope.ResolvedTypeRef(db.scopegraph.TypeGraph()) optimized, wasOptimized := db.buildOptimizedBinaryOperatorExpression(node, parentType, leftExpr, rightExpr) if wasOptimized { return optimized } callExpr := codedom.MemberCall(codedom.StaticMemberReference(operator, parentType, node), operator, []codedom.Expression{leftExpr, rightExpr}, node) if modifier != nil { return modifier(callExpr) } return callExpr }
// AsImplementable returns the given node as an SRGImplementable (if applicable). func (g *SRG) AsImplementable(node compilergraph.GraphNode) (SRGImplementable, bool) { switch node.Kind() { case parser.NodeTypeConstructor: fallthrough case parser.NodeTypeFunction: fallthrough case parser.NodeTypeProperty: fallthrough case parser.NodeTypeOperator: fallthrough case parser.NodeTypeField: fallthrough case parser.NodeTypeVariable: fallthrough case parser.NodeTypePropertyBlock: return SRGImplementable{node, g}, true default: return SRGImplementable{}, false } }
// buildUnaryOperatorExpression builds the CodeDOM for a unary operator. func (db *domBuilder) buildUnaryOperatorExpression(node compilergraph.GraphNode, modifier exprModifier) codedom.Expression { scope, _ := db.scopegraph.GetScope(node) operator, _ := scope.CalledOperator(db.scopegraph.TypeGraph()) if operator.IsNative() { return db.buildNativeUnaryExpression(node, operatorMap[node.Kind()]) } childScope, _ := db.scopegraph.GetScope(node.GetNode(parser.NodeUnaryExpressionChildExpr)) parentType := childScope.ResolvedTypeRef(db.scopegraph.TypeGraph()) childExpr := db.getExpression(node, parser.NodeUnaryExpressionChildExpr) callExpr := codedom.MemberCall(codedom.StaticMemberReference(operator, parentType, node), operator, []codedom.Expression{childExpr}, node) if modifier != nil { return modifier(callExpr) } return callExpr }
// buildNamedAccess builds the CodeDOM for a member access expression. func (db *domBuilder) buildNamedAccess(node compilergraph.GraphNode, name string, childExprNode *compilergraph.GraphNode) codedom.Expression { scope, _ := db.scopegraph.GetScope(node) namedReference, hasNamedReference := db.scopegraph.GetReferencedName(scope) // Reference to an unknown name or a nullable member access must be a dynamic access. if !hasNamedReference || node.Kind() == parser.NodeNullableMemberAccessExpression { return codedom.DynamicAccess(db.buildExpression(*childExprNode), name, node) } // Reference to a local name is a var or parameter. if namedReference.IsLocal() { return codedom.LocalReference(namedReference.Name(), node) } // Check for a reference to a type. if typeRef, isType := namedReference.Type(); isType { return codedom.StaticTypeReference(typeRef, node) } // Check for a reference to a member. if memberRef, isMember := namedReference.Member(); isMember { // If the member is under a child expression, build as an access expression. if childExprNode != nil { childExpr := db.buildExpression(*childExprNode) _, underFuncCall := node.TryGetIncomingNode(parser.NodeFunctionCallExpressionChildExpr) isAliasedFunctionReference := scope.ResolvedTypeRef(db.scopegraph.TypeGraph()).HasReferredType(db.scopegraph.TypeGraph().FunctionType()) if isAliasedFunctionReference && !underFuncCall { return codedom.DynamicAccess(childExpr, memberRef.Name(), node) } else { return codedom.MemberReference(childExpr, memberRef, node) } } else { // This is a direct access of a static member. Generate an access under the module. return codedom.StaticMemberReference(memberRef, db.scopegraph.TypeGraph().AnyTypeReference(), node) } } panic("Unknown kind of named access") return nil }
// buildStatements builds the CodeDOM for the given SRG node and returns it as start and end statements. func (db *domBuilder) buildStatements(node compilergraph.GraphNode) (codedom.Statement, codedom.Statement) { switch node.Kind() { case parser.NodeTypeStatementBlock: return db.buildStatementBlock(node) case parser.NodeTypeReturnStatement: stm := db.buildReturnStatement(node) return stm, stm case parser.NodeTypeRejectStatement: stm := db.buildRejectStatement(node) return stm, stm case parser.NodeTypeYieldStatement: stm := db.buildYieldStatement(node) return stm, stm case parser.NodeTypeConditionalStatement: return db.buildConditionalStatement(node) case parser.NodeTypeLoopStatement: return db.buildLoopStatement(node) case parser.NodeTypeExpressionStatement: stm := db.buildExpressionStatement(node) return stm, stm case parser.NodeTypeContinueStatement: stm := db.buildContinueStatement(node) return stm, stm case parser.NodeTypeBreakStatement: stm := db.buildBreakStatement(node) return stm, stm case parser.NodeTypeAssignStatement: stm := db.buildAssignStatement(node) return stm, stm case parser.NodeTypeVariableStatement: stm := db.buildVarStatement(node) return stm, stm case parser.NodeTypeWithStatement: stm := db.buildWithStatement(node) return stm, stm case parser.NodeTypeSwitchStatement: return db.buildSwitchStatement(node) case parser.NodeTypeMatchStatement: return db.buildMatchStatement(node) case parser.NodeTypeArrowStatement: return db.buildArrowStatement(node) case parser.NodeTypeResolveStatement: return db.buildResolveStatement(node) default: panic(fmt.Sprintf("Unknown SRG statement node: %s", node.Kind())) return nil, nil } }
// buildExpression builds the CodeDOM for the given SRG node and returns it as an expression. Will // panic if the returned DOM type is not an expression. func (db *domBuilder) buildExpression(node compilergraph.GraphNode) codedom.Expression { switch node.Kind() { // Access Expressions. case parser.NodeMemberAccessExpression: fallthrough case parser.NodeNullableMemberAccessExpression: fallthrough case parser.NodeDynamicMemberAccessExpression: return db.buildMemberAccessExpression(node) case parser.NodeTypeIdentifierExpression: return db.buildIdentifierExpression(node) case parser.NodeGenericSpecifierExpression: return db.buildGenericSpecifierExpression(node) case parser.NodeCastExpression: return db.buildCastExpression(node) case parser.NodeStreamMemberAccessExpression: return db.buildStreamMemberAccessExpression(node) // Await Expression. case parser.NodeTypeAwaitExpression: return db.buildAwaitExpression(node) // Lambda Expressions. case parser.NodeTypeLambdaExpression: return db.buildLambdaExpression(node) // SML Expressions. case parser.NodeTypeSmlExpression: return db.buildSmlExpression(node) case parser.NodeTypeSmlText: return db.buildSmlText(node) // Flow Expressions. case parser.NodeTypeConditionalExpression: return db.buildConditionalExpression(node) case parser.NodeTypeLoopExpression: return db.buildLoopExpression(node) // Op Expressions. case parser.NodeRootTypeExpression: return db.buildRootTypeExpression(node) case parser.NodeFunctionCallExpression: return db.buildFunctionCall(node) case parser.NodeSliceExpression: return db.buildSliceExpression(node) case parser.NodeNullComparisonExpression: return db.buildNullComparisonExpression(node) case parser.NodeAssertNotNullExpression: return db.buildAssertNotNullExpression(node) case parser.NodeIsComparisonExpression: return db.buildIsComparisonExpression(node) case parser.NodeInCollectionExpression: return db.buildInCollectionExpression(node) case parser.NodeBitwiseNotExpression: return db.buildUnaryOperatorExpression(node, nil) case parser.NodeKeywordNotExpression: return db.buildUnaryOperatorExpression(node, func(expr codedom.Expression) codedom.Expression { boolType := db.scopegraph.TypeGraph().BoolTypeReference() childExpr := codedom.UnaryOperation("!", codedom.NominalUnwrapping(expr, boolType, node), node) return codedom.NominalWrapping( childExpr, db.scopegraph.TypeGraph().BoolType(), node) }) case parser.NodeDefineRangeExpression: fallthrough case parser.NodeBitwiseXorExpression: fallthrough case parser.NodeBitwiseOrExpression: fallthrough case parser.NodeBitwiseAndExpression: fallthrough case parser.NodeBitwiseShiftLeftExpression: fallthrough case parser.NodeBitwiseShiftRightExpression: fallthrough case parser.NodeBinaryAddExpression: fallthrough case parser.NodeBinarySubtractExpression: fallthrough case parser.NodeBinaryMultiplyExpression: fallthrough case parser.NodeBinaryDivideExpression: fallthrough case parser.NodeBinaryModuloExpression: return db.buildBinaryOperatorExpression(node, nil) case parser.NodeComparisonEqualsExpression: return db.buildBinaryOperatorExpression(node, nil) case parser.NodeComparisonNotEqualsExpression: return db.buildBinaryOperatorExpression(node, func(expr codedom.Expression) codedom.Expression { boolType := db.scopegraph.TypeGraph().BoolTypeReference() childExpr := codedom.UnaryOperation("!", codedom.NominalUnwrapping(expr, boolType, node), node) return codedom.NominalRefWrapping( childExpr, boolType.NominalDataType(), boolType, node) }) case parser.NodeComparisonLTEExpression: return db.buildBinaryOperatorExpression(node, func(expr codedom.Expression) codedom.Expression { intType := db.scopegraph.TypeGraph().IntTypeReference() boolType := db.scopegraph.TypeGraph().BoolTypeReference() childExpr := codedom.BinaryOperation(codedom.NominalUnwrapping(expr, intType, node), "<=", codedom.LiteralValue("0", node), node) return codedom.NominalRefWrapping( childExpr, boolType.NominalDataType(), boolType, node) }) case parser.NodeComparisonLTExpression: return db.buildBinaryOperatorExpression(node, func(expr codedom.Expression) codedom.Expression { intType := db.scopegraph.TypeGraph().IntTypeReference() boolType := db.scopegraph.TypeGraph().BoolTypeReference() childExpr := codedom.BinaryOperation(codedom.NominalUnwrapping(expr, intType, node), "<", codedom.LiteralValue("0", node), node) return codedom.NominalRefWrapping( childExpr, boolType.NominalDataType(), boolType, node) }) case parser.NodeComparisonGTEExpression: return db.buildBinaryOperatorExpression(node, func(expr codedom.Expression) codedom.Expression { intType := db.scopegraph.TypeGraph().IntTypeReference() boolType := db.scopegraph.TypeGraph().BoolTypeReference() childExpr := codedom.BinaryOperation(codedom.NominalUnwrapping(expr, intType, node), ">=", codedom.LiteralValue("0", node), node) return codedom.NominalRefWrapping( childExpr, boolType.NominalDataType(), boolType, node) }) case parser.NodeComparisonGTExpression: return db.buildBinaryOperatorExpression(node, func(expr codedom.Expression) codedom.Expression { intType := db.scopegraph.TypeGraph().IntTypeReference() boolType := db.scopegraph.TypeGraph().BoolTypeReference() childExpr := codedom.BinaryOperation(codedom.NominalUnwrapping(expr, intType, node), ">", codedom.LiteralValue("0", node), node) return codedom.NominalRefWrapping( childExpr, boolType.NominalDataType(), boolType, node) }) // Boolean operators. case parser.NodeBooleanAndExpression: return db.buildBooleanBinaryExpression(node, "&&") case parser.NodeBooleanOrExpression: return db.buildBooleanBinaryExpression(node, "||") case parser.NodeBooleanNotExpression: return db.buildBooleanUnaryExpression(node, "!") // Literals. case parser.NodeStructuralNewExpression: return db.buildStructuralNewExpression(node) case parser.NodeNumericLiteralExpression: return db.buildNumericLiteral(node) case parser.NodeBooleanLiteralExpression: return db.buildBooleanLiteral(node) case parser.NodeStringLiteralExpression: return db.buildStringLiteral(node) case parser.NodeNullLiteralExpression: return db.buildNullLiteral(node) case parser.NodeThisLiteralExpression: return db.buildThisLiteral(node) case parser.NodeValLiteralExpression: return db.buildValLiteral(node) case parser.NodeListExpression: return db.buildListExpression(node) case parser.NodeSliceLiteralExpression: return db.buildSliceLiteralExpression(node) case parser.NodeMappingLiteralExpression: return db.buildMappingLiteralExpression(node) case parser.NodeMapExpression: return db.buildMapExpression(node) case parser.NodeTypeTemplateString: return db.buildTemplateStringExpression(node) case parser.NodeTaggedTemplateLiteralString: return db.buildTaggedTemplateString(node) default: panic(fmt.Sprintf("Unknown SRG expression node: %s", node.Kind())) return nil } }
// findAddedNameInScope finds the {parameter, with, loop, var} node exposing the given name, if any. func (g *SRG) findAddedNameInScope(name string, node compilergraph.GraphNode) (compilergraph.GraphNode, bool) { nodeSource := node.Get(parser.NodePredicateSource) nodeStartIndex := node.GetValue(parser.NodePredicateStartRune).Int() // Note: This filter ensures that the name is accessible in the scope of the given node by checking that // the node adding the name contains the given node. containingFilter := func(q compilergraph.GraphQuery) compilergraph.Query { startRune := node.GetValue(parser.NodePredicateStartRune).Int() endRune := node.GetValue(parser.NodePredicateEndRune).Int() return q. In(parser.NodePredicateTypeMemberParameter, parser.NodeLambdaExpressionInferredParameter, parser.NodeLambdaExpressionParameter, parser.NodePredicateTypeMemberGeneric, parser.NodeStatementNamedValue, parser.NodeAssignedDestination, parser.NodeAssignedRejection, parser.NodePredicateChild, parser.NodeStatementBlockStatement). InIfKind(parser.NodeStatementBlockStatement, parser.NodeTypeResolveStatement). HasWhere(parser.NodePredicateStartRune, compilergraph.WhereLTE, startRune). HasWhere(parser.NodePredicateEndRune, compilergraph.WhereGTE, endRune) } nit := g.layer.StartQuery(name). In("named"). Has(parser.NodePredicateSource, nodeSource). IsKind(parser.NodeTypeParameter, parser.NodeTypeNamedValue, parser.NodeTypeAssignedValue, parser.NodeTypeVariableStatement, parser.NodeTypeLambdaParameter, parser.NodeTypeGeneric). FilterBy(containingFilter). BuildNodeIterator(parser.NodePredicateStartRune, parser.NodePredicateEndRune) // Sort the nodes found by location and choose the closest node. var results = make(scopeResultNodes, 0) for nit.Next() { node := nit.Node() startIndex := nit.GetPredicate(parser.NodePredicateStartRune).Int() // If the node is a variable statement or assigned value, we have do to additional checks // (since they are not block scoped but rather statement scoped). if node.Kind() == parser.NodeTypeVariableStatement || node.Kind() == parser.NodeTypeAssignedValue { endIndex := nit.GetPredicate(parser.NodePredicateEndRune).Int() if node.Kind() == parser.NodeTypeAssignedValue { if parentNode, ok := node.TryGetIncomingNode(parser.NodeAssignedDestination); ok { endIndex = parentNode.GetValue(parser.NodePredicateEndRune).Int() } else if parentNode, ok := node.TryGetIncomingNode(parser.NodeAssignedRejection); ok { endIndex = parentNode.GetValue(parser.NodePredicateEndRune).Int() } else { panic("Missing assigned parent") } } // Check that the startIndex of the variable statement is <= the startIndex of the parent node if startIndex > nodeStartIndex { continue } // Ensure that the scope starts after the end index of the variable. Otherwise, the variable // name could be used in its initializer expression (which is expressly disallowed). if nodeStartIndex <= endIndex { continue } } results = append(results, scopeResultNode{node, startIndex}) } if len(results) == 1 { // If there is a single result, return it. return results[0].node, true } else if len(results) > 1 { // Otherwise, sort the list by startIndex and choose the one closest to the scope node. sort.Sort(results) return results[0].node, true } return compilergraph.GraphNode{}, false }
func (db *domBuilder) buildOptimizedBinaryOperatorExpression(node compilergraph.GraphNode, parentType typegraph.TypeReference, leftExpr codedom.Expression, rightExpr codedom.Expression) (codedom.Expression, bool) { // Verify this is a supported native operator. opString, hasOp := operatorMap[node.Kind()] if !hasOp { return nil, false } // Verify we have a native binary operator we can optimize. if !parentType.IsNominal() { return nil, false } isNumeric := false switch { case parentType.IsDirectReferenceTo(db.scopegraph.TypeGraph().IntType()): isNumeric = true case parentType.IsDirectReferenceTo(db.scopegraph.TypeGraph().BoolType()): fallthrough case parentType.IsDirectReferenceTo(db.scopegraph.TypeGraph().StringType()): fallthrough default: return nil, false } // Handle the various kinds of operators. switch node.Kind() { case parser.NodeComparisonEqualsExpression: fallthrough case parser.NodeComparisonNotEqualsExpression: // Always allowed. break case parser.NodeComparisonLTEExpression: fallthrough case parser.NodeComparisonLTExpression: fallthrough case parser.NodeComparisonGTEExpression: fallthrough case parser.NodeComparisonGTExpression: // Only allowed for number. if !isNumeric { return nil, false } } boolType := db.scopegraph.TypeGraph().BoolTypeReference() unwrappedLeftExpr := codedom.NominalUnwrapping(leftExpr, parentType, node) unwrappedRightExpr := codedom.NominalUnwrapping(rightExpr, parentType, node) compareExpr := codedom.BinaryOperation(unwrappedLeftExpr, opString, unwrappedRightExpr, node) return codedom.NominalRefWrapping(compareExpr, boolType.NominalDataType(), boolType, node), true }
// inferTypesForConditionalExpressionContext returns a modified context for the then or else branches of // a conditional statement that contains a type override of a named identifer if the comparison has clarified // its type. For example a conditional expression of `a is null` will make the type of `a` be null under // the then branch while being non-null under the `else` branch. func (sb *scopeBuilder) inferTypesForConditionalExpressionContext(baseContext scopeContext, conditionalExprNode compilergraph.GraphNode, option inferrenceOption) scopeContext { // Make sure the conditional expression is valid. conditionalExprScope := sb.getScope(conditionalExprNode, baseContext) if !conditionalExprScope.GetIsValid() { return baseContext } checkIsExpression := func(isExpressionNode compilergraph.GraphNode, setToNull bool) scopeContext { // Invert the null-set if requested. if option == inferredInverted { setToNull = !setToNull } // Ensure the left expression of the `is` has valid scope. leftScope := sb.getScope(isExpressionNode.GetNode(parser.NodeBinaryExpressionLeftExpr), baseContext) if !leftScope.GetIsValid() { return baseContext } // Ensure that the left expression refers to a named scope. leftNamed, isNamed := sb.getNamedScopeForScope(leftScope) if !isNamed { return baseContext } // Ensure that the left expression does not have a void type. We know it is valid // due to the check above. valueType, _ := leftNamed.ValueType(baseContext) if valueType.IsVoid() { return baseContext } // Lookup the right expression. If it is itself a `not`, then we invert the set to null. rightExpr := isExpressionNode.GetNode(parser.NodeBinaryExpressionRightExpr) if rightExpr.Kind() == parser.NodeKeywordNotExpression { setToNull = !setToNull } // Add an override for the named node. leftNamedNode, _ := leftScope.NamedReferenceNode(sb.sg.srg, sb.sg.tdg) if setToNull { return baseContext.withTypeOverride(leftNamedNode, sb.sg.tdg.NullTypeReference()) } else { return baseContext.withTypeOverride(leftNamedNode, leftScope.ResolvedTypeRef(sb.sg.tdg).AsNonNullable()) } } // TODO: If we add more comparisons or forms here, change this into a more formal comparison // system rather than hand-written checks. exprKind := conditionalExprNode.Kind() switch exprKind { case parser.NodeIsComparisonExpression: // Check the `is` expression itself to see if we can add the inferred type. return checkIsExpression(conditionalExprNode, true) case parser.NodeBooleanNotExpression: // If the ! is in front of an `is` expression, then invert it. childExpr := conditionalExprNode.GetNode(parser.NodeUnaryExpressionChildExpr) if childExpr.Kind() == parser.NodeIsComparisonExpression { return checkIsExpression(childExpr, false) } } return baseContext }
// getScopeHandler returns the scope building handler for nodes of the given type. func (sb *scopeBuilder) getScopeHandler(node compilergraph.GraphNode) scopeHandler { switch node.Kind() { // Members. case parser.NodeTypeProperty: fallthrough case parser.NodeTypePropertyBlock: fallthrough case parser.NodeTypeFunction: fallthrough case parser.NodeTypeConstructor: fallthrough case parser.NodeTypeOperator: return sb.scopeImplementedMember case parser.NodeTypeVariable: return sb.scopeVariable case parser.NodeTypeField: return sb.scopeField // Statements. case parser.NodeTypeStatementBlock: return sb.scopeStatementBlock case parser.NodeTypeBreakStatement: return sb.scopeBreakStatement case parser.NodeTypeContinueStatement: return sb.scopeContinueStatement case parser.NodeTypeYieldStatement: return sb.scopeYieldStatement case parser.NodeTypeReturnStatement: return sb.scopeReturnStatement case parser.NodeTypeRejectStatement: return sb.scopeRejectStatement case parser.NodeTypeConditionalStatement: return sb.scopeConditionalStatement case parser.NodeTypeLoopStatement: return sb.scopeLoopStatement case parser.NodeTypeWithStatement: return sb.scopeWithStatement case parser.NodeTypeVariableStatement: return sb.scopeVariableStatement case parser.NodeTypeSwitchStatement: return sb.scopeSwitchStatement case parser.NodeTypeMatchStatement: return sb.scopeMatchStatement case parser.NodeTypeAssignStatement: return sb.scopeAssignStatement case parser.NodeTypeExpressionStatement: return sb.scopeExpressionStatement case parser.NodeTypeNamedValue: return sb.scopeNamedValue case parser.NodeTypeAssignedValue: return sb.scopeAssignedValue case parser.NodeTypeArrowStatement: return sb.scopeArrowStatement case parser.NodeTypeResolveStatement: return sb.scopeResolveStatement // Await expression. case parser.NodeTypeAwaitExpression: return sb.scopeAwaitExpression // SML expression. case parser.NodeTypeSmlExpression: return sb.scopeSmlExpression case parser.NodeTypeSmlText: return sb.scopeSmlText // Flow expressions. case parser.NodeTypeConditionalExpression: return sb.scopeConditionalExpression case parser.NodeTypeLoopExpression: return sb.scopeLoopExpression // Access expressions. case parser.NodeCastExpression: return sb.scopeCastExpression case parser.NodeMemberAccessExpression: return sb.scopeMemberAccessExpression case parser.NodeNullableMemberAccessExpression: return sb.scopeNullableMemberAccessExpression case parser.NodeDynamicMemberAccessExpression: return sb.scopeDynamicMemberAccessExpression case parser.NodeStreamMemberAccessExpression: return sb.scopeStreamMemberAccessExpression // Operator expressions. case parser.NodeDefineRangeExpression: return sb.scopeDefineRangeExpression case parser.NodeSliceExpression: return sb.scopeSliceExpression case parser.NodeBitwiseXorExpression: return sb.scopeBitwiseXorExpression case parser.NodeBitwiseOrExpression: return sb.scopeBitwiseOrExpression case parser.NodeBitwiseAndExpression: return sb.scopeBitwiseAndExpression case parser.NodeBitwiseShiftLeftExpression: return sb.scopeBitwiseShiftLeftExpression case parser.NodeBitwiseShiftRightExpression: return sb.scopeBitwiseShiftRightExpression case parser.NodeBitwiseNotExpression: return sb.scopeBitwiseNotExpression case parser.NodeBinaryAddExpression: return sb.scopeBinaryAddExpression case parser.NodeBinarySubtractExpression: return sb.scopeBinarySubtractExpression case parser.NodeBinaryMultiplyExpression: return sb.scopeBinaryMultiplyExpression case parser.NodeBinaryDivideExpression: return sb.scopeBinaryDivideExpression case parser.NodeBinaryModuloExpression: return sb.scopeBinaryModuloExpression case parser.NodeBooleanAndExpression: return sb.scopeBooleanBinaryExpression case parser.NodeBooleanOrExpression: return sb.scopeBooleanBinaryExpression case parser.NodeBooleanNotExpression: return sb.scopeBooleanUnaryExpression case parser.NodeKeywordNotExpression: return sb.scopeKeywordNotExpression case parser.NodeComparisonEqualsExpression: return sb.scopeEqualsExpression case parser.NodeComparisonNotEqualsExpression: return sb.scopeEqualsExpression case parser.NodeComparisonLTEExpression: return sb.scopeComparisonExpression case parser.NodeComparisonLTExpression: return sb.scopeComparisonExpression case parser.NodeComparisonGTEExpression: return sb.scopeComparisonExpression case parser.NodeComparisonGTExpression: return sb.scopeComparisonExpression case parser.NodeNullComparisonExpression: return sb.scopeNullComparisonExpression case parser.NodeAssertNotNullExpression: return sb.scopeAssertNotNullExpression case parser.NodeIsComparisonExpression: return sb.scopeIsComparisonExpression case parser.NodeInCollectionExpression: return sb.scopeInCollectionExpression case parser.NodeFunctionCallExpression: return sb.scopeFunctionCallExpression case parser.NodeGenericSpecifierExpression: return sb.scopeGenericSpecifierExpression case parser.NodeRootTypeExpression: return sb.scopeRootTypeExpression // Literal expressions. case parser.NodeBooleanLiteralExpression: return sb.scopeBooleanLiteralExpression case parser.NodeNumericLiteralExpression: return sb.scopeNumericLiteralExpression case parser.NodeStringLiteralExpression: return sb.scopeStringLiteralExpression case parser.NodeListExpression: return sb.scopeListLiteralExpression case parser.NodeSliceLiteralExpression: return sb.scopeSliceLiteralExpression case parser.NodeMappingLiteralExpression: return sb.scopeMappingLiteralExpression case parser.NodeMapExpression: return sb.scopeMapLiteralExpression case parser.NodeNullLiteralExpression: return sb.scopeNullLiteralExpression case parser.NodeThisLiteralExpression: return sb.scopeThisLiteralExpression case parser.NodeTypeLambdaExpression: return sb.scopeLambdaExpression case parser.NodeValLiteralExpression: return sb.scopeValLiteralExpression case parser.NodeStructuralNewExpression: return sb.scopeStructuralNewExpression case parser.NodeStructuralNewExpressionEntry: return sb.scopeStructuralNewExpressionEntry // Template string. case parser.NodeTaggedTemplateLiteralString: return sb.scopeTaggedTemplateString case parser.NodeTypeTemplateString: return sb.scopeTemplateStringExpression // Named expressions. case parser.NodeTypeIdentifierExpression: return sb.scopeIdentifierExpression default: panic(fmt.Sprintf("Unknown SRG node in scoping: %v", node.Kind())) } }