gotype: support function types

This commit is contained in:
mappu 2020-04-16 18:36:34 +12:00
parent 3f8377d9fe
commit fc0008a208
2 changed files with 45 additions and 7 deletions

View File

@ -1,14 +1,31 @@
package main package main
import (
"strings"
)
type gotype struct { type gotype struct {
SliceOf *gotype SliceOf *gotype
MapKey *gotype MapKey *gotype
MapVal *gotype MapVal *gotype
PtrTo *gotype PtrTo *gotype
Plain string
IsFunc bool
FuncParams []gotype
FuncReturn []gotype
Plain string
// TODO channel-of (although we will never? construct one from PHP source) // TODO channel-of (although we will never? construct one from PHP source)
} }
func goTypeListToString(gotypes []gotype) string {
ret := make([]string, 0, len(gotypes))
for _, gt := range gotypes {
ret = append(ret, gt.AsGoString())
}
return strings.Join(ret, `, `)
}
func (gt gotype) AsGoString() string { func (gt gotype) AsGoString() string {
if gt.SliceOf != nil { if gt.SliceOf != nil {
return "[]" + gt.SliceOf.AsGoString() return "[]" + gt.SliceOf.AsGoString()
@ -19,17 +36,38 @@ func (gt gotype) AsGoString() string {
} else if gt.PtrTo != nil { } else if gt.PtrTo != nil {
return "*" + gt.PtrTo.AsGoString() return "*" + gt.PtrTo.AsGoString()
} else if gt.IsFunc {
ret := "func(" + goTypeListToString(gt.FuncParams) + `)`
if len(gt.FuncReturn) == 1 {
ret += ` ` + gt.FuncReturn[0].AsGoString()
} else if len(gt.FuncReturn) >= 2 {
ret += ` (` + goTypeListToString(gt.FuncReturn) + `)`
}
return ret
} else { } else {
return gt.Plain return gt.Plain
} }
} }
func (gt gotype) IsPlain() bool {
if gt.SliceOf != nil || gt.MapKey != nil || gt.PtrTo != nil || gt.IsFunc {
return false
}
return true
}
func (gt gotype) Equals(other *gotype) bool {
return gt.AsGoString() == other.AsGoString()
}
// ZeroValue returns a Go literal string for the zero value of this type. // ZeroValue returns a Go literal string for the zero value of this type.
func (gt gotype) ZeroValue() string { func (gt gotype) ZeroValue() string {
if gt.SliceOf != nil || gt.MapKey != nil || gt.PtrTo != nil { if !gt.IsPlain() {
return `nil` // gt.AsGoString() + "{}" return `nil`
} }
// It's a plain type // It's a plain type

View File

@ -43,11 +43,11 @@ func (this *Scope) Set(Name string, Type gotype) *LocalVar {
if lv := this.Has(Name); lv != nil { if lv := this.Has(Name); lv != nil {
// Update known type for existing variable // Update known type for existing variable
if lv.Type == unknownVarType { if lv.Type.Equals(&unknownVarType) {
lv.Type = Type lv.Type = Type
} else if lv.Type == Type { } else if lv.Type.Equals(&Type) {
// no-op, more evidence for the same type // no-op, more evidence for the same type
} else if lv.Type != Type { } else if !lv.Type.Equals(&Type) {
// conflicting type information // conflicting type information
lv.Type = mixedVarType lv.Type = mixedVarType
} }