aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-05-21 15:36:48 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:24:49 +0000
commit0a568f9a7e7ded43811e1a13189a6c09fcccdbac (patch)
tree1c7483f0c7ae1377158c8c0980093d227672974c
parentadd trigseq to lib/rhythm (diff)
downloadalive-0a568f9a7e7ded43811e1a13189a6c09fcccdbac.tar.gz
alive-0a568f9a7e7ded43811e1a13189a6c09fcccdbac.zip
indexing into types
-rw-r--r--alv/type.moon24
-rw-r--r--spec/type_spec.moon24
2 files changed, 44 insertions, 4 deletions
diff --git a/alv/type.moon b/alv/type.moon
index ecd1066..408edff 100644
--- a/alv/type.moon
+++ b/alv/type.moon
@@ -4,6 +4,7 @@
-- @module type
import opairs from require 'alv.util'
import result from require 'alv.cycle'
+import Error from require 'alv.error'
shared_shape = (a, b) ->
for key in pairs a
@@ -35,6 +36,11 @@ class Type
-- @tparam any b
-- @treturn bool
+ --- index into this type or throw a error.
+ -- @function get
+ -- @tparam any key
+ -- @treturn Type
+
--- create a `SigStream` of this type.
-- @tparam ?any init initial value
-- @treturn SigStream
@@ -67,6 +73,8 @@ class Primitive extends Type
eq: (a, b) => a == b
+ get: (key) => error "cannot index into Primitive type '#{@}'"
+
__eq: (other) => @name == other.name
__tostring: => @name
@@ -93,10 +101,8 @@ class Struct extends Type
return false
true
- __eq: (other) => same @types, other.types
- __tostring: =>
- inner = table.concat ["#{k}: #{v}" for k, v in opairs @types], ' '
- "{#{inner}}"
+ get: (key) =>
+ assert @types[key], Error 'index', "#{@} has no '#{key}' key"
--- create a new struct type with a subset of keys.
project: (keys) =>
@@ -105,6 +111,11 @@ class Struct extends Type
types[key] = @types[key]
@@ types
+ __eq: (other) => same @types, other.types
+ __tostring: =>
+ inner = table.concat ["#{k}: #{v}" for k, v in opairs @types], ' '
+ "{#{inner}}"
+
--- instantiate a Primitive type.
-- @classmethod
-- @tparam {string=Type} types
@@ -127,6 +138,11 @@ class Array extends Type
return false
true
+ get: (key) =>
+ assert (type key) == 'number'
+ assert key >= 0 and key < @size, Error 'index', "index '#{key}' out of range!"
+ @type
+
__eq: (other) => @size == other.size and @type == other.type
__tostring: => "#{@type}[#{@size}]"
diff --git a/spec/type_spec.moon b/spec/type_spec.moon
index b6315f1..2ffdb49 100644
--- a/spec/type_spec.moon
+++ b/spec/type_spec.moon
@@ -36,6 +36,11 @@ describe 'Primitive', ->
assert.is.true num\eq a, a
assert.is.false num\eq a, b
+ it ':get errors', ->
+ assert.has.error -> bool\get 'hello'
+ assert.has.error -> bool\get 2
+ assert.has.error -> bool\get!
+
describe 'Array', ->
vec3 = Array 3, num
str32 = Array 2, Array 3, str
@@ -69,6 +74,18 @@ describe 'Array', ->
assert.is.false str32\eq { {'a', 'b', 'c'}, {'d', 'e', 'f'} },
{ {'a', 'b', 'c'}, {'d', 'e', 'g'} }
+ it ':get verifies size range', ->
+ assert.has.error -> vec3\get -1
+ assert.is.equal num, vec3\get 0
+ assert.is.equal num, vec3\get 1
+ assert.is.equal num, vec3\get 2
+ assert.has.error -> vec3\get 3
+
+ assert.is.equal (Array 3, str), str32\get 1
+
+ assert.has.error -> vec3\get!
+ assert.has.error -> vec3\get 'fail'
+
describe 'Struct', ->
play = Struct { note: str, dur: num }
abc = Struct { c: num, b: num, a: num }
@@ -98,6 +115,13 @@ describe 'Struct', ->
assert.is.true play\eq { dur: 0.5, note: c }, { dur: 0.5, note: c }
assert.is.false play\eq { dur: 0.5, note: c }, { dur: 0.5, note: {} }
+ it ':get verifies key exists', ->
+ assert.is.equal str, play\get 'note'
+ assert.is.equal num, play\get 'dur'
+ assert.has.error -> play\get!
+ assert.has.error -> play\get ''
+ assert.has.error -> play\get 'something'
+
describe 'T', ->
it 'provides shorthand for Primitives', ->
assert.is.equal num, T.num