Skip to content

Commit

Permalink
Properties: add "Self" sloc to messages of implicit Property_Error exc.
Browse files Browse the repository at this point in the history
When a property raises an error, for instance because it tries to get
some field in a null node, it would be nice to include the sloc of the
node in that property, so that error messages give users a clue about
how it relates to the Ada source code that Libadalang analyzes, which
would be useful to workaround or investigate an issue.

Note that adding this sloc information is done on a best effort basis.
As a notable example, the Property_Error exception raised in the lexical
environment lookup system do not provide it, as the "Self" node for the
property that triggers a lexical env lookup is not available there, and
taking this information to this point would require a lot of logistics,
and possibly run time performance degradation.

Closes #635
  • Loading branch information
pmderodat committed Jul 26, 2022
1 parent c174e5c commit de0d147
Show file tree
Hide file tree
Showing 27 changed files with 248 additions and 115 deletions.
11 changes: 8 additions & 3 deletions langkit/expressions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2630,7 +2630,7 @@ def to_symbol(self, prefix):
"""
prefix_expr = construct(prefix, T.String)
return CallExpr('Sym', 'String_To_Symbol', T.Symbol,
['Self.Unit.Context', prefix_expr],
[construct(Self), 'Self.Unit.Context', prefix_expr],
abstract_expr=self)


Expand Down Expand Up @@ -5434,8 +5434,13 @@ def as_int(self, expr):
if the big integer is out of range.
"""
big_int_expr = construct(expr, T.BigInt)
return CallExpr('Small_Int', 'To_Integer', T.Int, [big_int_expr],
abstract_expr=self)
return CallExpr(
'Small_Int',
'To_Integer',
T.Int,
[construct(Self), big_int_expr],
abstract_expr=self,
)


class Arithmetic(AbstractExpression):
Expand Down
11 changes: 8 additions & 3 deletions langkit/expressions/boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from langkit.diagnostics import check_source_language
from langkit.expressions.base import (
AbstractExpression, AbstractVariable, BasicExpr, BindingScope, CallExpr,
ComputingExpr, LiteralExpr, PropertyDef, attr_call, construct,
ComputingExpr, LiteralExpr, PropertyDef, Self, attr_call, construct,
dsl_document, expr_or_null, render, sloc_info_arg, unsugar
)

Expand Down Expand Up @@ -289,8 +289,13 @@ def construct(self):
self.LE: 'Less_Or_Equal',
self.GT: 'Greater_Than',
self.GE: 'Greater_Or_Equal'}[self.operator]
return CallExpr('Node_Comp', 'Compare', T.Bool,
[lhs, rhs, relation], abstract_expr=self)
return CallExpr(
'Node_Comp',
'Compare',
T.Bool,
[construct(Self), lhs, rhs, relation],
abstract_expr=self,
)

# Otherwise, expect strict equality for both operands and use the
# native comparison operator for code generation.
Expand Down
4 changes: 2 additions & 2 deletions langkit/expressions/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from langkit.expressions.base import (
AbstractExpression, AbstractNodeData, AbstractVariable, CallExpr,
ComputingExpr, FieldAccessExpr, LocalVars, NullCheckExpr, PropertyDef,
ResolvedExpression, SequenceExpr, T, UncheckedCastExpr, VariableExpr,
ResolvedExpression, Self, SequenceExpr, T, UncheckedCastExpr, VariableExpr,
attr_call, attr_expr, auto_attr, auto_attr_custom, construct, render,
unsugar
)
Expand Down Expand Up @@ -865,7 +865,7 @@ def collection_get(self: AbstractExpression,
or_null_expr = construct(or_null)
result: ResolvedExpression = CallExpr(
'Get_Result', 'Get', element_type,
[coll_expr, index_expr, or_null_expr]
[construct(Self), coll_expr, index_expr, or_null_expr]
)

if as_entity:
Expand Down
7 changes: 5 additions & 2 deletions langkit/expressions/envs.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,11 @@ class IsVisibleFromExpr(CallExpr):
def __init__(self, referenced_env, base_env, abstract_expr=None):
super().__init__(
'Is_Visible', 'Is_Visible_From', T.Bool,
[construct(referenced_env, T.LexicalEnv),
construct(base_env, T.LexicalEnv)],
[
construct(Self),
construct(referenced_env, T.LexicalEnv),
construct(base_env, T.LexicalEnv),
],
abstract_expr=abstract_expr
)

Expand Down
11 changes: 8 additions & 3 deletions langkit/templates/array_types_ada.mako
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@
## Helper getter generated for properties code. Used in CollectionGet's code
function Get
(T : ${cls.name};
(Node : ${T.root_node.name};
T : ${cls.name};
Index : Integer;
Or_Null : Boolean := False) return ${elt_type};
-- When Index is positive, return the Index'th element in T. Otherwise,
Expand Down Expand Up @@ -208,7 +209,8 @@
---------
function Get
(T : ${cls.name};
(Node : ${T.root_node.name};
T : ${cls.name};
Index : Integer;
Or_Null : Boolean := False) return ${elt_type}
is
Expand All @@ -234,7 +236,10 @@
elsif Or_Null then
return ${cls.element_type.nullexpr};
else
raise Property_Error with "out-of-bounds array access";
Raise_Property_Exception
(Node,
Property_Error'Identity,
"out-of-bounds array access");
end if;
end Get;
Expand Down
6 changes: 4 additions & 2 deletions langkit/templates/astnode_types_ada.mako
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,11 @@
## it's fine for the empty/root environments, as they don't
## trigger relocations.
if Is_Foreign_Strict (Env, Self) then
raise Property_Error with
Raise_Property_Exception
(Self,
Property_Error'Identity,
"unsound foreign environment in RefEnvs ("
& "${ref_env.str_location})";
& "${ref_env.str_location})");
end if;
% endif
Expand Down
Loading

0 comments on commit de0d147

Please sign in to comment.