Skip to content

Commit

Permalink
cl: update typesRecorder api
Browse files Browse the repository at this point in the history
  • Loading branch information
visualfc committed Dec 10, 2023
1 parent 6c081ba commit 5e9e990
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 82 deletions.
75 changes: 32 additions & 43 deletions cl/internal/typesutil/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,27 @@ import (
"github.com/goplus/gox"
)

// An operandMode specifies the (addressing) mode of an operand.
type operandMode byte
// An OperandMode specifies the (addressing) mode of an operand.
type OperandMode byte

const (
invalid operandMode = iota // operand is invalid
novalue // operand represents no value (result of a function call w/o result)
builtin // operand is a built-in function
typexpr // operand is a type
constant_ // operand is a constant; the operand's typ is a Basic type
variable // operand is an addressable variable
mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
value // operand is a computed value
commaok // like value, but operand may be used in a comma,ok expression
commaerr // like commaok, but second value is error, not boolean
cgofunc // operand is a cgo function
Invalid OperandMode = iota // operand is invalid
NoValue // operand represents no value (result of a function call w/o result)
Builtin // operand is a built-in function
TypExpr // operand is a type
Constant // operand is a constant; the operand's typ is a Basic type
Variable // operand is an addressable variable
MapIndex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
Value // operand is a computed value
CommaOK // like value, but operand may be used in a comma,ok expression
CommaErr // like commaok, but second value is error, not boolean
CgoFunc // operand is a cgo function
)

// TypeAndValue reports the type and value (for constants)
// of the corresponding expression.
type TypeAndValue struct {
mode operandMode
mode OperandMode
Type types.Type
Value constant.Value
}
Expand All @@ -55,70 +55,59 @@ func NewTypeAndValueForType(typ types.Type) (ret types.TypeAndValue) {
typ = t.Type()
}
ret.Type = typ
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = typexpr
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = TypExpr
return
}

func NewTypeAndValueForValue(typ types.Type, val constant.Value) (ret types.TypeAndValue) {
var mode operandMode
func NewTypeAndValueForValue(typ types.Type, val constant.Value, mode OperandMode) (ret types.TypeAndValue) {
switch t := typ.(type) {
case *gox.TypeType:
typ = t.Type()
}
if val != nil {
mode = constant_
} else {
mode = value
mode = Constant
}
ret.Type = typ
ret.Value = val
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = mode
return
}

func NewTypeAndValueForVariable(typ types.Type) (ret types.TypeAndValue) {
ret.Type = typ
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = variable
return
}

func NewTypeAndValueForMapIndex(typ types.Type) (ret types.TypeAndValue) {
ret.Type = typ
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = mapindex
return
}

func NewTypeAndValueForCallResult(typ types.Type, val constant.Value) (ret types.TypeAndValue) {
var mode operandMode
var mode OperandMode
if typ == nil {
ret.Type = &types.Tuple{}
mode = novalue
mode = NoValue
} else {
ret.Type = typ
if val != nil {
ret.Value = val
mode = constant_
mode = Constant
} else {
mode = value
mode = Value
}
}
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = mode
return
}

func NewTypeAndValueForObject(obj types.Object) (ret types.TypeAndValue) {
var mode operandMode
var mode OperandMode
var val constant.Value
switch v := obj.(type) {
case *types.Const:
mode = constant_
mode = Constant
val = v.Val()
case *types.TypeName:
mode = typexpr
mode = TypExpr
case *types.Var:
mode = variable
mode = Variable
case *types.Func:
mode = value
mode = Value
case *types.Builtin:
mode = builtin
mode = Builtin
case *types.Nil:
mode = value
mode = Value
}
ret.Type = obj.Type()
ret.Value = val
Expand Down
12 changes: 2 additions & 10 deletions cl/internal/typesutil/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,10 @@ func TestTypeAndValue(t *testing.T) {
if !ret.IsType() {
t.Fatal("NewTypeAndValueForType: not type?")
}
ret = NewTypeAndValueForValue(tyInt, constant.MakeInt64(1))
ret = NewTypeAndValueForValue(tyInt, constant.MakeInt64(1), Constant)
if ret.Value == nil {
t.Fatal("NewTypeAndValueForValue: not const?")
}
ret = NewTypeAndValueForVariable(tyInt)
if !ret.Addressable() {
t.Fatal("NewTypeAndValueForVariable: not variable?")
}
ret = NewTypeAndValueForMapIndex(tyInt)
if !(!ret.Addressable() && ret.Assignable()) {
t.Fatal("NewTypeAndValueForVariable: not map?")
}
ret = NewTypeAndValueForCallResult(tyInt, nil)
if !ret.IsValue() {
t.Fatal("NewTypeAndValueForCall: not value?")
Expand Down Expand Up @@ -72,7 +64,7 @@ func TestTypeAndValue(t *testing.T) {
if !ret.IsValue() {
t.Fatal("NewTypeAndValueForObject: not value?")
}
ret = NewTypeAndValueForValue(types.Typ[types.UntypedNil], nil)
ret = NewTypeAndValueForValue(types.Typ[types.UntypedNil], nil, Value)
if !ret.IsNil() {
t.Fatal("NewTypeAndValueForValue: not nil?")
}
Expand Down
60 changes: 34 additions & 26 deletions cl/recorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/goplus/gop/ast"
"github.com/goplus/gop/ast/fromgo"
"github.com/goplus/gop/cl/internal/typesutil"
"github.com/goplus/gop/token"
"github.com/goplus/gox"
)

Expand Down Expand Up @@ -60,51 +61,51 @@ func newTypeRecord(rec Recorder) *typesRecorder {
return &typesRecorder{rec, make(map[ast.Expr]types.TypeAndValue)}
}

func (rec *typesRecorder) recordTypeValue(ctx *blockCtx, expr ast.Expr) {
e := ctx.cb.Get(-1)
rec.Type(expr, typesutil.NewTypeAndValueForValue(e.Type, e.CVal))
}

func (rec *typesRecorder) recordTypeVariable(ctx *blockCtx, expr ast.Expr) {
e := ctx.cb.Get(-1)
t, _ := gox.DerefType(e.Type)
rec.Type(expr, typesutil.NewTypeAndValueForVariable(t))
}

func (rec *typesRecorder) recordTypeMapIndex(ctx *blockCtx, expr ast.Expr) {
func (rec *typesRecorder) recordTypeValue(ctx *blockCtx, expr ast.Expr, mode typesutil.OperandMode) {
e := ctx.cb.Get(-1)
t, _ := gox.DerefType(e.Type)
rec.Type(expr, typesutil.NewTypeAndValueForMapIndex(t))
rec.Type(expr, typesutil.NewTypeAndValueForValue(t, e.CVal, mode))
}

func (rec *typesRecorder) indexExpr(ctx *blockCtx, expr *ast.IndexExpr) {
if tv, ok := rec.types[expr.X]; ok {
switch tv.Type.(type) {
case *types.Map:
rec.recordTypeMapIndex(ctx, expr)
rec.recordTypeValue(ctx, expr, typesutil.MapIndex)
return
case *types.Slice:
rec.recordTypeVariable(ctx, expr)
rec.recordTypeValue(ctx, expr, typesutil.Variable)
return
}
}
switch expr.X.(type) {
case *ast.CompositeLit:
rec.recordTypeValue(ctx, expr)
rec.recordTypeValue(ctx, expr, typesutil.Value)
default:
rec.recordTypeValue(ctx, expr, typesutil.Variable)
}
}

func (rec *typesRecorder) unaryExpr(ctx *blockCtx, expr *ast.UnaryExpr) {
switch expr.Op {
case token.ARROW:
rec.recordTypeValue(ctx, expr, typesutil.CommaOK)
default:
rec.recordTypeVariable(ctx, expr)
rec.recordTypeValue(ctx, expr, typesutil.Value)
}
}

func (rec *typesRecorder) recordCallExpr(ctx *blockCtx, v *ast.CallExpr, fnt types.Type) {
e := ctx.cb.Get(-1)
rec.Type(v.Fun, typesutil.NewTypeAndValueForValue(fnt, nil))
if _, ok := rec.types[v.Fun]; !ok {
rec.Type(v.Fun, typesutil.NewTypeAndValueForValue(fnt, nil, typesutil.Value))
}
rec.Type(v, typesutil.NewTypeAndValueForCallResult(e.Type, e.CVal))
}

func (rec *typesRecorder) recordCompositeLit(ctx *blockCtx, v *ast.CompositeLit, typ types.Type) {
rec.Type(v.Type, typesutil.NewTypeAndValueForType(typ))
rec.Type(v, typesutil.NewTypeAndValueForValue(typ, nil))
rec.Type(v, typesutil.NewTypeAndValueForValue(typ, nil, typesutil.Value))
}

func (rec *typesRecorder) recordType(ctx *blockCtx, typ ast.Expr, t types.Type) {
Expand All @@ -120,14 +121,14 @@ func (rec *typesRecorder) recordExpr(ctx *blockCtx, expr ast.Expr, rhs bool) {
switch v := expr.(type) {
case *ast.Ident:
case *ast.BasicLit:
rec.recordTypeValue(ctx, v)
rec.recordTypeValue(ctx, v, typesutil.Value)
case *ast.CallExpr:
case *ast.SelectorExpr:
rec.recordTypeVariable(ctx, v)
rec.recordTypeValue(ctx, v, typesutil.Variable)
case *ast.BinaryExpr:
rec.recordTypeValue(ctx, v)
rec.recordTypeValue(ctx, v, typesutil.Value)
case *ast.UnaryExpr:
rec.recordTypeValue(ctx, v)
rec.unaryExpr(ctx, v)
case *ast.FuncLit:
case *ast.CompositeLit:
case *ast.SliceLit:
Expand All @@ -136,20 +137,27 @@ func (rec *typesRecorder) recordExpr(ctx *blockCtx, expr ast.Expr, rhs bool) {
rec.indexExpr(ctx, v)
case *ast.IndexListExpr:
case *ast.SliceExpr:
rec.recordTypeValue(ctx, v)
rec.recordTypeValue(ctx, v, typesutil.Value)
case *ast.StarExpr:
rec.recordTypeVariable(ctx, v)
rec.recordTypeValue(ctx, v, typesutil.Variable)
case *ast.ArrayType:
rec.recordTypeValue(ctx, v, typesutil.TypExpr)
case *ast.MapType:
rec.recordTypeValue(ctx, v, typesutil.TypExpr)
case *ast.StructType:
rec.recordTypeValue(ctx, v, typesutil.TypExpr)
case *ast.ChanType:
rec.recordTypeValue(ctx, v, typesutil.TypExpr)
case *ast.InterfaceType:
rec.recordTypeValue(ctx, v, typesutil.TypExpr)
case *ast.ComprehensionExpr:
case *ast.TypeAssertExpr:
rec.recordTypeValue(ctx, v, typesutil.CommaOK)
case *ast.ParenExpr:
rec.recordTypeValue(ctx, v)
rec.recordTypeValue(ctx, v, typesutil.Value)
case *ast.ErrWrapExpr:
case *ast.FuncType:
rec.recordTypeValue(ctx, v, typesutil.TypExpr)
case *ast.Ellipsis:
case *ast.KeyValueExpr:
default:
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@ require (
golang.org/x/sys v0.14.0 // indirect
)

retract (
v1.1.12
)
retract v1.1.12
27 changes: 27 additions & 0 deletions x/typesutil/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,30 @@ func test() {
}
`)
}

func TestTypeAssert(t *testing.T) {
testInfo(t, `package main
func test() {
var a interface{} = 100
if n, ok := a.(int); ok {
_ = n
}
}
`)
}

func TestChan(t *testing.T) {
testInfo(t, `package main
func test() {
var ch chan int
select {
case n, ok := <-ch:
_ = n
_ = ok
break
}
}
`)
}

0 comments on commit 5e9e990

Please sign in to comment.