From 358a57b4b9bcfd361e6d4ec11c931188e9950b3d Mon Sep 17 00:00:00 2001 From: Nicholas Wiersma Date: Fri, 21 Aug 2020 10:56:03 +0200 Subject: [PATCH] feat: add star expression type checking 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. --- interp/cfg.go | 11 +++++++++++ interp/interp_eval_test.go | 8 ++++++++ interp/typecheck.go | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/interp/cfg.go b/interp/cfg.go index f8db96abc..7403adb61 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -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 @@ -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 { diff --git a/interp/interp_eval_test.go b/interp/interp_eval_test.go index 6c5439dee..c68fde24f 100644 --- a/interp/interp_eval_test.go +++ b/interp/interp_eval_test.go @@ -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{ diff --git a/interp/typecheck.go b/interp/typecheck.go index f7f1c11ca..008377392 100644 --- a/interp/typecheck.go +++ b/interp/typecheck.go @@ -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,