Skip to content

Commit

Permalink
Merge branch 'topic/1288' into 'master'
Browse files Browse the repository at this point in the history
Fix user-defined literals aspect association name resolution

Closes #1288

See merge request eng/libadalang/libadalang!1554
  • Loading branch information
thvnx committed Feb 28, 2024
2 parents 3b74355 + 2e87463 commit a2fbb54
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 53 deletions.
130 changes: 120 additions & 10 deletions ada/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,24 @@ def is_keyword(token=T.Token, language_version=T.Symbol):
Static method. Return the standard Wide_Wide_Character type.
"""
)
std_string_type = Property(
Self.std_entity('String').cast(T.BaseTypeDecl), public=True,
doc="""
Static method. Return the standard String type.
"""
)
std_wide_string_type = Property(
Self.std_entity('Wide_String').cast(T.BaseTypeDecl), public=True,
doc="""
Static method. Return the standard Wide_String type.
"""
)
std_wide_wide_string_type = Property(
Self.std_entity('Wide_Wide_String').cast(T.BaseTypeDecl),
public=True, doc="""
Static method. Return the standard Wide_Wide_String type.
"""
)

std_root_types = Property(
Self.std_entity('root_types_').cast(T.PackageDecl)._.children_env,
Expand Down Expand Up @@ -2055,6 +2073,15 @@ class Aspect(Struct):
""")


class UserDefinedFunctionSubpSpec(Struct):
"""
Structure to hold an expected subprogram specification (parameters and
return types only) denoted by an user defined function.
"""
subp_params_types = UserField(T.BaseTypeDecl.entity.array)
subp_return_type = UserField(T.BaseTypeDecl.entity)


@abstract
class BasicDecl(AdaNode):
"""
Expand Down Expand Up @@ -8660,6 +8687,48 @@ def variable_indexing_fns():
)
)

@langkit_property(return_type=T.BasicDecl.entity.array)
def user_defined_literal_fns(aspect=T.Symbol):
"""
Return the functions detoned by the user defined literal aspect
``aspect`` for this type.
"""
# User-defined literal aspects denote a function with a result type of
# ``Entity`` and one parameter that is of type ``String`` (or
# ``Wide_Wide_String`` for ``String_Literal``).
expected_spec = Var(UserDefinedFunctionSubpSpec.new(
subp_params_types=If(
aspect == 'String_Literal',
Self.std_wide_wide_string_type,
Self.std_string_type
).singleton,
subp_return_type=Entity
))
# ``Real_Literal`` detoned function can be overrode by a function with
# a result type of ``Entity`` and two parameters that are of type
# ``String``.
expected_specs = Var(If(
aspect == 'Real_Literal',
UserDefinedFunctionSubpSpec.new(
subp_params_types=[Self.std_string_type, Self.std_string_type],
subp_return_type=Entity
),
No(T.UserDefinedFunctionSubpSpec)
).singleton.concat(expected_spec.singleton))

return Entity.get_aspect_spec_expr(aspect).then(
lambda a: a.cast_or_raise(T.Name)
.all_env_elements_internal(seq=False).filtermap(
lambda e: e.cast(T.BasicDecl),
lambda env_el:
env_el.cast_or_raise(T.BasicDecl).subp_spec_or_null.then(
lambda ss: expected_specs.any(
lambda es: ss.match_expected_user_defined_function(es)
)
)
)
)


class ConcreteTypeDecl(TypeDecl):
"""
Expand Down Expand Up @@ -10764,7 +10833,7 @@ def xref_equation():
& expr.expect_bool_derived_type
) & Entity.args.at(1)._.assoc_expr.then(
lambda msg:
Bind(msg.expected_type_var, Self.std_entity('String'))
Bind(msg.expected_type_var, Self.std_string_type)
& msg.sub_equation
& msg.matches_expected_type,
default_val=LogicTrue()
Expand Down Expand Up @@ -10798,7 +10867,7 @@ def xref_equation():
expr.sub_equation
),

Bind(expr.expected_type_var, Self.std_entity("String"))
Bind(expr.expected_type_var, Self.std_string_type)
& expr.sub_equation
& expr.matches_expected_type
),
Expand Down Expand Up @@ -11388,6 +11457,11 @@ def xref_equation():
Entity.id.name_is('Stable_Properties'),
Entity.stable_properties_assoc_equation,

Entity.id.name_symbol.any_of(
'Integer_Literal', 'Real_Literal', 'String_Literal'
),
Entity.user_defined_literals_equation(target.cast(T.TypeDecl)),

# Constant_Indexing and Variable_Indexing aspects name expression
# can denotes one or more functions. Since name resolution can set
# only one reference for a name, only keep the first function
Expand Down Expand Up @@ -11452,6 +11526,22 @@ def stable_properties_assoc_equation():
)
)

@langkit_property(return_type=Equation, dynamic_vars=[env, origin])
def user_defined_literals_equation(target=T.TypeDecl):
"""
Equation for the case where this is an aspect assoc for a
user-defined literal.
"""
return Bind(
Entity.expr.cast_or_raise(T.Identifier).ref_var,
target.as_entity.user_defined_literal_fns(
Entity.id.name_symbol
).at(
# First result in the list is the last override if any
0
)
)

@langkit_property(return_type=T.String)
def aspect_name(n=T.Name.entity):
"""
Expand Down Expand Up @@ -19395,6 +19485,26 @@ def match_other(other=T.BaseFormalParamHolder.entity,
other.cast_or_raise(BaseSubpSpec), match_names
)

@langkit_property(return_type=Bool)
def match_expected_user_defined_function(fn=T.UserDefinedFunctionSubpSpec):
"""
Return whether UserDefinedFunctionSubpSpec's signature matches Self's.
"""
return And(
Entity.return_type.matching_type(fn.subp_return_type),
Entity.unpacked_formal_params.then(
lambda params: And(
params.length == fn.subp_params_types.length,
params.filter(
lambda i, p:
Not(p.formal_decl.formal_type.matching_type(
fn.subp_params_types.at(i)
))
).is_null
)
)
)

@langkit_property(return_type=LexicalEnv, dynamic_vars=[origin])
def defining_env():
"""
Expand Down Expand Up @@ -20428,13 +20538,13 @@ def xref_equation():
Entity.access_equation,

rel_name == 'Image',
Entity.image_equation(Self.std_entity('String')),
Entity.image_equation(Self.std_string_type),

rel_name == 'Wide_Image',
Entity.image_equation(Self.std_entity('Wide_String')),
Entity.image_equation(Self.std_wide_string_type),

rel_name == 'Wide_Wide_Image',
Entity.image_equation(Self.std_entity('Wide_Wide_String')),
Entity.image_equation(Self.std_wide_wide_string_type),

rel_name == 'Enum_Rep',
Entity.enum_rep_equation,
Expand All @@ -20453,7 +20563,7 @@ def xref_equation():
Entity.universal_real_equation,

rel_name == 'Img',
Entity.img_equation(Self.std_entity('String')),
Entity.img_equation(Self.std_string_type),

rel_name == 'Tag', Entity.tag_attr_equation,

Expand Down Expand Up @@ -20498,10 +20608,10 @@ def xref_equation():

rel_name.any_of('External_Tag', 'Type_Key'),
Entity.prefix.sub_equation
& Bind(Self.type_var, Self.std_entity('String')),
& Bind(Self.type_var, Self.std_string_type),

rel_name == 'Target_Name',
Bind(Self.type_var, Self.std_entity('String')),
Bind(Self.type_var, Self.std_string_type),

rel_name == 'Storage_Pool', Entity.storage_pool_equation,

Expand Down Expand Up @@ -21073,7 +21183,7 @@ def xref_equation():
lambda er: And(
# The expected type of that error message is always String,
# according to RM 11.3 - 3.1/2.
Bind(er.expected_type_var, Self.std_entity('String')),
Bind(er.expected_type_var, Self.std_string_type),
er.sub_equation
),
default_val=LogicTrue()
Expand Down Expand Up @@ -22492,7 +22602,7 @@ def xref_equation():
lambda er: And(
# The expected type of that error message is always String,
# according to RM 11.3 - 3.1/2.
Bind(er.expected_type_var, Self.std_entity('String')),
Bind(er.expected_type_var, Self.std_string_type),
er.sub_equation
),
default_val=LogicTrue()
Expand Down
4 changes: 4 additions & 0 deletions testsuite/tests/name_resolution/user_defined_int_lit/test.adb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ procedure Test is
package Big_Ints is
type Big_Int is private
with Integer_Literal => To_Big_Int;
pragma Test_Block;

function To_Big_Int (X : Boolean) return Big_Int;
function To_Big_Int (X : String) return Big_Int;
function To_Big_Int (X, Y : String) return Big_Int;
function To_Big_Int (X : String) return Integer;

private
type Big_Int is record
Expand Down
56 changes: 34 additions & 22 deletions testsuite/tests/name_resolution/user_defined_int_lit/test.out
Original file line number Diff line number Diff line change
@@ -1,75 +1,87 @@
Analyzing test.adb
##################

Resolving xrefs for node <ObjectDecl ["X"] test.adb:21:4-21:30>
Resolving xrefs for node <AspectAssoc test.adb:4:15-4:44>
*********************************************************

Expr: <Id "Integer_Literal" test.adb:4:15-4:30>
references: None
type: None
expected type: None
Expr: <Id "To_Big_Int" test.adb:4:34-4:44>
references: <DefiningName "To_Big_Int" test.adb:8:16-8:26>
type: None
expected type: None

Resolving xrefs for node <ObjectDecl ["X"] test.adb:25:4-25:30>
***************************************************************

Expr: <DottedName test.adb:21:8-21:24>
Expr: <DottedName test.adb:25:8-25:24>
references: <DefiningName "Big_Int" test.adb:3:12-3:19>
type: None
expected type: None
Expr: <Id "Big_Ints" test.adb:21:8-21:16>
Expr: <Id "Big_Ints" test.adb:25:8-25:16>
references: <DefiningName "Big_Ints" test.adb:2:12-2:20>
type: None
expected type: None
Expr: <Id "Big_Int" test.adb:21:17-21:24>
Expr: <Id "Big_Int" test.adb:25:17-25:24>
references: <DefiningName "Big_Int" test.adb:3:12-3:19>
type: None
expected type: None
Expr: <Int test.adb:21:28-21:29>
Expr: <Int test.adb:25:28-25:29>
references: None
type: <ConcreteTypeDecl ["Universal_Int_Type_"] __standard:116:3-116:45>
expected type: <ConcreteTypeDecl ["Big_Int"] test.adb:3:7-4:45>

Resolving xrefs for node <ObjectDecl ["Y"] test.adb:25:4-25:30>
Resolving xrefs for node <ObjectDecl ["Y"] test.adb:29:4-29:30>
***************************************************************

Expr: <DottedName test.adb:25:8-25:24>
Expr: <DottedName test.adb:29:8-29:24>
references: <DefiningName "Big_Int" test.adb:3:12-3:19>
type: None
expected type: None
Expr: <Id "Big_Ints" test.adb:25:8-25:16>
Expr: <Id "Big_Ints" test.adb:29:8-29:16>
references: <DefiningName "Big_Ints" test.adb:2:12-2:20>
type: None
expected type: None
Expr: <Id "Big_Int" test.adb:25:17-25:24>
Expr: <Id "Big_Int" test.adb:29:17-29:24>
references: <DefiningName "Big_Int" test.adb:3:12-3:19>
type: None
expected type: None
Expr: <Id "N" test.adb:25:28-25:29>
references: <DefiningName "N" test.adb:24:4-24:5>
Expr: <Id "N" test.adb:29:28-29:29>
references: <DefiningName "N" test.adb:28:4-28:5>
type: <ConcreteTypeDecl ["Universal_Int_Type_"] __standard:116:3-116:45>
expected type: <ConcreteTypeDecl ["Big_Int"] test.adb:3:7-4:45>

Resolving xrefs for node <ObjectDecl ["Z"] test.adb:29:4-29:21>
Resolving xrefs for node <ObjectDecl ["Z"] test.adb:33:4-33:21>
***************************************************************

Expr: <Id "Big_Pos" test.adb:29:8-29:15>
references: <DefiningName "Big_Pos" test.adb:28:12-28:19>
Expr: <Id "Big_Pos" test.adb:33:8-33:15>
references: <DefiningName "Big_Pos" test.adb:32:12-32:19>
type: None
expected type: None
Expr: <Int test.adb:29:19-29:20>
Expr: <Int test.adb:33:19-33:20>
references: None
type: <ConcreteTypeDecl ["Universal_Int_Type_"] __standard:116:3-116:45>
expected type: <SubtypeDecl ["Big_Pos"] test.adb:28:4-28:40>
expected type: <SubtypeDecl ["Big_Pos"] test.adb:32:4-32:40>

Resolving xrefs for node <ObjectDecl ["XX"] test.adb:32:4-32:31>
Resolving xrefs for node <ObjectDecl ["XX"] test.adb:36:4-36:31>
****************************************************************

Expr: <DottedName test.adb:32:9-32:25>
Expr: <DottedName test.adb:36:9-36:25>
references: <DefiningName "Big_Int" test.adb:3:12-3:19>
type: None
expected type: None
Expr: <Id "Big_Ints" test.adb:32:9-32:17>
Expr: <Id "Big_Ints" test.adb:36:9-36:17>
references: <DefiningName "Big_Ints" test.adb:2:12-2:20>
type: None
expected type: None
Expr: <Id "Big_Int" test.adb:32:18-32:25>
Expr: <Id "Big_Int" test.adb:36:18-36:25>
references: <DefiningName "Big_Int" test.adb:3:12-3:19>
type: None
expected type: None
Expr: <Id "X" test.adb:32:29-32:30>
references: <DefiningName "X" test.adb:21:4-21:5>
Expr: <Id "X" test.adb:36:29-36:30>
references: <DefiningName "X" test.adb:25:4-25:5>
type: <ConcreteTypeDecl ["Big_Int"] test.adb:3:7-4:45>
expected type: <ConcreteTypeDecl ["Big_Int"] test.adb:3:7-4:45>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ procedure Test is
package Big_Reals is
type Big_Real is private
with Real_Literal => To_Big_Real;
pragma Test_Block;

function To_Big_Real (X : String) return Big_Real;
function To_Big_Real (X, Y : String) return Big_Real;
Expand Down
Loading

0 comments on commit a2fbb54

Please sign in to comment.