Replies: 2 comments 4 replies
-
Regarding the drawbacks of Option A: abstract class Name(var localName: String, var parent: Name?, private val delimiter: String) {
override fun toString() = localName + (if (parent != null) delimiter + parent.toString() else "")
override fun equals(other: Any?): Boolean = TODO("Add checks for both Name objects and Strings")
override fun hashCode() = toString().hashCode()
operator fun getValue(node: Node, property: KProperty<*>) = toString()
operator fun setValue(node: Node, property: KProperty<*>, s: String) {
parent = null
localName = s
// maybe analyze [s] to generate parents too
}
}
// or use a language frontend specific factory method to get Name objects with the correct delimiter
class JavaName(localName: String, parent: Name? = null) : Name(localName, parent, ".")
abstract class Node(val nameObject: Name) {
var name: String by nameObject // access to name is delegated to getValue and setValue of nameObject
}
class JavaNode(nameObject: Name) : Node(nameObject) This would allow the following syntax: val node = JavaNode(JavaName("myName"))
node.name == "myName" // returns true
node.nameObject.localName = "myOtherName"
node.name == "myOtherName" // returns true
node.nameObject == JavaName("myOtherName") // also returns true
node.nameObject == "myOtherName" // also returns true With some hacks we can get even closer at the cost of loosing static type checking: https://stackoverflow.com/a/46371105 |
Beta Was this translation helpful? Give feedback.
-
From a software engineering perspective, having a |
Beta Was this translation helpful? Give feedback.
-
As discussed in the last developers meeting, we have a major problem about consistent naming of things and we need to tackle this before redesigning anything close to symbol resolving.
The current situation
Everyone
Node
has aname
property. This is set mostly to the local name of a declaration or expression, such asprintf
. However, there are two special cases to naming:RecordDeclaration
expects to have its fully qualified name (FQN) set to thename
property, otherwise certain things won't resolve.CallExpression
has an additionalfqn
field that expects the FQN of the call target, such asMyClass::method
. However, this only seems to be used for static call resolutions? Not exactly sureMethodDeclaration
nodes that "live" outside of a class be namedMyClass::method
, although I cannot 100 % confirm this in the code right now.We have a major problem in properly resolving scoped calls because for some of the nodes, we do not know its FQN and for some we just seem to ignore it.
There are also two functions in the
ScopeManager
that try to retrieve the current "namespace":currentNamePrefix
andcurrentNamePrefixWithDelimiter
although I am a bit lost why there are two functions, one of which just seems to append the current namespace delimiter (such as::
). I would assume that this works correctly.Possible Solutions
Option A:
Name
classThe first option would be to keep using one
name
field (and removing all others), but instead of having this asString
, it would be a specialName
class which does the heavy lifting. AName
would then probably have properties like asimpleName
and aparent
to model something likeName("method", "MyClass", "::")
.Advantages
Cleaner and we can "enforce" proper hierarchy in names.
Drawbacks
Name
class such asnode.name = Name("myName")
, even though we only want a simple name without any namespace. Maybe there is some Kotlin magic? @maximilian-galanisLanguageFrontend
that does that for us.(to be finished later)
Option B: Two fields
name
andfqn
Alternatively, we introduce two fields.
name
which is always the local name andfqn
which is the (optional) FQN of the node.Advantages
Leaner, can use
String
for both.Disadvantages
We once again rely on the developer to do things right, e.g., having the right delimiter and we cannot enforce proper hierarchy of names because it is just a string.
Option C: Maybe both-ish?
Third option could be to keep
name
as a string and have a separate field (maybefqn
maybefullName
) that uses theName
class. But we still then would need to keep them in sync. But this could maybe be done with Kotlin setters/getters, wherename
is basically just a virtual property andfullName
is the backing field.Beta Was this translation helpful? Give feedback.
All reactions