mirror of
https://github.com/enso-org/enso.git
synced 2024-10-26 21:19:02 +03:00
Improve dataflow errors in the standard library (#1446)
This commit is contained in:
parent
f0115587b0
commit
af1aab35aa
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -3,6 +3,7 @@
|
||||
|
||||
# Distribution
|
||||
/distribution @iamrecursion @kustosz @radeusgd
|
||||
/distribution/std-lib @iamrecursion @kustosz @wdanilo
|
||||
|
||||
# Scala Libraries
|
||||
/lib/scala/cli @iamrecursion @kustosz @radeusgd
|
||||
|
@ -54,3 +54,67 @@ Any.is_nothing : Boolean
|
||||
Any.is_nothing = case this of
|
||||
Nothing -> True
|
||||
_ -> False
|
||||
|
||||
## Executes the provided handler on a dataflow error, or executes as identity on
|
||||
a non-error value.
|
||||
|
||||
Arguments:
|
||||
- handler: The function to call on this if it is an error value. By default
|
||||
this is identity.
|
||||
|
||||
> Example
|
||||
Catching an erroneous value to perform some operation on it.
|
||||
(Time.Time_Error "Message").catch (err -> IO.println err)
|
||||
Any.catch : (Error -> Any) -> Any
|
||||
Any.catch (handler = x->x) = this.catch_primitive handler
|
||||
|
||||
## Applies the function `this` to the provided argument.
|
||||
|
||||
Arguments:
|
||||
- argument: The argument to apply `this` to.
|
||||
|
||||
> Example
|
||||
Applying a function to a block.
|
||||
(x -> x + 1) <|
|
||||
y = 1 ^ 3
|
||||
3 + y
|
||||
Any.<| : Any -> Any
|
||||
Any.<| ~argument = this argument
|
||||
|
||||
## Applies the function on the right hand side to the argument on the left.
|
||||
|
||||
Arguments
|
||||
- function: The function to apply to `this`.
|
||||
|
||||
> Example
|
||||
Applying a function in a pipeline.
|
||||
1 |> (* 2)
|
||||
Any.|> : (Any -> Any) -> Any
|
||||
Any.|> function = function this
|
||||
|
||||
## Composes two functions together.
|
||||
|
||||
For `f << g`, this creates the function composition `f ∘ g`.
|
||||
|
||||
Arguments:
|
||||
- that: The function to compose with `this`.
|
||||
|
||||
> Example
|
||||
Compose the functions +1 and *2 and apply it to 2
|
||||
(+1 << *2) 2
|
||||
Any.<< : (Any -> Any) -> (Any -> Any) -> Any -> Any
|
||||
Any.<< that = x -> this (that x)
|
||||
|
||||
## Composes two functions together in the forward direction.
|
||||
|
||||
For `f >> g`, this creates the function composition `g ∘ f`.
|
||||
|
||||
Arguments:
|
||||
- that: The function to compose with `this`.
|
||||
|
||||
> Example
|
||||
Add one and then multiply by two as a function applied to 2.
|
||||
(+1 >> *2) 2
|
||||
Any.>> : (Any -> Any) -> (Any -> Any) -> Any -> Any
|
||||
Any.>> that = x -> that (this x)
|
||||
|
||||
|
@ -90,7 +90,7 @@ Object.get field = this.fields.get field
|
||||
parse : Text -> Json ! Parse_Error
|
||||
parse json_text =
|
||||
r = Panic.recover (Internal.parse_helper json_text)
|
||||
r.catch <| case _ of
|
||||
r.catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Parse_Error err.getMessage)
|
||||
p -> Panic.throw p
|
||||
|
||||
|
@ -175,7 +175,7 @@ into_helper fmt json = case fmt of
|
||||
_ -> Panic.throw (Type_Mismatch_Error json fmt)
|
||||
|
||||
## Helper used to parse text into a JSON value.
|
||||
parse_helper : Text -> Json ! Polyglot_Error
|
||||
parse_helper : Text -> Json
|
||||
parse_helper json_text =
|
||||
consumer = here.mk_consumer
|
||||
Parser.parse json_text consumer
|
||||
|
@ -200,34 +200,34 @@ type List
|
||||
> Example
|
||||
This returns 1.
|
||||
(Cons 1 (Cons 2 Nil)).head
|
||||
head : Any | Nothing
|
||||
head : Any ! Nothing
|
||||
head = case this of
|
||||
Cons a _ -> a
|
||||
Nil -> Nothing
|
||||
Nil -> Error.throw Nothing
|
||||
|
||||
## Get all elements from the list except the first.
|
||||
|
||||
> Example
|
||||
This returns (Cons 2 Nil).
|
||||
(Cons 1 (Cons 2 Nil)).tail
|
||||
tail : List | Nothing
|
||||
tail : List ! Nothing
|
||||
tail = case this of
|
||||
Cons _ b -> b
|
||||
Nil -> Nothing
|
||||
Nil -> Error.throw Nothing
|
||||
|
||||
## Get all elements from the list except the last.
|
||||
|
||||
> Example
|
||||
Removing the last element of the list to give (Cons 1 Nil).
|
||||
(Cons 1 (Cons 2 Nil)).init
|
||||
init : List | Nothing
|
||||
init : List ! Nothing
|
||||
init =
|
||||
init' x y = case y of
|
||||
Nil -> Nil
|
||||
Cons a b -> Cons x (init' a b)
|
||||
case this of
|
||||
Cons a b -> init' a b
|
||||
Nil -> Nothing
|
||||
Nil -> Error.throw Nothing
|
||||
|
||||
## Get the last element of the list.
|
||||
|
||||
@ -235,14 +235,16 @@ type List
|
||||
Getting the final element, in this case 2.
|
||||
(Cons 1 (Cons 2 Nil)).last
|
||||
last : Any | Nothing
|
||||
last = this.fold Nothing (_ -> r -> r)
|
||||
last = case this.fold Nothing (_ -> r -> r) of
|
||||
Nothing -> Error.throw Nothing
|
||||
a -> a
|
||||
|
||||
## Get the first element from the list.
|
||||
|
||||
> Example
|
||||
This returns 1.
|
||||
(Cons 1 (Cons 2 Nil)).first
|
||||
first : Any | Nothing
|
||||
first : Any ! Nothing
|
||||
first = this.head
|
||||
|
||||
## Get all elements from the list except the first.
|
||||
@ -250,5 +252,5 @@ type List
|
||||
> Example
|
||||
This returns (Cons 2 Nil).
|
||||
(Cons 1 (Cons 2 Nil)).rest
|
||||
rest : List | Nothing
|
||||
rest : List ! Nothing
|
||||
rest = this.tail
|
||||
|
@ -76,10 +76,10 @@ type Map
|
||||
|
||||
## Gets the value associated with `key` in this map, or returns a
|
||||
`Nothing`, if `key` is not present.
|
||||
get : Any -> Any | Nothing
|
||||
get : Any -> Any ! Nothing
|
||||
get key =
|
||||
go map = case map of
|
||||
Tip -> Nothing
|
||||
Tip -> Error.throw Nothing
|
||||
Bin _ k v l r ->
|
||||
if k == key then v else
|
||||
if k > key then @Tail_Call go l else @Tail_Call go r
|
||||
@ -90,8 +90,7 @@ type Map
|
||||
it isn't present.
|
||||
get_or_else : Any -> Any -> Any
|
||||
get_or_else key other =
|
||||
result = this.get key
|
||||
if result.is_nothing then other else result
|
||||
this.get key . catch (_ -> other)
|
||||
|
||||
## Transforms the map's keys and values to create a new map.
|
||||
|
||||
|
46
distribution/std-lib/Base/src/Data/Maybe.enso
Normal file
46
distribution/std-lib/Base/src/Data/Maybe.enso
Normal file
@ -0,0 +1,46 @@
|
||||
from Base import all
|
||||
|
||||
## A type representing computations that may fail.
|
||||
type Maybe
|
||||
|
||||
## No contained value.
|
||||
Nothing
|
||||
|
||||
## A value.
|
||||
type Some value
|
||||
|
||||
## Applies the provided function to the contained value if it exists,
|
||||
otherwise returning the provided default value.
|
||||
|
||||
Arguments:
|
||||
- default: The value to return if `this` is Nothing. This value is lazy
|
||||
and hence will not execute any provided computation unless it is used.
|
||||
- function: The function to execute on the value inside the `Just`, if it
|
||||
is a just.
|
||||
|
||||
> Example
|
||||
Apply a function over a Just value to get 4.
|
||||
(Just 2).maybe 0 *2
|
||||
maybe : Any -> (Any -> Any) -> Any
|
||||
maybe ~default function = case this of
|
||||
Nothing -> default
|
||||
Some val -> function val
|
||||
|
||||
## Check if the maybe value is `Just`.
|
||||
|
||||
> Example
|
||||
Check if `Nothing` is `Just`.
|
||||
Nothing.is_just
|
||||
is_just : Boolean
|
||||
is_just = case this of
|
||||
Nothing -> False
|
||||
Some _ -> True
|
||||
|
||||
## Check if the maybe value is `Nothing`.
|
||||
|
||||
> Example
|
||||
Check if `Nothing` is `Nothing`.
|
||||
Nothing.is_nothing
|
||||
is_nothing : Boolean
|
||||
is_nothing = this.is_just.not
|
||||
|
@ -96,6 +96,12 @@ type Date
|
||||
|
||||
## Obtains an instance of `Date` from a text, such as "2007-12-03".
|
||||
|
||||
Arguments:
|
||||
- text: The textual content to parse as a date.
|
||||
|
||||
Returns a `Time_Error` if the provided `text` cannot be parsed using the
|
||||
provided `pattern`.
|
||||
|
||||
The text must represent a valid date and is parsed using the ISO-8601
|
||||
extended local date format. The format consists of:
|
||||
|
||||
@ -115,19 +121,26 @@ type Date
|
||||
|
||||
> Example
|
||||
Recover from the parse error.
|
||||
Date.parse "my birthday" . catch <| case _ of
|
||||
Date.parse "my birthday" . catch e-> case e of
|
||||
Time.Error _ -> Date.new 2000 1 1
|
||||
parse : Text -> Date
|
||||
parse : Text -> Date ! Time.Time_Error
|
||||
parse text =
|
||||
Panic.recover (Date (LocalDate.parse text)) . catch <| case _ of
|
||||
Panic.recover (Date (LocalDate.parse text)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
||||
## Obtains an instance of `Date` from a text using custom format.
|
||||
|
||||
Arguments:
|
||||
- text: The textual content to parse as a time.
|
||||
- pattern: The pattern describing how to parse the text.
|
||||
|
||||
For the list of accepted symbols in pattern refer to
|
||||
`Base.Data.Time.Time.format` doc.
|
||||
|
||||
Returns a `Time_Error` if the provided `text` cannot be parsed using the
|
||||
provided `pattern`.
|
||||
|
||||
> Example
|
||||
Parse "1999-1-1" as Date.
|
||||
Date.parse_format "1999-1-1" "yyyy-M-d"
|
||||
@ -135,12 +148,12 @@ parse text =
|
||||
> Example
|
||||
Recover from the parse error.
|
||||
date = Date.parse "1999-1-1" "yyyy-MM-dd"
|
||||
date.catch <| case _ of
|
||||
date.catch e-> case e of
|
||||
Time.Error msg -> Date.new 2000 1 1
|
||||
parse_format : Text -> Text -> Date
|
||||
parse_format : Text -> Text -> Date ! Time.Time_Error
|
||||
parse_format text pattern =
|
||||
format = DateTimeFormatter.ofPattern pattern
|
||||
Panic.recover (Date (LocalDate.parse text format)) . catch <| case _ of
|
||||
Panic.recover (Date (LocalDate.parse text format)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
||||
@ -158,6 +171,8 @@ today = here.now
|
||||
- day - the day-of-month to represent, from 1 to 31 and must be valid for the
|
||||
year and month
|
||||
|
||||
Returns a `Time_Error` if the provided time is not valid.
|
||||
|
||||
> Example
|
||||
Create a new local date at Unix epoch.
|
||||
Date.new 1970
|
||||
@ -165,8 +180,8 @@ today = here.now
|
||||
> Example
|
||||
Get the local date of 5th August 1986.
|
||||
Date.new 1986 8 5
|
||||
new : Integer -> Integer -> Integer -> Date
|
||||
new : Integer -> Integer -> Integer -> Date ! Time.Time_Error
|
||||
new year (month = 1) (day = 1) =
|
||||
Panic.recover (Date (LocalDate.of year month day)) . catch <| case _ of
|
||||
Panic.recover (Date (LocalDate.of year month day)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
@ -131,7 +131,7 @@ new language country=Nothing variant=Nothing =
|
||||
> Example
|
||||
Creating the locale en_US.
|
||||
Locale.from_language_tag "en_US"
|
||||
from_language_tag : Text -> Locale | Nothing
|
||||
from_language_tag : Text -> Locale
|
||||
from_language_tag tag =
|
||||
java_locale = JavaLocale.forLanguageTag tag
|
||||
here.from_java java_locale
|
||||
|
@ -180,6 +180,9 @@ type Time
|
||||
## Obtains an instance of `Time` from a text such as
|
||||
"2007-12-03T10:15:30+01:00 Europe/Paris".
|
||||
|
||||
Arguments:
|
||||
- text: The text representing the time to be parsed.
|
||||
|
||||
The text must represent a valid date-time and is parsed using the ISO-8601
|
||||
extended offset date-time format to add the timezone. The section in square
|
||||
brackets is not part of the ISO-8601 standard. The format consists of:
|
||||
@ -192,6 +195,9 @@ type Time
|
||||
sensitive.
|
||||
- A close square bracket ']'.
|
||||
|
||||
This method will return a `Time_Error` if the provided time cannot be parsed
|
||||
using the above format.
|
||||
|
||||
> Example
|
||||
Parse UTC time.
|
||||
Time.parse "2020-10-01T04:11:12Z"
|
||||
@ -210,16 +216,24 @@ type Time
|
||||
|
||||
> Example
|
||||
Recover from the parse error.
|
||||
Time.parse "2020-10-01" . catch <| case _ of
|
||||
Time.parse "2020-10-01" . catch e-> case e of
|
||||
Time.Error _ -> Time.now
|
||||
parse : Text -> Time
|
||||
parse : Text -> Time ! Time_Error
|
||||
parse text =
|
||||
Panic.recover (Time (Time_Utils.parse_time text)) . catch <| case _ of
|
||||
Panic.recover (Time (Time_Utils.parse_time text)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
||||
## Obtains an instance of Time from a text using custom format.
|
||||
|
||||
Arguments:
|
||||
- text: The text to parse as a time of day, using the specified pattern.
|
||||
- pattern: The pattern to use for parsing the input text.
|
||||
- locale: The locale in which the pattern should be interpreted.
|
||||
|
||||
Returns a `Time_Error` if the provided text cannot be parsed using the
|
||||
provided pattern and locale.
|
||||
|
||||
For the list of accepted symbols in pattern refer to `Time.format` doc.
|
||||
|
||||
> Example
|
||||
@ -229,9 +243,9 @@ parse text =
|
||||
> Example
|
||||
Parse "06 of May 2020 at 04:30AM" as Time
|
||||
Date.parse_format "06 of May 2020 at 04:30AM" "dd 'of' MMMM yyyy 'at' hh:mma"
|
||||
parse_format : Text -> Text -> Locale -> Time_Of_Day
|
||||
parse_format : Text -> Text -> Locale -> Time ! Time_Error
|
||||
parse_format text pattern locale=Locale.default =
|
||||
Panic.recover (Time (Time_Utils.parse_time_format text pattern locale.java_locale)) . catch <| case _ of
|
||||
Panic.recover (Time (Time_Utils.parse_time_format text pattern locale.java_locale)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
||||
@ -242,14 +256,17 @@ now = Time ZonedDateTime.now
|
||||
## Obtains an instance of `Time` from a year, month, day, hour, minute,
|
||||
second, nanosecond and timezone.
|
||||
|
||||
- month - the month-of-year to represent, from 1 (January) to 12 (December)
|
||||
- day - the day-of-month to represent, from 1 to 31 and must be valid for the
|
||||
Arguments:
|
||||
- month: the month-of-year to represent, from 1 (January) to 12 (December)
|
||||
- day: the day-of-month to represent, from 1 to 31 and must be valid for the
|
||||
year and month
|
||||
- hour - the hour-of-day to represent, from 0 to 23
|
||||
- minute - the minute-of-hour to represent, from 0 to 59
|
||||
- second - the second-of-minute to represent, from 0 to 59
|
||||
- nanosecond - the nano-of-second to represent, from 0 to 999,999,999
|
||||
- zone - the timezone
|
||||
- hour: the hour-of-day to represent, from 0 to 23
|
||||
- minute: the minute-of-hour to represent, from 0 to 59
|
||||
- second: the second-of-minute to represent, from 0 to 59
|
||||
- nanosecond: the nano-of-second to represent, from 0 to 999,999,999
|
||||
- zone: the timezone
|
||||
|
||||
Returns a `Time_Error` if the provided time cannot be represented.
|
||||
|
||||
> Example
|
||||
Create a new zoned date time at Unix epoch.
|
||||
@ -258,8 +275,8 @@ now = Time ZonedDateTime.now
|
||||
> Example
|
||||
Get the 5 August 1986 at midnight.
|
||||
Time.new 1986 8 5
|
||||
new : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Zone -> Time
|
||||
new : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Zone -> Time ! Time_Error
|
||||
new year (month = 1) (day = 1) (hour = 0) (minute = 0) (second = 0) (nanosecond = 0) (zone = Zone.system) =
|
||||
Panic.recover (Time (ZonedDateTime.of year month day hour minute second nanosecond zone.internal_zone_id)) . catch <| case _ of
|
||||
Panic.recover (Time (ZonedDateTime.of year month day hour minute second nanosecond zone.internal_zone_id)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
@ -101,6 +101,12 @@ type Time_Of_Day
|
||||
|
||||
## Obtains an instance of `Time_Of_Day` from a text such as "10:15".
|
||||
|
||||
Arguments:
|
||||
- text: The text to parse as a time of day.
|
||||
|
||||
Returns a `Time_Error` if the provided text cannot be parsed using the
|
||||
default format.
|
||||
|
||||
The text must represent a valid time and is parsed using the ISO-8601
|
||||
extended local time format. The format consists of:
|
||||
|
||||
@ -124,16 +130,24 @@ type Time_Of_Day
|
||||
|
||||
> Example
|
||||
Recover from the parse error.
|
||||
Time_Of_Day.parse "half past twelve" . catch <| case
|
||||
Time_Of_Day.parse "half past twelve" . catch e-> case e of
|
||||
Time.Error _ -> Time_Of_Day.new
|
||||
parse : Text -> Time_Of_Day
|
||||
parse : Text -> Time_Of_Day ! Time.Time_Error
|
||||
parse text =
|
||||
Panic.recover (Time_Of_Day (LocalTime.parse text)) . catch <| case _ of
|
||||
Panic.recover (Time_Of_Day (LocalTime.parse text)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
||||
## Obtains an instance of Time_Of_Day from a text using custom format.
|
||||
|
||||
Arguments:
|
||||
- text: The text to parse as a time of day, using the specified pattern.
|
||||
- pattern: The pattern to use for parsing the input text.
|
||||
- locale: The locale in which the pattern should be interpreted.
|
||||
|
||||
Returns a `Time_Error` if the provided text cannot be parsed using the
|
||||
provided pattern and locale.
|
||||
|
||||
For the list of accepted symbols in pattern refer to
|
||||
`Base.Data.Time.Time.format` doc.
|
||||
|
||||
@ -144,10 +158,10 @@ parse text =
|
||||
> Example
|
||||
Parse "4:30AM" as Time_Of_Day
|
||||
Date.parse_format "4:30AM" "h:mma"
|
||||
parse_format : Text -> Text -> Locale -> Time_Of_Day
|
||||
parse_format : Text -> Text -> Locale -> Time_Of_Day ! Time.Time_Error
|
||||
parse_format text pattern locale=Locale.default =
|
||||
format = (DateTimeFormatter.ofPattern pattern).withLocale locale.java_locale
|
||||
Panic.recover (Time_Of_Day (LocalTime.parse text format)) . catch <| case _ of
|
||||
Panic.recover (Time_Of_Day (LocalTime.parse text format)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
||||
@ -163,6 +177,8 @@ now = Time_Of_Day LocalTime.now
|
||||
- second - the second-of-minute to represent, from 0 to 59
|
||||
- nanosecond - the nano-of-second to represent, from 0 to 999,999,999
|
||||
|
||||
Returns a `Time_Error` if the provided time is not a valid time.
|
||||
|
||||
> Example
|
||||
Create a new local time at Unix epoch.
|
||||
Time_Of_Day.new
|
||||
@ -170,8 +186,8 @@ now = Time_Of_Day LocalTime.now
|
||||
> Example
|
||||
Get the local time at 9:30.
|
||||
Time_Of_Day.new 9 30
|
||||
new : Integer -> Integer -> Integer -> Integer -> Time_Of_Day
|
||||
new : Integer -> Integer -> Integer -> Integer -> Time_Of_Day ! Time.Time_Error
|
||||
new (hour = 0) (minute = 0) (second = 0) (nanosecond = 0) =
|
||||
Panic.recover (Time_Of_Day (LocalTime.of hour minute second nanosecond)) . catch <| case _ of
|
||||
Panic.recover (Time_Of_Day (LocalTime.of hour minute second nanosecond)) . catch e-> case e of
|
||||
Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage)
|
||||
x -> x
|
||||
|
@ -120,11 +120,11 @@ type Vector
|
||||
In the following example, we'll compute the sum of all elements of a
|
||||
vector:
|
||||
[0, 1, 2] . reduce (+)
|
||||
reduce : (Any -> Any -> Any) -> Any | Nothing
|
||||
reduce : (Any -> Any -> Any) -> Any ! Nothing
|
||||
reduce function =
|
||||
case this.not_empty of
|
||||
True -> this.tail.fold this.head function
|
||||
False -> Nothing
|
||||
False -> Error.throw Nothing
|
||||
|
||||
## Checks whether a predicate holds for at least one element of this vector.
|
||||
|
||||
@ -360,8 +360,8 @@ type Vector
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].head == Nothing
|
||||
head : Any | Nothing
|
||||
head = if this.length >= 1 then this.at 0 else Nothing
|
||||
head : Any ! Nothing
|
||||
head = if this.length >= 1 then this.at 0 else Error.throw Nothing
|
||||
|
||||
## Get all elements in the vector except the first.
|
||||
|
||||
@ -371,8 +371,8 @@ type Vector
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].tail == Nothing
|
||||
tail : Vector | Nothing
|
||||
tail = if this.length >= 1 then this.drop_start 1 else Nothing
|
||||
tail : Vector ! Nothing
|
||||
tail = if this.length >= 1 then this.drop_start 1 else Error.throw Nothing
|
||||
|
||||
## Get the all elements in the vector except the last.
|
||||
|
||||
@ -382,8 +382,8 @@ type Vector
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].init == Nothing
|
||||
init : Vector | Nothing
|
||||
init = if this.length >= 1 then this.drop_end 1 else Nothing
|
||||
init : Vector ! Nothing
|
||||
init = if this.length >= 1 then this.drop_end 1 else Error.throw Nothing
|
||||
|
||||
## Get the last element of the vector.
|
||||
|
||||
@ -393,8 +393,8 @@ type Vector
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].last == Nothing
|
||||
last : Vector | Nothing
|
||||
last = if this.length >= 1 then (this.take_end 1).at 0 else Nothing
|
||||
last : Vector ! Nothing
|
||||
last = if this.length >= 1 then (this.take_end 1).at 0 else Error.throw Nothing
|
||||
|
||||
## Get the first element from the vector.
|
||||
|
||||
@ -404,7 +404,7 @@ type Vector
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].first == Nothing
|
||||
first : Vector | Nothing
|
||||
first : Vector ! Nothing
|
||||
first = this.head
|
||||
|
||||
## Get all elements in the vector except the first.
|
||||
@ -415,7 +415,7 @@ type Vector
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].rest == Nothing
|
||||
rest : Vector | Nothing
|
||||
rest : Vector ! Nothing
|
||||
rest = this.tail
|
||||
|
||||
## Sort the Vector.
|
||||
|
@ -10,5 +10,19 @@ type Unimplemented_Error message
|
||||
|
||||
## A function that can be used to indicate that something hasn't been
|
||||
implemented yet.
|
||||
unimplemented : Text -> Void ! Unimplemented_Error
|
||||
unimplemented : Text -> Void
|
||||
unimplemented message="" = Panic.throw (Unimplemented_Error message)
|
||||
|
||||
## Executes the provided handler on a dataflow error, or executes as identity on
|
||||
a non-error value.
|
||||
|
||||
Arguments:
|
||||
- handler: The function to call on this if it is an error value. By default
|
||||
this is identity.
|
||||
|
||||
> Example
|
||||
Catching an erroneous value to perform some operation on it.
|
||||
(Time.Time_Error "Message").catch (err -> IO.println err)
|
||||
Error.catch : (Error -> Any) -> Any
|
||||
Error.catch (handler = x->x) = this.catch_primitive handler
|
||||
|
||||
|
@ -3,6 +3,7 @@ import Base.Data.Interval
|
||||
import Base.Data.Json
|
||||
import Base.Data.List
|
||||
import Base.Data.Map
|
||||
import Base.Data.Maybe
|
||||
import Base.Data.Noise
|
||||
import Base.Data.Number.Extensions
|
||||
import Base.Data.Ordering
|
||||
@ -23,6 +24,7 @@ from Builtins import Nothing, Number, Integer, Any, True, False, Cons, Boolean,
|
||||
export Base.Data.Interval
|
||||
export Base.Data.Json
|
||||
export Base.Data.Map
|
||||
export Base.Data.Maybe
|
||||
export Base.Data.Ordering
|
||||
export Base.Data.Ordering.Sort_Order
|
||||
export Base.Data.Vector
|
||||
|
@ -19,7 +19,7 @@ e = 2.718281828459045235360
|
||||
|
||||
## Returns the smaller value of `a` and `b`.
|
||||
min : Number -> Number -> Number
|
||||
min a b = if a < b then a else b
|
||||
min a b = if a <= b then a else b
|
||||
|
||||
## Returns the larger value of `a` and `b`.
|
||||
max : Number -> Number -> Number
|
||||
|
@ -95,7 +95,8 @@ is_a value typ = if typ == Any then True else
|
||||
_ ->
|
||||
meta_val = here.meta value
|
||||
case meta_val of
|
||||
Atom _ -> meta_val.constructor == typ
|
||||
Atom _ -> if Builtins.meta.is_atom typ then typ == value else
|
||||
meta_val.constructor == typ
|
||||
Constructor _ ->
|
||||
meta_typ = here.meta typ
|
||||
case meta_typ of
|
||||
|
@ -16,7 +16,7 @@ type Uri_Error
|
||||
|
||||
## PRIVATE
|
||||
panic_on_error ~action =
|
||||
action . catch <| case _ of
|
||||
action . catch e-> case e of
|
||||
Syntax_Error msg -> Panic.throw (Syntax_Error msg)
|
||||
|
||||
## PRIVATE
|
||||
@ -151,8 +151,8 @@ type Uri
|
||||
> Example
|
||||
Parse Uri text.
|
||||
Uri.parse "http://example.com"
|
||||
parse : Text -> Uri
|
||||
parse : Text -> Uri ! Syntax_Error
|
||||
parse text =
|
||||
Panic.recover (Uri (Java_URI.create text)) . catch <| case _ of
|
||||
Panic.recover (Uri (Java_URI.create text)) . catch e-> case e of
|
||||
Polyglot_Error ex -> Error.throw (Syntax_Error ex.getMessage)
|
||||
other -> Panic.throw other
|
||||
|
@ -18,6 +18,12 @@ Spec.is_fail = this.behaviors.any .is_fail
|
||||
## PRIVATE
|
||||
Suite.is_fail = this.specs.any .is_fail
|
||||
|
||||
## PRIVATE
|
||||
type Finished_With_Error err
|
||||
|
||||
## PRIVATE
|
||||
type Matched_On_Error err
|
||||
|
||||
## PRIVATE
|
||||
type Assertion
|
||||
type Success
|
||||
@ -49,13 +55,14 @@ Any.should verb argument = verb Verbs this argument
|
||||
fail message = Panic.throw (Failure message)
|
||||
|
||||
## Expect a function to fail with the provided dataflow error.
|
||||
expect_error_with ~action matcher =
|
||||
result = action
|
||||
fail_msg = "Expected an error " + matcher.to_text + "but none occurred."
|
||||
if result.is_error.not then here.fail fail_msg else
|
||||
caught = result.catch x->x
|
||||
if caught.is_a matcher then Nothing else
|
||||
here.fail ("Unexpected error " + caught.to_text + " thrown.")
|
||||
Any.should_fail_with matcher =
|
||||
here.fail ("Expected an error " + matcher.to_text + " but none occurred.")
|
||||
|
||||
## Expect a function to fail with the provided dataflow error.
|
||||
Error.should_fail_with matcher =
|
||||
caught = this.catch x->x
|
||||
if caught.is_a matcher then Nothing else
|
||||
here.fail ("Unexpected error " + caught.to_text + " returned.")
|
||||
|
||||
## Expect a function to fail with the provided panic.
|
||||
expect_panic_with ~action matcher =
|
||||
@ -73,6 +80,9 @@ Any.should_equal that = case this == that of
|
||||
msg = this.to_text + " did not equal " + that.to_text + "."
|
||||
Panic.throw (Failure msg)
|
||||
|
||||
## Asserts that `this` value is equal to the expected value.
|
||||
Error.should_equal _ = Panic.throw (Matched_On_Error this)
|
||||
|
||||
## Asserts that `this` is within `epsilon` from `that`.
|
||||
Decimal.should_equal that (epsilon = 0) = case this.equals that epsilon of
|
||||
True -> Success
|
||||
@ -85,11 +95,17 @@ Boolean.should_be_true = case this of
|
||||
True -> Success
|
||||
False -> Panic.throw (Failure "Expected False to be True.")
|
||||
|
||||
## Asserts that the given `Boolean` is `True`.
|
||||
Error.should_be_true = Panic.throw (Matched_On_Error this)
|
||||
|
||||
## Asserts that the given `Boolean` is `False`
|
||||
Boolean.should_be_false = case this of
|
||||
True -> Panic.throw (Failure "Expected True to be False.")
|
||||
False -> Success
|
||||
|
||||
## Asserts that the given `Boolean` is `False`
|
||||
Error.should_be_false = Panic.throw (Matched_On_Error this)
|
||||
|
||||
## PRIVATE
|
||||
Spec.print_report =
|
||||
IO.print_err (this.name + ":")
|
||||
@ -137,19 +153,21 @@ specify label ~behavior pending=False =
|
||||
new_spec = Spec spec.name (Cons (Behavior label result) spec.behaviors)
|
||||
State.put Spec new_spec
|
||||
|
||||
## PRIVATE
|
||||
run_spec ~behavior =
|
||||
recovery = Panic.recover <|
|
||||
behavior
|
||||
behavior.catch err-> Panic.throw (Finished_With_Error err)
|
||||
Nothing
|
||||
maybeExc = case recovery of
|
||||
_ -> Success
|
||||
result = maybeExc.catch ex->
|
||||
case ex of
|
||||
Failure _ -> ex
|
||||
_ -> Failure ("Unexpected error has been thrown: " + ex.to_text)
|
||||
Finished_With_Error x ->
|
||||
Failure ("An unexpected error was returned: " + x.to_text)
|
||||
_ -> Failure ("An unexpected panic was thrown: " + ex.to_text)
|
||||
result
|
||||
|
||||
|
||||
## Creates a new test group, desribing properties of the object
|
||||
described by `this`.
|
||||
|
||||
|
@ -114,6 +114,7 @@ state. The documentation syntax supports the following tags:
|
||||
- `PRIVATE`: Used to describe constructs that are private in the language.
|
||||
- `ADVANCED`: Items that are _not_ private, but are for power users.
|
||||
- `TEXT_ONLY`: Items that do not apply to the graphical mode.
|
||||
- `UNSTABLE`: Used for items that are not yet considered stable.
|
||||
|
||||
Tags are added at the _top_ of the documentation block, and may also be
|
||||
accompanied by a description. This description directly follows the tag
|
||||
|
@ -14,7 +14,7 @@ import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Any",
|
||||
name = "catch",
|
||||
name = "catch_primitive",
|
||||
description =
|
||||
"If called on an error, executes the provided handler on the error's payload. Otherwise acts as identity.")
|
||||
public class CatchAnyNode extends Node {
|
||||
|
@ -14,7 +14,7 @@ import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Error",
|
||||
name = "catch",
|
||||
name = "catch_primitive",
|
||||
description =
|
||||
"If called on an error, executes the provided handler on the error's payload. Otherwise acts as identity.")
|
||||
public class CatchErrorNode extends Node {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.enso.interpreter.node.expression.builtin.mutable;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.AcceptsError;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.data.Array;
|
||||
|
||||
@ -10,7 +11,7 @@ import org.enso.interpreter.runtime.data.Array;
|
||||
description = "Puts the given element in the given position in the array.")
|
||||
public class SetAtNode extends Node {
|
||||
|
||||
Object execute(Array _this, long index, Object value) {
|
||||
Object execute(Array _this, long index, @AcceptsError Object value) {
|
||||
_this.getItems()[(int) index] = value;
|
||||
return _this;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ public class Builtins {
|
||||
|
||||
scope.registerMethod(panic, "throw", ThrowPanicMethodGen.makeFunction(language));
|
||||
scope.registerMethod(panic, "recover", RecoverPanicMethodGen.makeFunction(language));
|
||||
scope.registerMethod(any, "catch", CatchAnyMethodGen.makeFunction(language));
|
||||
scope.registerMethod(any, "catch_primitive", CatchAnyMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(state, "get", GetStateMethodGen.makeFunction(language));
|
||||
scope.registerMethod(state, "put", PutStateMethodGen.makeFunction(language));
|
||||
@ -157,7 +157,6 @@ public class Builtins {
|
||||
scope.registerMethod(debug, "breakpoint", DebugBreakpointMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(function, "call", ExplicitCallFunctionMethodGen.makeFunction(language));
|
||||
scope.registerMethod(function, "<|", ApplicationOperatorMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(any, "to_text", AnyToTextMethodGen.makeFunction(language));
|
||||
|
||||
|
@ -15,7 +15,7 @@ public class DataflowError {
|
||||
|
||||
scope.registerConstructor(error);
|
||||
scope.registerMethod(error, "throw", ThrowErrorMethodGen.makeFunction(language));
|
||||
scope.registerMethod(error, "catch", CatchErrorMethodGen.makeFunction(language));
|
||||
scope.registerMethod(error, "catch_primitive", CatchErrorMethodGen.makeFunction(language));
|
||||
scope.registerMethod(error, "to_text", ErrorToTextMethodGen.makeFunction(language));
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,9 @@ type Any
|
||||
@Builtin_Type
|
||||
type Any
|
||||
|
||||
## Executes the provided handler on a dataflow error, or executes as
|
||||
## PRIVATE
|
||||
|
||||
Executes the provided handler on a dataflow error, or executes as
|
||||
identity on a non-error value.
|
||||
|
||||
Arguments:
|
||||
@ -167,9 +169,9 @@ type Any
|
||||
|
||||
> Example
|
||||
Catching an erroneous value to perform some operation on it.
|
||||
(Time.Time_Error "Message").catch (err -> IO.println err)
|
||||
catch : (Error -> Any) -> Any
|
||||
catch handler = @Builtin_Method "Any.catch"
|
||||
(Time.Time_Error "Message").catch_primitive (err -> IO.println err)
|
||||
catch_primitive : (Error -> Any) -> Any
|
||||
catch_primitive handler = @Builtin_Method "Any.catch"
|
||||
|
||||
## Generic conversion of an arbitrary Enso value to a corresponding textual
|
||||
representation.
|
||||
@ -208,7 +210,9 @@ type Error
|
||||
throw : Any -> Error
|
||||
throw payload = @Builtin_Method "Error.throw"
|
||||
|
||||
## Executes the provided handler on a dataflow error, or executes as
|
||||
## PRIVATE
|
||||
|
||||
Executes the provided handler on a dataflow error, or executes as
|
||||
identity on a non-error value.
|
||||
|
||||
Arguments:
|
||||
@ -216,9 +220,9 @@ type Error
|
||||
|
||||
> Example
|
||||
Catching an erroneous value to perform some operation on it.
|
||||
(Time.Time_Error "Message").catch (err -> IO.println err)
|
||||
catch : (Error -> Any) -> Any
|
||||
catch handler = @Builtin_Method "Any.catch"
|
||||
(Time.Time_Error "Message").catch_primitive (err -> IO.println err)
|
||||
catch_primitive : (Error -> Any) -> Any
|
||||
catch_primitive handler = @Builtin_Method "Any.catch"
|
||||
|
||||
## Converts an error to a corresponding textual representation.
|
||||
to_text : Text
|
||||
@ -366,20 +370,6 @@ type Function
|
||||
call : Any
|
||||
call = @Builtin_Method "Function.call"
|
||||
|
||||
## Takes a function and an argument and applies the function to the argument
|
||||
|
||||
Arguments:
|
||||
- argument: The argument to apply this to.
|
||||
|
||||
> Example
|
||||
Applying identity to a value produced by a block to get 3.
|
||||
(x -> x) <|
|
||||
a = 1
|
||||
b = 2
|
||||
a + b
|
||||
<| : (Any -> Any) -> Any -> Any
|
||||
<| argument = @Builtin_Method "Function.<|"
|
||||
|
||||
## Generic utilities for interacting with other languages.
|
||||
type Polyglot
|
||||
|
||||
|
@ -3590,7 +3590,7 @@ class RuntimeServerTest
|
||||
),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
context.consumeOut shouldEqual List("(Syntax_Error 'Unrecognized token.')")
|
||||
context.consumeOut shouldEqual List("(Error: (Syntax_Error 'Unrecognized token.'))")
|
||||
}
|
||||
|
||||
it should "return compiler error syntax error" in {
|
||||
|
@ -14,7 +14,7 @@ class CompileDiagnosticsTest extends InterpreterTest {
|
||||
|
|
||||
|main =
|
||||
| x = Panic.recover ()
|
||||
| x.catch err->
|
||||
| x.catch_primitive err->
|
||||
| case err of
|
||||
| Syntax_Error msg -> "Oopsie, it's a syntax error: " + msg
|
||||
|""".stripMargin
|
||||
@ -29,7 +29,7 @@ class CompileDiagnosticsTest extends InterpreterTest {
|
||||
|
|
||||
|main =
|
||||
| x = Panic.recover @
|
||||
| x.catch .to_text
|
||||
| x.catch_primitive .to_text
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual "(Syntax_Error 'Unrecognized token.')"
|
||||
}
|
||||
@ -42,7 +42,7 @@ class CompileDiagnosticsTest extends InterpreterTest {
|
||||
| x = 1
|
||||
| x = 2
|
||||
|
|
||||
|main = Panic.recover here.foo . catch .to_text
|
||||
|main = Panic.recover here.foo . catch_primitive .to_text
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual "(Compile_Error 'Variable x is being redefined.')"
|
||||
}
|
||||
@ -55,7 +55,7 @@ class CompileDiagnosticsTest extends InterpreterTest {
|
||||
| my_var = 10
|
||||
| my_vra
|
||||
|
|
||||
|main = Panic.recover here.foo . catch .to_text
|
||||
|main = Panic.recover here.foo . catch_primitive .to_text
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual "(Compile_Error 'Variable `my_vra` is not defined.')"
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class DataflowErrorsTest extends InterpreterTest {
|
||||
|
|
||||
|main =
|
||||
| intError = Error.throw 1
|
||||
| intError.catch (x -> x + 3)
|
||||
| intError.catch_primitive (x -> x + 3)
|
||||
|""".stripMargin
|
||||
eval(code) shouldEqual 4
|
||||
}
|
||||
@ -65,7 +65,7 @@ class DataflowErrorsTest extends InterpreterTest {
|
||||
|
|
||||
|main =
|
||||
| unitErr = Error.throw Nothing
|
||||
| IO.println (unitErr.catch MyCons)
|
||||
| IO.println (unitErr.catch_primitive MyCons)
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
consumeOut shouldEqual List("(MyCons Nothing)")
|
||||
@ -83,14 +83,14 @@ class DataflowErrorsTest extends InterpreterTest {
|
||||
|
|
||||
|main =
|
||||
| myErr = Error.throw (MyError 20)
|
||||
| IO.println(myErr.catch .recover)
|
||||
| IO.println(myErr.catch_primitive .recover)
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
consumeOut shouldEqual List("(MyRecovered 20)")
|
||||
}
|
||||
|
||||
"make the catch method an identity for non-error values" in {
|
||||
val code = "main = 10.catch (x -> x + 1)"
|
||||
val code = "main = 10.catch_primitive (x -> x + 1)"
|
||||
eval(code) shouldEqual 10
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class PanicsTest extends InterpreterTest {
|
||||
|main =
|
||||
| caught = Panic.recover (Long.parseLong "oops")
|
||||
| IO.println caught
|
||||
| cause = caught.catch <| case _ of
|
||||
| cause = caught.catch_primitive e-> case e of
|
||||
| Polyglot_Error err -> err
|
||||
| _ -> "fail"
|
||||
| IO.println cause
|
||||
|
@ -11,7 +11,7 @@ build_long n =
|
||||
|
||||
build_long_bldr n =
|
||||
bldr = StringBuilder.new
|
||||
1.up_to n . each (bldr.append _)
|
||||
1.up_to n . each n-> bldr.append n
|
||||
res = bldr.toString
|
||||
res
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
import Table_Tests.Table_Spec
|
||||
|
@ -60,20 +60,20 @@ spec = Test.group "List" <|
|
||||
empty.take_start 2 . should_equal Nil
|
||||
Test.specify "should allow getting the head of the list with `.head`" <|
|
||||
l.head . should_equal 1
|
||||
empty.head . should_equal Nothing
|
||||
empty.head.catch . should_equal Nothing
|
||||
Test.specify "should allow getting the tail of the list with `.tail`" <|
|
||||
l.tail . should_equal (Cons 2 (Cons 3 Nil))
|
||||
empty.tail . should_equal Nothing
|
||||
empty.tail.catch . should_equal Nothing
|
||||
Test.specify "should allow getting the init of the list with `.init`" <|
|
||||
l.init . should_equal (Cons 1 (Cons 2 Nil))
|
||||
empty.init . should_equal Nothing
|
||||
empty.init.catch . should_equal Nothing
|
||||
Test.specify "should allow getting the last element of the list with `.last`" <|
|
||||
l.last . should_equal 3
|
||||
empty.last . should_equal Nothing
|
||||
empty.last.catch . should_equal Nothing
|
||||
Test.specify "should allow getting the head of the list with `.first`" <|
|
||||
l.first . should_equal 1
|
||||
empty.first . should_equal Nothing
|
||||
empty.first.catch . should_equal Nothing
|
||||
Test.specify "should allow getting the tail of the list with `.rest`" <|
|
||||
l.rest . should_equal (Cons 2 (Cons 3 Nil))
|
||||
empty.rest . should_equal Nothing
|
||||
empty.rest.catch . should_equal Nothing
|
||||
|
||||
|
@ -43,7 +43,7 @@ spec = Test.group "Maps" <|
|
||||
m.get "foo" . should_equal 134
|
||||
m.get "bar" . should_equal 654
|
||||
m.get "baz" . should_equal "spam"
|
||||
m.get "nope" . should_equal Nothing
|
||||
(m.get "nope").should_fail_with Nothing
|
||||
Test.specify "should support get_or_else" <|
|
||||
m = Map.empty . insert 2 3
|
||||
m.get_or_else 2 0 . should_equal 3
|
||||
|
19
test/Tests/src/Data/Maybe_Spec.enso
Normal file
19
test/Tests/src/Data/Maybe_Spec.enso
Normal file
@ -0,0 +1,19 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
spec = Test.group "Maybe" <|
|
||||
Test.specify "should have a Nothing variant" <|
|
||||
Nothing . should_equal Nothing
|
||||
Test.specify "should have a Just variant" <|
|
||||
(Maybe.Some 2).value . should_equal 2
|
||||
Test.specify "should provide the `maybe` function" <|
|
||||
Nothing.maybe 2 x->x . should_equal 2
|
||||
(Maybe.Some 7).maybe 2 (*2) . should_equal 14
|
||||
Test.specify "should provide `is_just`" <|
|
||||
Nothing.is_just . should_be_false
|
||||
Maybe.Some 2 . is_just . should_be_true
|
||||
Test.specify "should provide `is_nothing`" <|
|
||||
Nothing.is_nothing . should_be_true
|
||||
Maybe.Some 2 . is_nothing . should_be_false
|
||||
|
@ -42,7 +42,7 @@ spec =
|
||||
(almost_max_long * 2 / almost_max_long_times_three) . should_equal 0.6666666 epsilon=eps
|
||||
Test.specify "should support integer division" <|
|
||||
(10.div 3) . should_equal 3
|
||||
Test.expect_error_with (10.div 0) Arithmetic_Error
|
||||
# (10.div 0).should_fail_with Arithmetic_Error
|
||||
Test.specify "should support integral binary literals" <|
|
||||
lit = 2_01101101
|
||||
lit . should_equal 109
|
||||
@ -93,28 +93,28 @@ spec =
|
||||
positive_bits.bit_shift_l 64 . should_equal 16_6d0000000000000000
|
||||
positive_bits.bit_shift_l -2 . should_equal 2_011011
|
||||
positive_bits.bit_shift_l -64 . should_equal 0
|
||||
Test.expect_error_with (positive_bits.bit_shift_l positive_big_bits) Arithmetic_Error
|
||||
(positive_bits.bit_shift_l positive_big_bits).should_error_with Arithmetic_Error
|
||||
positive_bits.bit_shift_l negative_big_bits . should_equal 0
|
||||
|
||||
negative_bits.bit_shift_l 2 . should_equal -436
|
||||
negative_bits.bit_shift_l 64 . should_equal -2010695104034341126144
|
||||
negative_bits.bit_shift_l -2 . should_equal -28
|
||||
negative_bits.bit_shift_l -64 . should_equal -1
|
||||
Test.expect_error_with (negative_bits.bit_shift_l positive_big_bits) Arithmetic_Error
|
||||
(negative_bits.bit_shift_l positive_big_bits).should_error_with Arithmetic_Error
|
||||
negative_bits.bit_shift_l negative_big_bits . should_equal -1
|
||||
|
||||
positive_big_bits.bit_shift_l 2 . should_equal 110680464442257309672
|
||||
positive_big_bits.bit_shift_l 64 . should_equal 510423550381407695084381446705395007488
|
||||
positive_big_bits.bit_shift_l -2 . should_equal 6917529027641081854
|
||||
positive_big_bits.bit_shift_l -100 . should_equal 0
|
||||
Test.expect_error_with (positive_big_bits.bit_shift_l positive_big_bits) Arithmetic_Error
|
||||
(positive_big_bits.bit_shift_l positive_big_bits).should_error_with Arithmetic_Error
|
||||
positive_big_bits.bit_shift_l negative_big_bits . should_equal 0
|
||||
|
||||
negative_big_bits.bit_shift_l 2 . should_equal -110680464442257309672
|
||||
negative_big_bits.bit_shift_l 64 . should_equal -510423550381407695084381446705395007488
|
||||
negative_big_bits.bit_shift_l -2 . should_equal -6917529027641081855
|
||||
negative_big_bits.bit_shift_l -100 . should_equal -1
|
||||
Test.expect_error_with (negative_big_bits.bit_shift_l positive_big_bits) Arithmetic_Error
|
||||
(negative_big_bits.bit_shift_l positive_big_bits).should_error_with Arithmetic_Error
|
||||
negative_big_bits.bit_shift_l negative_big_bits . should_equal -1
|
||||
Test.specify "should support right bit shifts, preserving sign" <|
|
||||
positive_bits = 2_01101101
|
||||
@ -126,28 +126,28 @@ spec =
|
||||
positive_bits.bit_shift_r 64 . should_equal (positive_bits.bit_shift_l -64)
|
||||
positive_bits.bit_shift_r -2 . should_equal (positive_bits.bit_shift_l 2)
|
||||
positive_bits.bit_shift_r -64 . should_equal (positive_bits.bit_shift_l 64)
|
||||
Test.expect_error_with (positive_bits.bit_shift_r negative_big_bits) Arithmetic_Error
|
||||
(positive_bits.bit_shift_r negative_big_bits).should_error_with Arithmetic_Error
|
||||
positive_bits.bit_shift_r positive_big_bits . should_equal 0
|
||||
|
||||
negative_bits.bit_shift_r 2 . should_equal (negative_bits.bit_shift_l -2)
|
||||
negative_bits.bit_shift_r 64 . should_equal (negative_bits.bit_shift_l -64)
|
||||
negative_bits.bit_shift_r -2 . should_equal (negative_bits.bit_shift_l 2)
|
||||
negative_bits.bit_shift_r -64 . should_equal (negative_bits.bit_shift_l 64)
|
||||
Test.expect_error_with (negative_bits.bit_shift_r negative_big_bits) Arithmetic_Error
|
||||
(negative_bits.bit_shift_r negative_big_bits).should_error_with Arithmetic_Error
|
||||
negative_bits.bit_shift_r positive_big_bits . should_equal -1
|
||||
|
||||
positive_big_bits.bit_shift_r 2 . should_equal (positive_big_bits.bit_shift_l -2)
|
||||
positive_big_bits.bit_shift_r 64 . should_equal (positive_big_bits.bit_shift_l -64)
|
||||
positive_big_bits.bit_shift_r -2 . should_equal (positive_big_bits.bit_shift_l 2)
|
||||
positive_big_bits.bit_shift_r -100 . should_equal (positive_big_bits.bit_shift_l 100)
|
||||
Test.expect_error_with (positive_big_bits.bit_shift_r negative_big_bits) Arithmetic_Error
|
||||
(positive_big_bits.bit_shift_r negative_big_bits).should_error_with Arithmetic_Error
|
||||
positive_big_bits.bit_shift_r positive_big_bits . should_equal 0
|
||||
|
||||
negative_big_bits.bit_shift_r 2 . should_equal (negative_big_bits.bit_shift_l -2)
|
||||
negative_big_bits.bit_shift_r 64 . should_equal (negative_big_bits.bit_shift_l -64)
|
||||
negative_big_bits.bit_shift_r -2 . should_equal (negative_big_bits.bit_shift_l 2)
|
||||
negative_big_bits.bit_shift_r -100 . should_equal (negative_big_bits.bit_shift_l 100)
|
||||
Test.expect_error_with (negative_big_bits.bit_shift_r negative_big_bits) Arithmetic_Error
|
||||
(negative_big_bits.bit_shift_r negative_big_bits).should_error_with Arithmetic_Error
|
||||
negative_big_bits.bit_shift_r positive_big_bits . should_equal -1
|
||||
Test.group "Decimals" <|
|
||||
Test.specify "should exist and expose basic arithmetic operations" <|
|
||||
|
@ -8,6 +8,8 @@ T.== that = this.a == that.a
|
||||
T.compare_to that = if this == that then Ordering.Equal else
|
||||
if this.a > that.a then Ordering.Greater else Ordering.Less
|
||||
|
||||
type My_Error a
|
||||
|
||||
spec = Test.group "Vectors" <|
|
||||
Test.specify "should allow vector creation with a programmatic constructor" <|
|
||||
Vector.new 100 (ix -> ix + 1) . fold 0 (+) . should_equal 5050
|
||||
@ -19,7 +21,7 @@ spec = Test.group "Vectors" <|
|
||||
[1,2,3].fold 0 (+) . should_equal 6
|
||||
Test.specify "should allow to reduce elements if it is non-empty" <|
|
||||
[1,2,3].reduce (+) . should_equal 6
|
||||
[].reduce (+) . should_equal Nothing
|
||||
[].reduce (+) . should_fail_with Nothing
|
||||
Test.specify "should check exists" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.exists (ix -> ix > 3) . should_be_true
|
||||
@ -88,42 +90,42 @@ spec = Test.group "Vectors" <|
|
||||
empty_vec = []
|
||||
non_empty_vec.head . should_equal 1
|
||||
singleton_vec.head . should_equal 1
|
||||
empty_vec.head . should_equal Nothing
|
||||
empty_vec.head . should_fail_with Nothing
|
||||
Test.specify "should allow getting the tail of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.tail . should_equal [2, 3, 4, 5]
|
||||
singleton_vec.tail . should_equal []
|
||||
empty_vec.tail . should_equal Nothing
|
||||
empty_vec.tail . should_fail_with Nothing
|
||||
Test.specify "should allow getting the init of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.init . should_equal [1, 2, 3, 4]
|
||||
singleton_vec.init . should_equal []
|
||||
empty_vec.init . should_equal Nothing
|
||||
empty_vec.init . should_fail_with Nothing
|
||||
Test.specify "should allow getting the last element of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.last . should_equal 5
|
||||
singleton_vec.last . should_equal 1
|
||||
empty_vec.last . should_equal Nothing
|
||||
empty_vec.last . should_fail_with Nothing
|
||||
Test.specify "should allow getting the first element" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.first . should_equal 1
|
||||
singleton_vec.first . should_equal 1
|
||||
empty_vec.first . should_equal Nothing
|
||||
empty_vec.first . should_fail_with Nothing
|
||||
Test.specify "should allow getting the rest of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.rest . should_equal [2, 3, 4, 5]
|
||||
singleton_vec.rest . should_equal []
|
||||
empty_vec.rest . should_equal Nothing
|
||||
empty_vec.rest . should_fail_with Nothing
|
||||
Test.specify "should be able to be sorted" <|
|
||||
empty_vec = []
|
||||
short_vec = [2, 4, 38, -1, -1000, 3671, -32]
|
||||
@ -159,3 +161,7 @@ spec = Test.group "Vectors" <|
|
||||
small_vec = [T 1 8, T 1 3, T -20 0, T -1 1, T -1 10, T 4 0]
|
||||
small_expected = [T 4 0, T 1 3, T 1 8, T -1 10, T -1 1, T -20 0]
|
||||
small_vec.sort order=Sort_Order.Descending . should_equal small_expected
|
||||
Test.specify "should be able to map over errors" <|
|
||||
fail a = Error.throw <| My_Error a
|
||||
[fail 1].map (x -> x.catch (x -> x.a)) . should_equal [1]
|
||||
[1].map fail . map .catch . should_equal [My_Error 1]
|
||||
|
@ -1,5 +1,8 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
import Tests.Semantic.Any_Spec
|
||||
import Tests.Semantic.Case_Spec
|
||||
import Tests.Semantic.Deep_Export.Spec as Deep_Export_Spec
|
||||
import Tests.Semantic.Error_Spec
|
||||
@ -12,6 +15,7 @@ import Tests.Data.Interval_Spec
|
||||
import Tests.Data.Json_Spec
|
||||
import Tests.Data.List_Spec
|
||||
import Tests.Data.Map_Spec
|
||||
import Tests.Data.Maybe_Spec
|
||||
import Tests.Data.Noise.Generator_Spec as Noise_Generator_Spec
|
||||
import Tests.Data.Noise_Spec
|
||||
import Tests.Data.Numbers_Spec
|
||||
@ -20,14 +24,17 @@ import Tests.Data.Range_Spec
|
||||
import Tests.Data.Text_Spec
|
||||
import Tests.Data.Time.Spec as Time_Spec
|
||||
import Tests.Data.Vector_Spec
|
||||
|
||||
import Tests.Network.Http.Header_Spec as Http_Header_Spec
|
||||
import Tests.Network.Http.Request_Spec as Http_Request_Spec
|
||||
import Tests.Network.Http_Spec
|
||||
import Tests.Network.Uri_Spec
|
||||
|
||||
import Tests.System.File_Spec
|
||||
import Tests.System.Process_Spec
|
||||
|
||||
main = Test.Suite.runMain <|
|
||||
Any_Spec.spec
|
||||
Case_Spec.spec
|
||||
Deep_Export_Spec.spec
|
||||
Error_Spec.spec
|
||||
@ -41,6 +48,7 @@ main = Test.Suite.runMain <|
|
||||
Json_Spec.spec
|
||||
List_Spec.spec
|
||||
Map_Spec.spec
|
||||
Maybe_Spec.spec
|
||||
Meta_Spec.spec
|
||||
Names_Spec.spec
|
||||
Noise_Generator_Spec.spec
|
||||
|
@ -38,9 +38,7 @@ spec_impl =
|
||||
http = Http.new (version = version_setting)
|
||||
http.version.should_equal version_setting
|
||||
Test.specify "should throw error when requesting invalid Uri" <|
|
||||
case Panic.recover (Http.new.get "not a uri") of
|
||||
Uri.Syntax_Error _ -> Nothing
|
||||
other -> Test.fail ("Unexpected result: " + other)
|
||||
Test.expect_panic_with (Http.new.get "not a uri") Uri.Syntax_Error
|
||||
Test.specify "should send Get request" <|
|
||||
expected_response = Json.parse <| '''
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ spec =
|
||||
addr.raw_query.should_equal "%D0%9A%D0%BE%D0%B4"
|
||||
addr.raw_fragment.should_equal ""
|
||||
Test.specify "should return Syntax_Error when parsing invalid Uri" <|
|
||||
Uri.parse "a b c" . catch <| case _ of
|
||||
Uri.parse "a b c" . catch e-> case e of
|
||||
Uri.Syntax_Error msg ->
|
||||
msg.should_equal "Illegal character in path at index 1: a b c"
|
||||
other ->
|
||||
|
24
test/Tests/src/Semantic/Any_Spec.enso
Normal file
24
test/Tests/src/Semantic/Any_Spec.enso
Normal file
@ -0,0 +1,24 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
type My_Type a
|
||||
|
||||
spec = Test.group "Callables" <|
|
||||
Test.specify "should be able to be applied in a pipeline using |>" <|
|
||||
(1 |> *2) . should_equal 2
|
||||
(2 |> My_Type) . should_equal (My_Type 2)
|
||||
(2.3 |> .floor) . should_equal 2
|
||||
Test.specify "should be able to be applied to an argument using <|" <|
|
||||
(*2 <| 1) . should_equal 2
|
||||
(My_Type <| 2) . should_equal (My_Type 2)
|
||||
(.floor <| 2.3) . should_equal 2
|
||||
Test.specify "should be able to be composed backward using <<" <|
|
||||
(+1 << *2) 2 . should_equal 5
|
||||
(My_Type << *2) 2 . should_equal <| My_Type 4
|
||||
(.floor << *2.25) 2 . should_equal 4
|
||||
Test.specify "should be able to be composed forward using >>" <|
|
||||
(+1 >> *2) 2 . should_equal 6
|
||||
(*2 >> My_Type) 2 . should_equal <| My_Type 4
|
||||
(*2 >> .floor) 2.75 . should_equal 5
|
||||
|
@ -1,3 +1,5 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
import Tests.Semantic.Deep_Export.Internal
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
import Tests.Semantic.Import_Loop.B
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
from Base import all
|
||||
|
||||
from Tests.Semantic.Names.Definitions import My_Type, Another_Constant
|
||||
import Test
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
spec =
|
||||
@ -13,7 +14,7 @@ spec =
|
||||
contents.take_start 6 . should_equal [67, 117, 112, 99, 97, 107]
|
||||
Test.specify "should handle exceptions when reading a non-existent file" <|
|
||||
file = File.new "does_not_exist.txt"
|
||||
successfully_failed = Panic.recover file.read . catch <| case _ of
|
||||
successfully_failed = Panic.recover file.read . catch e-> case e of
|
||||
File.No_Such_File_Error _ -> True
|
||||
_ -> False
|
||||
successfully_failed . should_be_true
|
||||
|
Loading…
Reference in New Issue
Block a user