gotype: initial commit of Go type abstraction

This commit is contained in:
mappu 2020-04-11 12:49:08 +12:00
parent 71a4efbbda
commit 86266ae676
3 changed files with 68 additions and 9 deletions

59
gotype.go Normal file
View File

@ -0,0 +1,59 @@
package main
type gotype struct {
SliceOf *gotype
MapKey *gotype
MapVal *gotype
PtrTo *gotype
Plain string
// TODO channel-of (although we will never? construct one from PHP source)
}
func (gt gotype) AsGoString() string {
if gt.SliceOf != nil {
return "[]" + gt.SliceOf.AsGoString()
} else if gt.MapKey != nil {
return "map[" + gt.MapKey.AsGoString() + "]" + gt.MapVal.AsGoString()
} else if gt.PtrTo != nil {
return "*" + gt.PtrTo.AsGoString()
} else {
return gt.Plain
}
}
// 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() + "{}"
}
// It's a plain type
switch gt.Plain {
case "byte",
"int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64",
"float", "float64":
return `0`
case "bool":
return `false`
case "string":
return `""`
case "rune":
return `''`
default:
// probably a struct type
return gt.AsGoString() + `{}`
}
}

View File

@ -253,7 +253,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
// 'Modifiers' - protected public readonly ... // 'Modifiers' - protected public readonly ...
// prop.Modifiers // prop.Modifiers
memberVars = append(memberVars, name+" "+memberType) memberVars = append(memberVars, name+" "+memberType.AsGoString())
case *stmt.ClassConstList: case *stmt.ClassConstList:
// Class constant // Class constant
@ -1471,7 +1471,7 @@ func removeParens(expr string) string {
func (this *conversionState) resolveName(n node.Node) (string, error) { func (this *conversionState) resolveName(n node.Node) (string, error) {
// TODO support namespace lookups // TODO support namespace lookups
ret := unknownVarType ret := unknownVarType.AsGoString()
if n == nil || n == node.Node(nil) { if n == nil || n == node.Node(nil) {
return ret, nil return ret, nil
} }
@ -1709,9 +1709,9 @@ func (this *conversionState) convertArrayLiteralCommon(items []node.Node) (strin
} }
if isMapType { if isMapType {
return `map[` + keyType + `]` + valType + `{` + strings.Join(entries, " ") + `}`, nil return `map[` + keyType.AsGoString() + `]` + valType.AsGoString() + `{` + strings.Join(entries, " ") + `}`, nil
} else { } else {
return `[]` + valType + `{` + strings.Join(entries, " ") + `}`, nil return `[]` + valType.AsGoString() + `{` + strings.Join(entries, " ") + `}`, nil
} }
} }

View File

@ -1,13 +1,13 @@
package main package main
const ( var (
unknownVarType string = `unknown` // placeholder unknownVarType gotype = gotype{Plain: `unknown`} // placeholder
mixedVarType string = `mixed` // when setting an incompatible type mixedVarType gotype = gotype{Plain: `mixed`} // when setting an incompatible type
) )
type LocalVar struct { type LocalVar struct {
Name string Name string
Type string Type gotype
} }
type Scope struct { type Scope struct {
@ -39,7 +39,7 @@ func (this *Scope) Has(varName string) *LocalVar {
return nil // not found return nil // not found
} }
func (this *Scope) Set(Name, Type string) *LocalVar { 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