Commit Graph

105356 Commits

Author SHA1 Message Date
Tom Tromey
d8a4ed8ad1 Implement Ada resolution
Ada has a parser post-pass that implements "resolution".  This process
replaces some opcodes with function calls.  For example, a "+"
operation might be replaced with a call to the appropriate overloaded
function.

This differs from the approach taken for the same problem in C++.
However, in this series I chose not to try to make changes outside of
rewrite the expression data structure.  So, resolution remains.

The new approach to resolution is to introduce an interface class,
that some concrete operations implement.  Then, the Ada code will use
this to resolve the expression tree.  Because new-style expressions
are built as ordinary objects, and don't require rewriting the data
structure in place, in the new code this processing will be done in
the parser.  By the end of the series, some special cases in this area
that exist only for Ada will be removed.

gdb/ChangeLog
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 07:28:36 -07:00
Tom Tromey
efe3af2f9a Implement function calls for Ada
This implements function calls for Ada.  This takes a different
approach than that used for other languages, primarily because Ada
requires special treatment generally.  The "ordinary" special case for
just the callee didn't really apply neatly here; there's only one case
in Ada needing special callee treatment.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_funcall_operation::evaluate): New method.
	* ada-exp.h (class ada_var_msym_value_operation) <get_symbol>: New
	method.
	(class ada_funcall_operation): New.
2021-03-08 07:28:36 -07:00
Tom Tromey
ebc06ad8f4 Introduce ada_structop_operation
This adds class ada_structop_operation, which implements
STRUCTOP_STRUCT for Ada.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_structop_operation::evaluate): New method.
	* ada-exp.h (class ada_structop_operation): New.
2021-03-08 07:28:35 -07:00
Tom Tromey
e8c33fa16a Introduce ada_unop_ind_operation
This adds class ada_unop_ind_operation, which implements UNOP_IND for
Ada.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_unop_ind_operation::evaluate): New method.
	* ada-exp.h (class ada_unop_ind_operation): New.
2021-03-08 07:28:35 -07:00
Tom Tromey
065ec8268d Introduce ada_binop_exp_operation
This adds class ada_binop_exp_operation, which implements BINOP_EXP
for Ada.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_binop_exp): No longer static.
	* ada-exp.h (ada_binop_exp_operation): New typedef.
2021-03-08 07:28:35 -07:00
Tom Tromey
9e99f48f27 Introduce ada_atr_val_operation
This adds class ada_atr_val_operation, which implements OP_ATR_VAL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_val_atr): No longer static.
	(ada_atr_val_operation::evaluate): New method.
	* ada-exp.h (class ada_atr_val_operation): New.
2021-03-08 07:28:35 -07:00
Tom Tromey
7631cf6cc8 Introduce ada_pos_operation
This adds class ada_pos_operation, a new typedef that implements
OP_ATR_POS.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_pos_atr): No longer static.
	* ada-exp.h (ada_pos_operation): New typedef.
2021-03-08 07:28:35 -07:00
Tom Tromey
7992accc6e Refactor value_pos_atr
This refactors value_pos_atr to be directly usable by a new operation
implementation.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_pos_atr): Rename from value_pos_atr.  Change
	parameters.
	(ada_evaluate_subexp): Use it.
2021-03-08 07:28:34 -07:00
Tom Tromey
6ad3b8bf3b Implement Ada min and max operations
This implement the Ada min and max operations using an existing
template class.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_binop_minmax): No longer static.
	* ada-exp.h (ada_binop_min_operation, ada_binop_max_operation):
	New typedefs.
2021-03-08 07:28:34 -07:00
Tom Tromey
3f4a0053d9 Introduce ada_var_msym_value_operation
This adds class ada_var_msym_value_operation, which implements
OP_VAR_MSYM_VALUE for Ada.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_var_msym_value_operation::evaluate_for_cast):
	New method.
	* ada-exp.h (class ada_var_msym_value_operation): New.
2021-03-08 07:28:34 -07:00
Tom Tromey
99a3b1e77b Introduce ada_var_value_operation
This adds class ada_var_value_operation, which implements OP_VAR_VALUE
for Ada.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_var_value_operation::evaluate_for_cast)
	(ada_var_value_operation::evaluate): New methods.
	* ada-exp.h (class ada_var_value_operation): New.
2021-03-08 07:28:34 -07:00
Tom Tromey
60fa02ca6f Implement some Ada OP_ATR_ operations
This implements a few Ada OP_ATR_ operations.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_unop_atr_operation::evaluate): New method.
	* ada-exp.h (class ada_unop_atr_operation): New.
2021-03-08 07:28:33 -07:00
Tom Tromey
82c3886e24 Introduce ada_binop_in_bounds
This adds class ada_binop_in_bounds, which implements BINOP_IN_BOUNDS.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_binop_in_bounds): No longer static.
	* ada-exp.h (class ada_binop_in_bounds_operation): New.
2021-03-08 07:28:33 -07:00
Tom Tromey
1b1ebfab47 Introduce ada_ternop_slice
This adds class ada_ternop_slice, which implements TERNOP_SLICE for
Ada.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_ternop_slice): No longer static.
	* ada-exp.h (class ada_ternop_slice_operation): New.
2021-03-08 07:28:33 -07:00
Tom Tromey
039e4b76be Introduce ada_bitwise_operation
This adds class ada_bitwise_operation, which is used to implement the
Ada bitwise operators.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-exp.h (ada_bitwise_operation): New template class.
	(ada_bitwise_and_operation, ada_bitwise_ior_operation)
	(ada_bitwise_xor_operation): New typedefs.
2021-03-08 07:28:33 -07:00
Tom Tromey
6e8fb7b723 Implement Ada equality operators
This implements the Ada equal and not-equal operators.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_equal_binop): No longer static.
	* ada-exp.h (class ada_binop_equal_operation): New.
2021-03-08 07:28:32 -07:00
Tom Tromey
d9e7db065e Implement Ada multiplicative operators
This implements the Ada multiplicative operators, using an existing
template class.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_mult_binop): No longer static.
	* ada-exp.h (ada_binop_mul_operation ada_binop_div_operation)
	(ada_binop_rem_operation, ada_binop_mod_operation): New typedefs.
2021-03-08 07:28:32 -07:00
Tom Tromey
73796c7326 Introduce ada_binop_addsub_operation
This adds class ada_binop_addsub_operation, which implements the Ada +
and - operators.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_binop_addsub_operation::evaluate): New method.
	* ada-exp.h (class ada_binop_addsub_operation): New.
2021-03-08 07:28:32 -07:00
Tom Tromey
cd9a314824 Split out some Ada type resolution code
This splits some Ada type resolution code out of resolve_subexp into
new functions that can be reused.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.h (ada_find_operator_symbol, ada_resolve_funcall)
	(ada_resolve_variable): Declare.
	* ada-lang.c (ada_find_operator_symbol, ada_resolve_funcall)
	(ada_resolve_variable): New functions.
	(resolve_subexp): Update.
2021-03-08 07:28:32 -07:00
Tom Tromey
cf12b17fd0 Implement OpenCL ternary conditional operator
This implements the ?: ternary conditional operator for OpenCL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* opencl-lang.c (opencl_ternop_cond_operation::evaluate): New
	method.
	* c-exp.h (class opencl_ternop_cond_operation): New.
2021-03-08 07:28:31 -07:00
Tom Tromey
944fd3b812 Implement OpenCL logical binary operations
This implements "&&" and "||" for OpenCL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* opencl-lang.c (opencl_logical_binop_operation::evaluate): New
	method.
	* c-exp.h (class opencl_logical_binop_operation): New.
2021-03-08 07:28:31 -07:00
Tom Tromey
33b7921462 Introduce opencl_structop_operation
This adds class opencl_structop_operation, which implements
STRUCTOP_STRUCT for OpenCL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* opencl-lang.c (opencl_structop_operation::evaluate): New
	method.
	* c-exp.h (class opencl_structop_operation): New.
2021-03-08 07:28:31 -07:00
Tom Tromey
2492ba36f6 Introduce opencl_notequal_operation
This adds the opencl_notequal_operation typedef, implementing "!=" for
OpenCL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* opencl-lang.c (opencl_logical_not): No longer static.  Change
	parameters.
	(evaluate_subexp_opencl): Update.
	* c-exp.h (opencl_notequal_operation): New typedef.
2021-03-08 07:28:31 -07:00
Tom Tromey
a88c3c8dd3 Implement OpenCL binary operations
This implements various OpenCL binary operations, adding a new
template class to do so.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* opencl-lang.c (opencl_relop, eval_opencl_assign): No longer
	static.  Change parameters.
	(eval_opencl_assign): No longer static.  Add "op" parameter.
	(evaluate_subexp_opencl): Update.
	* c-exp.h (opencl_binop_operation): New template class.
	(opencl_assign_operation, opencl_equal_operation)
	(opencl_notequal_operation, opencl_less_operation)
	(opencl_gtr_operation, opencl_geq_operation)
	(opencl_leq_operation): New typedefs.
2021-03-08 07:28:31 -07:00
Tom Tromey
e967770468 Introduce opencl_cast_type_operation
This adds class opencl_cast_type_operation, which implements
UNOP_CAST_TYPE for OpenCL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* opencl-lang.c (opencl_value_cast): No longer static.
	* c-exp.h (opencl_cast_type_operation): New typedef.
2021-03-08 07:28:30 -07:00
Tom Tromey
f403a4e4a5 Implement fortran_allocated_operation
This implements the Fortran ALLOCATED intrinsic.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* f-exp.h (eval_op_f_allocated): Declare.
	(fortran_allocated_operation): New typedef.
	* f-lang.c (eval_op_f_allocated): No longer static.
2021-03-08 07:28:30 -07:00
Tom Tromey
eb4c927182 Implement Fortran associated operations
This implements the Fortran 1- and 2-argument "associated" operations.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* f-lang.c (eval_op_f_associated): New functions.
	* f-exp.h (fortran_associated_1arg, fortran_associated_2arg): New
	typedefs.
2021-03-08 07:28:30 -07:00
Tom Tromey
58a76c7264 Introduce classes for Fortran bound intrinsics
This adds class fortran_bound_1arg and fortran_bound_2arg, to
implement the Fortran lbound and ubound intrinsics.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* f-lang.c (fortran_bound_1arg::evaluate)
	(fortran_bound_2arg::evaluate): New methods.
	* f-exp.h (class fortran_bound_1arg, class fortran_bound_2arg):
	New.
2021-03-08 07:28:30 -07:00
Tom Tromey
2f98abe174 Introduce fortran_undetermined
This adds class fortran_undetermined, which implements
OP_F77_UNDETERMINED_ARGLIST.  fortran_range_operation is also added
here, as it is needed by fortran_undetermined.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* expop.h (class unop_addr_operation) <get_expression>: New
	method.
	* f-lang.c (fortran_undetermined::value_subarray)
	(fortran_undetermined::evaluate): New methods.
	(fortran_prepare_argument): New overload.
	* f-exp.h (class fortran_range_operation)
	(class fortran_undetermined): New classes.
2021-03-08 07:28:30 -07:00
Tom Tromey
638fd74a61 Implement Rust funcall operation
This adds the special code needed to handle the Rust function call
operation.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (rust_structop::evaluate_funcall): New method.
	* rust-exp.h (class rust_structop) <evaluate_funcall>: Declare
	method.
2021-03-08 07:28:29 -07:00
Tom Tromey
a00b7254fb Implement function call operations
This implement function call operations.

The current function call code relies on some very lengthy code
(evaluate_funcall is 398 lines...) to distinguish between the
different opcodes that might appear in the callee position.

Rather than try to replicate this, and have a function that tried to
dissect many different kinds of operation subclass, this patch instead
puts the work into the callee.  A new operation::evaluate_funcall
method is added, and then this is overridden in the classes that
require special treatment.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* expression.h (class operation) <evaluate_funcall>: New methods.
	* expop.h (class scope_operation) <evaluate_funcall>: New method.
	(class var_value_operation) <evaluate_funcall>: New method.
	(class structop_base_operation) <evaluate_funcall>: New method.
	(class var_msym_value_operation) <evaluate_funcall>: New method.
	(class structop_member_base): New class.
	(class structop_member_operation): Derive from
	structop_member_base.
	(class structop_mptr_operation): Derive from
	structop_member_base.
	(class funcall_operation): New class.
	* eval.c (operation::evaluate_funcall)
	(var_value_operation::evaluate_funcall)
	(scope_operation::evaluate_funcall)
	(structop_member_base::evaluate_funcall)
	(structop_base_operation::evaluate_funcall): New methods.
2021-03-08 07:28:29 -07:00
Tom Tromey
1c02eb3035 Introduce array_operation
This adds class array_operation, which implements OP_ARRAY.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* expop.h (class array_operation): New.
	* eval.c (array_operation::evaluate_struct_tuple)
	(array_operation::evaluate): New methods.
2021-03-08 07:28:29 -07:00
Tom Tromey
e447908052 Introduce class adl_func_operation
This adds class adl_func_operation, which implements
argument-dependent lookup function calls.

Other function calls will be handled in a different way.  However,
because ADL calls were created in a single spot in the C++ parser, and
because they had different semantics from the other cases, it was
convenient to treat them specially.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* expop.h (class adl_func_operation): New.
	* eval.c (adl_func_operation::evaluate): New method.
2021-03-08 07:28:29 -07:00
Tom Tromey
95d49dfbba Introduce ada_unop_range_operation
This adds class ada_unop_range_operation, which implements
UNOP_IN_RANGE.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_unop_in_range): No longer static.
	* ada-exp.h (class ada_unop_range_operation): New.
2021-03-08 07:28:28 -07:00
Tom Tromey
7c15d377de Implement some Ada unary operations
This implements a few Ada unary operations, using the existing
unop_operation template class.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_unop_neg, ada_atr_tag, ada_atr_size, ada_abs):
	No longer static.
	* ada-exp.h (ada_neg_operation, ada_atr_tag_operation)
	(ada_atr_size_operation, ada_abs_operation): New typedefs.
2021-03-08 07:28:28 -07:00
Tom Tromey
5019124b1d Implement the "&&" and "||" operators
This implements the "&&" and "||" operators.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* expop.h (class logical_and_operation)
	(class logical_or_operation): New.
	* eval.c (logical_and_operation::evaluate)
	(logical_or_operation::evaluate): New methods.
	* ax-gdb.c (logical_and_operation::do_generate_ax)
	(logical_or_operation::do_generate_ax): New methods.
2021-03-08 07:28:28 -07:00
Tom Tromey
2bc9b40ce1 Add two simple Modula-2 operations
This adds a couple of simple Modula-2 operations.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* m2-lang.c (eval_op_m2_high, eval_op_m2_subscript): No longer
	static.
	* m2-exp.h: New file.
2021-03-08 07:28:28 -07:00
Tom Tromey
5947d337d6 Introduce rust_aggregate_operation
This adds class rust_aggregate_operation, which implements
OP_AGGREGATE for Rust.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (rust_aggregate_operation::evaluate): New method.
	* rust-exp.h (class rust_aggregate_operation): New.
2021-03-08 07:28:27 -07:00
Tom Tromey
e4407a202d Implement Rust field operations
This implements the field operations STRUCTOP_STRUCT and
STRUCTOP_ANONYMOUS, for Rust.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (eval_op_rust_struct_anon, eval_op_rust_structop):
	No longer static.
	* rust-exp.h (class rust_struct_anon): New.
	(class rust_structop): New.
2021-03-08 07:28:27 -07:00
Tom Tromey
9db6b6ddbd Introduce rust_range_operation
This adds class rust_range_operation, which implements OP_RANGE.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (rust_range): No longer static.
	* rust-exp.h (class rust_range_operation): New.
2021-03-08 07:28:27 -07:00
Tom Tromey
6ce1ad679a Introduce rust_subscript_operation
This adds class rust_subscript_operation, which implements
BINOP_SUBSCRIPT for Rust.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (rust_subscript): No longer static.
	* rust-exp.h (class rust_subscript_operation): New.
2021-03-08 07:28:27 -07:00
Tom Tromey
11dd3dce44 Introduce rust_unop_ind_operation
This adds class rust_unop_ind_operation, which implements UNOP_IND for
Rust.  Rust requires a special case here to handle trait objects.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (eval_op_rust_ind): No longer static.  Add "opcode"
	parameter.
	(rust_evaluate_subexp): Update.
	* rust-exp.h (class rust_unop_ind_operation): New.
2021-03-08 07:28:27 -07:00
Tom Tromey
6fab435953 Implement some Rust operations
This implements some straightforward Rust operations, using existing
template classes.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (eval_op_rust_complement, eval_op_rust_array): No
	longer static.  Add "opcode" parameter.
	(rust_evaluate_subexp): Update.
	* rust-exp.h: New file.
2021-03-08 07:28:26 -07:00
Tom Tromey
9dcd3e2957 Implement several Fortran operations
This implements several straightforward Fortran operations, primarily
by reusing existing template classes.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* f-lang.c (eval_op_f_abs, eval_op_f_mod, eval_op_f_ceil)
	(eval_op_f_floor, eval_op_f_modulo, eval_op_f_cmplx)
	(eval_op_f_kind): No longer static.  Add "opcode" parameter.
	(evaluate_subexp_f): Update.
	* f-exp.h: New file.
2021-03-08 07:28:26 -07:00
Tom Tromey
fc715eb288 Introduce ada_ternop_range_operation
This adds class ada_ternop_range_operation, which implements
TERNOP_IN_RANGE.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_ternop_range_operation::evaluate): New method.
	* ada-exp.h (class ada_ternop_range_operation): New.
2021-03-08 07:28:26 -07:00
Tom Tromey
cc6bd32eea Introduce ada_qual_operation
This adds class ada_qual_operation, which implements UNOP_QUAL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_qual_operation::evaluate): New method.
	* ada-exp.h (class ada_qual_operation): New.
2021-03-08 07:28:26 -07:00
Tom Tromey
42fecb6183 Introduce ada_string_operation
This adds class ada_string_operation, which implements string
constants for Ada.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_string_operation::evaluate): New method.
	* ada-exp.h (class ada_string_operation): New.
2021-03-08 07:28:25 -07:00
Tom Tromey
03070ee9c7 Introduce ada_wrapped_operation
This adds class ada_wrapped_operation, which is used to wrap some
generic operations with a bit of Ada-specific handling.  This
corresponds to the old "default" case in ada_evaluate_subexp.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* ada-lang.c (ada_wrapped_operation::evaluate): New method.
	* ada-exp.h: New file.
2021-03-08 07:28:25 -07:00
Tom Tromey
821e72d775 Introduce multi_subscript_operation
This adds class multi_subscript_operation, which implements
MULTI_SUBSCRIPT.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* expop.h (class multi_subscript_operation): New.
	* eval.c (multi_subscript_operation::evaluate): New method.
2021-03-08 07:28:25 -07:00
Tom Tromey
085734dd95 Introduce objc_msgcall_operation
This adds class objc_msgcall_operation, which implements
OP_OBJC_MSGCALL.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

	* eval.c (objc_msgcall_operation::evaluate): New method.
	* c-exp.h (class objc_msgcall_operation): New.
2021-03-08 07:28:25 -07:00