+2021-03-08 Tom Tromey <tom@tromey.com>
+
+ * ada-lang.c (ada_var_value_operation::resolve)
+ (ada_funcall_operation::resolve)
+ (ada_ternop_slice_operation::resolve): New methods.
+ * ada-exp.h (struct ada_resolvable): New.
+ (class ada_var_value_operation): Derive from ada_resolvable.
+ <get_block, resolve>: New methods.
+ (class ada_funcall_operation): Derive from ada_resolvable.
+ <resolve>: New method.
+ (class ada_ternop_slice_operation): Derive from ada_resolvable.
+ <resolve>: New method.
+
2021-03-08 Tom Tromey <tom@tromey.com>
* ada-lang.c (ada_funcall_operation::evaluate): New method.
namespace expr
{
+/* The base class for Ada type resolution. Ada operations that want
+ to participate in resolution implement this interface. */
+struct ada_resolvable
+{
+ /* Resolve this object. EXP is the expression being resolved.
+ DEPROCEDURE_P is true if a symbol that refers to a zero-argument
+ function may be turned into a function call. PARSE_COMPLETION
+ and TRACKER are passed in from the parser context. CONTEXT_TYPE
+ is the expected type of the expression, or nullptr if none is
+ known. This method should return true if the operation should be
+ replaced by a function call with this object as the callee. */
+ virtual bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) = 0;
+};
+
/* In Ada, some generic operations must be wrapped with a handler that
handles some Ada-specific type conversions. */
class ada_wrapped_operation
/* Ada array- or string-slice operation. */
class ada_ternop_slice_operation
- : public maybe_constant_operation<operation_up, operation_up, operation_up>
+ : public maybe_constant_operation<operation_up, operation_up, operation_up>,
+ public ada_resolvable
{
public:
enum exp_opcode opcode () const override
{ return TERNOP_SLICE; }
+
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
};
/* Implement BINOP_IN_BOUNDS for Ada. */
/* Variant of var_value_operation for Ada. */
class ada_var_value_operation
- : public var_value_operation
+ : public var_value_operation, public ada_resolvable
{
public:
symbol *get_symbol () const
{ return std::get<0> (m_storage); }
+ const block *get_block () const
+ { return std::get<1> (m_storage); }
+
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
+
protected:
using operation::do_generate_ax;
/* Function calls for Ada. */
class ada_funcall_operation
- : public tuple_holding_operation<operation_up, std::vector<operation_up>>
+ : public tuple_holding_operation<operation_up, std::vector<operation_up>>,
+ public ada_resolvable
{
public:
struct expression *exp,
enum noside noside) override;
+ bool resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type) override;
+
enum exp_opcode opcode () const override
{ return OP_FUNCALL; }
};
return ada_to_fixed_value (arg1);
}
+bool
+ada_var_value_operation::resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type)
+{
+ symbol *sym = std::get<0> (m_storage);
+ if (SYMBOL_DOMAIN (sym) == UNDEF_DOMAIN)
+ {
+ block_symbol resolved
+ = ada_resolve_variable (sym, std::get<1> (m_storage),
+ context_type, parse_completion,
+ deprocedure_p, tracker);
+ std::get<0> (m_storage) = resolved.symbol;
+ std::get<1> (m_storage) = resolved.block;
+ }
+
+ if (deprocedure_p
+ && SYMBOL_TYPE (std::get<0> (m_storage))->code () == TYPE_CODE_FUNC)
+ return true;
+
+ return false;
+}
+
value *
ada_atr_val_operation::evaluate (struct type *expect_type,
struct expression *exp,
}
}
+bool
+ada_funcall_operation::resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type)
+{
+ operation_up &callee_op = std::get<0> (m_storage);
+
+ ada_var_value_operation *avv
+ = dynamic_cast<ada_var_value_operation *> (callee_op.get ());
+ if (avv == nullptr)
+ return false;
+
+ symbol *sym = avv->get_symbol ();
+ if (SYMBOL_DOMAIN (sym) != UNDEF_DOMAIN)
+ return false;
+
+ const std::vector<operation_up> &args_up = std::get<1> (m_storage);
+ int nargs = args_up.size ();
+ std::vector<value *> argvec (nargs);
+
+ for (int i = 0; i < args_up.size (); ++i)
+ argvec[i] = args_up[i]->evaluate (nullptr, exp, EVAL_AVOID_SIDE_EFFECTS);
+
+ const block *block = avv->get_block ();
+ block_symbol resolved
+ = ada_resolve_funcall (sym, block,
+ context_type, parse_completion,
+ nargs, argvec.data (),
+ tracker);
+
+ std::get<0> (m_storage)
+ = make_operation<ada_var_value_operation> (resolved.symbol,
+ resolved.block);
+ return false;
+}
+
+bool
+ada_ternop_slice_operation::resolve (struct expression *exp,
+ bool deprocedure_p,
+ bool parse_completion,
+ innermost_block_tracker *tracker,
+ struct type *context_type)
+{
+ /* Historically this check was done during resolution, so we
+ continue that here. */
+ value *v = std::get<0> (m_storage)->evaluate (context_type, exp,
+ EVAL_AVOID_SIDE_EFFECTS);
+ if (ada_is_any_packed_array_type (value_type (v)))
+ error (_("cannot slice a packed array"));
+ return false;
+}
+
}
/* Implement the evaluate_exp routine in the exp_descriptor structure