diff --git a/gotype.go b/gotype.go index b0b917e..885bbbf 100644 --- a/gotype.go +++ b/gotype.go @@ -1,14 +1,31 @@ package main +import ( + "strings" +) + type gotype struct { SliceOf *gotype MapKey *gotype MapVal *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) } +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 { if gt.SliceOf != nil { return "[]" + gt.SliceOf.AsGoString() @@ -19,17 +36,38 @@ func (gt gotype) AsGoString() string { } else if gt.PtrTo != nil { 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 { 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. func (gt gotype) ZeroValue() string { - if gt.SliceOf != nil || gt.MapKey != nil || gt.PtrTo != nil { - return `nil` // gt.AsGoString() + "{}" - + if !gt.IsPlain() { + return `nil` } // It's a plain type diff --git a/scope.go b/scope.go index cf92bd4..1dc4094 100644 --- a/scope.go +++ b/scope.go @@ -43,11 +43,11 @@ func (this *Scope) Set(Name string, Type gotype) *LocalVar { if lv := this.Has(Name); lv != nil { // Update known type for existing variable - if lv.Type == unknownVarType { + if lv.Type.Equals(&unknownVarType) { lv.Type = Type - } else if lv.Type == Type { + } else if lv.Type.Equals(&Type) { // no-op, more evidence for the same type - } else if lv.Type != Type { + } else if !lv.Type.Equals(&Type) { // conflicting type information lv.Type = mixedVarType }