Keys now support constants

This commit is contained in:
Sasha Koshka 2024-04-21 11:31:41 -04:00
parent f4480fe6b1
commit cc5173dd52
7 changed files with 78 additions and 63 deletions

View File

@ -47,7 +47,7 @@ func (this *Tree) analyzeConstant (
if err != nil { return nil, err }
typedef, err := this.analyzeTypedef(constant.Position(), entity.Key {
Unit: unit,
Name: constant.TypeName,
Type: constant.TypeName,
}, false) // TODO perhaps we should accept incomplete ones?
if err != nil { return nil, err }
constant.Unit = typedef.Unit()
@ -151,8 +151,8 @@ func (this *Tree) analyzeCall (
unit, err := this.resolveNickname(call.Position(), call.UnitNickname)
if err != nil { return nil, err }
function, err := this.analyzeFunction(call.Position(), entity.Key {
Unit: unit,
Name: call.Name,
Unit: unit,
Function: call.Name,
})
if err != nil { return nil, err }
call.Function = function

View File

@ -20,7 +20,7 @@ func (this *Tree) analyzeFunction (
// error if function is missing
function, exists := this.rawFunctions[key]
if !exists {
return nil, errors.Errorf(pos, "no function named %s", key.Name)
return nil, errors.Errorf(pos, "no function named %s", key.Function)
}
// set unit

View File

@ -14,12 +14,12 @@ func (this *Tree) analyzeMethod (
error,
) {
// get parent typedef
typeKey := key.StripMethod()
typeKey := key.OnlyType()
owner, err := this.analyzeTypedef(pos, typeKey, false)
if err != nil { return nil, err }
// return if exists already
if method, exists := owner.Methods[key.Method]; exists {
if method, exists := owner.Methods[key.Function]; exists {
return method, nil
}
@ -65,7 +65,7 @@ func (this *Tree) analyzeMethod (
Referenced: &entity.TypeNamed {
Pos: method.Position(),
Unt: key.Unit,
Name: key.Name,
Name: key.Type,
Type: owner.Type,
},
},
@ -75,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[key.Method] = method
owner.Methods[key.Function] = method
// analyze method body
if method.Body != nil {
@ -93,10 +93,10 @@ func (this *Tree) methodExists (pos errors.Position, key entity.Key) (bool, erro
if existsInRaw { return true, nil }
// check parent typedef
typeKey := key.StripMethod()
typeKey := key.OnlyType()
owner, err := this.analyzeTypedef(pos, typeKey, false)
if err != nil { return false, err }
_, existsInType := owner.Methods[key.Method]
_, existsInType := owner.Methods[key.Function]
return existsInType, nil
}
@ -126,9 +126,9 @@ func (this *Tree) analyzeMethodOrBehaviorInternal (
case *entity.TypeNamed:
ty := ty.(*entity.TypeNamed)
key := entity.Key {
Unit: ty.Type.Unit(),
Name: ty.Name,
Method: name,
Unit: ty.Type.Unit(),
Type: ty.Name,
Function: name,
}
exists, err := this.methodExists(pos, key)
if err != nil { return nil, err }

View File

@ -45,7 +45,7 @@ func (this *Tree) assembleRawMaps () error {
case *entity.Typedef:
key := entity.Key {
Unit: this.unit,
Name: declaration.Name,
Type: declaration.Name,
}
err := this.topLevelNameAvailable(declaration.Position(), key)
if err != nil { return err }
@ -54,8 +54,8 @@ func (this *Tree) assembleRawMaps () error {
case *entity.Function:
key := entity.Key {
Unit: this.unit,
Name: declaration.Signature.Name,
Unit: this.unit,
Function: declaration.Signature.Name,
}
err := this.topLevelNameAvailable(declaration.Position(), key)
if err != nil { return err }
@ -63,9 +63,9 @@ func (this *Tree) assembleRawMaps () error {
case *entity.Method:
key := entity.Key {
Unit: this.unit,
Name: declaration.TypeName,
Method: declaration.Signature.Name,
Unit: this.unit,
Type: declaration.TypeName,
Function: declaration.Signature.Name,
}
err := this.topLevelNameAvailable(declaration.Position(), key)
if err != nil { return err }
@ -76,35 +76,35 @@ func (this *Tree) assembleRawMaps () error {
}
func (this *Tree) topLevelNameAvailable (currentPos errors.Position, key entity.Key) error {
if fsplParser.IsReserved(key.Name) {
if fsplParser.IsReserved(key.Type) {
return errors.Errorf (
currentPos, "cannot shadow reserved identifier %s",
key.Name)
key.Type)
}
if _, isPrimitive := primitiveTypes[key.Name]; isPrimitive {
if _, isPrimitive := primitiveTypes[key.Type]; isPrimitive {
return errors.Errorf (
currentPos, "cannot shadow primitive %s",
key.Name)
key.Type)
}
if _, isBuiltin := builtinTypes[key.Name]; isBuiltin {
if _, isBuiltin := builtinTypes[key.Type]; isBuiltin {
return errors.Errorf (
currentPos, "cannot shadow builtin %s",
key.Name)
key.Type)
}
if ty, isType := this.rawTypes[key]; isType {
return errors.Errorf (
currentPos, "%s already declared at %v",
key.Name, ty.Position())
key.Type, ty.Position())
}
if function, isFunction := this.rawFunctions[key]; isFunction {
return errors.Errorf (
currentPos, "%s already declared at %v",
key.Name, function.Position())
key.Function, function.Position())
}
if method, isMethod := this.rawMethods[key]; isMethod {
return errors.Errorf (
currentPos, "%s.%s already declared at %v",
key.Name, key.Method, method.Position())
key.Type, key.Function, method.Position())
}
return nil
}
@ -123,9 +123,9 @@ func (this *Tree) analyzeDeclarations () error {
_, err := this.analyzeMethod (
rawMethod.Position(),
entity.Key {
Unit: this.unit,
Name: rawMethod.TypeName,
Method: rawMethod.Signature.Name,
Unit: this.unit,
Type: rawMethod.TypeName,
Function: rawMethod.Signature.Name,
})
if err != nil { return err }
}
@ -157,7 +157,7 @@ func (this *Tree) ensure () {
for name, ty := range builtinTypes {
// builtin types have a zero UUID in their key
this.Types[entity.Key { Name: name }] = &entity.Typedef {
this.Types[entity.Key { Type: name }] = &entity.Typedef {
Acc: entity.AccessPublic,
Name: name,
Type: ty,

View File

@ -14,7 +14,7 @@ func (this *Tree) analyzeTypedef (
error,
) {
// return a builtin if it exists (search types with zero uuid)
if definition, exists := this.Types[entity.Key { Name: key.Name }]; exists {
if definition, exists := this.Types[entity.Key { Type: key.Type }]; exists {
return definition, nil
}
@ -30,14 +30,14 @@ func (this *Tree) analyzeTypedef (
} else {
return nil, errors.Errorf (
pos, "type %s cannot be used in this context",
key.Name)
key.Type)
}
}
// check if it is even real
definition, exists := this.rawTypes[key]
if !exists {
return nil, errors.Errorf(pos, "no type named %s", key.Name)
return nil, errors.Errorf(pos, "no type named %s", key.Type)
}
// update unit
@ -148,7 +148,7 @@ func (this *Tree) analyzeTypeInternal (
rootKey := func () entity.Key {
return entity.Key {
Unit: this.unit,
Name: root.Name,
Type: root.Name,
}
}
updateIncompleteInfo := func () {
@ -182,7 +182,7 @@ func (this *Tree) analyzeTypeInternal (
// analyze the typedef
def, err := this.analyzeTypedef(ty.Position(), entity.Key {
Unit: unit,
Name: ty.Name,
Type: ty.Name,
}, acceptIncomplete)
if err != nil { return nil, err }

View File

@ -28,16 +28,45 @@ func (hash Hash) Number () uint64 {
// Key globally indexes top level entities in contexts where modules matter.
type Key struct {
Unit uuid.UUID
Name string
Method string
Unit uuid.UUID
// TypeName is the name of the type
Type string
// Constant is the name of the constant
Constant string
// Function is the name of the method or function
Function string
}
func (key Key) String () string {
out := fmt.Sprintf("%v::%v", key.Unit, key.Name)
if key.Method != "" {
out = fmt.Sprintf("%s.%s", out, key.Method)
return fmt.Sprintf("%v::%s", key.Unit, key.name())
}
// 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)
unit := base64.StdEncoding.EncodeToString(data[:])
return fmt.Sprintf("%v::%s", unit, key.name())
}
func (key Key) name () string {
out := ""
switch {
case key.Constant != "": out = key.Constant
case key.Function != "": out = fmt.Sprintf("[%s]", key.Function)
}
if key.Type != "" {
if out == "" {
out = key.Type
} else {
out = fmt.Sprintf("%s.%s", key.Type, out)
}
}
return out
}
@ -47,24 +76,10 @@ func (key Key) Hash () Hash {
return NewHash([]byte("Key:" + key.String()))
}
// 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)
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 = ""
// OnlyType returns a copy of the key that refers to a type instead of a method
// or constant.
func (key Key) OnlyType () Key {
key.Constant = ""
key.Function = ""
return key
}

View File

@ -53,7 +53,7 @@ func (this *TypeNamed) String () string {
func (this *TypeNamed) Hash () Hash {
return Key {
Unit: this.Type.Unit(),
Name: this.Name,
Type: this.Name,
}.Hash()
}
func (this *TypeNamed) Equals (ty Type) bool {