Example #1
0
// buildBooleanBinaryExpression builds the CodeDOM for a boolean unary operator.
func (db *domBuilder) buildBooleanBinaryExpression(node compilergraph.GraphNode, op string) codedom.Expression {
	boolType := db.scopegraph.TypeGraph().BoolTypeReference()
	leftExpr := codedom.NominalUnwrapping(db.getExpression(node, parser.NodeBinaryExpressionLeftExpr), boolType, node)
	rightExpr := codedom.NominalUnwrapping(db.getExpression(node, parser.NodeBinaryExpressionRightExpr), boolType, node)
	return codedom.NominalWrapping(
		codedom.BinaryOperation(leftExpr, op, rightExpr, node),
		db.scopegraph.TypeGraph().BoolType(),
		node)
}
Example #2
0
// buildIsComparisonExpression builds the CodeDOM for an is comparison operator.
func (db *domBuilder) buildIsComparisonExpression(node compilergraph.GraphNode) codedom.Expression {
	generatedLeftExpr := db.getExpression(node, parser.NodeBinaryExpressionLeftExpr)

	// Check for a `not` subexpression. If found, we invert the check.
	op := "=="
	rightExpr := node.GetNode(parser.NodeBinaryExpressionRightExpr)
	if rightExpr.Kind() == parser.NodeKeywordNotExpression {
		op = "!="
		rightExpr = rightExpr.GetNode(parser.NodeUnaryExpressionChildExpr)
	}

	generatedRightExpr := db.buildExpression(rightExpr)
	return codedom.NominalWrapping(
		codedom.BinaryOperation(generatedLeftExpr, op, generatedRightExpr, node),
		db.scopegraph.TypeGraph().BoolType(),
		node)
}
Example #3
0
// 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
	}
}
Example #4
0
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
}
Example #5
0
// buildNativeBinaryExpression builds the CodeDOM for a native unary operator.
func (db *domBuilder) buildNativeBinaryExpression(node compilergraph.GraphNode, op string) codedom.Expression {
	leftExpr := db.getExpression(node, parser.NodeBinaryExpressionLeftExpr)
	rightExpr := db.getExpression(node, parser.NodeBinaryExpressionRightExpr)
	return codedom.BinaryOperation(leftExpr, op, rightExpr, node)
}
Example #6
0
// buildNullComparisonExpression builds the CodeDOM for a null comparison (??) operator.
func (db *domBuilder) buildNullComparisonExpression(node compilergraph.GraphNode) codedom.Expression {
	leftExpr := db.getExpression(node, parser.NodeBinaryExpressionLeftExpr)
	rightExpr := db.getExpression(node, parser.NodeBinaryExpressionRightExpr)
	return codedom.BinaryOperation(leftExpr, "??", rightExpr, node)
}