Skip to content

Commit

Permalink
Adding type annotations and enabling auto-scoping (#10173)
Browse files Browse the repository at this point in the history
- Renamed `Missing_Required_Argument` to `Missing_Argument`, and added `throw` method.
- Add default widget to `Case_Sensitivity.Insensitive locale`.
- Switch to auto scoping for `parse_type_selector`.
- Add type annotation to various simple typed arguments in `Table` and `DB_Table`.
- Altered `Filter_Condition` to have `Missing_Argument` for all non-defaulted arguments.
- Added resolution of `Column_Ref` passed as auto-scoped to `Table_Ref`.
- Altered `Simple_Calculation` to have `Missing_Argument` for all non-defaulted arguments.
- Altered `Join_Condition` to have `Missing_Argument` for all non-defaulted arguments.
- Altered `Sort_Column` to have `Missing_Argument` for all non-defaulted arguments.
- Altered `Aggregate_Column` to have `Missing_Argument` for all non-defaulted arguments.

**rename_columns:**
![image](https://github.com/enso-org/enso/assets/4699705/08aaba0f-687a-450c-9781-8eadc062bd50)

**aggregate:**
![image](https://github.com/enso-org/enso/assets/4699705/c29e7944-1a1c-4020-9fe0-528d874b8049)

**join:**
![image](https://github.com/enso-org/enso/assets/4699705/50038166-e56d-48c5-9eeb-bd46fa415e46)

**set:**
![image](https://github.com/enso-org/enso/assets/4699705/bee2462a-dafb-4bd4-b102-ec73edb4fb93)
  • Loading branch information
jdunkerley authored Jun 10, 2024
1 parent b5969cf commit d938c96
Show file tree
Hide file tree
Showing 33 changed files with 398 additions and 383 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import project.Data.Text.Text
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Common.Incomparable_Values
import project.Errors.Common.Missing_Argument
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Function.Function
import project.Meta
import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True
from project.Data.Filter_Condition.Filter_Condition import all
from project.Data.Text.Extensions import all
Expand All @@ -22,25 +24,25 @@ polyglot java import org.enso.base.Regex_Utils

type Filter_Condition
## Is less than a value (or another column, in case of Table operations)?
Less than:Any action:Filter_Action=Filter_Action.Keep
Less than=(Missing_Argument.throw "than") action:Filter_Action=Filter_Action.Keep

## Is less than or equal to a value (or another column, in case of Table operations)?
Equal_Or_Less than:Any action:Filter_Action=Filter_Action.Keep
Equal_Or_Less than=(Missing_Argument.throw "than") action:Filter_Action=Filter_Action.Keep

## Is equal to a value (or another column, in case of Table operations)?
Equal to:Any action:Filter_Action=Filter_Action.Keep
Equal to=(Missing_Argument.throw "to") action:Filter_Action=Filter_Action.Keep

## Is greater than or equal to a value (or another column, in case of Table operations)?
Equal_Or_Greater than:Any action:Filter_Action=Filter_Action.Keep
Equal_Or_Greater than=(Missing_Argument.throw "than") action:Filter_Action=Filter_Action.Keep

## Is greater than a value (or another column, in case of Table operations)?
Greater than:Any action:Filter_Action=Filter_Action.Keep
Greater than=(Missing_Argument.throw "than") action:Filter_Action=Filter_Action.Keep

## Is not equal to a value (or another column, in case of Table operations)?
Not_Equal to:Any action:Filter_Action=Filter_Action.Keep
Not_Equal to=(Missing_Argument.throw "to") action:Filter_Action=Filter_Action.Keep

## Is between (inclusive) two values (or columns, in case of Table operations)?
Between lower:Any upper:Any action:Filter_Action=Filter_Action.Keep
Between lower=(Missing_Argument.throw "lower") upper=(Missing_Argument.throw "upper") action:Filter_Action=Filter_Action.Keep

## Is equal to another value, ignoring case (Text only)?

Expand All @@ -55,31 +57,31 @@ type Filter_Condition
This ensures that different ways of expressing the same character in
the underlying binary representation are considered equal.
@locale Locale.default_widget
Equal_Ignore_Case (to : Text | Any) (locale:Locale=Locale.default) action:Filter_Action=Filter_Action.Keep
Equal_Ignore_Case (to = (Missing_Argument.throw "to")) (locale:Locale=Locale.default) action:Filter_Action=Filter_Action.Keep

## Does the value start with a prefix (Text only)?

? Table Operations
It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked.
Starts_With (prefix : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep
Starts_With (prefix = (Missing_Argument.throw "prefix")) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep

## Does the value end with a suffix (Text only)?

? Table Operations
It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked.
Ends_With (suffix : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep
Ends_With (suffix = (Missing_Argument.throw "suffix")) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep

## Does the value contain the substring (Text only)?

? Table Operations
It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked.
Contains (substring : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep
Contains (substring = (Missing_Argument.throw "substring")) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep

## Is equal to Nothing?
Is_Nothing action:Filter_Action=Filter_Action.Keep
Expand Down Expand Up @@ -127,7 +129,7 @@ type Filter_Condition
Due to this limitation, Unicode normalization has been disabled for
this function, so beware that some equivalent graphemes like 'ś' and
's\u0301' will not be matched.
Like (pattern : Text | Any) action:Filter_Action=Filter_Action.Keep
Like (pattern = (Missing_Argument.throw "pattern")) action:Filter_Action=Filter_Action.Keep

## Is the value contained in `values`?

Expand All @@ -141,7 +143,16 @@ type Filter_Condition
Using Columns can be particularly useful for Database operations, as
uploading a temporary table and using its column for an `Is_In` check
will likely be faster than using the vector directly.
Is_In values:Vector|Any action:Filter_Action=Filter_Action.Keep
Is_In values=[] action:Filter_Action=Filter_Action.Keep

## PRIVATE
Resolves a possibly auto-scoped value to a concrete value.
resolve_auto_scoped : Any -> Any
resolve_auto_scoped filter =
resolve filter:Filter_Condition = filter
case filter of
_ : Function -> Panic.catch Any (resolve filter) _->filter
_ -> filter

## ICON convert
Converts a `Filter_Condition` condition into a predicate taking an
Expand Down Expand Up @@ -295,43 +306,15 @@ unify_condition_or_predicate : Filter_Condition | (Any -> Boolean) -> (Any -> Bo
unify_condition_or_predicate (condition_or_predicate : Filter_Condition | (Any -> Boolean)) =
case condition_or_predicate of
condition : Filter_Condition -> condition.to_predicate
predicate -> handle_constructor_missing_arguments predicate predicate
predicate -> predicate

## PRIVATE
unify_condition_predicate_or_element condition =
case condition of
condition : Filter_Condition -> condition.to_predicate
predicate : Function -> handle_constructor_missing_arguments predicate predicate
predicate : Function -> predicate
element -> (== element)

## PRIVATE
Checks if the given `function` is actually a `Filter_Condition` constructor
that is just missing arguments. If so, it will report a more friendly error.
Otherwise it will run the `continuation`.
handle_constructor_missing_arguments function ~continuation =
is_filter_condition_constructor = case Meta.meta function of
constructor : Meta.Constructor ->
constructor.declaring_type == Meta.meta Filter_Condition
## Special case for multi-argument constructors with some but not all
arguments applied.

For example, `Meta.meta (Filter_Condition.Between 10)` will return a `Meta.Primitive`.
We rely on its text representation being of the form `Filter_Condition.Between[Filter_Condition.enso:41-343]`.
_ : Meta.Primitive ->
text = function.to_text
prefix = "Filter_Condition."
if (text.starts_with prefix && text.contains "[Filter_Condition.enso:") . not then False else
## The additional check for capital letter is needed, because otherwise, we get false positives:
`(Filter_Condition.Greater 1).to_predicate` evaluates to function whose text representation
may start with `Filter_Condition.handle_nothing`. Such functions are not constructors.
constructor_letter = text.get prefix.length ""
constructor_letter >= "A" && constructor_letter <= "Z"

_ -> False
if is_filter_condition_constructor.not then continuation else
message = "Got a Filter_Condition constructor without all required arguments provided. Please provide the missing arguments."
Error.throw (Illegal_Argument.Error message)

## PRIVATE
Extends the provided predicate to handle `Nothing` values without error.
The new predicate will return `False` for `Nothing`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import project.Data.Text.Text
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Common.Missing_Argument
import project.Errors.Common.Type_Error
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Function.Function
Expand Down Expand Up @@ -35,7 +36,7 @@ type Index_Sub_Range
Last (count : Integer = 1)

## Select elements from the start while the predicate returns `True`.
While (predicate : (Any -> Boolean))
While (predicate : (Any -> Boolean) = Missing_Argument.throw "predicate")

## Selects specific indexes (starting from 0) either as an `Integer` or a
`Range`.
Expand All @@ -47,21 +48,21 @@ type Index_Sub_Range
Only ranges with positive step and positive indices are supported.
Individual integer indices can be negative which allows for indexing
from the end of the collection.
By_Index (indexes : (Integer | Range | Vector (Integer | Range)))
By_Index (indexes : (Integer | Range | Vector (Integer | Range)) = Missing_Argument.throw "indexes")

## Gets a random sample of entries, without repetitions.

If `count` is greater than the length of the input, a random permutation
of all elements from the input is selected.
Sample (count:Integer) (seed:Integer|Nothing=Nothing)
Sample (count : Integer = 1) (seed:Integer|Nothing=Nothing)

## Gets every Nth entry.

Arguments:
- step: The step between consecutive entries that are included.
- first: The first entry to include. If it is outside of bounds of the
input, an error is raised.
Every (step:Integer) (first:Integer=0)
Every (step:Integer=1) (first:Integer=0)

## PRIVATE
Convert to a display representation of this Index_Sub_Range.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type Case_Sensitivity

Arguments:
- locale: The locale used for the comparison.
@locale Locale.default_widget
Insensitive (locale : Locale = Locale.default)

## PRIVATE
Expand Down
23 changes: 15 additions & 8 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso
Original file line number Diff line number Diff line change
Expand Up @@ -460,16 +460,23 @@ type Out_Of_Memory

## Indicates that an expression cannot be evaluated because somewhere within it,
a function does not have all required arguments provided.
type Missing_Required_Argument
type Missing_Argument
## PRIVATE
Indicates that an expression cannot be evaluated because somewhere within
it, a function does not have all required arguments provided.
Error (argument_name : Text) (function_name : Text) (call_location : Source_Location | Nothing)
Error (argument_name : Text) (function_name : Text | Nothing = Nothing) (call_location : Source_Location | Nothing = Nothing)

## PRIVATE
to_display_text : Text
to_display_text self =
"Missing required argument `" + self.argument_name + "` in function `" + self.function_name + "`."
to_display_text self = case self.function_name of
Nothing -> "Provide a value for the argument `" + self.argument_name + "`."
_ -> "Missing required argument `" + self.argument_name + "` in function `" + self.function_name + "`."

## PRIVATE
Throws an error saying that a required argument has not been provided.
throw : Text -> Nothing ! Missing_Argument
throw argument_name:Text =
Error.throw (Missing_Argument.Error argument_name)

## PRIVATE
Throws an error saying that a required argument has not been provided.
Expand All @@ -482,16 +489,16 @@ type Missing_Required_Argument

> Example

my_function (arg1 = Missing_Required_Argument.ensure_present "arg1") (arg2 = 100) = arg1+arg2
ensure_present : Text -> Nothing ! Missing_Required_Argument
ensure_present (argument_name : Text = Missing_Required_Argument.ensure_present "argument_name") =
my_function (arg1 = Missing_Argument.ensure_present "arg1") (arg2 = 100) = arg1+arg2
ensure_present : Text -> Nothing ! Missing_Argument
ensure_present (argument_name : Text = Missing_Argument.ensure_present "argument_name") =
stack_trace = Runtime.get_stack_trace
function_frame = stack_trace . at 1
caller_frame = stack_trace . at 2

function_name = function_frame.name
call_location = caller_frame.source_location
Error.throw (Missing_Required_Argument.Error argument_name function_name call_location)
Error.throw (Missing_Argument.Error argument_name function_name call_location)

## Warning when additional warnings occurred.
type Additional_Warnings
Expand Down
15 changes: 2 additions & 13 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Widget_Helpers.enso
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,6 @@ make_format_chooser include_number:Boolean=True include_date:Boolean=True includ
Creates a Multiple_Choice Widget for selecting data cleanse operations.
make_data_cleanse_vector_selector : Display -> Widget
make_data_cleanse_vector_selector display:Display=Display.Always =
options = Vector.build builder->
builder.append (Option "Leading_Whitespace" "Named_Pattern.Leading_Whitespace")
builder.append (Option "Trailing_Whitespace" "Named_Pattern.Trailing_Whitespace")
builder.append (Option "Duplicate_Whitespace" "Named_Pattern.Duplicate_Whitespace")
builder.append (Option "All_Whitespace" "Named_Pattern.All_Whitespace")
builder.append (Option "Leading_Numbers" "Named_Pattern.Leading_Numbers")
builder.append (Option "Trailing_Numbers" "Named_Pattern.Trailing_Numbers")
builder.append (Option "Non_ASCII" "Named_Pattern.Non_ASCII")
builder.append (Option "Tabs" "Named_Pattern.Tabs")
builder.append (Option "Letters" "Named_Pattern.Letters")
builder.append (Option "Numbers" "Named_Pattern.Numbers")
builder.append (Option "Punctuation" "Named_Pattern.Punctuation")
builder.append (Option "Symbols" "Named_Pattern.Symbols")
patterns = ['Leading_Whitespace', 'Trailing_Whitespace', 'Duplicate_Whitespace', 'All_Whitespace', 'Leading_Numbers', 'Trailing_Numbers', 'Non_ASCII', 'Tabs', 'Letters', 'Numbers', 'Punctuation', 'Symbols']
options = patterns.map f-> Option f (".." + f)
Multiple_Choice values=options display=display
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ type DB_Column
@type (Widget_Helpers.parse_type_selector include_auto=False)
@format (make_format_chooser include_number=False)
parse : Value_Type | Auto -> Text | Data_Formatter -> Problem_Behavior -> DB_Column
parse self type format:(Text | Data_Formatter)="" on_problems=Report_Warning =
parse self type:(Value_Type | Auto) format:(Text | Data_Formatter)="" on_problems=Report_Warning =
if type == Auto then Error.throw (Unsupported_Database_Operation.Error "The `Auto` parse type is not supported by the Database backend. Either pick a specific type or materialize the table to memory using `.read`.") else
if format != "" then Error.throw (Unsupported_Database_Operation.Error "Custom formatting is not supported by the Database backend. Please set the format to `''` to use the default settings, or if custom formatting is needed, materialize the table to memory using `.read` first.") else
Value_Type.expect_text self <|
Expand Down
Loading

0 comments on commit d938c96

Please sign in to comment.