lang: types: Add an iterator helper to our types lib
This commit is contained in:
@@ -75,3 +75,100 @@ func TypeStructTagToFieldName(st reflect.Type) (map[string]string, error) {
|
|||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iter applies a function to each type in the top-level type. It stops if that
|
||||||
|
// function errors, and returns that error to the top-level caller. It panics if
|
||||||
|
// it encounters an invalid or partial type struct. This version starts at the
|
||||||
|
// top and works its way deeper.
|
||||||
|
func Iter(typ *Type, fn func(*Type) error) error {
|
||||||
|
if err := fn(typ); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch typ.Kind {
|
||||||
|
case KindBool:
|
||||||
|
case KindStr:
|
||||||
|
case KindInt:
|
||||||
|
case KindFloat:
|
||||||
|
|
||||||
|
case KindList:
|
||||||
|
if typ.Val == nil {
|
||||||
|
panic("malformed list type")
|
||||||
|
}
|
||||||
|
if err := Iter(typ.Val, fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case KindMap:
|
||||||
|
if typ.Key == nil || typ.Val == nil {
|
||||||
|
panic("malformed map type")
|
||||||
|
}
|
||||||
|
if err := Iter(typ.Key, fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := Iter(typ.Val, fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case KindStruct: // {a bool; b int}
|
||||||
|
if typ.Map == nil {
|
||||||
|
panic("malformed struct type")
|
||||||
|
}
|
||||||
|
if len(typ.Map) != len(typ.Ord) {
|
||||||
|
panic("malformed struct length")
|
||||||
|
}
|
||||||
|
for _, k := range typ.Ord {
|
||||||
|
t, ok := typ.Map[k]
|
||||||
|
if !ok {
|
||||||
|
panic("malformed struct order")
|
||||||
|
}
|
||||||
|
if t == nil {
|
||||||
|
panic("malformed struct field")
|
||||||
|
}
|
||||||
|
if err := Iter(t, fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case KindFunc:
|
||||||
|
if typ.Map == nil {
|
||||||
|
panic("malformed func type")
|
||||||
|
}
|
||||||
|
if len(typ.Map) != len(typ.Ord) {
|
||||||
|
panic("malformed func length")
|
||||||
|
}
|
||||||
|
for _, k := range typ.Ord {
|
||||||
|
t, ok := typ.Map[k]
|
||||||
|
if !ok {
|
||||||
|
panic("malformed func order")
|
||||||
|
}
|
||||||
|
if t == nil {
|
||||||
|
panic("malformed func field")
|
||||||
|
}
|
||||||
|
if err := Iter(t, fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if typ.Out != nil {
|
||||||
|
if err := Iter(typ.Out, fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
|
case KindVariant:
|
||||||
|
if err := Iter(typ.Var, fn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case KindUnification:
|
||||||
|
if typ.Uni == nil {
|
||||||
|
panic("malformed unification variable")
|
||||||
|
}
|
||||||
|
// nothing to do
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("malformed type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user