Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve abstraction for AssocList, fix bug in optional else #315

Merged
merged 5 commits into from
Mar 1, 2021

Conversation

jsiek
Copy link
Contributor

@jsiek jsiek commented Feb 28, 2021

Created a persistent map abstraction for AssocList, replacing the low-level cons abstraction.

Also fixed a bug in the interpreter regarding optional else clause of an if statement.
I had forgotten to update HandleValue in a previous commit.

@jsiek jsiek requested a review from dabrahams February 28, 2021 12:43
@google-cla google-cla bot added the cla: yes PR meets CLA requirements according to bot. label Feb 28, 2021
Copy link

@dabrahams dabrahams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely an improvement!

I left lots of detailed comments, many of which I don't expect to be addressed in this PR. Some I feel a little strongly should be addressed (e.g. keeping Cons private and out of APIs), but mostly I've said a lot so you can understand how I'm thinking about readability and the future. So please feel free to argue with me, defer improvements to later PRs, etc.

@@ -21,8 +21,8 @@ namespace Carbon {

State* state = nullptr;

auto PatternMatch(Value* pat, Value* val, Env*, std::list<std::string>*, int)
-> Env*;
auto PatternMatch(Value* pat, Value* val, Env, std::list<std::string>*, int)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you're in here, it would be great to have a comment explaining what this function does, and especially the difference in meaning between returning a null optional and returning the 3rd parameter unchanged (or an empty Env). I realize comments are a whole project unto themselves, but the problem is, without the comment, any change becomes very difficult to review, and you're the only one who knows this code.

(N.B. I would always give the parameters names that can be referred to in the comment.)

V value;
AssocList* next;
};
auto Extend(const K& k, const V& v) -> void {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if extend is a good name for this. It writes a new association, replacing any existing one for k, right?
If this were swift, it would be easy and idiomatic to write it as the setter for a subscript. In C++, I dunno, SetValueAt is the best name I can come up with.

Suggested change
auto Extend(const K& k, const V& v) -> void {
auto SetValueAt(const K& k, const V& v) -> void {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extend is the name from the PL literature, but I can see that the name by-itself doesn't really convey the right meaning. I like your suggestion.

namespace Carbon {

template <class K, class V>
struct AssocList {
AssocList(K k, V v, AssocList* n) : key(k), value(v), next(n) {}
class AssocList {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as we're reshaping this, how about this?

Suggested change
class AssocList {
class Dictionary {

return alist->value;
} else {
return Lookup(line_num, alist->next, key, print_key);
auto Extending(const K& k, const V& v) -> AssocList<K, V> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto Extending(const K& k, const V& v) -> AssocList<K, V> {
auto SettingValueAt(const K& k, const V& v) -> AssocList<K, V> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another problem with Extending(k, v) is that it reads like it's extending k.

CheckAlive(v, exp->line_num);
frame->todo.Pop();
frame->todo.Push(MakeValAct(v));
auto a = CurrentEnv(state).Lookup(*(exp->u.variable.name));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps another place where auto isn't helping.

Suggested change
auto a = CurrentEnv(state).Lookup(*(exp->u.variable.name));
Address a = CurrentEnv(state).Lookup(*(exp->u.variable.name));

Or is that

Suggested change
auto a = CurrentEnv(state).Lookup(*(exp->u.variable.name));
optional<Address> a = CurrentEnv(state).Lookup(*(exp->u.variable.name));

?

Though if I knew what a meant (its role) it probably would have been fine, e.g.

Suggested change
auto a = CurrentEnv(state).Lookup(*(exp->u.variable.name));
auto variableStorageLocation = CurrentEnv(state).Lookup(*(exp->u.variable.name));

frame->todo.Pop();
frame->todo.Push(MakeValAct(v));
auto a = CurrentEnv(state).Lookup(*(exp->u.variable.name));
if (a) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggests we want some kind of unwrapOrError abstraction for optionals or better yet env.ValueAssertedAt(k, closureThatFormatsTheErrorMessage). C++ sure is clumsy at this.

Value* v = state->heap[a];
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(v));
auto a = CurrentEnv(state).Lookup(*(exp->u.variable.name));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto a = CurrentEnv(state).Lookup(*(exp->u.variable.name));
Address a = CurrentEnv(state).Lookup(*(exp->u.variable.name));

@@ -1141,16 +1162,17 @@ void HandleValue() {
Value* v = act->results[0];
Value* p = act->results[1];
// Address a = AllocateValue(CopyVal(v));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unexplained commented out code is more harmful than helpful IMO

Suggested change
// Address a = AllocateValue(CopyVal(v));

@@ -660,16 +664,16 @@ auto TopLevel(std::list<Declaration*>* fs) -> std::pair<TypeEnv*, Env*> {

auto FunctionDeclaration::TopLevel(ExecutionEnvironment& tops) const -> void {
auto t = TypeOfFunDef(tops.first, tops.second, definition);
tops.first = new TypeEnv(Name(), t, tops.first);
tops.first.Extend(Name(), t);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing; we're associating t with the empty Name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name() isn't empty... that's a getter method that you defined... so that's the name of the choice.

…that use pointers, shouldn't have been there yet
@jsiek
Copy link
Contributor Author

jsiek commented Mar 1, 2021

I'm going to address Dave's comments in a subsequent PR... I forgot to make a branch for this one so I'm not sure how to update it...

@jsiek jsiek merged commit e77dfa6 into carbon-language:trunk Mar 1, 2021
@dabrahams dabrahams mentioned this pull request Mar 1, 2021
fowles pushed a commit that referenced this pull request Mar 1, 2021
chandlerc pushed a commit that referenced this pull request Jun 28, 2022
* improve abstraction for AssocList, fix bug in optional else

* add flag for tracing output, clean up code for output

* turned off tracing by default, updated goldens, removed two examples that use pointers, shouldn't have been there yet
chandlerc pushed a commit that referenced this pull request Jun 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes PR meets CLA requirements according to bot.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants