Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990package core
import ( "git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/expression" "git.urbach.dev/cli/q/src/optimizer" "git.urbach.dev/cli/q/src/ssa" "git.urbach.dev/cli/q/src/token" "git.urbach.dev/cli/q/src/types")
// evaluateBinary converts a binary expression to an SSA value.func (f *Function) evaluateBinary(expr *expression.Expression) (ssa.Value, error) { left := expr.Children[0] right := expr.Children[1] swapped := false
if expr.Token.Kind.IsCommutative() { leftComplexity := optimizer.Complexity(left) rightComplexity := optimizer.Complexity(right)
if rightComplexity > leftComplexity { left, right = right, left swapped = true } }
leftValue, err := f.evaluateRight(left)
if err != nil { return nil, err }
rightValue, err := f.evaluateRight(right)
if err != nil { return nil, err }
leftType := leftValue.Type() rightType := rightValue.Type() leftStructType, leftIsStruct := types.Unwrap(leftType).(*types.Struct) rightStructType, rightIsStruct := types.Unwrap(rightType).(*types.Struct)
if leftIsStruct && rightIsStruct && leftStructType == types.String && rightStructType == types.String { switch expr.Token.Kind { case token.Add: return f.evaluateStringOp("concat", leftValue, rightValue, expr.Source()) case token.Equal: return f.evaluateStringOp("equal", leftValue, rightValue, expr.Source()) case token.NotEqual: equal, err := f.evaluateStringOp("equal", leftValue, rightValue, expr.Source())
if err != nil { return nil, err }
v := f.Append(&ssa.UnaryOp{ Op: token.Not, Operand: equal, Source: expr.Source(), })
return v, nil } }
if leftIsStruct || rightIsStruct { return nil, errors.New(InvalidStructOperation, f.File, expr.Token) }
if !types.IsCastable(leftType, rightType) && !types.IsCastable(rightType, leftType) { return nil, errors.New(&TypeMismatch{Encountered: leftType.Name(), Expected: rightType.Name()}, f.File, left.Source()) }
v := &ssa.BinaryOp{ Left: leftValue, Right: rightValue, Op: expr.Token.Kind, Swapped: swapped, Source: expr.Source(), }
if v.Op.IsComparison() { f.Block().Append(v) return v, nil }
return f.Append(v), nil}