Skip to content

Commit

Permalink
feat: add star expression type checking
Browse files Browse the repository at this point in the history
This adds type checking to StarExpr. This also fixes a bug in assignment where the symbol type was updated but not the scope type associated with it.
  • Loading branch information
nrwiersma committed Aug 21, 2020
1 parent 3640f2f commit 358a57b
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 0 deletions.
11 changes: 11 additions & 0 deletions interp/cfg.go
Expand Up @@ -518,6 +518,11 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
if updateSym {
sym.typ = dest.typ
sym.rval = src.rval
// As we are updating the sym type, we need to update the sc.type
// when the sym has an index.
if sym.index >= 0 {
sc.types[sym.index] = sym.typ.frameType()
}
}
n.findex = dest.findex
n.level = dest.level
Expand Down Expand Up @@ -1554,6 +1559,12 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
default:
// dereference expression
wireChild(n)

err = check.starExpr(n.child[0])
if err != nil {
break
}

if c0 := n.child[0]; c0.typ.cat == valueT {
n.typ = &itype{cat: valueT, rtype: c0.typ.rtype.Elem()}
} else {
Expand Down
8 changes: 8 additions & 0 deletions interp/interp_eval_test.go
Expand Up @@ -70,6 +70,14 @@ func TestEvalArithmetic(t *testing.T) {
})
}

func TestEvalStar(t *testing.T) {
i := interp.New(interp.Options{})
runTests(t, i, []testCase{
{src: `a := &struct{A int}{1}; b := *a`, res: "{1}"},
{src: `a := struct{A int}{1}; b := *a`, err: "1:57: invalid operation: cannot indirect \"a\""},
})
}

func TestEvalAssign(t *testing.T) {
i := interp.New(interp.Options{})
runTests(t, i, []testCase{
Expand Down
8 changes: 8 additions & 0 deletions interp/typecheck.go
Expand Up @@ -106,6 +106,14 @@ func (check typecheck) addressExpr(n *node) error {
return nil
}

// starExpr type checks a star expression on a variable.
func (check typecheck) starExpr(n *node) error {
if n.typ.TypeOf().Kind() != reflect.Ptr {
return n.cfgErrorf("invalid operation: cannot indirect %q", n.name())
}
return nil
}

var unaryOpPredicates = opPredicates{
aPos: isNumber,
aNeg: isNumber,
Expand Down

0 comments on commit 358a57b

Please sign in to comment.