Skip to content

Commit f2cb1f0

Browse files
Support on_problems=Problem_Behavior.Report_Warning and Map_Error wrapping in Vector.map (#8595)
Implements `Warnings.get_all wrap_errors=True` which wraps warnings attached to values inside vectors with `Map_Error`, which includes the position of the value within the vector. See [the documentation](https://github.com/enso-org/enso/blob/develop/docs/semantics/wrapped-errors.md) for more details. `get_all wrap_errors=True` does not change the warnings that are attached to values -- it wraps them before returning them to the caller, but does not change the original warnings attached to the values. Wrapped warnings only appear attached to the vector itself. The values inside the vector do not have their warnings wrapped. Warning propagation is not changed at all; `Warnings.get_all` (with default `wrap_errors=False`) behaves as before. `get_all wrap_errors=True` is meant to be used primarily by the IDE, although it can be used anywhere this wrapping is desired.
1 parent b8e93b3 commit f2cb1f0

File tree

56 files changed

+587
-239
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+587
-239
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@
599599
- [Support for loading big Excel files.][8403]
600600
- [Added new `Filter_Condition`s - `Equal_Ignore_Case`, `Is_Nan`, `Is_Infinite`
601601
and `Is_Finite`.][8539]
602+
- [Support `on_problems=Problem_Behavior.Report_Warning` in `Vector.map`.][8595]
602603
- [Added text_length to Column][8606]
603604
- [Added none delimiter option for Data.Read][8627]
604605
- [Added text_left and text_right to Column][8691]
@@ -861,6 +862,7 @@
861862
[8403]: https://github.com/enso-org/enso/pull/8403
862863
[8539]: https://github.com/enso-org/enso/pull/8539
863864
[8564]: https://github.com/enso-org/enso/pull/8564
865+
[8595]: https://github.com/enso-org/enso/pull/8595
864866
[8606]: https://github.com/enso-org/enso/pull/8606
865867
[8627]: https://github.com/enso-org/enso/pull/8627
866868
[8691]: https://github.com/enso-org/enso/pull/8691

distribution/lib/Standard/Base/0.0.0-dev/src/Data/Statistics.enso

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ type Statistic
154154
- statistics: Set of statistics to calculate.
155155
compute_bulk : Vector -> Vector Statistic -> Vector Any
156156
compute_bulk data statistics=[Statistic.Count, Statistic.Sum] =
157-
moment_order = statistics.map on_problems=No_Wrap.Value .order
157+
moment_order = statistics.map on_problems=No_Wrap .order
158158
has_min_max = statistics.any (s-> s == Statistic.Minimum || s == Statistic.Maximum)
159159
max_moment_order = moment_order.filter (v-> v != Nothing) . fold 0 .max
160160
counter = data.fold (Accumulator.new has_min_max max_moment_order) current-> value-> compute_fold current value
@@ -165,7 +165,7 @@ type Statistic
165165
Error.throw (Illegal_Argument.Error ("Can only compute " + stat.to_text + " on numerical data sets."))
166166

167167
if max_moment_order > 0 && counter.moments.is_nothing then report_error statistics else
168-
statistics.map on_problems=No_Wrap.Value statistic-> case statistic of
168+
statistics.map on_problems=No_Wrap statistic-> case statistic of
169169
Statistic.Covariance series -> check_if_empty counter.count <| calculate_correlation_statistics data series . covariance
170170
Statistic.Pearson series -> check_if_empty counter.count <| calculate_correlation_statistics data series . pearsonCorrelation
171171
Statistic.R_Squared series -> check_if_empty counter.count <| calculate_correlation_statistics data series . rSquared
@@ -198,7 +198,7 @@ type Statistic
198198
_ -> False
199199

200200
if statistics.any is_unsupported then Error.throw (Illegal_Argument.Error ("Unsupported Statistics ( " + (statistics.filter is_unsupported . to_text) ") for running calculations.")) else
201-
moment_order = statistics.map on_problems=No_Wrap.Value .order
201+
moment_order = statistics.map on_problems=No_Wrap .order
202202
has_min_max = statistics.any (s-> s == Statistic.Minimum || s == Statistic.Maximum)
203203
max_moment_order = moment_order.filter (v-> v != Nothing) . fold 0 .max
204204

@@ -209,7 +209,7 @@ type Statistic
209209
data.fold counter current->value->
210210
result = compute_fold current value
211211

212-
row = Panic.throw_wrapped_if_error <| statistics.map on_problems=No_Wrap.Value s-> case s of
212+
row = Panic.throw_wrapped_if_error <| statistics.map on_problems=No_Wrap s-> case s of
213213
Statistic.Maximum -> if result.count == 0 then Nothing else result.maximum
214214
Statistic.Minimum -> if result.count == 0 then Nothing else result.minimum
215215
_ -> result.compute s

distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,11 +1354,17 @@ type Builder
13541354
Vector.from_polyglot_array self.java_builder.toArray
13551355

13561356
## PRIVATE
1357-
Describes an error produced by a function mapped over a Vector. Includes the
1358-
function argument's position in the vector.
1357+
Describes an error attached to a value within a `Vector`. The `index` field
1358+
contains the index into the `Vector` at which the error occurred.
1359+
1360+
If a value is nested within multiple `Vector`s, its warnings are wrapped
1361+
with `Map_Error` multiple times. The outermost `Map_Error` index indicates
1362+
the index into the outermost `Vector`, the second `Map_Error` index the index
1363+
into the sub-`Vector` within the outermost `Vector`, and so on.
13591364

13601365
An error that is wrapped as a `Map_Error` can be caught as a `Map_Error`, or
13611366
as itself. In the latter case, the `Map_Error` wrapper is stripped off.
1367+
@Builtin_Type
13621368
type Map_Error
13631369
## PRIVATE
13641370
Creates a new `Map_Error` from the given index and underlying error.
@@ -1371,8 +1377,6 @@ type Map_Error
13711377
## PRIVATE
13721378
Indicates that a method should not wrap thrown errors in `Map_Error`.
13731379
type No_Wrap
1374-
## PRIVATE
1375-
Value
13761380

13771381
## PRIVATE
13781382
Wrapped_Error.from (that : Map_Error) = Wrapped_Error.Value that that.inner_error

distribution/lib/Standard/Base/0.0.0-dev/src/Error.enso

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,13 @@ type Error
142142
Maybe.Some inner_error -> handler inner_error
143143

144144
## PRIVATE
145-
Convert a wrapped error to a Wrapped_Error. If the argument is not a
146-
wrapped error, Nothing is returned.
147-
as_wrapped_error : Any -> Wrapped_Error | Nothing
148-
as_wrapped_error error_value =
149-
Panic.catch No_Such_Conversion (Wrapped_Error.from error_value) _->Nothing
150-
151-
## PRIVATE
152-
Determines if this is the specified error wrapper, and, if so, returns
153-
the inner error. This only unwraps once.
154-
unwrap_error : Any -> Any -> Maybe Any
155-
unwrap_error wrapper_error_type error_value =
156-
case Error.as_wrapped_error error_value of
157-
Wrapped_Error.Value wrapping_error inner_error ->
158-
if wrapping_error.is_a wrapper_error_type then Maybe.Some inner_error else Maybe.None
159-
Nothing -> Maybe.None
145+
Remove all wrapping errors, returning the inner error. If the argument is
146+
not a wrapping error, it is returned unchanged.
147+
unwrap : Any -> Any
148+
unwrap error_value =
149+
Panic.catch No_Such_Conversion handler=_->error_value <|
150+
wrapped_error = Wrapped_Error.from error_value
151+
@Tail_Call Error.unwrap wrapped_error.inner_error
160152

161153
## Transforms an error.
162154

distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -66,35 +66,23 @@ vector_from_function_primitive length constructor = @Builtin_Method "Array_Like_
6666
ignored.
6767
vector_from_function : Integer -> (Integer -> Any) -> Problem_Behavior | No_Wrap -> Vector Any
6868
vector_from_function length function on_problems=Problem_Behavior.Report_Error =
69-
if on_problems == Problem_Behavior.Report_Warning then
70-
Unimplemented.throw "on_problems=Problem_Behavior.Report_Warning is unimplemented for `Vector.map`"
7169
num_errors = Ref.new 0
7270
wrapped_function i =
7371
result = function i
74-
case result.is_error of
75-
False ->
76-
## TODO: implement this correctly.
77-
See https://github.com/enso-org/enso/issues/8371
78-
79-
if Warning.has_warnings result . not then result else
80-
Warning.map_attached_warnings (w-> Maybe.Some (Map_Error.Error i w)) result
81-
result
82-
True ->
83-
case on_problems of
84-
Problem_Behavior.Ignore ->
85-
Nothing
86-
Problem_Behavior.Report_Error ->
72+
if result.is_error.not then result else
73+
case on_problems of
74+
Problem_Behavior.Ignore ->
75+
Nothing
76+
Problem_Behavior.Report_Error ->
77+
result.catch_primitive caught->
78+
Error.throw (Map_Error.Error i caught)
79+
No_Wrap -> result
80+
Problem_Behavior.Report_Warning ->
81+
with_error_maybe = if num_errors.get >= MAX_MAP_WARNINGS then Nothing else
8782
result.catch_primitive caught->
88-
Error.throw (Map_Error.Error i caught)
89-
No_Wrap.Value -> result
90-
## TODO: implement this correctly.
91-
See https://github.com/enso-org/enso/issues/8371
92-
Problem_Behavior.Report_Warning ->
93-
with_error_maybe = if num_errors.get >= MAX_MAP_WARNINGS then Nothing else
94-
result.catch_primitive caught->
95-
Warning.attach (Map_Error.Error i caught) Nothing
96-
num_errors.modify (_+1)
97-
with_error_maybe
83+
Warning.attach caught Nothing
84+
num_errors.modify (_+1)
85+
with_error_maybe
9886
results = vector_from_function_primitive length wrapped_function
9987
if num_errors.get <= MAX_MAP_WARNINGS then results else
10088
err = Additional_Warnings.Error num_errors.get-MAX_MAP_WARNINGS

distribution/lib/Standard/Base/0.0.0-dev/src/Main.enso

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ import project.Data.Time.Period.Period
4949
import project.Data.Time.Time_Of_Day.Time_Of_Day
5050
import project.Data.Time.Time_Period.Time_Period
5151
import project.Data.Time.Time_Zone.Time_Zone
52-
import project.Data.Vector.Map_Error
5352
import project.Data.Vector.Vector
5453
import project.Data.XML.XML_Document
5554
import project.Data.XML.XML_Element
@@ -145,7 +144,6 @@ export project.Data.Time.Period.Period
145144
export project.Data.Time.Time_Of_Day.Time_Of_Day
146145
export project.Data.Time.Time_Period.Time_Period
147146
export project.Data.Time.Time_Zone.Time_Zone
148-
export project.Data.Vector.Map_Error
149147
export project.Data.Vector.Vector
150148
export project.Data.XML.XML_Document
151149
export project.Data.XML.XML_Element

distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP.enso

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ type HTTP
120120
boundary = body_publisher_and_boundary.second
121121
boundary_header_list = if boundary.is_nothing then [] else [Header.multipart_form_data boundary]
122122
all_headers = headers + boundary_header_list
123-
mapped_headers = all_headers.map on_problems=No_Wrap.Value .to_java_pair
123+
mapped_headers = all_headers.map on_problems=No_Wrap .to_java_pair
124124

125125
response = Response.Value (EnsoSecretHelper.makeRequest self.internal_http_client builder req.uri.to_java_representation mapped_headers)
126126
if error_on_failure_code.not || response.code.is_success then response else
@@ -178,7 +178,7 @@ type HTTP
178178
## PRIVATE
179179
parse_headers : Vector (Header | Pair Text Text) -> Vector Header
180180
parse_headers headers =
181-
headers . map on_problems=No_Wrap.Value h-> case h of
181+
headers . map on_problems=No_Wrap h-> case h of
182182
_ : Vector -> Header.new (h.at 0) (h.at 1)
183183
_ : Pair -> Header.new (h.at 0) (h.at 1)
184184
_ : Header -> h

distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import project.Data.Index_Sub_Range.Index_Sub_Range
44
import project.Data.Maybe.Maybe
55
import project.Data.Numbers.Integer
66
import project.Data.Pair.Pair
7+
import project.Data.Set.Set
8+
import project.Data.Vector.Map_Error
79
import project.Data.Vector.No_Wrap
810
import project.Data.Vector.Vector
911
import project.Error.Error
@@ -58,8 +60,13 @@ type Warning
5860
ADVANCED
5961
Gets all the warnings attached to the given value. Warnings are returned in the
6062
reverse-chronological order with respect to their attachment time.
61-
get_all : Any -> Vector Warning
62-
get_all value = Vector.from_polyglot_array (get_all_array value)
63+
64+
Arguments:
65+
- value: The value to get the attached warnings of.
66+
- wrap_errors: If true, warnings attached to elements in array-likes are
67+
wrapped in Map_Error.
68+
get_all : Any -> Boolean -> Vector Warning
69+
get_all value wrap_errors:Boolean=False = Vector.from_polyglot_array (get_all_array value wrap_errors)
6370

6471
## PRIVATE
6572
ADVANCED
@@ -288,8 +295,8 @@ attach_with_stacktrace value warning origin = @Builtin_Method "Warning.attach_wi
288295
## PRIVATE
289296

290297
Builtin function that gets all the warnings attached to the given value.
291-
get_all_array : Any -> Array Warning
292-
get_all_array value = @Builtin_Method "Warning.get_all_array"
298+
get_all_array : Any -> Boolean -> Array Warning
299+
get_all_array value should_wrap = @Builtin_Method "Warning.get_all_array"
293300

294301
## PRIVATE
295302

@@ -309,7 +316,7 @@ set_array value warnings = @Builtin_Method "Warning.set_array"
309316
map_attached_warnings_helper : (Any -> Maybe Any) -> Any -> Integer -> Any
310317
map_attached_warnings_helper mapper value frames_to_drop =
311318
warnings = Warning.get_all value
312-
mapped_warnings = warnings.map on_problems=No_Wrap.Value warning->
319+
mapped_warnings = warnings.map on_problems=No_Wrap warning->
313320
case mapper warning.value of
314321
Maybe.Some new_payload ->
315322
self_call_name = "Warning.map_attached_warnings_helper"

distribution/lib/Standard/Database/0.0.0-dev/src/Data/Take_Drop_Helpers.enso

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ take_drop_helper take_drop table selector =
3333
row_column_name = table.make_temp_column_name
3434
table_with_row_number = table.add_row_number name=row_column_name from=0
3535

36-
subqueries = ranges.map on_problems=No_Wrap.Value range->
36+
subqueries = ranges.map on_problems=No_Wrap range->
3737
generate_subquery table_with_row_number row_column_name range
3838
combined = subqueries.reduce (a-> b-> a.union b)
3939
combined.remove_columns row_column_name

distribution/lib/Standard/Database/0.0.0-dev/src/Internal/IR/Context.enso

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ type Context
163163
rewrite_internal_column column =
164164
Internal_Column.Value column.name column.sql_type_reference (SQL_Expression.Column alias column.name)
165165

166-
new_columns = column_lists.map on_problems=No_Wrap.Value columns->
167-
columns.map on_problems=No_Wrap.Value rewrite_internal_column
166+
new_columns = column_lists.map on_problems=No_Wrap columns->
167+
columns.map on_problems=No_Wrap rewrite_internal_column
168168

169169
encapsulated_columns = column_lists.flat_map columns->
170170
columns.map column-> [column.name, column.expression]

distribution/lib/Standard/Database/0.0.0-dev/src/Internal/Upload_Table.enso

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ verify_structure_hint structure_hint column_names =
188188
resolve_primary_key structure primary_key = case primary_key of
189189
Nothing -> Nothing
190190
_ : Vector -> if primary_key.is_empty then Nothing else
191-
validated = primary_key.map on_problems=No_Wrap.Value key->
191+
validated = primary_key.map on_problems=No_Wrap key->
192192
if key.is_a Text then key else
193193
Error.throw (Illegal_Argument.Error ("Primary key must be a vector of column names, instead got a " + (Meta.type_of key . to_display_text)))
194194
validated.if_not_error <|
@@ -303,7 +303,7 @@ first_column_name_in_structure structure = case structure of
303303
prepare_create_table_statement : Connection -> Text -> Vector Column_Description -> Vector Text -> Boolean -> Problem_Behavior -> SQL_Statement
304304
prepare_create_table_statement connection table_name columns primary_key temporary on_problems =
305305
type_mapping = connection.dialect.get_type_mapping
306-
column_descriptors = columns.map on_problems=No_Wrap.Value def->
306+
column_descriptors = columns.map on_problems=No_Wrap def->
307307
sql_type = type_mapping.value_type_to_sql def.value_type on_problems
308308
sql_type_text = type_mapping.sql_type_to_text sql_type
309309
Create_Column_Descriptor.Value def.name sql_type_text def.constraints
@@ -485,7 +485,7 @@ check_update_arguments_structure_match source_table target_table key_columns upd
485485
if missing_target_key_columns.not_empty then Error.throw (Missing_Input_Columns.Error missing_target_key_columns.to_vector "the target table") else
486486
if (update_action != Update_Action.Insert) && key_columns.is_empty then Error.throw (Illegal_Argument.Error "For the `update_action = "+update_action.to_text+"`, the `key_columns` must be specified to define how to match the records.") else
487487
# Verify type matching
488-
problems = source_table.columns.flat_map on_problems=No_Wrap.Value check_source_column
488+
problems = source_table.columns.flat_map on_problems=No_Wrap check_source_column
489489
problems.if_not_error <|
490490
on_problems.attach_problems_before problems action
491491

distribution/lib/Standard/Table/0.0.0-dev/src/Data/Column.enso

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,7 +1919,7 @@ type Column
19191919
map : (Any -> Any) -> Boolean -> Value_Type | Auto -> Column ! Invalid_Value_Type
19201920
map self function skip_nothing=True expected_value_type=Auto =
19211921
new_fn = if skip_nothing then (x-> if x.is_nothing then Nothing else function x) else function
1922-
new_st = self.to_vector.map on_problems=No_Wrap.Value new_fn
1922+
new_st = self.to_vector.map on_problems=No_Wrap new_fn
19231923
Column.from_vector self.name new_st value_type=expected_value_type
19241924

19251925
## ALIAS combine, join by row position, merge
@@ -1967,7 +1967,7 @@ type Column
19671967
function x y
19681968
False -> function
19691969
new_name = naming_helper.binary_operation_name "x" self that
1970-
vec = self.to_vector.zip on_problems=No_Wrap.Value that.to_vector new_fn
1970+
vec = self.to_vector.zip on_problems=No_Wrap that.to_vector new_fn
19711971
Column.from_vector new_name vec value_type=expected_value_type
19721972

19731973
## GROUP Standard.Base.Metadata

distribution/lib/Standard/Table/0.0.0-dev/src/Data/Data_Formatter.enso

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ type Data_Formatter
125125
vector = case formats of
126126
v : Vector -> v
127127
singleton -> [singleton]
128-
converted = vector.map on_problems=No_Wrap.Value elem->
128+
converted = vector.map on_problems=No_Wrap elem->
129129
## Ensure the element is a `Date_Time_Formatter` or is converted to it.
130130
We need to convert _each_ element - we cannot perform a 'bulk' conversion like `vector : Vector Date_Time_Formatter` because of erasure.
131131
checked = elem : Date_Time_Formatter
@@ -210,17 +210,17 @@ type Data_Formatter
210210
## PRIVATE
211211
make_date_parser self = self.wrap_base_parser <|
212212
Panic.catch Java_Exception handler=(caught_panic-> Error.throw (Illegal_Argument.Error caught_panic.payload.getMessage)) <|
213-
DateParser.new (self.date_formats.map on_problems=No_Wrap.Value .get_java_formatter_for_parsing)
213+
DateParser.new (self.date_formats.map on_problems=No_Wrap .get_java_formatter_for_parsing)
214214

215215
## PRIVATE
216216
make_date_time_parser self = self.wrap_base_parser <|
217217
Panic.catch Java_Exception handler=(caught_panic-> Error.throw (Illegal_Argument.Error caught_panic.payload.getMessage)) <|
218-
DateTimeParser.new (self.datetime_formats.map on_problems=No_Wrap.Value .get_java_formatter_for_parsing)
218+
DateTimeParser.new (self.datetime_formats.map on_problems=No_Wrap .get_java_formatter_for_parsing)
219219

220220
## PRIVATE
221221
make_time_of_day_parser self = self.wrap_base_parser <|
222222
Panic.catch Java_Exception handler=(caught_panic-> Error.throw (Illegal_Argument.Error caught_panic.payload.getMessage)) <|
223-
TimeOfDayParser.new (self.time_formats.map on_problems=No_Wrap.Value .get_java_formatter_for_parsing)
223+
TimeOfDayParser.new (self.time_formats.map on_problems=No_Wrap .get_java_formatter_for_parsing)
224224

225225
## PRIVATE
226226
make_identity_parser self = self.wrap_base_parser IdentityParser.new

0 commit comments

Comments
 (0)