Analyzer checks uniqueness of types in union by comparing hashes

This commit is contained in:
Sasha Koshka 2024-03-02 12:06:35 -05:00
parent 8beb785009
commit 3a1d9632dc
2 changed files with 31 additions and 18 deletions

View File

@ -156,11 +156,11 @@ func (this *Tree) analyzeTypeInternal (
ty.Acc = access ty.Acc = access
ty, err = this.assembleStructMap(ty) ty, err = this.assembleStructMap(ty)
updateIncompleteInfo() updateIncompleteInfo()
if err != nil { return ty, err } if err != nil { return nil, err }
for name, member := range ty.MemberMap { for name, member := range ty.MemberMap {
ty.MemberMap[name].Ty, ty.MemberMap[name].Ty,
err = this.analyzeType(member.Ty, false) err = this.analyzeType(member.Ty, false)
if err != nil { return ty, err } if err != nil { return nil, err }
} }
return ty, nil return ty, nil
@ -170,19 +170,30 @@ func (this *Tree) analyzeTypeInternal (
ty.Acc = access ty.Acc = access
ty, err = this.assembleInterfaceMap(ty) ty, err = this.assembleInterfaceMap(ty)
updatePseudoCompleteInfo() updatePseudoCompleteInfo()
if err != nil { return ty, err } if err != nil { return nil, err }
for name, behavior := range ty.BehaviorMap { for name, behavior := range ty.BehaviorMap {
ty.BehaviorMap[name], err = this.analyzeBehavior(behavior) ty.BehaviorMap[name], err = this.analyzeBehavior(behavior)
if err != nil { return ty, err } if err != nil { return nil, err }
} }
return ty, nil return ty, nil
// union type // union type
case *entity.TypeUnion: case *entity.TypeUnion:
// TODO this is a model for how all of the composite analysis
// processes should work. it is deterministic and covers
// everything. Change struct, interface, sig, etc to match
ty.Unt = this.unit ty.Unt = this.unit
ty.Acc = access ty.Acc = access
ty, err = this.assembleUnionMap(ty)
updateIncompleteInfo() updateIncompleteInfo()
return this.analyzeTypeUnion(ty) if err != nil { return nil, err }
for index, allowed := range ty.Allowed {
allowed, err = this.analyzeType(allowed, false)
if err != nil { return nil, err }
ty.Allowed[index] = allowed
ty.AllowedMap[ty.AllowedOrder[index]] = allowed
}
return ty, nil
// integer type // integer type
case *entity.TypeInt: case *entity.TypeInt:
@ -272,19 +283,19 @@ func (this *Tree) assembleInterfaceMap (ty *entity.TypeInterface) (*entity.TypeI
return ty, nil return ty, nil
} }
func (this *Tree) analyzeTypeUnion (ty *entity.TypeUnion) (*entity.TypeUnion, error) { func (this *Tree) assembleUnionMap (ty *entity.TypeUnion) (*entity.TypeUnion, error) {
ty.AllowedMap = make(map[entity.Hash] entity.Type)
ty.AllowedOrder = make([]entity.Hash, len(ty.Allowed))
for index, allowed := range ty.Allowed { for index, allowed := range ty.Allowed {
allowed, err := this.analyzeType(allowed, true) hash := allowed.Hash()
if err != nil { return nil, err } if previous, exists := ty.AllowedMap[hash]; exists {
ty.Allowed[index] = allowed
for _, check := range ty.Allowed[:index] {
if entity.TypesEqual(check, allowed) {
return ty, errors.Errorf ( return ty, errors.Errorf (
allowed.Position(), "%v already listed in union at %v", allowed.Position(), "%v already listed in union at %v",
allowed, check.Position()) allowed, previous.Position())
}
} }
ty.AllowedMap [hash] = allowed
ty.AllowedOrder[index] = hash
ty.Allowed [index] = allowed
} }
return ty, nil return ty, nil
} }

View File

@ -254,6 +254,8 @@ type TypeUnion struct {
// Semantics // Semantics
Acc Access Acc Access
Unt uuid.UUID Unt uuid.UUID
AllowedOrder []Hash
AllowedMap map[Hash] Type
} }
func (*TypeUnion) ty(){} func (*TypeUnion) ty(){}
func (this *TypeUnion) Position () errors.Position { return this.Pos } func (this *TypeUnion) Position () errors.Position { return this.Pos }