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

Setup PyDough AST backreferences and hidden backreferences #21

Merged
merged 101 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
4c861a9
Setting up AST module, simple verifier, and basic test [RUN CI]
knassre-bodo Oct 24, 2024
3144e94
Added deducer initial impl and tests
knassre-bodo Oct 24, 2024
5b25976
Fixing AST invocation
knassre-bodo Oct 24, 2024
4b5b0b0
Merge branch 'kian/setup_type_verifiers' into kian/setup_type_deducers
knassre-bodo Oct 24, 2024
8c8eff0
Merge branch 'main' into kian/setup_type_verifiers
knassre-bodo Oct 25, 2024
bd4e5a2
Added messages to type test assertions
knassre-bodo Oct 25, 2024
be5bb3a
Updating after pulling from main [RUN CI]
knassre-bodo Oct 25, 2024
c4aa476
Merge branch 'kian/setup_type_verifiers' into kian/setup_type_deducers
knassre-bodo Oct 25, 2024
0a2a3a8
Revisions [RUN CI]
knassre-bodo Oct 25, 2024
2fd66f1
Added expression operators, binary operators, simple binop fixture-ba…
knassre-bodo Oct 25, 2024
9fb5101
Fixing tpye inference
knassre-bodo Oct 25, 2024
80c980f
Revising verifiers
knassre-bodo Oct 25, 2024
d70ae7d
Updating type deducers
knassre-bodo Oct 25, 2024
2626fe9
Removing merge conflicts [RUN CI]
knassre-bodo Oct 25, 2024
9cf3512
Adding operator registry import magic [RUN CI]
knassre-bodo Oct 28, 2024
a64349f
Adding operator registries, expression function calls
knassre-bodo Oct 28, 2024
657a2d4
[RUN CI]
knassre-bodo Oct 28, 2024
6331886
Initial impl WIP
knassre-bodo Oct 28, 2024
d35a934
Renaming expression function operators accordingly
knassre-bodo Oct 28, 2024
5c7a018
Merge branch 'kian/setup_expression_operators' into kian/setup_expres…
knassre-bodo Oct 28, 2024
1167458
Adding valid typing test
knassre-bodo Oct 28, 2024
5273f04
Adding node builder, info class for tests, and refactoring imports
knassre-bodo Oct 28, 2024
d12058a
Fixing import bug
knassre-bodo Oct 28, 2024
dd4c3bc
Compressing test imports
knassre-bodo Oct 28, 2024
1d501de
Refactoring metadata imports
knassre-bodo Oct 28, 2024
5eff4ac
Updating metadata imports
knassre-bodo Oct 28, 2024
c2b7d7c
Minor revisions
knassre-bodo Oct 28, 2024
8b92a7f
[RUN CI]
knassre-bodo Oct 28, 2024
1337863
[RUN CI]
knassre-bodo Oct 28, 2024
51b99d8
Updating types
knassre-bodo Oct 28, 2024
624e277
[RUN CI]
knassre-bodo Oct 28, 2024
5221fb0
Merge branch 'kian/update_metadata_imports' into kian/setup_type_dedu…
knassre-bodo Oct 28, 2024
6262a60
Merge branch 'kian/update_metadata_imports' into kian/setup_type_veri…
knassre-bodo Oct 28, 2024
01dad04
Adding module-level docstrings
knassre-bodo Oct 28, 2024
b4b13ff
Updating module level docstrings and inits [RUN CI]
knassre-bodo Oct 28, 2024
5a8a7a0
Resolving upstream conflicts
knassre-bodo Oct 28, 2024
275470d
Resolving conflicts
knassre-bodo Oct 28, 2024
3b8e8d9
Adding class docstring
knassre-bodo Oct 28, 2024
b3877b7
Adding class docstring
knassre-bodo Oct 28, 2024
aac48f3
Merge branch 'kian/setup_type_verifiers' into kian/setup_type_deducers
knassre-bodo Oct 28, 2024
0388683
Updating import paths [RUN CI]
knassre-bodo Oct 28, 2024
f9214cf
Resolivng conflicts and imports
knassre-bodo Oct 28, 2024
fedc9ea
Adding TODO strings
knassre-bodo Oct 28, 2024
7f7fae4
Squishing imports
knassre-bodo Oct 28, 2024
e605f7b
Removing duplicate
knassre-bodo Oct 28, 2024
39b6aae
Resolving conflicts
knassre-bodo Oct 28, 2024
92bbb48
Adjusting imports
knassre-bodo Oct 28, 2024
691e6ca
Adjusting testing setup with tpch_node_builder
knassre-bodo Oct 28, 2024
66dfb07
Added more info/builder-based tests [RUN CI]
knassre-bodo Oct 28, 2024
671a399
Adding/implementing collections semantics WIP
knassre-bodo Oct 29, 2024
c8438b9
Resolving conflicts [RUN CI]
knassre-bodo Oct 29, 2024
b87b0bc
Porting over collection files
knassre-bodo Oct 29, 2024
d1b788d
Resolving conflicts
knassre-bodo Oct 29, 2024
10302fe
Pulling down from expression nodes
knassre-bodo Oct 29, 2024
8095ee6
Removing collection logic
knassre-bodo Oct 29, 2024
8748c7c
Resolving conflicts
knassre-bodo Oct 29, 2024
2cc521b
Pushing subcollection components into next PR
knassre-bodo Oct 29, 2024
9939abc
Resolving conflicts
knassre-bodo Oct 29, 2024
7a86de3
Set up collection info pipelining for tests
knassre-bodo Oct 29, 2024
c7b8733
Minor update
knassre-bodo Oct 29, 2024
f293f5f
Minor update
knassre-bodo Oct 29, 2024
d2022bf
Renaming files [RUN CI]
knassre-bodo Oct 29, 2024
d6dd999
Experimenting with tree string
knassre-bodo Oct 29, 2024
2d17449
Experimenting with tree string
knassre-bodo Oct 29, 2024
c9e1c15
Finished implementing subcollection and compound reasoning
knassre-bodo Oct 30, 2024
d46b369
Adjusting test utils [RUN CI]
knassre-bodo Oct 30, 2024
7f7d2db
Adjusting tree string comment
knassre-bodo Oct 30, 2024
e2f013d
Cleaning up TestInfo classes
knassre-bodo Oct 30, 2024
dc610f6
Resolving conflicts
knassre-bodo Oct 30, 2024
2495111
Fixing typo
knassre-bodo Oct 30, 2024
65cb2b7
Fixing test info [RUN CI]
knassre-bodo Oct 30, 2024
a654dbb
Resolving conflicts [RUN CI]
knassre-bodo Oct 30, 2024
3a3255a
Adding error tests [RUN CI]
knassre-bodo Oct 30, 2024
f4d5031
Added back reference classes
knassre-bodo Oct 30, 2024
c7317ad
Added string based tests and backreference error tests
knassre-bodo Oct 31, 2024
2bcffe9
Pulling up downstream changes to expressions [RUN CI]
knassre-bodo Oct 31, 2024
52ede47
Pulling downstream changes [RUN CI]
knassre-bodo Oct 31, 2024
655ed42
Merge branch 'kian/init_collections' into kian/setup_collections
knassre-bodo Oct 31, 2024
dc24539
Pulling downstreamc changes and adding some comments
knassre-bodo Oct 31, 2024
228ab0f
Adding more comments [RUN CI]
knassre-bodo Oct 31, 2024
cdd94a4
Merge branch 'kian/setup_collections' into kian/setup_backreference
knassre-bodo Oct 31, 2024
f3e4ce7
Pulling up minor binary operator change
knassre-bodo Nov 1, 2024
13aa372
Test additions WIP
knassre-bodo Nov 1, 2024
9cdd534
Adding more nested binop string tests [RUN CI]
knassre-bodo Nov 1, 2024
852813c
Merge branch 'kian/setup_expression_nodes' into kian/init_collections
knassre-bodo Nov 1, 2024
5df1983
Merge branch 'kian/init_collections' into kian/setup_collections
knassre-bodo Nov 1, 2024
4a085f0
Resolving conflicts and pulling up downstream changes [RUN CI]
knassre-bodo Nov 1, 2024
dddc592
Refactoring drastically to have global context that table collections…
knassre-bodo Nov 3, 2024
8c4c0b0
Resolving conflicts and updating subcollection class hierarchy
knassre-bodo Nov 3, 2024
25b1809
Resolving conflcits after pulling down changes to subcollection class…
knassre-bodo Nov 3, 2024
9f0fef6
Revisions [RUN CI]
knassre-bodo Nov 4, 2024
45a2dec
Merge branch 'kian/init_collections' into kian/setup_collections
knassre-bodo Nov 4, 2024
6319122
Revisions [RUN CI]
knassre-bodo Nov 4, 2024
73d9324
Merge branch 'kian/setup_collections' into kian/setup_backreference
knassre-bodo Nov 4, 2024
afa93d3
resolving conflicts
knassre-bodo Nov 4, 2024
209858b
Merge branch 'kian/ast_expr_collection_part_1' into kian/setup_collec…
knassre-bodo Nov 4, 2024
25adaae
Resolving conflicts
knassre-bodo Nov 4, 2024
261544a
Resolving conflicts (part 1)
knassre-bodo Nov 4, 2024
68ed253
Resolving conflicts (part 2)
knassre-bodo Nov 4, 2024
42ab7be
Merge branch 'kian/setup_collections' into kian/setup_backreference
knassre-bodo Nov 4, 2024
15999dd
Resolving merge conflicts (part 1)
knassre-bodo Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions pydough/pydough_ast/collections/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
"GlobalContext",
"CollectionAccess",
"SubCollection",
"CompoundSubCollection",
]

from .collection_ast import PyDoughCollectionAST
from .table_collection import TableCollection
from .sub_collection import SubCollection
from .compound_sub_collection import CompoundSubCollection
from .calc import Calc
from .global_context import GlobalContext
from .collection_access import CollectionAccess
71 changes: 71 additions & 0 deletions pydough/pydough_ast/collections/back_reference_collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""
TODO: add file-level docstring
"""

__all__ = ["BackReferenceCollection"]

from typing import Dict, Tuple
from pydough.pydough_ast.abstract_pydough_ast import PyDoughAST
from .collection_ast import PyDoughCollectionAST
from pydough.pydough_ast.errors import PyDoughASTException
from .collection_access import CollectionAccess


class BackReferenceCollection(CollectionAccess):
"""
The AST node implementation class representing a subcollection of an
ancestor collection.
"""

def __init__(
self,
parent: PyDoughCollectionAST,
term_name: str,
back_levels: int,
):
if not (isinstance(back_levels, int) and back_levels > 0):
raise PyDoughASTException(
f"Expected number of levels in BACK to be a positive integer, received {back_levels!r}"
)
self._term_name: str = term_name
self._back_levels: int = back_levels
for _ in range(back_levels):
self._ancestor = self._ancestor.ancestor_context
if self._ancestor is None:
msg: str = "1 level" if back_levels == 1 else f"{back_levels} levels"
raise PyDoughASTException(
f"Cannot reference back {msg} above {parent!r}"
)
self._collection_access: CollectionAccess = self._ancestor.get_term(term_name)
super().__init__(self._collection_access.collection, parent)

@property
def back_levels(self) -> int:
"""
The number of levels upward that the backreference refers to.
"""
return self._back_levels

@property
def term_name(self) -> str:
"""
The name of the subcollection being accessed from the ancestor.
"""
return self._term_name

@property
def collection_access(self) -> CollectionAccess:
"""
The collection access property of the ancestor that BACK points to.
"""
return self._collection_access

@property
def properties(self) -> Dict[str, Tuple[int | None, PyDoughAST]]:
return self.collection_access.properties

def to_string(self) -> str:
return f"BACK({self.back_levels}).{self._subcollection.to_string()}"

def to_tree_form(self) -> None:
raise NotImplementedError
22 changes: 22 additions & 0 deletions pydough/pydough_ast/collections/compound_sub_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from pydough.pydough_ast.abstract_pydough_ast import PyDoughAST
from .collection_ast import PyDoughCollectionAST
from .sub_collection import SubCollection
from .hidden_back_reference_collection import HiddenBackReferenceCollection
from pydough.pydough_ast.expressions.hidden_back_reference_expression import (
HiddenBackReferenceExpression,
)


class CompoundSubCollection(SubCollection):
Expand Down Expand Up @@ -160,6 +164,24 @@ def properties(self) -> Dict[str, Tuple[int | None, PyDoughAST]]:
raise PyDoughASTException(
f"Undefined inherited properties: {undefined_inherited}"
)
for alias, (location, original_name) in self._inheritance_sources.items():
calc_idx, expr = self._properties[alias]
ancestor: PyDoughCollectionAST = self._subcollection_chain[location]
back_levels: int = len(self.subcollection_chain) - location
if isinstance(expr, PyDoughCollectionAST):
self._properties[alias] = (
calc_idx,
HiddenBackReferenceCollection(
self, ancestor, alias, original_name, back_levels
),
)
else:
self._properties[alias] = (
calc_idx,
HiddenBackReferenceExpression(
self, ancestor, alias, original_name, back_levels
),
)
return self._properties

def to_tree_form(self) -> None:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""
TODO: add file-level docstring
"""

__all__ = ["HiddenBackReferenceCollection"]


from .collection_ast import PyDoughCollectionAST
from .back_reference_collection import BackReferenceCollection
from .collection_access import CollectionAccess


class HiddenBackReferenceCollection(BackReferenceCollection):
"""
The AST node implementation class representing a subcollection of an
ancestor collection.
"""

def __init__(
self,
compound: PyDoughCollectionAST,
ancestor: PyDoughCollectionAST,
alias: str,
term_name: str,
back_levels: int,
):
self._term_name: str = term_name
self._back_levels: int = back_levels
self._ancestor: PyDoughCollectionAST = ancestor
self._subcollection: PyDoughCollectionAST = self._ancestor.get_term(term_name)
self._alias: str = alias
self._collection_access: CollectionAccess = self._ancestor.get_term(term_name)
super(BackReferenceCollection, self).__init__(
self._collection_access.collection, ancestor
)

@property
def alias(self) -> str:
"""
The alias that the back reference uses.
"""
return self._alias

def to_string(self) -> str:
return f"{self.parent.to_string()}.{self.alias}"

def to_tree_string(self) -> str:
raise NotImplementedError
2 changes: 2 additions & 0 deletions pydough/pydough_ast/expressions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
"Literal",
"ExpressionFunctionCall",
"Reference",
"BackReferenceExpression",
]

from .expression_ast import PyDoughExpressionAST
from .column_property import ColumnProperty
from .literal import Literal
from .expression_function_call import ExpressionFunctionCall
from .reference import Reference
from .back_reference_expression import BackReferenceExpression
76 changes: 76 additions & 0 deletions pydough/pydough_ast/expressions/back_reference_expression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
TODO: add file-level docstring
"""

__all__ = ["BackReferenceExpression"]

from . import PyDoughExpressionAST
from pydough.types import PyDoughType
from pydough.pydough_ast.collections import PyDoughCollectionAST
from pydough.pydough_ast.errors import PyDoughASTException
from .reference import Reference


class BackReferenceExpression(Reference):
"""
The AST node implementation class representing a reference to a term in
the ancestor context.
"""

def __init__(
self, collection: PyDoughCollectionAST, term_name: str, back_levels: int
):
if not (isinstance(back_levels, int) and back_levels > 0):
raise PyDoughASTException(
f"Expected number of levels in BACK to be a positive integer, received {back_levels!r}"
)
self._collection: PyDoughCollectionAST = collection
self._term_name: str = term_name
self._back_levels: int = back_levels
self._ancestor: PyDoughCollectionAST = collection
for _ in range(back_levels):
self._ancestor = self._ancestor.ancestor_context
if self._ancestor is None:
msg: str = "1 level" if back_levels == 1 else f"{back_levels} levels"
raise PyDoughASTException(
f"Cannot reference back {msg} above {collection!r}"
)
self._expression: PyDoughExpressionAST = self._ancestor.get_term(term_name)

@property
def back_levels(self) -> int:
"""
The number of levels upward that the backreference refers to.
"""
return self._back_levels

@property
def ancestor(self) -> PyDoughCollectionAST:
"""
The specific ancestor collection that the ancestor refers to.
"""
return self._ancestor

@property
def expression(self) -> PyDoughExpressionAST:
"""
The original expression that the reference refers to.
"""
return self._expression

@property
def pydough_type(self) -> PyDoughType:
return self.expression.pydough_type

@property
def is_aggregation(self) -> bool:
return self.expression.is_aggregation

def requires_enclosing_parens(self, parent: PyDoughExpressionAST) -> bool:
return False

def to_string(self) -> str:
return f"BACK({self.back_levels}).{self.term_name}"

def equals(self, other: "BackReferenceExpression") -> bool:
return super().equals(other) and self.ancestor.equals(other.ancestor)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
TODO: add file-level docstring
"""

__all__ = ["HiddenBackReferenceExpression"]

from . import PyDoughExpressionAST
from pydough.pydough_ast.collections import PyDoughCollectionAST
from .back_reference_expression import BackReferenceExpression


class HiddenBackReferenceExpression(BackReferenceExpression):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similarly, only used inside compounds.

"""
The AST node implementation class representing a reference to a term in
the ancestor context through the lens of a compound relationship's
inherited properties.
"""

def __init__(
self,
collection: PyDoughCollectionAST,
ancestor: PyDoughCollectionAST,
alias: str,
term_name: str,
back_levels: int,
):
self._collection: PyDoughCollectionAST = collection
self._alias: str = alias
self._term_name: str = term_name
self._back_levels: int = back_levels
self._ancestor: PyDoughCollectionAST = ancestor
self._expression: PyDoughExpressionAST = self._ancestor.get_term(term_name)

@property
def alias(self) -> str:
"""
The alias that the back reference uses.
"""
return self._alias

def to_string(self) -> str:
return f"HiddenBackReferenceExpression[{self.back_levels}:{self.term_name}]"
23 changes: 23 additions & 0 deletions pydough/pydough_ast/node_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
ExpressionFunctionCall,
ColumnProperty,
Reference,
BackReferenceExpression,
)
from .pydough_operators import PyDoughOperatorAST, builtin_registered_operators
from .errors import PyDoughASTException
Expand Down Expand Up @@ -132,6 +133,28 @@ def build_reference(self, collection: PyDoughCollectionAST, name: str) -> Refere
"""
return Reference(collection, name)

def build_back_reference_expression(
self, collection: PyDoughCollectionAST, name: str, levels: int
) -> Reference:
"""
Creates a new reference to an expression from an ancestor collection.

Args:
`collection`: the collection that the back reference comes from.
`name`: the name of the expression being referenced.
`levels`: the number of levels back from `collection` the reference
refers to.

Returns:
The newly created PyDough Back Reference.

Raises:
`PyDoughASTException`: if `name` does not refer to an expression in
the ancestor collection, or the collection does not have `levels`
many ancestors.
"""
return BackReferenceExpression(collection, name, levels)

def build_global_context(self) -> GlobalContext:
"""
Creates a new global context for the graph.
Expand Down
Loading