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

Rework Collections for Expect and Name #439

Merged
merged 24 commits into from
Jan 14, 2023
Merged

Conversation

JSAbrahams
Copy link
Owner

@JSAbrahams JSAbrahams commented Jan 9, 2023

Relevant issues

Summary

As has been a running theme for the past few days, this PR changes quite a lot more than originally intended.
However, we had some sloppy code which I figured would be best to clean up now instead of laborously splitting it over many PR's.
For now I see this a one in a set of major refactors, which for now is fine since I'm the only active developer.
Best to just improve the quality of the codebase now and get rid of as many bugs as possible by generalizing the type system as much as possible.
This includes getting rid of as much superfluous logic as possible.

Main change: Except::Collection to Expect::Call { ... }

Remove the collection Expect construct.
Instead, we use generics now and substitution of generics to deal with unification of collections.

  • Trim Collection type in annotated AST since that is not a valid type annotation in Python.
  • Add recursive substitution of names.
    Useful if we want to substitute temporary names.
  • Add unification and substitution of generics within names.
    Useful if we want to substitute generics which are temporary names.

This greatly simplifies a lot of exceptions we had to make for collections.
We also get to make use of type annotation logic now.

Secondary: Remove NameVariant

Instead, we just make use of Tuple[...] and Callable[Tuple[...],[...] by making helper methods which create these for us on the fly.
Under the hood, it's always StringName.
For now, I leave optionality untouched, so we don't make use of Optional[...], but instead have a boolean in TrueName.

This makes it much easier to match names directly and simplifies a lot of substitution logic within Name.
The changes here don't affect the codebase outside of name too much, because most of it was abstracted away.
But it does greatly reduce the chances of introducing a bug.
And it also simplifies the unification stage even further.

To accomodate these changes, we also revamp the generic system:

  • The context now also substitutes the generics within parents when performing a class lookup.
  • We perform matching when checking if a class if a class of another class.
    Specifically, if the literal of the names are equal (checking the lits in StringName { lit1, generics: [Name] }), we check proceed to check for each generic whether self is name of other as long as the generic count is the same.

Added Tests

TODO: list tests

@JSAbrahams JSAbrahams added the code quality: general Code quality issue not relevant to a particular module label Jan 9, 2023
@JSAbrahams JSAbrahams added this to the v0.3.6 | Dictionaries milestone Jan 9, 2023
@JSAbrahams JSAbrahams self-assigned this Jan 9, 2023
Remove the collection Expect construct.
Instead, we use generics now and substitution of
generics to deal with unification of collections.

- Ignore collection type in output
- Make temporary variables top-level

Need to augment the unification rule for types a
bit. If generics match and any generic is
temporary, these must be substituted as well.
- __iter__() call, which gives iterator.
  We constrain this using a temporary type
- __next__() call, whose return type is
  constrained to the collection type
Need to generalize how we convert mamba types
to Python types in generate stage.
In particular:
- When encountering types in the wild
- When encountering constructors in the wild

And _only_ in those situations so we don't
accidentally change identifiers with say class
names.
@JSAbrahams
Copy link
Owner Author

Add issue that we should only override identifiers with Python type in:

  • types
  • constructor calls

Makes unification logic much simpler.
Now easier to check whether something callable
or tuple.
Also simply generate by not looking at type
annotations, except for class arguments.
We are now dependent on the check stage to
annotate variables
When looking up classes in context, we convert
generic parents to concrete parents (in the form
of StringNames).

So, Collection[Int] is a super of Set[Int]:
- Set has a parent Collection[Int]
- We check that Collection[Int] is super of
  itself:
  - The first part is equal to itself.
    We also see that it has the same amount of
    generics as itself.
    - We proceed to perform this now for each
      generic by matching them.
@JSAbrahams JSAbrahams changed the title Remove Expect::Collection Rework Collections for Expect and Name Jan 10, 2023
}

pub trait IsTemp {
fn is_temp(&self) -> bool;
}

pub trait MatchTempName {
fn temp_map(&self, other: &StringName, mapping: HashMap<Name, Name>, pos: Position) -> TypeResult<HashMap<Name, Name>>;
Copy link
Owner Author

Choose a reason for hiding this comment

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

Hm perhaps some of this logic could be re-used for match_name?
They are very similar, except for the if statement.
So if you can pass a predicate then they're the same basically.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Do this at the end perhaps when we have a build where all the tests pass again.
Will make it much easier to quickly verify the refactor.

src/check/name/mod.rs Outdated Show resolved Hide resolved
Also match identifier with any expression if no
type present.
src/check/name/mod.rs Outdated Show resolved Hide resolved
}
};
match (ty, expr) {
(Some(ty), Some(expr)) => {
Copy link
Owner Author

@JSAbrahams JSAbrahams Jan 11, 2023

Choose a reason for hiding this comment

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

Have we tested type and expr?
Should the logic below for Some(expr) not also be here?
Tuple literals are bound, so it should be fine, but perhaps just a small comment to make it clear so this doesn't appear like an oversight.

If it should be here, then better to have wildcard for ty and just have a small if let Some(...) = ... binding for ty in the body.

And remove unnecessary push_ty in unify_ty.
For tuples we make an exception by iterating over
the elements and checking that they each define
__str__().

Also add extra rule for self.
In union, self is always equal to entity_name.
Other arguments are left as-is.
Should restructure name such the Name can have
nested unions.
@codecov
Copy link

codecov bot commented Jan 12, 2023

Codecov Report

Merging #439 (cb8fb18) into develop (7d06ae2) will decrease coverage by 0.13%.
The diff coverage is 85.27%.

@@             Coverage Diff             @@
##           develop     #439      +/-   ##
===========================================
- Coverage    88.59%   88.46%   -0.14%     
===========================================
  Files          110      107       -3     
  Lines        11956    11729     -227     
===========================================
- Hits         10593    10376     -217     
+ Misses        1363     1353      -10     
Impacted Files Coverage Δ
src/check/constrain/constraint/iterator.rs 84.61% <0.00%> (ø)
src/check/constrain/unify/mod.rs 75.00% <ø> (ø)
src/check/context/field/mod.rs 54.28% <ø> (ø)
src/generate/convert/control_flow.rs 90.25% <ø> (ø)
src/parse/lex/result.rs 14.28% <0.00%> (ø)
src/parse/result.rs 43.07% <0.00%> (ø)
src/check/result.rs 76.92% <33.33%> (+1.36%) ⬆️
src/generate/convert/ty.rs 57.14% <33.33%> (-12.25%) ⬇️
src/check/context/parent/mod.rs 42.85% <42.85%> (ø)
src/check/context/arg/generic.rs 76.54% <50.00%> (ø)
... and 71 more

@JSAbrahams JSAbrahams marked this pull request as ready for review January 14, 2023 19:29
@JSAbrahams JSAbrahams merged commit 6dcd7a8 into develop Jan 14, 2023
@JSAbrahams JSAbrahams deleted the rework-collection branch January 14, 2023 19:35
@JSAbrahams JSAbrahams mentioned this pull request Jan 21, 2023
JSAbrahams added a commit that referenced this pull request Jan 21, 2023
* Add substitution of names

Remove the collection Expect construct.
Instead, we use generics now and substitution of
generics to deal with unification of collections.

- Ignore collection type in output
- Make temporary variables top-level

Need to augment the unification rule for types a
bit. If generics match and any generic is
temporary, these must be substituted as well.

* Match and substitute generic

* Create two constraints for every col

- __iter__() call, which gives iterator.
  We constrain this using a temporary type
- __next__() call, whose return type is
  constrained to the collection type

* Get rid of Generic NodeTy

Need to generalize how we convert mamba types
to Python types in generate stage.
In particular:
- When encountering types in the wild
- When encountering constructors in the wild

And _only_ in those situations so we don't
accidentally change identifiers with say class
names.

* Add type annotation to non-nested builders

* Get rid of tuple construct

* Remove NameVariants

* Simplify Name to Core in generation

* Match generics when checking parent

When looking up classes in context, we convert
generic parents to concrete parents (in the form
of StringNames).

* Deal with variable generics for tuples

* Rework identifier matching with ty, expr

We added extra logic to deal with:
- tuple literals
- streamlining of tuples of identifiers

Tuple matching still trips up when not matching
with tuple literals.
Perhaps we do need some logic in the unification
stage, but this should be a last resort.

* Name hash is deterministic

* Recursively deconstruct builders

* Reorder generation in lookup

* Add extra __str__ rule to unify stage

For tuples we make an exception by iterating over
the elements and checking that they each define
__str__().

Also add extra rule for self.
In union, self is always equal to entity_name.
Other arguments are left as-is.

* Ensure nested Unions to_py deterministic

* Remove unnecessary class and function union
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code quality: general Code quality issue not relevant to a particular module enhancement: check New feature in the type check module enhancement: generate New feature in the core module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Constraint generation can be generalized to remove Expect::Collection construct
1 participant