fix(gen): only generate length assertion for non-scalar ops

This commit is contained in:
HEL
2026-07-07 11:22:07 +02:00
parent 1098e33d07
commit 5051e155c0
2 changed files with 22 additions and 14 deletions
+11 -7
View File
@@ -63,7 +63,7 @@ class ColumnMethodRegistry(MethodRegistry[Call]):
) )
return result.result return result.result
def _element_binary_op(self, call: Call, method: str) -> Type: def _element_binary_op(self, call: Call, method: str) -> tuple[Type, bool]:
"""Compute the result of an element-wise binary operation """Compute the result of an element-wise binary operation
This function delegates to the inner types for computing the resulting This function delegates to the inner types for computing the resulting
@@ -74,18 +74,21 @@ class ColumnMethodRegistry(MethodRegistry[Call]):
method (str): the method name method (str): the method name
Returns: Returns:
Type: the resulting type tuple[Type, bool]: the resulting type and a boolean indicating
whether the operand is a column
""" """
if len(call.positional) == 0: if len(call.positional) == 0:
return UnknownType() return UnknownType(), False
col_type1: Type = call.column.type col_type1: Type = call.column.type
operand: TypedExpr = call.positional[0] operand: TypedExpr = call.positional[0]
unfolded_operand: Type = unfold_type(operand[1]) unfolded_operand: Type = unfold_type(operand[1])
col_type2: Type col_type2: Type
column_operand: bool = isinstance(unfolded_operand, ColumnType)
# Operand is a column -> get the inner type # Operand is a column -> get the inner type
if isinstance(unfolded_operand, ColumnType): if column_operand:
col_type2 = unfolded_operand.type col_type2 = unfolded_operand.type
# Otherwise use the operand type itself # Otherwise use the operand type itself
else: else:
@@ -98,7 +101,7 @@ class ColumnMethodRegistry(MethodRegistry[Call]):
right=(operand[0], col_type2), right=(operand[0], col_type2),
method=method, method=method,
) )
return ColumnType(type=new_inner_type) return ColumnType(type=new_inner_type), column_operand
def _element_wise(self, call: Call, method: str) -> Type: def _element_wise(self, call: Call, method: str) -> Type:
"""Compute the result of an element-wise method call """Compute the result of an element-wise method call
@@ -115,6 +118,7 @@ class ColumnMethodRegistry(MethodRegistry[Call]):
""" """
# Build signature with new column type and generic operand # Build signature with new column type and generic operand
returns, column_operand = self._element_binary_op(call, method)
signature = Function( signature = Function(
params=ParamSpec( params=ParamSpec(
mixed=[ mixed=[
@@ -126,7 +130,7 @@ class ColumnMethodRegistry(MethodRegistry[Call]):
), ),
], ],
), ),
returns=self._element_binary_op(call, method), returns=returns,
) )
# Map arguments and compute result type # Map arguments and compute result type
@@ -136,7 +140,7 @@ class ColumnMethodRegistry(MethodRegistry[Call]):
positional=call.positional, positional=call.positional,
keywords=call.keywords, keywords=call.keywords,
) )
if result.is_valid: if result.is_valid and column_operand:
self._assert_same_length( self._assert_same_length(
call.call_expr, call.column_expr, call.positional[0][0] call.call_expr, call.column_expr, call.positional[0][0]
) )
+11 -7
View File
@@ -102,7 +102,7 @@ class FrameMethodRegistry(MethodRegistry[Call]):
return ColumnType(type=UnknownType()) return ColumnType(type=UnknownType())
return result return result
def _element_binary_op(self, call: Call, method: str) -> Type: def _element_binary_op(self, call: Call, method: str) -> tuple[Type, bool]:
"""Compute the result of an element-wise binary operation """Compute the result of an element-wise binary operation
This function delegates to the matching columns for computing resulting This function delegates to the matching columns for computing resulting
@@ -115,11 +115,12 @@ class FrameMethodRegistry(MethodRegistry[Call]):
method (str): the method name method (str): the method name
Returns: Returns:
Type: the resulting type tuple[Type, bool]: the resulting type and a boolean indicating
whether the operand is a frame
""" """
if len(call.positional) == 0: if len(call.positional) == 0:
return UnknownType() return UnknownType(), False
operand: TypedExpr = call.positional[0] operand: TypedExpr = call.positional[0]
new_columns: list[DataFrameType.Column] = [] new_columns: list[DataFrameType.Column] = []
@@ -128,7 +129,8 @@ class FrameMethodRegistry(MethodRegistry[Call]):
frame2: Optional[DataFrameType] = None frame2: Optional[DataFrameType] = None
# Get map of operand's columns by name, if the operand is a dataframe # Get map of operand's columns by name, if the operand is a dataframe
unfolded_other: Type = unfold_type(operand[1]) unfolded_other: Type = unfold_type(operand[1])
if isinstance(unfolded_other, DataFrameType): frame_operand: bool = isinstance(unfolded_other, DataFrameType)
if frame_operand:
frame2 = unfolded_other frame2 = unfolded_other
by_name = {col.name: col for col in frame2.columns if col.name is not None} by_name = {col.name: col for col in frame2.columns if col.name is not None}
@@ -180,7 +182,7 @@ class FrameMethodRegistry(MethodRegistry[Call]):
) )
) )
return DataFrameType(columns=new_columns) return DataFrameType(columns=new_columns), frame_operand
def _element_wise(self, call: Call, method: str) -> Type: def _element_wise(self, call: Call, method: str) -> Type:
"""Compute the result of an element-wise method call """Compute the result of an element-wise method call
@@ -196,6 +198,8 @@ class FrameMethodRegistry(MethodRegistry[Call]):
Type: the result type Type: the result type
""" """
# TODO: support sequence, Series, dict operand # TODO: support sequence, Series, dict operand
returns, frame_operand = self._element_binary_op(call, method)
# Build signature with new schema and generic operand # Build signature with new schema and generic operand
signature = Function( signature = Function(
params=ParamSpec( params=ParamSpec(
@@ -208,7 +212,7 @@ class FrameMethodRegistry(MethodRegistry[Call]):
), ),
], ],
), ),
returns=self._element_binary_op(call, method), returns=returns,
) )
# Map arguments and compute result type # Map arguments and compute result type
@@ -218,7 +222,7 @@ class FrameMethodRegistry(MethodRegistry[Call]):
positional=call.positional, positional=call.positional,
keywords=call.keywords, keywords=call.keywords,
) )
if result.is_valid: if result.is_valid and frame_operand:
self._assert_same_length( self._assert_same_length(
call.call_expr, call.frame_expr, call.positional[0][0] call.call_expr, call.frame_expr, call.positional[0][0]
) )