コード例 #1
0
ファイル: build_op_expr.go プロジェクト: Serulian/compiler
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
}