Skip to content

Commit

Permalink
Implemented null coalesce operator
Browse files Browse the repository at this point in the history
  • Loading branch information
Knetic committed Aug 11, 2016
1 parent 86c6121 commit 2923a49
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 0 deletions.
6 changes: 6 additions & 0 deletions OperatorToken.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const (

TERNARY_TRUE
TERNARY_FALSE
COALESCE
)

type OperatorPrecedence int
Expand Down Expand Up @@ -106,6 +107,8 @@ func findOperatorPrecedenceForSymbol(symbol OperatorSymbol) OperatorPrecedence {
fallthrough
case INVERT:
return PREFIX_PRECEDENCE
case COALESCE:
fallthrough
case TERNARY_TRUE:
fallthrough
case TERNARY_FALSE:
Expand Down Expand Up @@ -171,6 +174,7 @@ var PREFIX_SYMBOLS = map[string]OperatorSymbol{
var TERNARY_SYMBOLS = map[string]OperatorSymbol{
"?": TERNARY_TRUE,
":": TERNARY_FALSE,
"??": COALESCE,
}

// this is defined separately from ADDITIVE_SYMBOLS et al because it's needed for parsing, not stage planning.
Expand Down Expand Up @@ -296,6 +300,8 @@ func (this OperatorSymbol) String() string {
return "?"
case TERNARY_FALSE:
return ":"
case COALESCE:
return "??"
}
return ""
}
23 changes: 23 additions & 0 deletions evaluation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ func TestNoParameterEvaluation(test *testing.T) {
Input: "1 * 4 / 2 * 8",
Expected: 16.0,
},
EvaluationTest{
Name: "Null coalesce precedence",
Input: "true ?? true ? 100 + 200 : 400",
Expected: 300.0,
},
EvaluationTest{

Name: "Identical date equivalence",
Expand Down Expand Up @@ -437,6 +442,12 @@ func TestNoParameterEvaluation(test *testing.T) {
Input: "true + 'bar' == 'truebar'",
Expected: true,
},
EvaluationTest{

Name: "Null coalesce left",
Input: "1 ?? 2",
Expected: 1.0,
},
}

runEvaluationTests(evaluationTests, test)
Expand Down Expand Up @@ -845,6 +856,18 @@ func TestParameterizedEvaluation(test *testing.T) {
},
Expected: 0.0,
},
EvaluationTest{

Name: "Null coalesce right",
Input: "foo ?? 1.0",
Parameters: []EvaluationParameter{
EvaluationParameter{
Name: "foo",
Value: nil,
},
},
Expected: 1.0,
},
}

runEvaluationTests(evaluationTests, test)
Expand Down
19 changes: 19 additions & 0 deletions parsing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,25 @@ func TestTernaryParsing(test *testing.T) {
},
},
},
TokenParsingTest{

Name: "Null coalesce left",
Input: "1 ?? 2",
Expected: []ExpressionToken{
ExpressionToken{
Kind: NUMERIC,
Value: 1.0,
},
ExpressionToken{
Kind: TERNARY,
Value: "??",
},
ExpressionToken{
Kind: NUMERIC,
Value: 2.0,
},
},
},
}

runTokenParsingTest(tokenParsingTests, test)
Expand Down
3 changes: 3 additions & 0 deletions stagePlanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var stageSymbolMap = map[OperatorSymbol]evaluationOperator{
BITWISE_NOT: bitwiseNotStage,
TERNARY_TRUE: ternaryIfStage,
TERNARY_FALSE: ternaryElseStage,
COALESCE: ternaryElseStage,
}

/*
Expand Down Expand Up @@ -359,6 +360,8 @@ func findTypeChecks(symbol OperatorSymbol) typeChecks {
return typeChecks{}
case TERNARY_FALSE:
fallthrough
case COALESCE:
fallthrough
default:
return typeChecks{}
}
Expand Down

0 comments on commit 2923a49

Please sign in to comment.