From 32e29862f28e4851993b51b1d76f2832a799dc3b Mon Sep 17 00:00:00 2001 From: James Shubin Date: Sun, 20 Jan 2019 04:01:34 -0500 Subject: [PATCH] lang: Check that set type matches actual expression I forgot to include these two invariants which are occasionally necessary, although in most cases they're necessary to prevent incorrect code from getting past unification. In any case, they would have been caught by the engine. --- lang/parser.y | 3 +++ lang/structs.go | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/lang/parser.y b/lang/parser.y index ca13ca0c..5a3e32a7 100644 --- a/lang/parser.y +++ b/lang/parser.y @@ -859,6 +859,7 @@ arg: } ; bind: + // `$s = "hey"` VAR_IDENTIFIER EQUALS expr { posLast(yylex, yyDollar) // our pos @@ -867,6 +868,8 @@ bind: Value: $3.expr, } } + // `$x bool = true` + // `$x int = if true { 42 } else { 13 }` | VAR_IDENTIFIER type EQUALS expr { posLast(yylex, yyDollar) // our pos diff --git a/lang/structs.go b/lang/structs.go index 3ba22657..3fccc088 100644 --- a/lang/structs.go +++ b/lang/structs.go @@ -5255,6 +5255,15 @@ func (obj *ExprVar) Unify() ([]interfaces.Invariant, error) { return nil, fmt.Errorf("var `%s` does not exist in this scope", obj.Name) } + // if this was set explicitly by the parser + if obj.typ != nil { + invar := &unification.EqualsInvariant{ + Expr: obj, + Type: obj.typ, + } + invariants = append(invariants, invar) + } + // don't recurse because we already got this through the bind statement //invars, err := expr.Unify() //if err != nil { @@ -5531,6 +5540,15 @@ func (obj *ExprIf) Type() (*types.Type, error) { func (obj *ExprIf) Unify() ([]interfaces.Invariant, error) { var invariants []interfaces.Invariant + // if this was set explicitly by the parser + if obj.typ != nil { + invar := &unification.EqualsInvariant{ + Expr: obj, + Type: obj.typ, + } + invariants = append(invariants, invar) + } + // conditional expression might have some children invariants to share condition, err := obj.Condition.Unify() if err != nil {