diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f3643ca15c9..09e1cda57ad 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -29,16 +29,16 @@ Cargo.toml # Engine (old) # This section should be removed once the engine moves to /app/engine /build.sbt @4e6 @jaroslavtulach @hubertp -/distribution/ @4e6 @jdunkerley @radeusgd +/distribution/ @4e6 @jdunkerley @radeusgd @GregoryTravis /engine/ @4e6 @jaroslavtulach @hubertp /project/ @4e6 @jaroslavtulach @hubertp -/test/ @jdunkerley @radeusgd +/test/ @jdunkerley @radeusgd @GregoryTravis /tools/ @4e6 @jaroslavtulach @radeusgd # Enso Libraries # This section should be amended once the engine moves to /app/engine -/distribution/lib/ @jdunkerley @radeusgd -/std-bits/ @jdunkerley @radeusgd +/distribution/lib/ @jdunkerley @radeusgd @GregoryTravis +/std-bits/ @jdunkerley @radeusgd @GregoryTravis # Cloud Dashboard & Authentication /app/ide-desktop/lib/dashboard @PabloBuchu @indiv0 @somebody1234 diff --git a/app/gui/view/graph-editor/src/builtin/visualization/java_script/table.js b/app/gui/view/graph-editor/src/builtin/visualization/java_script/table.js index f12f628b4c6..49d5fa88979 100644 --- a/app/gui/view/graph-editor/src/builtin/visualization/java_script/table.js +++ b/app/gui/view/graph-editor/src/builtin/visualization/java_script/table.js @@ -32,6 +32,10 @@ class TableVisualization extends Visualization { } onDataReceived(data) { + function addRowIndex(data) { + return data.map((row, i) => ({ ['#']: i, ...row })) + } + function hasExactlyKeys(keys, obj) { return Object.keys(obj).length === keys.length && keys.every(k => obj.hasOwnProperty(k)) } @@ -65,44 +69,8 @@ class TableVisualization extends Visualization { if (content instanceof Object) { const type = content.type - if (type === 'BigInt') { - return BigInt(content.value) - } else if (content['_display_text_']) { + if (content['_display_text_']) { return content['_display_text_'] - } else if (type === 'Date') { - return new Date(content.year, content.month - 1, content.day) - .toISOString() - .substring(0, 10) - } else if (type === 'Time_Of_Day') { - const js_date = new Date( - 0, - 0, - 1, - content.hour, - content.minute, - content.second, - content.nanosecond / 1000000 - ) - return ( - js_date.toTimeString().substring(0, 8) + - (js_date.getMilliseconds() === 0 ? '' : '.' + js_date.getMilliseconds()) - ) - } else if (type === 'Date_Time') { - const js_date = new Date( - content.year, - content.month - 1, - content.day, - content.hour, - content.minute, - content.second, - content.nanosecond / 1000000 - ) - return ( - js_date.toISOString().substring(0, 10) + - ' ' + - js_date.toTimeString().substring(0, 8) + - (js_date.getMilliseconds() === 0 ? '' : '.' + js_date.getMilliseconds()) - ) } else { return `{ ${type} Object }` } @@ -136,7 +104,7 @@ class TableVisualization extends Visualization { sortable: true, filter: true, resizable: true, - minWidth: 50, + minWidth: 25, headerValueGetter: params => params.colDef.field, }, onColumnResized: e => this.lockColumnSize(e), @@ -158,22 +126,49 @@ class TableVisualization extends Visualization { }, ]) this.agGridOptions.api.setRowData([{ Error: parsedData.error }]) - } else if (parsedData.json != null && isMatrix(parsedData.json)) { - columnDefs = parsedData.json[0].map((_, i) => ({ field: i.toString() })) - rowData = parsedData.json + } else if (parsedData.type === 'Matrix') { + let defs = [{ field: '#' }] + for (let i = 0; i < parsedData.column_count; i++) { + defs.push({ field: i.toString() }) + } + columnDefs = defs + rowData = addRowIndex(parsedData.json) dataTruncated = parsedData.all_rows_count !== parsedData.json.length - } else if (parsedData.json != null && isObjectMatrix(parsedData.json)) { - let firstKeys = Object.keys(parsedData.json[0]) + } else if (parsedData.type === 'Object_Matrix') { + let defs = [{ field: '#' }] + let keys = {} + parsedData.json.forEach(val => { + if (val) { + Object.keys(val).forEach(k => { + if (!keys[k]) { + keys[k] = true + defs.push({ field: k }) + } + }) + } + }) + columnDefs = defs + rowData = addRowIndex(parsedData.json) + dataTruncated = parsedData.all_rows_count !== parsedData.json.length + } else if (isMatrix(parsedData.json)) { + // Kept to allow visualization from older versions of the backend. + columnDefs = [ + { field: '#' }, + ...parsedData.json[0].map((_, i) => ({ field: i.toString() })), + ] + rowData = addRowIndex(parsedData.json) + dataTruncated = parsedData.all_rows_count !== parsedData.json.length + } else if (isObjectMatrix(parsedData.json)) { + // Kept to allow visualization from older versions of the backend. + let firstKeys = [{ field: '#' }, ...Object.keys(parsedData.json[0])] columnDefs = firstKeys.map(field => ({ field })) - rowData = parsedData.json.map(obj => - firstKeys.reduce((acc, key) => ({ ...acc, [key]: toRender(obj[key]) }), {}) - ) + rowData = addRowIndex(parsedData.json) dataTruncated = parsedData.all_rows_count !== parsedData.json.length - } else if (parsedData.json != null && Array.isArray(parsedData.json)) { + } else if (Array.isArray(parsedData.json)) { columnDefs = [{ field: '#' }, { field: 'Value' }] rowData = parsedData.json.map((row, i) => ({ ['#']: i, Value: toRender(row) })) dataTruncated = parsedData.all_rows_count !== parsedData.json.length - } else if (parsedData.json != null) { + } else if (parsedData.json !== undefined) { columnDefs = [{ field: 'Value' }] rowData = [{ Value: toRender(parsedData.json) }] } else { diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Filter_Condition.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Filter_Condition.enso index ff3303eef0f..5472f621b58 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Filter_Condition.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Filter_Condition.enso @@ -199,6 +199,37 @@ type Filter_Condition Is_In values -> values.contains Not_In values -> elem -> values.contains elem . not + ## PRIVATE + Convert to a display representation of this Filter_Condition. + to_display_text : Text + to_display_text self = + render_case case_sensitivity = + if case_sensitivity == Case_Sensitivity.Default then "" else " Case " + case_sensitivity.to_display_text + + condition = case self of + Less value -> "<" + value.to_display_text + Equal_Or_Less value -> "<=" + value.to_display_text + Equal value -> "==" + value.to_display_text + Equal_Or_Greater value -> ">=" + value.to_display_text + Greater value -> ">" + value.to_display_text + Not_Equal value -> "!=" + value.to_display_text + Between lower upper -> "Between " + lower.to_display_text + " And " + upper.to_display_text + Starts_With prefix case_sensitivity -> "Starts With " + prefix.to_display_text + (render_case case_sensitivity) + Ends_With suffix case_sensitivity -> "Ends With " + suffix.to_display_text + (render_case case_sensitivity) + Contains substring case_sensitivity -> "Contains " + substring.to_display_text + (render_case case_sensitivity) + Not_Contains substring case_sensitivity -> "Not Contains " + substring.to_display_text + (render_case case_sensitivity) + Is_Nothing -> "is Nothing" + Not_Nothing -> "is Not Nothing" + Is_True -> "is True" + Is_False -> "is False" + Is_Empty -> "is Empty" + Not_Empty -> "is Not Empty" + Like sql_pattern -> "Like " + sql_pattern.to_display_text + Not_Like sql_pattern -> "Not Like " + sql_pattern.to_display_text + Is_In values -> "is in " + values.to_display_text + Not_In values -> "is not in " + values.to_display_text + "Filter Condition: " + condition + ## PRIVATE Gets a widget set up for a Filter_Condition. default_widget = diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Index_Sub_Range.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Index_Sub_Range.enso index 9f70c32dbec..ed5742ece30 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Index_Sub_Range.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Index_Sub_Range.enso @@ -2,6 +2,7 @@ import project.Any.Any import project.Data.Numbers.Integer import project.Data.Range.Range import project.Data.Range.Extensions +import project.Data.Text.Text import project.Data.Vector.Vector import project.Errors.Common.Index_Out_Of_Bounds import project.Error.Error @@ -55,6 +56,17 @@ type Index_Sub_Range input, an error is raised. Every (step:Integer) (first:Integer=0) + ## PRIVATE + Convert to a display representation of this Index_Sub_Range. + to_display_text : Text + to_display_text self = case self of + Index_Sub_Range.First count -> "First " + count.to_display_text + Index_Sub_Range.Last count -> "Last " + count.to_display_text + Index_Sub_Range.While f -> "While " + f.to_display_text + Index_Sub_Range.By_Index indexes -> "By_Index " + indexes.to_display_text + Index_Sub_Range.Sample count _ -> "Sample " + count.to_display_text + Index_Sub_Range.Every step first -> "Every " + step.to_display_text + (if first == 0 then "" else " from " + first.to_display_text) + ## PRIVATE Resolves a vector of ranges or indices into a vector of ranges that fit within a sequence. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Interval.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Interval.enso index 6c1aefa7132..b6681a32b67 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Interval.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Interval.enso @@ -1,4 +1,5 @@ import project.Data.Numbers.Number +import project.Data.Text.Text from project.Data.Boolean import Boolean, False @@ -136,3 +137,15 @@ type Interval example_not_empty = Interval.inclusive 0 0.001 . not_empty not_empty : Boolean not_empty self = self.is_empty.not + + ## PRIVATE + Convert to a display representation of this Interval. + to_display_text : Text + to_display_text self = + prefix = case self.start of + Bound.Exclusive s -> "(" + s.to_display_text + ", " + Bound.Inclusive s -> "[" + s.to_display_text + ", " + suffix = case self.end of + Bound.Exclusive e -> e.to_display_text + ")" + Bound.Inclusive e -> e.to_display_text + "]" + prefix + suffix diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Json.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Json.enso index c74c5270d3c..6e65dc862d8 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Json.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Json.enso @@ -180,6 +180,12 @@ type JS_Object to_text : Text to_text self = Json.stringify self + ## PRIVATE + Convert JS_Object to a friendly string. + to_display_text : Text + to_display_text self = + self.to_text.to_display_text + ## Convert to a JSON representation. to_json : Text to_json self = self.to_text diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Locale.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Locale.enso index 38777dc3207..fb62a605659 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Locale.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Locale.enso @@ -413,4 +413,11 @@ type Locale ## PRIVATE Converts the locale to text. to_text : Text | Nothing - to_text self = self.java_locale.toLanguageTag + to_text self = + tag = self.java_locale.toLanguageTag + if tag == "" then "Default" else tag + + ## PRIVATE + Convert Locale to a friendly string. + to_display_text : Text + to_display_text self = "Locale(" + self.to_text + ")" diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Maybe.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Maybe.enso index 314cff7325c..59a38a883ab 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Maybe.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Maybe.enso @@ -1,4 +1,5 @@ import project.Any.Any +import project.Data.Text.Text from project.Data.Boolean import Boolean, True, False @@ -54,5 +55,13 @@ type Maybe Maybe.None -> False Maybe.Some _ -> True + ## Check if the maybe value is `None`. is_none : Boolean is_none self = self.is_some.not + + ## PRIVATE + Convert Maybe to a friendly string. + to_display_text : Text + to_display_text self = case self of + Maybe.None -> "None" + Maybe.Some val -> "Some(" + val.to_display_text + ")" diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Noise.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Noise.enso index a5175f8d10f..ea76fd74ef8 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Noise.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Noise.enso @@ -7,28 +7,7 @@ import project.Errors.Unimplemented.Unimplemented polyglot java import java.lang.Long polyglot java import java.util.Random -## PRIVATE - - The interface for the noise generator abstraction. - - To be a valid generator, it must provide the `step` method as described - below. -type Generator - ## PRIVATE - - Step the generator to produce the next value.. - - Arguments: - - The input number, which is intended for use as a seed. - - A range for output values, which should range over the chosen output - type. - - The return type may be chosen freely by the generator implementation, as - it usually depends on the generator and its intended use. - step : Number -> Interval -> Any - step self _ _ = Unimplemented.throw "Only intended to demonstrate an interface." - -## A noise generator that implements a seeded deterministic random peterbation +## A noise generator that implements a seeded deterministic random perturbation of the input. It produces what is commonly termed "white" noise, where any value in the @@ -73,6 +52,6 @@ type Deterministic_Random > Example Deterministically perturb the input number 1. 1.noise -Number.noise : Interval -> Generator -> Any +Number.noise : Interval -> Deterministic_Random -> Any Number.noise self (interval = Interval.exclusive 0 1) gen=Deterministic_Random = gen.step self interval diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso index 183710f49c3..48d998c9ecb 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Numbers.enso @@ -10,9 +10,10 @@ from project.Data.Boolean import Boolean, True, False polyglot java import java.lang.Double polyglot java import java.lang.Math -polyglot java import java.lang.String polyglot java import java.lang.Long polyglot java import java.lang.NumberFormatException +polyglot java import java.text.DecimalFormat +polyglot java import java.text.DecimalFormatSymbols polyglot java import java.text.NumberFormat polyglot java import java.text.ParseException @@ -263,20 +264,21 @@ type Number log : Number -> Decimal log self base = self.ln / base.ln - ## UNSTABLE This API is not user-friendly and will be improved in the future. - - Converts a numeric value to a string, using the Java string formatting - syntax. + ## Converts a numeric value to a string, using the Java DecimalFormat + formatter. Arguments: - - fmt: The java-style formatting specifier. + - format: The java-style formatting specifier. > Example - Convert the value 5 to a string. + Convert the value 5000 to a string. - 5.format "%x" - format : Text -> Text - format self fmt = String.format fmt self + 5000.format "#,##0" + format : Text -> Locale -> Text + format self format locale=Locale.default = + symbols = DecimalFormatSymbols.new locale.java_locale + formatter = DecimalFormat.new format symbols + formatter.format self ## Checks equality of numbers, using an `epsilon` value. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso index 31cbe778651..0689b53f58c 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso @@ -1,6 +1,8 @@ import project.Any.Any import project.Data.Boolean.Boolean import project.Data.Numbers.Integer +import project.Data.Text.Text +import project.Data.Text.Extensions import project.Data.Vector.Vector import project.Errors.Common.Index_Out_Of_Bounds import project.Errors.Common.Not_Found @@ -248,6 +250,17 @@ type Pair f self.second Nothing + ## PRIVATE + Convert to a display representation of this Pair. + to_display_text : Text + to_display_text self = + first = self.first.to_display_text + second = self.second.to_display_text + if first.length + second.length < 73 then "Pair(" + first + ", " + second + ")" else + first_trim = if first.length > 36 then first.take 34 + " …" else first + second_trim = if second.length > 36 then second.take 34 + " …" else second + "Pair(" + first_trim + ", " + second_trim + ")" + ## PRIVATE check_start_valid start function max=3 = used_start = if start < 0 then start + 2 else start diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso index 71f94fad3c0..23a9738bff7 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso @@ -430,6 +430,14 @@ type Range @Tail_Call fold_function (function current value) (value + self.step) fold_function self.start self.start+self.step + ## PRIVATE + Convert to a display representation of this Range. + to_display_text : Text + to_display_text self = + start = "[" + self.start.to_display_text + " .. " + self.end.to_display_text + step = if self.step.abs == 1 then "" else " by " + self.step.to_display_text + start + step + "]" + ## PRIVATE throw_zero_step_error = Error.throw (Illegal_State.Error "A range with step = 0 is ill-formed.") diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Regression.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Regression.enso index e99d545b0c2..a4aa9c41118 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Regression.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Regression.enso @@ -24,6 +24,17 @@ type Model ## Fit a power series (y = A x ^ B) to the data. Power + ## PRIVATE + Convert to a display representation of this Model. + to_display_text : Text + to_display_text self = case self of + Model.Linear intercept -> + if intercept.is_nothing then "Linear" else "Linear(intercept: " + intercept.to_display_text + ")" + Model.Exponential intercept -> + if intercept.is_nothing then "Exponential" else "Exponential(intercept: " + intercept.to_display_text + ")" + Model.Logarithmic -> "Logarithmic" + Model.Power -> "Power" + ## PRIVATE Computes the R Squared value for a model and returns a new instance. fitted_model_with_r_squared : Any -> Number -> Number -> Vector -> Vector -> Fitted_Model @@ -33,7 +44,6 @@ type Model constructor a b r_squared ## PRIVATE - Computes the natural log series as long as all values are positive. ln_series : Vector -> Text -> Vector ! Illegal_Argument ln_series xs series_name="Values" = @@ -82,12 +92,16 @@ type Fitted_Model Display the fitted line. to_text : Text to_text self = - equation = case self of - Fitted_Model.Linear slope intercept _ -> slope.to_text + " * X + " + intercept.to_text - Fitted_Model.Exponential a b _ -> a.to_text + " * (" + b.to_text + " * X).exp" - Fitted_Model.Logarithmic a b _ -> a.to_text + " * X.ln + " + b.to_text - Fitted_Model.Power a b _ -> a.to_text + " * X ^ " + b.to_text - "Fitted_Model(" + equation + ")" + "Fitted_Model(" + self.to_display_text + ")" + + ## PRIVATE + Convert to a display representation of this Fitted_Model. + to_display_text : Text + to_display_text self = case self of + Fitted_Model.Linear slope intercept _ -> slope.to_text + " * X + " + intercept.to_text + Fitted_Model.Exponential a b _ -> a.to_text + " * (" + b.to_text + " * X).exp" + Fitted_Model.Logarithmic a b _ -> a.to_text + " * X.ln + " + b.to_text + Fitted_Model.Power a b _ -> a.to_text + " * X ^ " + b.to_text ## Use the model to predict a value. predict : Number -> Number @@ -108,7 +122,6 @@ type Fit_Error Error message ## PRIVATE - Converts the `Fit_Error` to a human-readable representation. to_display_text : Text to_display_text self = "Could not fit the model: " + self.message.to_text diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Case_Sensitivity.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Case_Sensitivity.enso index 236518aed7c..ac7017aff1b 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Case_Sensitivity.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Case_Sensitivity.enso @@ -23,6 +23,15 @@ type Case_Sensitivity - locale: The locale used for the comparison. Insensitive locale=Locale.default + ## PRIVATE + Convert Case_Sensitivity to a friendly string. + to_display_text : Text + to_display_text self = case self of + Case_Sensitivity.Default -> "Default" + Case_Sensitivity.Sensitive -> "Sensitive" + Case_Sensitivity.Insensitive locale -> + if locale == Locale.default then "Insensitive" else "Insensitive(" + locale.to_text + ")" + ## PRIVATE Creates a Java `TextFoldingStrategy` from the case sensitivity setting. folding_strategy : Case_Sensitivity -> TextFoldingStrategy @@ -43,7 +52,7 @@ type Case_Sensitivity Case_Sensitivity.Insensitive locale -> case locale == Locale.default of True -> True False -> - msg = "Custom locales are not supported for this operationc." + msg = "Custom locales are not supported for this operation." Error.throw (Illegal_Argument.Error msg) ## PRIVATE diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Encoding.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Encoding.enso index c9563c45c33..21749c2334a 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Encoding.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Encoding.enso @@ -107,3 +107,8 @@ type Encoding ## Encoding for Vietnamese (Windows). windows_1258 : Encoding windows_1258 = Encoding.Value "windows-1258" + + ## PRIVATE + Convert Encoding to a friendly string. + to_display_text : Text + to_display_text self = self.character_set diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Regex.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Regex.enso index cf20040a833..80e9a42d615 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Regex.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Regex.enso @@ -78,3 +78,8 @@ type Regex_Syntax_Error Arguments: - message: A description of the erroneous syntax. Error message + + ## PRIVATE + Provides a human-readable representation of the `Regex_Syntax_Error`. + to_display_text : Text + to_display_text self = "Regex Syntax Error:" + self.message diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Span.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Span.enso index 9042434289e..99b0059a0da 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Span.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Span.enso @@ -95,6 +95,12 @@ type Span to_utf_16_span self = Utf_16_Span.Value (range_to_char_indices self.parent self.range) self.parent + ## PRIVATE + Convert to a display representation of this Span. + to_display_text : Text + to_display_text self = self.text + + type Utf_16_Span ## A representation of a span of UTF-16 code units in Enso's `Text` type. @@ -165,6 +171,11 @@ type Utf_16_Span grapheme_end = grapheme_last + 1 Span.Value (grapheme_first.up_to grapheme_end) self.parent + ## PRIVATE + Convert to a display representation of this Span. + to_display_text : Text + to_display_text self = self.text + ## PRIVATE Utility function taking a range pointing at grapheme clusters and converting to a range on the underlying code units. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Ordering.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Ordering.enso index 37dd7e4a123..939464e7611 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Ordering.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Ordering.enso @@ -1,5 +1,6 @@ import project.Data.Locale.Locale import project.Data.Text.Case_Sensitivity.Case_Sensitivity +import project.Data.Text.Text import project.Nothing.Nothing from project.Data.Boolean import Boolean, True, False @@ -46,3 +47,9 @@ type Text_Ordering Text_Ordering.Default _ -> Case_Sensitivity.Default Text_Ordering.Case_Sensitive _ -> Case_Sensitivity.Sensitive Text_Ordering.Case_Insensitive locale _ -> Case_Sensitivity.Insensitive locale + + ## PRIVATE + Convert Text_Ordering to a friendly string. + to_display_text : Text + to_display_text self = + self.case_sensitivity.to_display_text + if self.sort_digits_as_numbers then " (Natural Order)" else "" diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Sub_Range.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Sub_Range.enso index 20bd2394745..81526f8d938 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Sub_Range.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Text_Sub_Range.enso @@ -40,6 +40,15 @@ type Text_Sub_Range Select an empty string if the input does not contain `delimiter`. After_Last (delimiter : Text) + ## PRIVATE + Convert to a display representation of this Index_Sub_Range. + to_display_text : Text + to_display_text self = case self of + Text_Sub_Range.Before delimiter -> "Before " + delimiter.to_display_text + Text_Sub_Range.Before_Last delimiter -> "Before Last " + delimiter.to_display_text + Text_Sub_Range.After delimiter -> "After " + delimiter.to_display_text + Text_Sub_Range.After_Last delimiter -> "After Last " + delimiter.to_display_text + type Codepoint_Ranges ## PRIVATE A list of codepoint ranges corresponding to the matched parts of the diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso index 3633dd911c1..34907d65c09 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso @@ -543,6 +543,12 @@ type Date _ -> Error.throw (Illegal_Argument.Error "Illegal period argument") + ## PRIVATE + Convert to a display representation of this Date. + to_display_text : Text + to_display_text self = + self.format "yyyy-MM-dd" + ## PRIVATE Convert to a JS_Object representing this Date. @@ -596,7 +602,6 @@ type Date format : Text -> Text format self pattern = Time_Utils.local_date_format self pattern - ## PRIVATE week_days_between start end = ## We split the interval into 3 periods: the first week (containing the diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Time.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Time.enso index 0c911b97636..e41da2a2f81 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Time.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Time.enso @@ -589,6 +589,13 @@ type Date_Time Time_Utils.datetime_adjust self Time_Utils.AdjustOp.MINUS period.internal_period ensure_in_epoch result result + ## PRIVATE + Convert to a display representation of this Date_Time. + to_display_text : Text + to_display_text self = + time_format = if self.nanosecond == 0 then "HH:mm:ss" else "HH:mm:ss.n" + self.format "yyyy-MM-dd "+time_format+" VV" + ## PRIVATE Convert to a JavaScript Object representing a Date_Time. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Duration.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Duration.enso index 0edc9007eff..b71cf1d4bc6 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Duration.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Duration.enso @@ -4,6 +4,8 @@ import project.Data.Numbers.Decimal import project.Data.Numbers.Integer import project.Data.Ordering.Comparable import project.Data.Pair.Pair +import project.Data.Text.Extensions +import project.Data.Text.Text import project.Data.Time.Date_Time.Date_Time import project.Data.Time.Period.Period import project.Data.Vector.Vector @@ -262,3 +264,17 @@ type Duration if self.milliseconds==0 . not then b.append ["milliseconds", self.milliseconds] if self.nanoseconds==0 . not then b.append ["nanoseconds", self.nanoseconds] JS_Object.from_pairs b.to_vector + + ## PRIVATE + Convert Duration to a friendly string. + to_display_text : Text + to_display_text self = if self == Duration.zero then "0s" else + h = if self.hours == 0 then "" else self.hours.to_text + "h " + + s = if self.seconds == 0 && self.nanoseconds == 0 then "" else + seconds = self.seconds + self.nanoseconds/1000000000 + seconds.format "00.##########" + "s" + + m = if self.minutes == 0 && (h=="" || s=="") then "" else self.minutes.to_text + "m " + + (h+m+s).trim diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso index e93430f79a0..ed1daadba25 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Period.enso @@ -1,12 +1,14 @@ import project.Any.Any import project.Data.Numbers.Integer +import project.Data.Ordering.Comparable +import project.Data.Text.Extensions +import project.Data.Text.Text import project.Data.Time.Date.Date import project.Data.Time.Duration.Duration -import project.Data.Ordering.Comparable -import project.Data.Text.Text import project.Error.Error import project.Errors.Illegal_Argument.Illegal_Argument import project.Errors.Time_Error.Time_Error +import project.Math import project.Meta import project.Nothing.Nothing import project.Panic.Panic @@ -128,3 +130,17 @@ type Period case err of DateTimeException -> Error.throw Time_Error.Error "Period subtraction failed" ArithmeticException -> Error.throw Illegal_Argument.Error "Arithmetic error" + + ## PRIVATE + Convert Period to a friendly string. + to_display_text : Text + to_display_text self = if self == Period.new then "0D" else + years = self.years + (self.months/12).floor + y = if years == 0 then "" else years.to_text + "Y " + + d = if self.days == 0 then "" else self.days.to_text + "D " + + months = self.months % 12 + m = if months == 0 && (y=="" || d=="") then "" else months.to_text + "M " + + (y + m + d) . trim diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Of_Day.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Of_Day.enso index 38f58eb58c9..74f107a536f 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Of_Day.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Of_Day.enso @@ -300,6 +300,13 @@ type Time_Of_Day cons_pair = ["constructor", "new"] JS_Object.from_pairs [type_pair, cons_pair, ["hour", self.hour], ["minute", self.minute], ["second", self.second], ["nanosecond", self.nanosecond]] + ## PRIVATE + Convert to a display representation of this Time_Of_Day. + to_display_text : Text + to_display_text self = + if self.nanosecond == 0 then self.format "HH:mm:ss" else + self.format "HH:mm:ss.n" + ## Format this time of day using the provided formatter pattern. Arguments: diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Zone.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Zone.enso index f9adbf6eff0..3a5f72aa8b3 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Zone.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Time_Zone.enso @@ -170,3 +170,8 @@ type Time_Zone type_pair = ["type", "Time_Zone"] cons_pair = ["constructor", "new"] JS_Object.from_pairs [type_pair, cons_pair, ["id", self.zone_id]] + + ## PRIVATE + Convert to a display representation of this Time_Zone. + to_display_text : Text + to_display_text self = self.to_text diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso index 2b5fa85f1a9..f509acd7b38 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso @@ -3,6 +3,7 @@ import project.Error.Error import project.Meta import project.Nothing.Nothing import project.Panic.Panic + from project.Data.Boolean import True, False polyglot java import java.lang.ClassCastException @@ -161,7 +162,9 @@ type No_Such_Method ## PRIVATE Convert the No_Such_Method error to a human-readable format. to_display_text : Text - to_display_text self = "Method `"+self.method_name+"` of "+self.target.to_display_text+" could not be found." + to_display_text self = + target_type_name = if Meta.is_polyglot self.target then self.target.to_display_text else (Meta.type_of self.target).to_display_text + "Method `"+self.method_name+"` of type "+target_type_name+" could not be found." @Builtin_Type type No_Such_Field @@ -174,6 +177,12 @@ type No_Such_Field - field_name: The name of the field that was being accessed. Error value field_name + ## PRIVATE + Convert the No_Such_Method error to a human-readable format. + to_display_text : Text + to_display_text self = + value_type_name = if Meta.is_polyglot self.value then self.value.to_display_text else (Meta.type_of self.value).to_display_text + "Field `"+self.field_name+"` of "+value_type_name+" could not be found." @Builtin_Type type Module_Not_In_Package_Error @@ -214,7 +223,7 @@ type Incomparable_Values to_display_text : Text to_display_text self = case self.left.is_nothing && self.right.is_nothing of - True -> "Incomparable_Values.Error" + True -> "Incomparable_Values" False -> "Cannot compare `" + self.left.to_text + "` with `" + self.right.to_text + "`" ## PRIVATE diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Meta/Enso_Project.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Meta/Enso_Project.enso index 1ccb2edd5a3..de3cdb8c2e4 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Meta/Enso_Project.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Meta/Enso_Project.enso @@ -12,7 +12,6 @@ type Project_Description - prim_config: The primitive config of the project. Value prim_root_file prim_config - ## Returns the root directory of the project. > Example diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/HTTP_Status_Code.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/HTTP_Status_Code.enso index 4fd19426146..a5fdf6e8bf1 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/HTTP_Status_Code.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/HTTP_Status_Code.enso @@ -1,4 +1,5 @@ import project.Data.Boolean.Boolean +import project.Data.Text.Text type HTTP_Status_Code ## 100 Continue. @@ -170,3 +171,49 @@ type HTTP_Status_Code ## Does the status code represent a successful response? is_success : Boolean is_success self = self.code >= 200 && self.code < 300 + + ## PRIVATE + Convert to a display representation of this HTTP_Status_Code. + to_display_text : Text + to_display_text self = case self.code of + 100 -> "Continue" + 101 -> "Switching Protocols" + 200 -> "OK" + 201 -> "Created" + 202 -> "Accepted" + 203 -> "Non-Authoritative Information" + 204 -> "No Content" + 205 -> "Reset Content" + 206 -> "Partial Content" + 300 -> "Multiple Choices" + 301 -> "Moved Permanently" + 302 -> "Found" + 303 -> "See Other" + 304 -> "Not Modified" + 305 -> "Use Proxy" + 307 -> "Temporary Redirect" + 400 -> "Bad Request" + 401 -> "Unauthorized" + 402 -> "Payment Required" + 403 -> "Forbidden" + 404 -> "Not Found" + 405 -> "Method Not Allowed" + 406 -> "Not Acceptable" + 407 -> "Proxy Authentication Required" + 408 -> "Request Timeout" + 409 -> "Conflict" + 410 -> "Gone" + 411 -> "Length Required" + 412 -> "Precondition Failed" + 413 -> "Request Entity Too Large" + 414 -> "Request-URI Too Long" + 415 -> "Unsupported Media Type" + 416 -> "Requested Range Not Satisfiable" + 417 -> "Expectation Failed" + 500 -> "Internal Server Error" + 501 -> "Not Implemented" + 502 -> "Bad Gateway" + 503 -> "Service Unavailable" + 504 -> "Gateway Timeout" + 505 -> "HTTP Version Not Supported" + _ -> "HTTP Status Code: " + self.code.to_text diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/Header.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/Header.enso index b931715bc73..b96d82d1318 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/Header.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP/Header.enso @@ -173,6 +173,12 @@ type Header text_plain : Header text_plain = Header.content_type "text/plain" + + ## PRIVATE + Convert to a display representation of this Header. + to_display_text : Text + to_display_text self = self.name + ": " + self.value.to_display_text + ## PRIVATE type Header_Comparator ## PRIVATE diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/URI.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/URI.enso index 90a502fea54..1e37e2e5245 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/URI.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/URI.enso @@ -188,6 +188,11 @@ type URI to_text : Text to_text self = self.internal_uri.toString + ## PRIVATE + Convert to a display representation of this URI. + to_display_text : Text + to_display_text self = self.to_text.to_display_text + ## PRIVATE Convert to a JavaScript Object representing this URI. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Random.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Random.enso index 19df6ba3c64..c673ae4587b 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Random.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Random.enso @@ -3,6 +3,8 @@ import project.Data.Boolean.Boolean import project.Data.Numbers.Integer import project.Data.Numbers.Decimal import project.Data.Vector.Vector +import project.Data.Json.JS_Object +import project.Data.Text.Text import project.Error.Error import project.Errors.Illegal_Argument.Illegal_Argument import project.System @@ -53,6 +55,17 @@ type Random_Number_Generator if range < Java_Integer.MAX_VALUE then min + (self.java_random.nextInt range) else Error.throw (Illegal_Argument.Error "Currently only integer ranges of up to 2^31-1 are supported.") + ## PRIVATE + Serialise to JS_Object + to_js_object : JS_Object + to_js_object self = + JS_Object.from_pairs [["type", "Random_Number_Generator"], ["constructor", "new"]] + + ## PRIVATE + Convert to a display representation of this Random_Number_Generator. + to_display_text : Text + to_display_text self = "Random_Number_Generator" + ## Returns a new vector containing a random sample of the input vector, without replacement. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File.enso index e681d8e85d9..4a542edd7a6 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File.enso @@ -676,6 +676,11 @@ type File to_text : Text to_text self = self.absolute . path + ## PRIVATE + Convert to a display representation of this File. + to_display_text : Text + to_display_text self = self.to_text + ## PRIVATE An output stream, allowing for interactive writing of contents into an open file. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/File_Permissions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/File_Permissions.enso index 314f6bd1125..1d0d06dfc19 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/File_Permissions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/File_Permissions.enso @@ -1,5 +1,6 @@ -import project.Data.Vector.Vector import project.Data.Boolean.Boolean +import project.Data.Text.Text +import project.Data.Vector.Vector polyglot java import java.nio.file.attribute.PosixFilePermission @@ -108,3 +109,12 @@ type File_Permissions others.append Permission.Execute File_Permissions.Value owner.to_vector group.to_vector others.to_vector + + ## PRIVATE + Convert to a display representation of this File_Permissions. + to_display_text : Text + to_display_text self = + owner = "Owner: " + (if self.owner_read then "r" else "-") + (if self.owner_write then "w" else "-") + (if self.owner_execute then "x" else "-") + group = "Group: " + (if self.group_read then "r" else "-") + (if self.group_write then "w" else "-") + (if self.group_execute then "x" else "-") + other = "Other: " + (if self.others_read then "r" else "-") + (if self.others_write then "w" else "-") + (if self.others_execute then "x" else "-") + owner + ", " + group + ", " + other diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Exit_Code.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Exit_Code.enso index 83a88bc9d77..ed0dcf3ed75 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Exit_Code.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Exit_Code.enso @@ -1,4 +1,5 @@ import project.Data.Numbers.Integer +import project.Data.Text.Text ## The exit codes that the process can return. type Exit_Code @@ -39,3 +40,10 @@ type Exit_Code to_number self = case self of Exit_Code.Success -> 0 Exit_Code.Failure code -> code + + ## PRIVATE + Convert to a display representation of this Exit_Code. + to_display_text : Text + to_display_text self = case self of + Exit_Code.Success -> "Success" + Exit_Code.Failure code -> "Failure " + code.to_display_text diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Process_Builder.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Process_Builder.enso index 6d33b4a212f..9ffc3177f13 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Process_Builder.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/System/Process/Process_Builder.enso @@ -78,3 +78,10 @@ type Process_Builder type Process_Result ## PRIVATE Value exit_code:Exit_Code stdout:Text stderr:Text + + ## PRIVATE + Convert to a display representation of this Process_Result. + to_display_text : Text + to_display_text self = case self.exit_code of + Exit_Code.Success -> "Success(" + self.stdout.to_display_text + ")" + _ -> self.exit_code.to_display_text + "(" + self.stderr.to_display_text + ")" diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso index 08aade3b3a4..0b7d54ccea2 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso @@ -28,7 +28,7 @@ type Warning ## ADVANCED Are any warnings attached to the value? - has_warnings : Any -> Boolean + has_warnings : Any -> Any -> Boolean has_warnings value warning_type=Any = Warning.get_all value . any (w-> w.value.is_a warning_type) @@ -36,7 +36,7 @@ type Warning Arguments: - warning_type: The type to remove if attached to the value. Defaults to all warnings. - remove_warnings : Any -> Any + remove_warnings : Any -> Any -> Any remove_warnings value warning_type=Any = Warning.detach_selected_warnings value (w-> w.is_a warning_type) . first diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso index 85558e26e9d..a4bc3bda892 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/Data/Table.enso @@ -1497,6 +1497,7 @@ type Table suffixing strategy. parse_to_columns : Text | Integer -> Text -> Case_Sensitivity -> Boolean -> Problem_Behavior -> Table parse_to_columns self column pattern="." case_sensitivity=Case_Sensitivity.Sensitive parse_values=True on_problems=Report_Error = + _ = [column, pattern, case_sensitivity, parse_values, on_problems] Error.throw (Unsupported_Database_Operation.Error "Table.parse_to_columns is not implemented yet for the Database backends.") ## PRIVATE diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Type/Value_Type.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Type/Value_Type.enso index a172ddcaf79..219458e79ce 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Type/Value_Type.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Data/Type/Value_Type.enso @@ -300,7 +300,6 @@ type Value_Type to_js_object : JS_Object to_js_object self = constructor_name = Meta.meta self . constructor . name - display_text = self.to_display_text additional_fields = case self of Value_Type.Integer size -> [["bits", size.to_bits]] @@ -316,7 +315,7 @@ type Value_Type [["type_name", type_name]] _ -> [] JS_Object.from_pairs <| - [["type", "Value_Type"], ["constructor", constructor_name], ["_display_text_", display_text]] + additional_fields + [["type", "Value_Type"], ["constructor", constructor_name]] + additional_fields ## The type representing inferring the column type automatically based on values present in the column. diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso index 903bd9163fb..c834d189799 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Errors.enso @@ -50,7 +50,7 @@ type Too_Many_Column_Names_Provided ## One or more column names were invalid during a rename operation. type Invalid_Output_Column_Names - Error (column_names : [Text]) + Error (column_names : Vector Text) ## PRIVATE diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso index b992b290c7a..5660b70a26d 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Table/Visualization.enso @@ -1,4 +1,5 @@ from Standard.Base import all +import Standard.Base.Data.Vector.Builder import Standard.Table.Data.Table.Table as Dataframe_Table import Standard.Table.Data.Column.Column as Dataframe_Column @@ -21,46 +22,109 @@ import project.Helpers prepare_visualization : Any -> Integer -> Text prepare_visualization y max_rows=1000 = Helpers.recover_errors <| x = Warning.set y [] - case x of + + result = case x of + _ : Vector -> make_json_for_vector x max_rows + _ : Array -> prepare_visualization x.to_vector max_rows + _ : Map -> make_json_for_map x max_rows + _ : JS_Object -> make_json_for_js_object x max_rows + _ : Dataframe_Column -> prepare_visualization x.to_table max_rows _ : Dataframe_Table -> - dataframe = x.take (First max_rows) + dataframe = x.take max_rows all_rows_count = x.row_count - included_rows = dataframe.row_count - index = Dataframe_Column.from_vector "#" (Vector.new included_rows i->i) - - make_json dataframe [index] all_rows_count - + index = Dataframe_Column.from_vector "#" (Vector.new dataframe.row_count i->i) + make_json_for_table dataframe [index] all_rows_count + _ : Database_Column -> prepare_visualization x.to_table max_rows _ : Database_Table -> - df = x.read max_rows + dataframe = x.read max_rows all_rows_count = x.row_count - - make_json df [] all_rows_count - - # We display columns as 1-column tables. - _ : Dataframe_Column -> - prepare_visualization x.to_table max_rows - _ : Database_Column -> - prepare_visualization x.to_table max_rows - - # TODO [RW] Should we truncate Vectors? - # We also visualize Vectors and arrays - _ : Vector -> - truncated = x.take (First max_rows) - JS_Object.from_pairs [["json", truncated], ["all_rows_count", x.length]] . to_text - _ : Array -> - prepare_visualization (Vector.from_polyglot_array x) max_rows - - # Serialize Maps - _ : Map -> - map_vector = Warning.clear (x.to_vector.take max_rows) - header = ["header", ["key", "value"]] - data = ["data", [map_vector.map .first, map_vector.map .second]] - all_rows = ["all_rows_count", x.size] - JS_Object.from_pairs [header, data, all_rows] . to_text - - # Anything else will be visualized with the JSON or matrix visualization + make_json_for_table dataframe [] all_rows_count _ -> - JS_Object.from_pairs [["json", x]] . to_text + js_value = x.to_js_object + value = if js_value.is_a JS_Object . not then js_value else + pairs = [['_display_text_', x.to_display_text]] + js_value.field_names.map f-> [f, make_json_for_value (js_value.get f)] + JS_Object.from_pairs pairs + JS_Object.from_pairs [["json", value]] + + result.to_text + +## Column Limit +max_columns = 250 + +## PRIVATE + Render Vector to JSON +make_json_for_vector : Vector -> Integer -> JS_Object +make_json_for_vector vector max_rows = + all_rows = ["all_rows_count", vector.length] + truncated = vector.take max_rows + + matrix = make_json_for_matrix (Vector.new_builder truncated.length) truncated + if matrix.is_nothing.not then JS_Object.from_pairs [["type", "Matrix"], all_rows, ["json", matrix], ["column_count", matrix.fold 0 c->v-> if v.is_nothing then c else c.max v.length]] else + object_matrix = make_json_for_object_matrix (Vector.new_builder truncated.length) truncated + if object_matrix.is_nothing.not then JS_Object.from_pairs [["type", "Object_Matrix"], all_rows, ["json", object_matrix]] else + JS_Object.from_pairs [["type", "Vector"], all_rows, ["json", truncated.map make_json_for_value]] + +## PRIVATE + Render Vector of Vector / Array to JSON +make_json_for_matrix : Builder -> Vector -> Integer -> Vector | Nothing +make_json_for_matrix current vector idx=0 = if idx == vector.length then current.to_vector else + row = vector.at idx + to_append = case row of + Nothing -> Nothing + _ : Vector -> row.take max_columns . map make_json_for_value + _ : Array -> row.to_vector.take max_columns . map make_json_for_value + _ -> False + if to_append == False then Nothing else + next = current.append to_append + @Tail_Call make_json_for_matrix next vector idx+1 + +## PRIVATE + Render Vector of Objects to JSON +make_json_for_object_matrix : Builder -> Vector -> Integer -> Vector | Nothing +make_json_for_object_matrix current vector idx=0 = if idx == vector.length then current.to_vector else + row = vector.at idx + to_append = case row of + Nothing -> Nothing + _ : Date -> False + _ : Time_Of_Day -> False + _ : Date_Time -> False + _ : Duration -> False + _ : Period -> False + _ : Map -> + pairs = row.keys.map k-> [k.to_text, make_json_for_value (row.get k)] + JS_Object.from_pairs pairs + _ -> + js_object = row.to_js_object + if js_object.is_a JS_Object . not then False else + if js_object.field_names.sort == ["type" , "constructor"] then False else + pairs = js_object.field_names.map f-> [f, make_json_for_value (js_object.get f)] + JS_Object.from_pairs pairs + if to_append == False then Nothing else + next = current.append to_append + @Tail_Call make_json_for_object_matrix next vector idx+1 + +## PRIVATE + Render Map to JSON +make_json_for_map : Map -> Integer -> JS_Object +make_json_for_map map max_items = + header = ["header", ["key", "value"]] + all_rows = ["all_rows_count", map.size] + map_vector = Warning.clear (map.to_vector.take max_items) + mapped = map_vector . map p-> [p.first.to_text, make_json_for_value p.second] + data = ["data", [mapped.map .first, mapped.map .second]] + JS_Object.from_pairs [header, data, all_rows, ["type", "Map"]] + +## PRIVATE + Render JS_Object to JSON +make_json_for_js_object : JS_Object -> Integer -> JS_Object +make_json_for_js_object js_object max_items = + fields = js_object.field_names + header = ["header", ["key", "value"]] + all_rows = ["all_rows_count", fields.length] + map_vector = Warning.clear (fields.take max_items) + mapped = map_vector . map p-> [p, make_json_for_value (js_object.get p)] + data = ["data", [mapped.map .first, mapped.map .second]] + JS_Object.from_pairs [header, data, all_rows, ["type", "Map"]] ## PRIVATE Creates a JSON representation for the visualizations. @@ -73,14 +137,51 @@ prepare_visualization y max_rows=1000 = Helpers.recover_errors <| `dataframe`. - all_rows_count: the number of all rows in the underlying data, useful if only a fragment is displayed. -make_json : (Dataframe_Table | Database_Table) -> Vector Dataframe_Column -> Integer -> Text -make_json dataframe indices all_rows_count = - get_vector c = Warning.set c.to_vector [] +make_json_for_table : Dataframe_Table -> Vector Dataframe_Column -> Integer -> JS_Object +make_json_for_table dataframe indices all_rows_count = + get_vector c = Warning.set (c.to_vector.map v-> make_json_for_value v) [] columns = dataframe.columns header = ["header", columns.map .name] data = ["data", columns.map get_vector] all_rows = ["all_rows_count", all_rows_count] ixes = ["indices", indices.map get_vector] ixes_header = ["indices_header", indices.map .name] - pairs = [header, data, all_rows, ixes, ixes_header] - JS_Object.from_pairs pairs . to_text + pairs = [header, data, all_rows, ixes, ixes_header, ["type", "Table"]] + JS_Object.from_pairs pairs + +## PRIVATE + Create JSON serialization of values for the table. +make_json_for_value : Any -> Integer -> Text +make_json_for_value val level=0 = case val of + Nothing -> Nothing + _ : Text -> val + _ : Number -> + js_version = val.to_js_object + if js_version.is_a JS_Object . not then js_version else + pairs = [['_display_text_', val.to_display_text]] + js_version.field_names.map f-> [f, js_version.get f] + JS_Object.from_pairs pairs + _ : Boolean -> val + _ : Vector -> + if level != 0 then "[… "+val.length.to_text+" items]" else + truncated = val.take 5 . map v-> (make_json_for_value v level+1).to_text + prepared = if val.length > 5 then truncated + ["… " + (val.length - 5).to_text+ " items"] else truncated + "[" + (prepared.join ", ") + "]" + _ : Array -> make_json_for_value val.to_vector level + _ : Map -> + if level != 0 then "{… "+val.size.to_text+" items}" else + truncated = val.keys.take 5 . map k-> k.to_text + ": " + (make_json_for_value (val.get k) level+1).to_text + prepared = if val.length > 5 then truncated + ["… " + (val.length - 5).to_text+ " items"] else truncated + "{" + (prepared.join ", ") + "}" + _ : Dataframe_Column -> make_json_for_value val.to_table level + _ : Database_Column -> make_json_for_value val.to_table level + _ : Dataframe_Table -> + if level != 0 then "Table{" + val.row_count + " rows x " + val.column_count + " columns}" else + truncated = val.columns.take 5 . map _.name + prepared = if val.column_count > 5 then truncated + ["… " + (val.column_count - 5).to_text+ " more"] else truncated + "Table{" + val.row_count.to_text + " rows x [" + (prepared.join ", ") + "]}" + _ : Database_Table -> + if level != 0 then "Table{" + val.row_count + " rows x " + val.column_count + " columns}" else + truncated = val.columns.take 5 . map _.name + prepared = if val.column_count > 5 then truncated + ["… " + (val.column_count - 5).to_text+ " more"] else truncated + "Table{" + val.row_count.to_text + " rows x [" + (prepared.join ", ") + "]}" + _ -> val.to_display_text diff --git a/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala b/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala index 0b2409eef17..dd3d4d19fa4 100644 --- a/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala +++ b/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala @@ -2989,7 +2989,7 @@ class RuntimeServerTest contextId, Seq( Api.ExecutionResult.Diagnostic.error( - "Type error: expected a function, but got 42 (Integer).", + "Type error: expected a function, but got 42.", Some(mainFile), Some(model.Range(model.Position(1, 7), model.Position(1, 19))), None, @@ -3136,7 +3136,7 @@ class RuntimeServerTest contextId, Seq( Api.ExecutionResult.Diagnostic.error( - "Method `+` of x (Unresolved_Symbol) could not be found.", + "Method `+` of type Function could not be found.", Some(mainFile), Some(model.Range(model.Position(3, 14), model.Position(3, 23))), None, @@ -3440,7 +3440,7 @@ class RuntimeServerTest contextId, Seq( Api.ExecutionResult.Diagnostic.error( - "Method `pi` of Number could not be found.", + "Method `pi` of type Number.type could not be found.", Some(mainFile), Some(model.Range(model.Position(3, 7), model.Position(3, 16))), None, diff --git a/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala b/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala index 1b0d23850fc..96f20746b04 100644 --- a/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala +++ b/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala @@ -1733,10 +1733,11 @@ class RuntimeVisualizationsTest Api.Response( requestId, Api.VisualisationExpressionFailed( - "Method `does_not_exist` of Main could not be found.", + "Method `does_not_exist` of type Main could not be found.", Some( Api.ExecutionResult.Diagnostic.error( - message = "Method `does_not_exist` of Main could not be found.", + message = + "Method `does_not_exist` of type Main could not be found.", stack = Vector( Api.StackTraceElement("", None, None, None), Api.StackTraceElement("Debug.eval", None, None, None) @@ -1817,10 +1818,10 @@ class RuntimeVisualizationsTest contextId, visualisationId, idMain, - "Method `visualise_me` of 50 (Integer) could not be found.", + "Method `visualise_me` of type Integer could not be found.", Some( Api.ExecutionResult.Diagnostic.error( - "Method `visualise_me` of 50 (Integer) could not be found.", + "Method `visualise_me` of type Integer could not be found.", None, Some(model.Range(model.Position(0, 5), model.Position(0, 19))), None, @@ -1929,10 +1930,10 @@ class RuntimeVisualizationsTest contextId, visualisationId, idMain, - "Method `visualise_me` of 51 (Integer) could not be found.", + "Method `visualise_me` of type Integer could not be found.", Some( Api.ExecutionResult.Diagnostic.error( - "Method `visualise_me` of 51 (Integer) could not be found.", + "Method `visualise_me` of type Integer could not be found.", Some(visualisationFile), Some(model.Range(model.Position(1, 11), model.Position(1, 25))), None, @@ -2134,10 +2135,10 @@ class RuntimeVisualizationsTest contextId, visualisationId, idMain, - "42 (Integer)", + "42", Some( Api.ExecutionResult.Diagnostic.error( - message = "42 (Integer)", + message = "42", file = Some(mainFile), location = Some(model.Range(model.Position(3, 4), model.Position(3, 18))), diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToDisplayTextNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToDisplayTextNode.java index d2391a655b6..8538bfc32fd 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToDisplayTextNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToDisplayTextNode.java @@ -1,6 +1,5 @@ package org.enso.interpreter.node.expression.builtin.text; -import com.ibm.icu.text.BreakIterator; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -13,6 +12,7 @@ import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.node.expression.builtin.text.util.TypeToDisplayTextNode; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.number.EnsoBigInteger; import org.enso.polyglot.common_utils.Core_Text_Utils; @BuiltinMethod(type = "Any", name = "to_display_text") @@ -35,6 +35,23 @@ public abstract class AnyToDisplayTextNode extends Node { } } + @Specialization + @CompilerDirectives.TruffleBoundary + Text convertInteger(long self) { + return Text.create(Long.toString(self)); + } + + @Specialization + @CompilerDirectives.TruffleBoundary + Text convertDouble(double self) { + return Text.create(Double.toString(self)); + } + + @Specialization + Text convertBigInteger(EnsoBigInteger bigInteger) { + return Text.create(bigInteger.toString()); + } + @Specialization Text convertText(Text self) { final var limit = 80; @@ -47,8 +64,8 @@ public abstract class AnyToDisplayTextNode extends Node { @CompilerDirectives.TruffleBoundary private static Text takePrefix(Text self, final int limit) { - var prefix = Core_Text_Utils.take_prefix(self.toString(), limit); - return Text.create(prefix); + var prefix = Core_Text_Utils.take_prefix(self.toString(), limit - 2); + return Text.create(prefix + " …"); } @Fallback diff --git a/engine/runtime/src/test/java/org/enso/interpreter/test/TypeMembersTest.java b/engine/runtime/src/test/java/org/enso/interpreter/test/TypeMembersTest.java index 7487d05f293..f1e13ed129d 100644 --- a/engine/runtime/src/test/java/org/enso/interpreter/test/TypeMembersTest.java +++ b/engine/runtime/src/test/java/org/enso/interpreter/test/TypeMembersTest.java @@ -118,7 +118,7 @@ public class TypeMembersTest { v.invokeMember(k); fail("Invoking " + k + " on " + v + " shall fail"); } catch (PolyglotException ex) { - assertEquals("No_Such_Field.Error", ex.getMessage()); + assertEquals("Field `" + k + "` of IntList could not be found.", ex.getMessage()); } } else { assertNotNull(msg + " - can be invoked", v.invokeMember(k)); diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/ImportsTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/ImportsTest.scala index 018033c88f3..ff739d19d05 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/ImportsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/ImportsTest.scala @@ -14,7 +14,7 @@ class ImportsTest extends PackageTest { "Overloaded methods" should "not be visible when not imported" in { the[InterpreterException] thrownBy evalTestProject( "TestNonImportedOverloads" - ) should have message "Method `method` of Mk_X could not be found." + ) should have message "Method `method` of type X could not be found." } "Import statements" should "report errors when they cannot be resolved" in { @@ -101,13 +101,13 @@ class ImportsTest extends PackageTest { "Importing module's types" should "not bring extension methods into the scope " in { the[InterpreterException] thrownBy evalTestProject( "Test_Extension_Methods_Failure" - ) should have message "Method `foo` of 1 (Integer) could not be found." + ) should have message "Method `foo` of type Integer could not be found." } "Compiler" should "detect name conflicts preventing users from importing submodules" in { the[InterpreterException] thrownBy evalTestProject( "TestSubmodulesNameConflict" - ) should have message "Method `c_mod_method` of C could not be found." + ) should have message "Method `c_mod_method` of type C.type could not be found." val outLines = consumeOut outLines(2) should include "Declaration of type C shadows module local.TestSubmodulesNameConflict.A.B.C making it inaccessible via a qualified name." @@ -183,7 +183,7 @@ class ImportsTest extends PackageTest { "Fully qualified names" should "detect conflicts with the exported types sharing the namespace" in { the[InterpreterException] thrownBy evalTestProject( "Test_Fully_Qualified_Name_Conflict" - ) should have message "Method `Foo` of Atom could not be found." + ) should have message "Method `Foo` of type Atom.type could not be found." val outLines = consumeOut outLines should have length 3 outLines( diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala index 833047be0cf..ef3bee9df5e 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala @@ -107,7 +107,7 @@ class MethodsTest extends InterpreterTest { |""".stripMargin the[InterpreterException] thrownBy eval( code - ) should have message "Method `foo` of 7 (Integer) could not be found." + ) should have message "Method `foo` of type Integer could not be found." } "be callable for any type when defined on Any" in { @@ -216,7 +216,7 @@ class MethodsTest extends InterpreterTest { |""".stripMargin the[InterpreterException] thrownBy eval( code - ) should have message "Method `new` of Mk_Foo could not be found." + ) should have message "Method `new` of type Foo could not be found." } "not be callable on Nothing when non-static" in { diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala index a2f350d0d6b..8b313a0a985 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala @@ -131,10 +131,10 @@ class TextTest extends InterpreterTest { "Syntax error: foo.", "Type error: expected `myvar` to be Nothing, but got List.", "Compile error: error :(.", - "Inexhaustive pattern match: no branch matches 32 (Integer).", + "Inexhaustive pattern match: no branch matches 32.", "Arithmetic error: cannot frobnicate quaternions.", "Type error: expected `that` to be Number, but got Text.", - "Type error: expected a function, but got 7 (Integer).", + "Type error: expected a function, but got 7.", "Wrong number of arguments. Expected 10, but got 20." ) } diff --git a/test/Table_Tests/src/Formatting/Parse_Values_Spec.enso b/test/Table_Tests/src/Formatting/Parse_Values_Spec.enso index 918b896affa..cd9881e87c3 100644 --- a/test/Table_Tests/src/Formatting/Parse_Values_Spec.enso +++ b/test/Table_Tests/src/Formatting/Parse_Values_Spec.enso @@ -413,6 +413,7 @@ spec = pUS2.to_vector . should_equal [1, 123, -1234, 1234567, Nothing] Problems.expect_warning (Invalid_Format.Error "ints" Value_Type.Integer ["12,34,56"]) pUS2 + ## Reject minus sign if already seen a bracket form cUS3 = Column.from_vector "ints" ["1", "(000,123)", "-1,234", "1,234,567", "12,34,56"] pUS3 = cUS3.parse type=Value_Type.Integer pUS3.to_vector . should_equal [1, -123, Nothing, 1234567, Nothing] @@ -423,6 +424,12 @@ spec = pUS4.to_vector . should_equal [1234, 1234, 1234567, -1234, Nothing] Problems.expect_warning (Invalid_Format.Error "ints" Value_Type.Integer ["($1,234,567)"]) pUS4 + ## Reject bracket notation for negative numbers if already seen a minus sign + cUS5 = Column.from_vector "ints" ["1", "000123", "-1,234", "1,234,567", "(123,456)"] + pUS5 = cUS5.parse type=Value_Type.Integer + pUS5.to_vector . should_equal [1, 123, -1234, 1234567, Nothing] + Problems.expect_warning (Invalid_Format.Error "ints" Value_Type.Integer ["(123,456)"]) pUS5 + Test.specify "should correctly parse integers in European formats" <| cDE = Column.from_vector "ints" ["1", "000123", "-1.234", "1.234.567", "12.34.56"] pDE = cDE.parse type=Value_Type.Integer @@ -470,6 +477,7 @@ spec = pUS2.to_vector . should_equal [1.23, 123, -1234.567, 1234567.789, Nothing] Problems.expect_warning (Invalid_Format.Error "floats" Value_Type.Float ["12,34.56"]) pUS2 + ## Reject minus sign if already seen a bracket form cUS3 = Column.from_vector "floats" ["1.23", "(000,123)", "-1,234.567", "1,234,567.789", "12,34.56"] pUS3 = cUS3.parse type=Value_Type.Float pUS3.to_vector . should_equal [1.23, -123, Nothing, 1234567.789, Nothing] @@ -480,6 +488,12 @@ spec = pUS4.to_vector . should_equal [12.34, 1234, 1234567.789, -1234.96, Nothing] Problems.expect_warning (Invalid_Format.Error "floats" Value_Type.Float ["($1,234,567)"]) pUS4 + ## Reject bracket notation for negative numbers if already seen a minus sign + cUS5 = Column.from_vector "floats" ["1.23", "000123", "-1,234.567", "1,234,567.789", "(123,456)"] + pUS5 = cUS5.parse type=Value_Type.Float + pUS5.to_vector . should_equal [1.23, 123, -1234.567, 1234567.789, Nothing] + Problems.expect_warning (Invalid_Format.Error "floats" Value_Type.Float ["(123,456)"]) pUS5 + Test.specify "should correctly parse decimals in European formats" <| cDE = Column.from_vector "floats" ["1,23", "000123", "-1.234,567", "1.234.567,789", "12.34,56"] pDE = cDE.parse type=Value_Type.Float diff --git a/test/Table_Tests/src/In_Memory/Table_Spec.enso b/test/Table_Tests/src/In_Memory/Table_Spec.enso index fb5d3d2cb47..239190e18f6 100644 --- a/test/Table_Tests/src/In_Memory/Table_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Table_Spec.enso @@ -525,12 +525,14 @@ spec = Test.specify "should work happily with mixed types" <| c_0 = ['A', ["H", "B", "C"]] + c_00 = ['AA', ["", "B", "C"]] c_1 = ['B', [Date.new 1980, Date.new 1979, Date.new 2000]] c_2 = ['x', [1, 2, 3]] c_3 = ['Y', [5.3, 56.2, 6.3]] c_4 = ['Z', [True, False, True]] - table = Table.new [c_0, c_1, c_2, c_3, c_4] - expect_column_names ["H", "1980-01-01", "1", "5.3", "True"] <| table.use_first_row_as_names + c_5 = ['ZZ', [Nothing, False, True]] + table = Table.new [c_0, c_00, c_1, c_2, c_3, c_4, c_5] + expect_column_names ["H", "Column_1", "1980-01-01", "1", "5.3", "True", "Column_2"] table.use_first_row_as_names Test.specify "should correctly handle problems: invalid names ''" <| c_0 = ['A', ["", "B", "C"]] diff --git a/test/Tests/src/Data/Map_Spec.enso b/test/Tests/src/Data/Map_Spec.enso index 132d4896ac5..e544a77d747 100644 --- a/test/Tests/src/Data/Map_Spec.enso +++ b/test/Tests/src/Data/Map_Spec.enso @@ -250,7 +250,7 @@ spec = vec = [[0, 0], [3, -5], [1, 2], [0, 1]] m1 = Map.from_vector vec m1.should_fail_with Illegal_Argument - m1.catch.message . should_equal "`Map.from_vector` encountered duplicate key: 0 (Integer)" + m1.catch.message . should_equal "`Map.from_vector` encountered duplicate key: 0" m2 = Map.from_vector vec allow_duplicates=True Problems.assume_no_problems m2 @@ -304,7 +304,7 @@ spec = m = Map.from_vector [[1, 2], [11, 3]] m2 = m.transform (k -> v -> [k % 10, v*2]) m2.should_fail_with Illegal_Argument - m2.catch.message . should_equal "`Map.transform` encountered duplicate key: 1 (Integer)" + m2.catch.message . should_equal "`Map.transform` encountered duplicate key: 1" Test.specify "should allow mapping over values" <| m = Map.empty . insert 1 2 . insert 2 4 diff --git a/test/Tests/src/Data/Noise/Generator_Spec.enso b/test/Tests/src/Data/Noise/Generator_Spec.enso index 72ad49a31d0..708d1c4cc05 100644 --- a/test/Tests/src/Data/Noise/Generator_Spec.enso +++ b/test/Tests/src/Data/Noise/Generator_Spec.enso @@ -1,18 +1,12 @@ from Standard.Base import all import Standard.Base.Errors.Unimplemented.Unimplemented -import Standard.Base.Data.Noise.Generator import Standard.Base.Data.Noise.Deterministic_Random from Standard.Test import Test, Test_Suite import Standard.Test.Extensions spec = - Test.group "Generator Interface" <| - gen = Generator - Test.specify "should not be invokable" <| - interval = Interval.inclusive 0 1 - Test.expect_panic_with (gen.step 1 interval) Unimplemented Test.group "Deterministic Random Noise Generator" <| gen = Deterministic_Random Test.specify "should always return the same output for the same input" <| diff --git a/test/Tests/src/Data/Text/Utils_Spec.enso b/test/Tests/src/Data/Text/Utils_Spec.enso index 671f06ff32a..97d08dcd987 100644 --- a/test/Tests/src/Data/Text/Utils_Spec.enso +++ b/test/Tests/src/Data/Text/Utils_Spec.enso @@ -98,18 +98,18 @@ spec = disp = long.to_display_text disp.length . should_equal 80 disp.characters.take (First 5) . should_equal [ 'H', 'e', 'l', 'l', 'o' ] - disp.characters.take (Last 6) . should_equal ['l', 'd', '!', ' ', 'H', 'e'] + disp.characters.take (Last 6) . should_equal ['l', 'd', '!', ' ', ' ', '…'] Test.specify "grapheme 1 conversion" <| txt = 'a\u0321\u0302'*100 - txt.to_display_text . should_equal 'a\u0321\u0302'*80 + txt.to_display_text . should_equal ('a\u0321\u0302'*78 + ' …') Test.specify "grapheme 2 conversion" <| txt = '\u0915\u094D\u0937\u093F'*100 - txt.to_display_text . should_equal '\u0915\u094D\u0937\u093F'*80 + txt.to_display_text . should_equal ('\u0915\u094D\u0937\u093F'*78 + ' …') Test.specify "grapheme 3 conversion" <| txt = '\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F'*100 - txt.to_display_text . should_equal '\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F'*80 + txt.to_display_text . should_equal ('\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F'*78 + ' …') main = Test_Suite.run_main spec diff --git a/test/Tests/src/Data/Time/Date_Time_Spec.enso b/test/Tests/src/Data/Time/Date_Time_Spec.enso index 254d314f256..b739b85e7c0 100644 --- a/test/Tests/src/Data/Time/Date_Time_Spec.enso +++ b/test/Tests/src/Data/Time/Date_Time_Spec.enso @@ -142,6 +142,7 @@ spec_with name create_new_datetime parse_datetime nanoseconds_loss_in_precision= time . second . should_equal 1 time . nanosecond . should_equal 0 time . zone . zone_id . should_equal "Europe/Paris" + time.to_display_text . should_equal "1970-01-01 00:00:01 Europe/Paris" Test.specify "should throw error when parsing invalid time" <| case parse_datetime "2008-1-1" . catch of @@ -199,6 +200,7 @@ spec_with name create_new_datetime parse_datetime nanoseconds_loss_in_precision= time . second . should_equal 1 time . nanosecond . should_equal 0 time . zone . zone_id . should_equal tz.zone_id + time.to_display_text . should_equal "1970-01-01 01:01:01 +01:01:01" Test.specify "should set id-based timezone" <| tz = Time_Zone.parse "Europe/Moscow" @@ -211,6 +213,7 @@ spec_with name create_new_datetime parse_datetime nanoseconds_loss_in_precision= time . second . should_equal 0 time . nanosecond . should_equal 0 time . zone . zone_id . should_equal tz.zone_id + time.to_display_text . should_equal "1970-01-01 03:00:00 Europe/Moscow" Test.specify "should get time of day from offsed-based time" <| time = parse_datetime "1970-01-01T00:00:01+01:00" . time_of_day diff --git a/test/Tests/src/Data/Time/Duration_Spec.enso b/test/Tests/src/Data/Time/Duration_Spec.enso index bda77111a0f..0d0d45a136b 100644 --- a/test/Tests/src/Data/Time/Duration_Spec.enso +++ b/test/Tests/src/Data/Time/Duration_Spec.enso @@ -34,6 +34,15 @@ spec = duration = (Duration.new hours=13) - (Duration.new hours=1) duration.hours . should_equal 12 + Test.specify "should render a friendly to display text" <| + Duration.new . to_display_text . should_equal "0s" + Duration.new seconds=30 . to_display_text . should_equal "30s" + Duration.new seconds=30 milliseconds=500 . to_display_text . should_equal "30.5s" + Duration.new hours=1 . to_display_text . should_equal "1h" + Duration.new hours=1 minutes=30 . to_display_text . should_equal "1h 30m" + Duration.new hours=1 seconds=30 . to_display_text . should_equal "1h 0m 30s" + Duration.new hours=1 minutes=30 seconds=30 . to_display_text . should_equal "1h 30m 30s" + Test.specify "should convert to Json" <| interval = (Duration.new nanoseconds=120) + (Duration.new seconds=30) + (Duration.new hours=14) interval.to_json.should_equal <| diff --git a/test/Tests/src/Data/Time/Period_Spec.enso b/test/Tests/src/Data/Time/Period_Spec.enso index 667ed04c90f..9895ae12686 100644 --- a/test/Tests/src/Data/Time/Period_Spec.enso +++ b/test/Tests/src/Data/Time/Period_Spec.enso @@ -41,4 +41,13 @@ spec = ((Period.new years=1 days=10) == (Period.new years=1 days=10)) . should_be_true ((Period.new days=1) != (Period.new months=1)) . should_be_true + Test.specify "should render a friendly to display text" <| + Period.new . to_display_text . should_equal "0D" + Period.new years=2 . to_display_text . should_equal "2Y" + Period.new months=24 . to_display_text . should_equal "2Y" + Period.new months=4 . to_display_text . should_equal "4M" + Period.new months=18 . to_display_text . should_equal "1Y 6M" + Period.new years=2 days=3 . to_display_text . should_equal "2Y 0M 3D" + Period.new days=18 . to_display_text . should_equal "18D" + main = Test_Suite.run_main spec diff --git a/test/Visualization_Tests/src/Table_Spec.enso b/test/Visualization_Tests/src/Table_Spec.enso index 8899dcb1343..2927ebb3f11 100644 --- a/test/Visualization_Tests/src/Table_Spec.enso +++ b/test/Visualization_Tests/src/Table_Spec.enso @@ -31,14 +31,14 @@ visualization_spec connection = p_all_rows = ["all_rows_count", all_rows] p_ixes = ["indices", ixes] p_ixes_header = ["indices_header", ixes_header] - pairs = [p_header, p_data, p_all_rows, p_ixes, p_ixes_header] + pairs = [p_header, p_data, p_all_rows, p_ixes, p_ixes_header, ["type", "Table"]] JS_Object.from_pairs pairs . to_text Test.group "Table Visualization" <| Test.specify "should wrap internal errors" <| bad_table = Database_Table.Value Nothing Nothing Nothing Nothing vis = Visualization.prepare_visualization bad_table 2 - json = JS_Object.from_pairs [["error", "Method `set_limit` of Nothing could not be found."]] + json = JS_Object.from_pairs [["error", "Method `set_limit` of type Nothing could not be found."]] vis . should_equal json.to_text Test.specify "should visualize database tables" <| @@ -69,30 +69,34 @@ visualization_spec connection = Test.specify "should handle Vectors" <| vis = Visualization.prepare_visualization [1, 2, 3] 2 - json = JS_Object.from_pairs [["json", [1, 2]], ["all_rows_count", 3]] + json = JS_Object.from_pairs [["type", "Vector"], ["all_rows_count", 3], ["json", [1, 2]]] vis . should_equal json.to_text vis2 = Visualization.prepare_visualization [[1, 2], [3, 4]] 2 - json2 = JS_Object.from_pairs [["json", [[1, 2], [3, 4]]], ["all_rows_count", 2]] + json2 = JS_Object.from_pairs [["type", "Matrix"], ["all_rows_count", 2], ["json", [[1, 2], [3, 4]]], ["column_count", 2]] vis2 . should_equal json2.to_text Test.specify "should handle Arrays" <| vis = Visualization.prepare_visualization ([1, 2, 3] . to_array) 2 - json = JS_Object.from_pairs [["json", [1, 2]], ["all_rows_count", 3]] + json = JS_Object.from_pairs [["type", "Vector"], ["all_rows_count", 3], ["json", [1, 2]]] vis . should_equal json.to_text Test.specify "should handle other datatypes" <| vis = Visualization.prepare_visualization (Foo.Value 42) 2 - json = JS_Object.from_pairs [["json", (Foo.Value 42)]] + json = JS_Object.from_pairs [["json", JS_Object.from_pairs [["_display_text_", (Foo.Value 42).to_display_text],["x", 42]]]] vis . should_equal json.to_text Test.specify "should visualize value type info" <| - Value_Type.Boolean.to_json . should_equal '{"type":"Value_Type","constructor":"Boolean","_display_text_":"Boolean"}' - Value_Type.Float.to_json . should_equal '{"type":"Value_Type","constructor":"Float","_display_text_":"Float (64 bits)","bits":64}' - Value_Type.Decimal.to_json . should_equal '{"type":"Value_Type","constructor":"Decimal","_display_text_":"Decimal (precision=Nothing, scale=Nothing)","precision":null,"scale":null}' - Value_Type.Char.to_json . should_equal '{"type":"Value_Type","constructor":"Char","_display_text_":"Char (max_size=Nothing, variable_length=True)","size":null,"variable_length":true}' - Value_Type.Unsupported_Data_Type.to_json . should_equal '{"type":"Value_Type","constructor":"Unsupported_Data_Type","_display_text_":"Unsupported_Data_Type","type_name":null}' + make_json vt = + js_object = vt.to_js_object + pairs = [["_display_text_", vt.to_display_text]] + vt.to_js_object.field_names.map f-> [f, js_object.get f] + JS_Object.from_pairs [["json", JS_Object.from_pairs pairs]] . to_text + Visualization.prepare_visualization Value_Type.Boolean . should_equal (make_json Value_Type.Boolean) + Visualization.prepare_visualization Value_Type.Float . should_equal (make_json Value_Type.Float) + Visualization.prepare_visualization Value_Type.Decimal . should_equal (make_json Value_Type.Decimal) + Visualization.prepare_visualization Value_Type.Char . should_equal (make_json Value_Type.Char) + Visualization.prepare_visualization Value_Type.Unsupported_Data_Type . should_equal (make_json Value_Type.Unsupported_Data_Type) spec = enso_project.data.create_directory diff --git a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso index 58897ef33a6..205a654c70c 100644 --- a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso +++ b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso @@ -1,6 +1,6 @@ -import project.Meta -import project.Error.Error import project.Any.Any +import project.Error.Error +import project.Meta @Builtin_Type @@ -50,7 +50,9 @@ type No_Such_Method method_name self = Meta.meta self.symbol . name - to_display_text self = "Method `"+self.method_name+"` of "+self.target.to_display_text+" could not be found." + to_display_text self = + target_type_name = if Meta.is_polyglot self.target then self.target.to_display_text else (Meta.type_of self.target).to_display_text + "Method `"+self.method_name+"` of type "+target_type_name+" could not be found." @Builtin_Type type Module_Not_In_Package_Error diff --git a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso index 199c427f5a7..2837626e421 100644 --- a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso +++ b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso @@ -10,6 +10,8 @@ type Primitive type_of value = @Builtin_Method "Meta.type_of" +is_polyglot value = @Builtin_Method "Meta.is_polyglot" + # A **very** minimal version of meta for the purpose of tests meta value = if is_unresolved_symbol value then Unresolved_Symbol.Value value else