Improving widgets for take/drop (#6641)

Related to #6410

# Important Notes
- Updated some `Meta` methods (needed for error handling):
- `Meta.Type` now has `name` and `qualified_name`.
- `Meta.Constructor` has `declaring_type` allowing to get the type that this constructor is associated with.
This commit is contained in:
Radosław Waśko 2023-05-12 17:33:15 +02:00 committed by GitHub
parent e62f97f26a
commit f5071a17fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 299 additions and 37 deletions

View File

@ -241,6 +241,7 @@ type Array
If an `Index_Sub_Range`, then the selection is interpreted following
the rules of that type.
If a `Range`, the selection is specified by two indices, from and to.
@range Index_Sub_Range.default_widget
take : (Index_Sub_Range | Range | Integer) -> Vector Any
take self range=(Index_Sub_Range.First 1) = Vector.take self range
@ -251,6 +252,7 @@ type Array
If an `Index_Sub_Range`, then the selection is interpreted following
the rules of that type.
If a `Range`, the selection is specified by two indices, from and to.
@range Index_Sub_Range.default_widget
drop : (Index_Sub_Range | Range | Integer) -> Vector Any
drop self range=(Index_Sub_Range.First 1) = Vector.drop self range

View File

@ -5,15 +5,22 @@ 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.Errors.Common.Type_Error
import project.Error.Error
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Function.Function
import project.Math
import project.Meta
import project.Panic.Panic
import project.Random
import project.Runtime.Ref.Ref
from project.Data.Boolean import Boolean, True, False
from project.Metadata.Widget import Single_Choice
from project.Metadata.Choice import Option
import project.Metadata.Display
type Index_Sub_Range
## Select the first `count` items.
@ -40,7 +47,7 @@ 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)) = [0])
By_Index (indexes : (Integer | Range | Vector (Integer | Range)))
## Gets a random sample of entries, without repetitions.
@ -67,6 +74,26 @@ type Index_Sub_Range
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
It includes all constructors of `Index_Sub_Range` but also `Range`, since
the `Index_Sub_Range` type is by default used in sum types containing
`Range` too.
default_options : Vector Option
default_options =
o1 = Option "First" "(Index_Sub_Range.First 1)"
o2 = Option "Last" "(Index_Sub_Range.Last 1)"
o3 = Option "While" "(Index_Sub_Range.While (x-> False))"
o4 = Option "By_Index" "(Index_Sub_Range.By_Index [0])"
o5 = Option "Sample" "(Index_Sub_Range.Sample 10)"
o6 = Option "Every" "(Index_Sub_Range.Every 2)"
o7 = Option "Range" "(Range.new 0 100)"
[o1, o2, o3, o4, o5, o6, o7]
## PRIVATE
default_widget : Single_Choice
default_widget =
Single_Choice display=Display.Always Index_Sub_Range.default_options
## PRIVATE
Resolves a vector of ranges or indices into a vector of ranges that fit
within a sequence.
@ -169,9 +196,9 @@ sort_and_merge_ranges ranges =
normalization on its own.
- range: The `Index_Sub_Range` to take from the collection.
take_helper : Integer -> (Integer -> Any) -> (Integer -> Integer -> Any) -> (Vector (Integer | Range) -> Vector Any) -> (Index_Sub_Range | Range | Integer) -> Any
take_helper length at single_slice slice_ranges index_sub_range = case index_sub_range of
take_helper length at single_slice slice_ranges range = case range of
count : Integer -> take_helper length at single_slice slice_ranges (Index_Sub_Range.First count)
_ : Range -> take_helper length at single_slice slice_ranges (Index_Sub_Range.By_Index index_sub_range)
_ : Range -> take_helper length at single_slice slice_ranges (Index_Sub_Range.By_Index range)
Index_Sub_Range.First count -> single_slice 0 (Math.min length count)
Index_Sub_Range.Last count -> single_slice length-count length
Index_Sub_Range.While predicate ->
@ -193,6 +220,7 @@ take_helper length at single_slice slice_ranges index_sub_range = case index_sub
if start >= length then single_slice 0 0 else
range = start.up_to length . with_step step
take_helper length at single_slice slice_ranges (Index_Sub_Range.By_Index range)
_ -> handle_unmatched_type [Index_Sub_Range, Range, Integer] range
## PRIVATE
A helper that implements dropping from an arbitrary collection using a set of
@ -219,9 +247,9 @@ take_helper length at single_slice slice_ranges index_sub_range = case index_sub
normalized.
- range: The `Index_Sub_Range` to drop from the collection.
drop_helper : Integer -> (Integer -> Any) -> (Integer -> Integer -> Any) -> (Vector (Integer | Range) -> Vector Any) -> (Index_Sub_Range | Range | Integer) -> Any
drop_helper length at single_slice slice_ranges index_sub_range = case index_sub_range of
_ : Integer -> single_slice index_sub_range length
_ : Range -> drop_helper length at single_slice slice_ranges (Index_Sub_Range.By_Index index_sub_range)
drop_helper length at single_slice slice_ranges range = case range of
_ : Integer -> single_slice range length
_ : Range -> drop_helper length at single_slice slice_ranges (Index_Sub_Range.By_Index range)
Index_Sub_Range.First count -> single_slice count length
Index_Sub_Range.Last count -> single_slice 0 length-count
Index_Sub_Range.While predicate ->
@ -245,3 +273,21 @@ drop_helper length at single_slice slice_ranges index_sub_range = case index_sub
if start >= length then single_slice 0 length else
range = start.up_to length . with_step step
drop_helper length at single_slice slice_ranges (Index_Sub_Range.By_Index range)
_ -> handle_unmatched_type [Index_Sub_Range, Range, Integer] range
## PRIVATE
handle_unmatched_type expected_types actual_value =
m = Meta.meta actual_value
return_type_error =
expected_types_str = expected_types . map .to_text . join " | "
Error.throw (Type_Error.Error expected_types_str actual_value "range")
case m of
_ : Meta.Constructor ->
declaring_type = m.declaring_type
is_expected_constructor = expected_types.map Meta.meta . contains declaring_type
if is_expected_constructor.not then return_type_error else
msg = "The constructor " + m.name + " is missing some arguments."
Error.throw (Illegal_Argument.Error msg)
_ -> case actual_value.is_a Function of
True -> Error.throw (Illegal_Argument.Error "Got a Function instead of a range, is a constructor argument missing?")
False -> return_type_error

View File

@ -939,6 +939,7 @@ Text.repeat self count=1 =
"Hello World!".take (By_Index [1, 0, 0, 6, 0]) == "eHHWH"
"Hello World!".take (By_Index [Range 0 3, 6, Range 6 12 2]) == "HelWWrd"
"Hello World!".take (Sample 3 seed=42) == "l d"
@range Text_Sub_Range.default_widget
Text.take : (Text_Sub_Range | Index_Sub_Range | Range | Integer) -> Text ! Index_Out_Of_Bounds
Text.take self range=(Index_Sub_Range.First 1) =
ranges = Codepoint_Ranges.resolve self range
@ -985,6 +986,7 @@ Text.take self range=(Index_Sub_Range.First 1) =
"Hello World!".drop (By_Index [1, 0, 0, 6, 0]) == "llo orld!"
"Hello World!".drop (By_Index [Range 0 3, 6, Range 6 12 2]) == "lo ol!"
"Hello World!".drop (Sample 3 seed=42) == "HeloWorl!"
@range Text_Sub_Range.default_widget
Text.drop : (Text_Sub_Range | Index_Sub_Range | Range) -> Text ! Index_Out_Of_Bounds
Text.drop self range=(Index_Sub_Range.First 1) =
ranges = Codepoint_Ranges.resolve self range

View File

@ -6,6 +6,7 @@ import project.Data.Range.Range
import project.Data.Text.Text
import project.Data.Vector.Vector
import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Common.Type_Error
import project.Error.Error
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Nothing.Nothing
@ -16,6 +17,11 @@ from project.Data.Boolean import Boolean, True, False
import project.Data.Index_Sub_Range as Index_Sub_Range_Module
import project.Data.Text.Span as Span_Module
from project.Data.Index_Sub_Range import handle_unmatched_type
from project.Metadata.Widget import Single_Choice
from project.Metadata.Choice import Option
import project.Metadata.Display
polyglot java import com.ibm.icu.text.BreakIterator
polyglot java import org.enso.base.Text_Utils
@ -41,13 +47,31 @@ type Text_Sub_Range
After_Last (delimiter : Text)
## PRIVATE
Convert to a display representation of this Index_Sub_Range.
Convert to a display representation of this `Text_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
Text_Sub_Range.Before delimiter -> "Before " + delimiter.pretty
Text_Sub_Range.Before_Last delimiter -> "Before Last " + delimiter.pretty
Text_Sub_Range.After delimiter -> "After " + delimiter.pretty
Text_Sub_Range.After_Last delimiter -> "After Last " + delimiter.pretty
## PRIVATE
default_options : Vector Option
default_options =
o1 = Option "Before" "(Text_Sub_Range.Before ' ')"
o2 = Option "Before_Last" "(Text_Sub_Range.Before_Last ' ')"
o3 = Option "After" "(Text_Sub_Range.After ' ')"
o4 = Option "After_Last" "(Text_Sub_Range.After_Last ' ')"
[o1, o2, o3, o4]
## PRIVATE
The widget for `Text_Sub_Range` also displays options for
`Index_Sub_Range` since the former is supposed to 'expand' the latter and
is always used together with it.
default_widget : Single_Choice
default_widget =
options = Index_Sub_Range.default_options + Text_Sub_Range.default_options
Single_Choice display=Display.Always options
type Codepoint_Ranges
## PRIVATE
@ -64,7 +88,7 @@ type Codepoint_Ranges
Returns a new sorted list of ranges where intersecting ranges have been
merged.
Empty subranges are not discarded.
Empty ranges are not discarded.
sorted_and_distinct_ranges : Vector Range
sorted_and_distinct_ranges self = if self.is_sorted_and_distinct then self.ranges else
Index_Sub_Range_Module.sort_and_merge_ranges self.ranges
@ -80,8 +104,8 @@ type Codepoint_Ranges
in such a way that the ranges returned by this method always have a step
equal to 1.
resolve : Text -> (Text_Sub_Range | Index_Sub_Range | Range | Integer) -> (Range | Codepoint_Ranges)
resolve text subrange =
case subrange of
resolve text range =
case range of
Text_Sub_Range.Before delimiter ->
if delimiter.is_empty then (0.up_to 0) else
span = Text_Utils.span_of text delimiter
@ -134,12 +158,14 @@ type Codepoint_Ranges
if step <= 0 then Error.throw (Illegal_Argument.Error "Step within Every must be positive.") else
len = text.length
if start >= len then 0.up_to 0 else
range = start.up_to text.length . with_step step
Codepoint_Ranges.resolve text (Index_Sub_Range.By_Index range)
simple_range = start.up_to text.length . with_step step
Codepoint_Ranges.resolve text (Index_Sub_Range.By_Index simple_range)
_ : Range ->
Codepoint_Ranges.resolve text (Index_Sub_Range.By_Index subrange)
Codepoint_Ranges.resolve text (Index_Sub_Range.By_Index range)
_ : Integer ->
Codepoint_Ranges.resolve text (Index_Sub_Range.First subrange)
Codepoint_Ranges.resolve text (Index_Sub_Range.First range)
_ -> handle_unmatched_type [Text_Sub_Range, Index_Sub_Range, Range, Integer] range
## PRIVATE
Utility function to find char indices for Text_Sub_Range.

View File

@ -758,6 +758,7 @@ type Vector a
If an `Index_Sub_Range`, then the selection is interpreted following
the rules of that type.
If a `Range`, the selection is specified by two indices, from and to.
@range Index_Sub_Range.default_widget
take : (Index_Sub_Range | Range | Integer) -> Vector Any
take self range=(Index_Sub_Range.First 1) = case range of
## We are using a specialized implementation for `take Sample`, because
@ -777,6 +778,7 @@ type Vector a
If an `Index_Sub_Range`, then the selection is interpreted following
the rules of that type.
If a `Range`, the selection is specified by two indices, from and to.
@range Index_Sub_Range.default_widget
drop : (Index_Sub_Range | Range | Integer) -> Vector Any
drop self range=(Index_Sub_Range.First 1) =
drop_helper self.length (self.at _) self.slice (slice_ranges self) range

View File

@ -44,10 +44,18 @@ type Type
## ADVANCED
Returns the fully qualified name of the type.
qualified_name : Text
qualified_name self =
c = self.value
get_qualified_type_name c
## ADVANCED
Returns the short name of the type.
name : Text
name self =
c = self.value ...
get_constructor_name c
c = self.value
get_short_type_name c
type Atom
## PRIVATE
@ -111,6 +119,13 @@ type Constructor
ctor = self.value ...
new_atom ctor fields.to_array
## ADVANCED
Returns the type that this constructor is a part of.
declaring_type : Type
declaring_type self =
c = self.value ...
Type.Value (get_constructor_declaring_type c)
type Primitive
## PRIVATE
ADVANCED
@ -504,3 +519,19 @@ get_simple_type_name value = @Builtin_Method "Meta.get_simple_type_name"
- value: the value to get the type of.
get_qualified_type_name : Any -> Text
get_qualified_type_name value = @Builtin_Method "Meta.get_qualified_type_name"
## PRIVATE
Returns a short name of a type (the last part of its qualified name).
Arguments:
- typ: the type to get the short name of.
get_short_type_name : Any -> Text
get_short_type_name typ = @Builtin_Method "Meta.get_short_type_name"
## PRIVATE
Returns the type that this constructor is a part of.
Arguments:
- constructor: the constructor to get the declaring type of.
get_constructor_declaring_type : Any -> Any
get_constructor_declaring_type constructor = @Builtin_Method "Meta.get_constructor_declaring_type"

View File

@ -749,6 +749,7 @@ type Column
Arguments:
- range: The selection of rows from the table to return.
@range Index_Sub_Range.default_widget
take : (Index_Sub_Range | Range | Integer) -> Column
take self range=(First 1) =
_ = range
@ -761,6 +762,7 @@ type Column
Arguments:
- range: The selection of rows from the table to remove.
@range Index_Sub_Range.default_widget
drop : (Index_Sub_Range | Range | Integer) -> Column
drop self range=(First 1) =
_ = range

View File

@ -522,6 +522,7 @@ type Table
Arguments:
- range: The selection of rows from the table to return.
@range Index_Sub_Range.default_widget
take : (Index_Sub_Range | Range | Integer) -> Table
take self range=(First 1) =
_ = range
@ -535,6 +536,7 @@ type Table
Arguments:
- range: The selection of rows from the table to remove.
@range Index_Sub_Range.default_widget
drop : (Index_Sub_Range | Range | Integer) -> Table
drop self range=(First 1) =
_ = range

View File

@ -1547,6 +1547,7 @@ type Column
Arguments:
- range: The selection of rows from the table to return.
@range Index_Sub_Range.default_widget
take : (Index_Sub_Range | Range | Integer) -> Column
take self range=(First 1) =
Index_Sub_Range_Module.take_helper self.length self.at self.slice (slice_ranges self) range
@ -1556,6 +1557,7 @@ type Column
Arguments:
- range: The selection of rows from the table to remove.
@range Index_Sub_Range.default_widget
drop : (Index_Sub_Range | Range | Integer) -> Column
drop self range=(First 1) =
Index_Sub_Range_Module.drop_helper self.length self.at self.slice (slice_ranges self) range

View File

@ -1148,6 +1148,7 @@ type Table
Take rows from the top of the table as long as their values sum to 10.
table.take (While row-> row.to_vector.compute Statistic.Sum == 10)
@range Index_Sub_Range.default_widget
take : (Index_Sub_Range | Range | Integer) -> Table
take self range=(First 1) =
Index_Sub_Range_Module.take_helper self.row_count self.rows.at self.slice (slice_ranges self) range
@ -1170,6 +1171,7 @@ type Table
Drop rows from the top of the table as long as their values sum to 10.
table.drop (While row-> row.to_vector.compute Statistic.Sum == 10)
@range Index_Sub_Range.default_widget
drop : (Index_Sub_Range | Range | Integer) -> Table
drop self range=(First 1) =
Index_Sub_Range_Module.drop_helper self.row_count self.rows.at self.slice (slice_ranges self) range

View File

@ -0,0 +1,17 @@
package org.enso.interpreter.node.expression.builtin.meta;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.data.Type;
@BuiltinMethod(
type = "Meta",
name = "get_constructor_declaring_type",
description = "Gets the type that declared this constructor.",
autoRegister = false)
public class GetConstructorDeclaringTypeNode extends Node {
Type execute(AtomConstructor cons) {
return cons.getType();
}
}

View File

@ -12,20 +12,8 @@ import org.enso.interpreter.runtime.data.text.Text;
name = "get_constructor_name",
description = "Gets the name of a constructor.",
autoRegister = false)
public abstract class GetConstructorNameNode extends Node {
static GetConstructorNameNode build() {
return GetConstructorNameNodeGen.create();
}
abstract Text execute(Object atom_constructor);
@Specialization
Text doConstructor(AtomConstructor cons) {
public class GetConstructorNameNode extends Node {
Text execute(AtomConstructor cons) {
return Text.create(cons.getName());
}
@Specialization
Text doType(Type type) {
return Text.create(type.getQualifiedName().toString());
}
}

View File

@ -0,0 +1,19 @@
package org.enso.interpreter.node.expression.builtin.meta;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.data.Type;
import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(
type = "Meta",
name = "get_short_type_name",
description = "Gets the short name of a Type.",
autoRegister = false)
public class GetShortTypeNameNode extends Node {
Text execute(Type type) {
return Text.create(type.getName());
}
}

View File

@ -1,6 +1,7 @@
from Standard.Base import all
from Standard.Base.Data.Index_Sub_Range.Index_Sub_Range import While, Sample, Every
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
import Standard.Base.Errors.Common.Type_Error
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
from Standard.Table.Errors import all
@ -151,8 +152,30 @@ spec setup =
rnd.at "alpha" . to_vector . should_equal alpha_sample
rnd.at "beta" . to_vector . should_equal beta_sample
Test.specify "should allow selecting rows as long as they satisfy a predicate" pending="While is not implemented for Table until the Row type is implemented." <|
Nothing
Test.specify "should allow selecting rows as long as they satisfy a predicate" <|
t = table_builder [["a", [1, 2, 3, 4]], ["b", [5, 6, 7, 8]]]
t2 = t.take (While (row -> row.at "a" < 3))
t2.row_count . should_equal 2
t2.at "a" . to_vector . should_equal [1, 2]
t2.at "b" . to_vector . should_equal [5, 6]
Test.specify "should gracefully handle missing constructor arguments" <|
t = table_builder [["X", [1, 2, 3]]]
t.take "FOO" . should_fail_with Type_Error
t.drop "FOO" . should_fail_with Type_Error
r1 = t.take (Index_Sub_Range.While)
r1.should_fail_with Illegal_Argument
r1.catch.to_display_text . should_contain "The constructor While is missing some arguments"
r2 = t.drop (Index_Sub_Range.Every ...)
r2.should_fail_with Illegal_Argument
r2.catch.to_display_text . should_contain "The constructor Every is missing some arguments"
r3 = t.take (Index_Sub_Range.First _)
r3.should_fail_with Illegal_Argument
r3.catch.to_display_text . should_contain "Got a Function instead of a range, is a constructor argument missing?"
Test.group prefix+"Column.take/drop" pending=take_drop_by_pending <|
table =
@ -310,3 +333,20 @@ spec setup =
three.drop (While (_ > 10)) . should_equal three
three.drop (While (_ < 10)) . should_equal empty
Test.specify "should gracefully handle missing constructor arguments" <|
c = table_builder [["X", [1, 2, 3]]] . at "X"
c.take "FOO" . should_fail_with Type_Error
c.drop "FOO" . should_fail_with Type_Error
r1 = c.take (Index_Sub_Range.While)
r1.should_fail_with Illegal_Argument
r1.catch.to_display_text . should_contain "The constructor While is missing some arguments"
r2 = c.drop (Index_Sub_Range.Every ...)
r2.should_fail_with Illegal_Argument
r2.catch.to_display_text . should_contain "The constructor Every is missing some arguments"
r3 = c.take (Index_Sub_Range.First _)
r3.should_fail_with Illegal_Argument
r3.catch.to_display_text . should_contain "Got a Function instead of a range, is a constructor argument missing?"

View File

@ -736,6 +736,25 @@ spec =
"".drop (Sample 0) . should_equal ""
"".drop (Sample 100) . should_equal ""
Test.specify "take and drop should gracefully handle missing constructor arguments" <|
"".take "FOO" . should_fail_with Type_Error
"".drop "FOO" . should_fail_with Type_Error
r1 = "".take (Index_Sub_Range.While)
r1.should_fail_with Illegal_Argument
r1.catch.to_display_text . should_contain "The constructor While is missing some arguments"
r2 = "".drop (Text_Sub_Range.Before ...)
r2.should_fail_with Illegal_Argument
r2.catch.to_display_text . should_contain "The constructor Before is missing some arguments"
r3 = "".take (Index_Sub_Range.First _)
r3.should_fail_with Illegal_Argument
r3.catch.to_display_text . should_contain "Got a Function instead of a range, is a constructor argument missing?"
# Double-check that constructors of _unexpected_ types are still yielding a type error.
"".take (Case_Sensitivity.Insensitive ...) . should_fail_with Type_Error
Test.specify "should correctly convert character case" <|
"FooBar Baz".to_case Case.Lower . should_equal "foobar baz"
"FooBar Baz".to_case Case.Upper . should_equal "FOOBAR BAZ"

View File

@ -413,7 +413,7 @@ type_spec name alter = Test.group name <|
vec.slice 1 1 . should_equal []
vec.slice 0 100 . should_equal [1, 2, 3, 4, 5, 6]
Meta.is_same_object vec (vec.slice 0 100) . should_be_true
Meta.meta Vector . name . should_equal (Meta.get_qualified_type_name (vec.slice 1 1))
Meta.get_qualified_type_name (vec.slice 1 1) . should_equal (Meta.meta Vector . qualified_name)
Test.specify "should define take and drop family of operations" <|
vec = alter [1, 2, 3, 4, 5, 6]
@ -536,6 +536,22 @@ type_spec name alter = Test.group name <|
alter ["a", "a", "a"] . drop (Sample 1) . should_equal ["a", "a"]
alter ["a", "a", "a"] . drop (Sample 100) . should_equal []
Test.specify "take/drop should gracefully handle missing constructor arguments" <|
[].take "FOO" . should_fail_with Type_Error
[].drop "FOO" . should_fail_with Type_Error
r1 = [].take (Index_Sub_Range.While)
r1.should_fail_with Illegal_Argument
r1.catch.to_display_text . should_contain "The constructor While is missing some arguments"
r2 = [].drop (Index_Sub_Range.Every ...)
r2.should_fail_with Illegal_Argument
r2.catch.to_display_text . should_contain "The constructor Every is missing some arguments"
r3 = [].take (Index_Sub_Range.First _)
r3.should_fail_with Illegal_Argument
r3.catch.to_display_text . should_contain "Got a Function instead of a range, is a constructor argument missing?"
Test.specify "should allow getting the last element of the vector" <|
non_empty_vec = alter [1, 2, 3, 4, 5]
singleton_vec = alter [1]
@ -763,5 +779,10 @@ spec =
arr
type_spec "Use Array_Proxy as vectors" v->
Array_Proxy.new v.length (ix -> v.at ix)
type_spec "Use a slice of an array as vectors" v->
v2 = v+[Nothing]
sliced_vector = v2.slice 0 v.length
sliced_array = sliced_vector.to_array
sliced_array
main = Test_Suite.run_main spec

View File

@ -207,6 +207,7 @@ spec =
Meta.is_atom typ . should_be_false
meta_typ = Meta.meta typ
meta_typ . should_be_a Meta.Type
meta_typ.name . should_equal "Boolean"
cons = case meta_typ of
Meta.Type.Value _ -> meta_typ.constructors
_ -> Test.fail "Should be a Meta.Type.Value: " + meta_typ.to_text
@ -222,6 +223,7 @@ spec =
Meta.is_atom typ . should_be_false
meta_typ = Meta.meta typ
meta_typ . should_be_a Meta.Type
meta_typ.name . should_equal "My_Type"
cons = case meta_typ of
Meta.Type.Value _ -> meta_typ.constructors
_ -> Test.fail "Should be a Meta.Type.Value: " + meta_typ.to_text
@ -229,6 +231,8 @@ spec =
cons.length . should_equal 1
cons.at 0 . should_be_a Meta.Constructor
cons . map (x -> x.name) . sort . should_equal [ "Value" ]
cons.each ctor->
ctor.declaring_type . should_equal meta_typ
Test.specify "methods of MyType" <|
typ = My_Type

View File

@ -0,0 +1,35 @@
from Standard.Base import all
import Standard.Base.Runtime.State
import Standard.Base.Metadata.Choice
import Standard.Base.Metadata.Widget
import Standard.Base.Metadata.Display
import Standard.Visualization.Widgets
from Standard.Test import Test, Test_Suite
import Standard.Test.Extensions
spec =
Test.group "Widgets for the Text type" <|
Test.specify "works for `take` and `drop`" <|
mock_text = "abc def"
default_widget = Text_Sub_Range.default_widget
expect = [["range", default_widget]] . to_json
json = Widgets.get_widget_json mock_text "take" ["range"]
json . should_equal expect
Widgets.get_widget_json mock_text "drop" ["range"] . should_equal expect
obj = json.parse_json
widget = obj.first.second
options = widget . at "values"
options.each o-> Test.with_clue o.to_text+": " <|
o.should_be_a JS_Object
labels = options.map o->
o.at "label"
labels.should_be_a Vector
labels.should_contain "First"
labels.should_contain "While"
labels.should_contain "After"
labels.should_contain "Before_Last"
main = Test_Suite.run_main spec

View File

@ -4,9 +4,11 @@ from Standard.Test import Test_Suite
import project.Widgets.Database_Widgets_Spec
import project.Widgets.Table_Widgets_Spec
import project.Widgets.Text_Widgets_Spec
spec =
Table_Widgets_Spec.spec
Database_Widgets_Spec.spec
Text_Widgets_Spec.spec
main = Test_Suite.run_main spec