entity.Key now has an optional method field
This commit is contained in:
parent
4166fb8817
commit
ff18aae2b6
|
@ -4,37 +4,29 @@ import "fmt"
|
|||
import "git.tebibyte.media/sashakoshka/fspl/errors"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||
|
||||
func (this *Tree) methodKey (typeKey entity.Key, name string) entity.Key {
|
||||
return entity.Key {
|
||||
Unit: typeKey.Unit,
|
||||
Name: typeKey.Name + "." + name,
|
||||
}
|
||||
}
|
||||
|
||||
// analyzeMethod analyzes a method that is directly owned by the specified type.
|
||||
func (this *Tree) analyzeMethod (
|
||||
pos errors.Position,
|
||||
typeKey entity.Key,
|
||||
name string,
|
||||
pos errors.Position,
|
||||
key entity.Key,
|
||||
) (
|
||||
*entity.Method,
|
||||
error,
|
||||
) {
|
||||
// get parent typedef
|
||||
typeKey := key.StripMethod()
|
||||
owner, err := this.analyzeTypedef(pos, typeKey, false)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
// return if exists already
|
||||
if method, exists := owner.Methods[name]; exists {
|
||||
if method, exists := owner.Methods[key.Method]; exists {
|
||||
return method, nil
|
||||
}
|
||||
|
||||
// error if method is missing
|
||||
method, exists := this.rawMethods[this.methodKey(typeKey, name)]
|
||||
method, exists := this.rawMethods[key]
|
||||
if !exists {
|
||||
return nil, errors.Errorf (
|
||||
pos, "no method named %s.%s",
|
||||
typeKey.Name, name)
|
||||
return nil, errors.Errorf(pos, "no method named %v", key)
|
||||
}
|
||||
|
||||
// set method's unit, very important information yes
|
||||
|
@ -72,8 +64,9 @@ func (this *Tree) analyzeMethod (
|
|||
Position: method.Position,
|
||||
Referenced: &entity.TypeNamed {
|
||||
Position: method.Position,
|
||||
Name: typeKey.Name,
|
||||
Type: owner.Type,
|
||||
Unt: key.Unit,
|
||||
Name: key.Name,
|
||||
Type: owner.Type,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -82,7 +75,7 @@ func (this *Tree) analyzeMethod (
|
|||
// add incomplete method to complete methods because there is enough
|
||||
// information for it to be complete from the point of view of other
|
||||
// parts of the code
|
||||
owner.Methods[name] = method
|
||||
owner.Methods[key.Method] = method
|
||||
|
||||
// analyze method body
|
||||
if method.Body != nil {
|
||||
|
@ -124,12 +117,13 @@ func (this *Tree) analyzeMethodOrBehaviorInternal (
|
|||
switch ty.(type) {
|
||||
case *entity.TypeNamed:
|
||||
ty := ty.(*entity.TypeNamed)
|
||||
typeKey := entity.Key {
|
||||
Unit: ty.Type.Unit(),
|
||||
Name: ty.Name,
|
||||
key := entity.Key {
|
||||
Unit: ty.Type.Unit(),
|
||||
Name: ty.Name,
|
||||
Method: name,
|
||||
}
|
||||
if this.methodExists(this.methodKey(typeKey, name)) {
|
||||
method, err := this.analyzeMethod(pos, typeKey, name)
|
||||
if this.methodExists(key) {
|
||||
method, err := this.analyzeMethod(pos, key)
|
||||
if err != nil { return nil, err }
|
||||
return method, nil
|
||||
} else {
|
||||
|
|
|
@ -40,69 +40,65 @@ func (this *Tree) Analyze (
|
|||
|
||||
func (this *Tree) assembleRawMaps () error {
|
||||
for _, declaration := range this.ast.Declarations {
|
||||
switch declaration.(type) {
|
||||
switch declaration := declaration.(type) {
|
||||
case *entity.Typedef:
|
||||
ty := declaration.(*entity.Typedef)
|
||||
err := this.topLevelNameAvailable(ty.Position, ty.Name)
|
||||
if err != nil { return err }
|
||||
ty.Methods = make(map[string] *entity.Method)
|
||||
this.rawTypes[entity.Key {
|
||||
key := entity.Key {
|
||||
Unit: this.unit,
|
||||
Name: ty.Name,
|
||||
}] = ty
|
||||
Name: declaration.Name,
|
||||
}
|
||||
err := this.topLevelNameAvailable(declaration.Position, key)
|
||||
if err != nil { return err }
|
||||
declaration.Methods = make(map[string] *entity.Method)
|
||||
this.rawTypes[key] = declaration
|
||||
|
||||
case *entity.Function:
|
||||
function := declaration.(*entity.Function)
|
||||
err := this.topLevelNameAvailable (
|
||||
function.Position,
|
||||
function.Signature.Name)
|
||||
if err != nil { return err }
|
||||
this.rawFunctions[entity.Key {
|
||||
key := entity.Key {
|
||||
Unit: this.unit,
|
||||
Name: function.Signature.Name,
|
||||
}] = function
|
||||
Name: declaration.Signature.Name,
|
||||
}
|
||||
err := this.topLevelNameAvailable(declaration.Position, key)
|
||||
if err != nil { return err }
|
||||
this.rawFunctions[key] = declaration
|
||||
|
||||
case *entity.Method:
|
||||
method := declaration.(*entity.Method)
|
||||
name := method.TypeName + "." + method.Signature.Name
|
||||
err := this.topLevelNameAvailable(method.Position, name)
|
||||
key := entity.Key {
|
||||
Unit: this.unit,
|
||||
Name: declaration.TypeName,
|
||||
Method: declaration.Signature.Name,
|
||||
}
|
||||
err := this.topLevelNameAvailable(declaration.Position, key)
|
||||
if err != nil { return err }
|
||||
this.rawMethods[entity.Key {
|
||||
Unit: this.unit,
|
||||
Name: name,
|
||||
}] = method
|
||||
this.rawMethods[key] = declaration
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *Tree) topLevelNameAvailable (currentPos errors.Position, name string) error {
|
||||
if _, isPrimitive := primitiveTypes[name]; isPrimitive {
|
||||
func (this *Tree) topLevelNameAvailable (currentPos errors.Position, key entity.Key) error {
|
||||
if _, isPrimitive := primitiveTypes[key.Name]; isPrimitive {
|
||||
return errors.Errorf (
|
||||
currentPos, "cannot shadow primitive %s",
|
||||
name)
|
||||
key.Name)
|
||||
}
|
||||
if _, isBuiltin := builtinTypes[name]; isBuiltin {
|
||||
if _, isBuiltin := builtinTypes[key.Name]; isBuiltin {
|
||||
return errors.Errorf (
|
||||
currentPos, "cannot shadow builtin %s",
|
||||
name)
|
||||
}
|
||||
key := entity.Key {
|
||||
Unit: this.unit,
|
||||
Name: name,
|
||||
key.Name)
|
||||
}
|
||||
if ty, isType := this.rawTypes[key]; isType {
|
||||
return errors.Errorf (
|
||||
currentPos, "%s already declared at %v",
|
||||
name, ty.Position)
|
||||
key.Name, ty.Position)
|
||||
}
|
||||
if function, isFunction := this.rawFunctions[key]; isFunction {
|
||||
return errors.Errorf (
|
||||
currentPos, "%s already declared at %v",
|
||||
name, function.Position)
|
||||
key.Name, function.Position)
|
||||
}
|
||||
if method, isMethod := this.rawMethods[key]; isMethod {
|
||||
return errors.Errorf (
|
||||
currentPos, "%s already declared at %v",
|
||||
name, method.Position)
|
||||
currentPos, "%s.%s already declared at %v",
|
||||
key.Name, key.Method, method.Position)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -121,10 +117,10 @@ func (this *Tree) analyzeDeclarations () error {
|
|||
_, err := this.analyzeMethod (
|
||||
rawMethod.Position,
|
||||
entity.Key {
|
||||
Unit: this.unit,
|
||||
Name: rawMethod.TypeName,
|
||||
},
|
||||
rawMethod.Signature.Name)
|
||||
Unit: this.unit,
|
||||
Name: rawMethod.TypeName,
|
||||
Method: rawMethod.Signature.Name,
|
||||
})
|
||||
if err != nil { return err }
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -7,22 +7,38 @@ import "git.tebibyte.media/sashakoshka/fspl/errors"
|
|||
|
||||
// Key globally indexes top level entities in contexts where modules matter.
|
||||
type Key struct {
|
||||
Unit uuid.UUID
|
||||
Name string
|
||||
Unit uuid.UUID
|
||||
Name string
|
||||
Method string
|
||||
}
|
||||
|
||||
func (key Key) String () string {
|
||||
return fmt.Sprintf("%v::%v", key.Unit, key.Name)
|
||||
out := fmt.Sprintf("%v::%v", key.Unit, key.Name)
|
||||
if key.Method != "" {
|
||||
out = fmt.Sprintf("%s.%s", out, key.Method)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// LinkName returns the name that the entity it refers to will be given when
|
||||
// compiled.
|
||||
func (key Key) LinkName () string {
|
||||
data := [16]byte(key.Unit)
|
||||
return fmt.Sprintf(
|
||||
out := fmt.Sprintf(
|
||||
"%s::%s",
|
||||
base64.StdEncoding.EncodeToString(data[:]),
|
||||
key.Name)
|
||||
if key.Method != "" {
|
||||
out = fmt.Sprintf("%s.%s", out, key.Method)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// StripMethod returns a copy of the key that refers to a type instead of a
|
||||
// method.
|
||||
func (key Key) StripMethod () Key {
|
||||
key.Method = ""
|
||||
return key
|
||||
}
|
||||
|
||||
// TopLevel is any construct that is placed at the root of a file.
|
||||
|
|
Loading…
Reference in New Issue