5

I am creating an AST, and I am currently introducing the concept of "scope". By implementing a scope, wherever an identifier (variable name) is used, I am able to determine its original declaration.

For the scope object, I was going to implement a dictionary as the underlying data structure. The dictionary would be keyed with the identifier object, with the value being the declaration object. The declaration object also contains a reference to the same identifier. So, something like:

class Identifier() {
    string name;
}

class Declaration() {
    Type type;
    Identifier ident;
}

class Scope() {
    Dictionary<Identifier,Declaration> identifiers;
}

What I want to know is, is keying a dictionary with a property of the key's corresponding value bad practice? Is there a better way to do this?

1

I don't see anything fundamentally wrong with this.

The fact that Identifier happens to be a member of Declaration, the type of values of your Scope's identifiers map is mostly coincidental, imho.

You could have as well opted for, say, this instead:

class Identifier() {
    string name;
}

class Declaration() {
    int id;
    Type type;
    Identifier identifier;
}

class Scope() {
    Dictionary<int, Declaration> identifiers; // (map from Declaration.id to Declaration)
}

But for whatever reason, you just found that using the Identifier itself as the "primary key" for the very Declaration which introduces it was more convenient.

What I find more intriguing, however, is why you haven't opted for the somewhat more common (I believe) for that sort of things:

class Identifier() {
    string name;
}

class Declaration() {
    Type type;
    Identifier identifier;
}

class Scope() {
    int id;
    List<Declaration> identifiers; // (declared at this scope level)
    Dictionary<int, Scope> innerScopes; // (map from Scope.id to Scope, useful for representing inner scopes, be they lexical or otherwise)
    Scope parent;
    bool IsRoot => parent == null;
}

etc?

Granted, though, my question is biased, because I usually prefer to decouple the information obtained from the syntactic analysis (ie, whatever AST you already have) and the one pertaining to the semantic one (your Scope class, populated only afterwards) -- where the main "link" between the two would be your Identifier class (eg, possibly uniquely keyed/indexed by the physical line/column location of the identifier's occurrence that declares it in the first place for this or that scope).

1
  • I also do not see a problem with this design as long as your value class is immutable. If the value of the identifier property in the value class can change after the dictionary is created, then this is not a good design.
    – Mike
    May 23 '18 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.