aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-08-21 11:54:42 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:24:49 +0000
commitf9a0ea48bf5be4fb6963e174317bd117914f10ef (patch)
treeaab5341beb75ae42bbd4df3bb5cc054a11d23735
parentmove array ops into library, implement concat and size (diff)
downloadalive-f9a0ea48bf5be4fb6963e174317bd117914f10ef.tar.gz
alive-f9a0ea48bf5be4fb6963e174317bd117914f10ef.zip
move struct ops into library
-rw-r--r--alv-lib/array.moon32
-rw-r--r--alv-lib/struct.moon125
-rw-r--r--alv/builtins.moon175
-rw-r--r--spec/lang/struct_spec.moon2
-rw-r--r--spec/test_setup.moon2
5 files changed, 144 insertions, 192 deletions
diff --git a/alv-lib/array.moon b/alv-lib/array.moon
index 94499bc..cb83334 100644
--- a/alv-lib/array.moon
+++ b/alv-lib/array.moon
@@ -1,16 +1,18 @@
import Array, Op, PureOp, Constant, Error, const, sig, evt from require 'alv.base'
+any = sig! / evt!
+
get = Constant.meta
meta:
name: 'get'
- summary: "Index into Arrays."
+ summary: "Index into an array."
examples: { '(get array i)' }
description: "Get the value at index `i` (starting at 0).
`i` has to be a constant expression."
value: class extends PureOp
- pattern: (sig! / evt!) + const.num
+ pattern: any + const.num
type: (inputs) =>
{ array, i } = inputs
array\type!\get i.result!
@@ -22,7 +24,7 @@ get = Constant.meta
set = Constant.meta
meta:
name: 'set'
- summary: "Update values in Arrays."
+ summary: "Update a value in an array."
examples: { '(set array i val)' }
description: "Set the value for `i` to `val`.
@@ -30,7 +32,7 @@ set = Constant.meta
`array` and `val` may be a !-stream."
value: class extends PureOp
- pattern: (sig! / evt!) + const.num + (sig! / evt!)
+ pattern: any + const.num + any
type: (inputs) =>
{ array, i, val } = inputs
type = array\type!
@@ -58,7 +60,7 @@ head = Constant.meta
examples: { '(head array)' }
value: class extends PureOp
- pattern: (sig! / evt!)*1
+ pattern: any*1
type: (inputs) =>
type = inputs[1]\type!
@@ -78,7 +80,7 @@ tail = Constant.meta
examples: { '(tail array)' }
value: class extends PureOp
- pattern: (sig! / evt!)*1
+ pattern: any*1
type: (inputs) =>
type = inputs[1]\type!
@@ -94,14 +96,14 @@ tail = Constant.meta
prepend = Constant.meta
meta:
name: 'prepend'
- summary: "Prepend a new value at the start of an Array."
+ summary: "Prepend a new value at the start of an array."
examples: { '(prepend array val)' }
description: "Prepend `val` to `array` at index `0`, moving other values back.
This is a pure op, so at most one of `array` and `val` may be a !-stream."
value: class extends PureOp
- pattern: (sig! / evt!) + (sig! / evt!)
+ pattern: any + any
type: (inputs) =>
{ array, val } = inputs
type = array\type!
@@ -124,7 +126,7 @@ This is a pure op, so at most one of `array` and `val` may be a !-stream."
insert = Constant.meta
meta:
name: 'insert'
- summary: "Insert new values into Arrays."
+ summary: "Insert a new value into an array."
examples: { '(insert array i val)' }
description: "Insert `val` into `array` at `i`, moving other values back if
necessary.
@@ -133,7 +135,7 @@ necessary.
`array` and `val` may be a !-stream."
value: class extends PureOp
- pattern: (sig! / evt!) + const.num + (sig! / evt!)
+ pattern: any + const.num + any
type: (inputs) =>
{ array, i, val } = inputs
type = array\type!
@@ -159,14 +161,14 @@ necessary.
remove = Constant.meta
meta:
name: 'remove'
- summary: "Remove values from Arrays."
+ summary: "Remove a value from an Array."
examples: { '(remove array i)' }
description: "Removes the value at index `i` from `array`.
`i` has to be a constant expression."
value: class extends PureOp
- pattern: (sig! / evt!) + const.num
+ pattern: any + const.num
type: (inputs) =>
{ array, i } = inputs
type = array\type!
@@ -187,7 +189,7 @@ remove = Constant.meta
size = Constant.meta
meta:
name: 'size'
- summary: "Get Array size"
+ summary: "Get the size of an array."
examples: { '(size array)' }
value: class extends Op
@@ -203,11 +205,11 @@ size = Constant.meta
concat = Constant.meta
meta:
name: 'concat'
- summary: "Concatenate Arrays"
+ summary: "Concatenate Arrays."
examples: { '(concat arr1 arr2 [arr3…])' }
value: class extends PureOp
- pattern: (sig! / evt!)\rep 2
+ pattern: any\rep 2
type: (inputs) =>
size = 0
type = inputs[1]\type!.type
diff --git a/alv-lib/struct.moon b/alv-lib/struct.moon
new file mode 100644
index 0000000..74e23f4
--- /dev/null
+++ b/alv-lib/struct.moon
@@ -0,0 +1,125 @@
+import Struct, Op, PureOp, Constant, Error, const, sig, evt from require 'alv.base'
+
+any = sig! / evt!
+key_type = const.str / const.sym
+
+get = Constant.meta
+ meta:
+ name: 'get'
+ summary: "Index into a struct."
+ examples: { '(get struct key)' }
+ description: "Get the value at `key`.
+
+`key` has to be a constant expression."
+
+ value: class extends PureOp
+ pattern: any + key_type
+ type: (inputs) =>
+ { struct, key } = inputs
+ struct\type!\get key.result!
+
+ tick: =>
+ { struct, key } = @unwrap_all!
+ @out\set struct[key]
+
+set = Constant.meta
+ meta:
+ name: 'set'
+ summary: "Update values in a struct."
+ examples: { '(set struct key val)' }
+ description: "Set the value for `key` to `val`.
+
+`key` has to be a constant expression. This is a pure op, so at most one of
+`struct` and `val` may be a !-stream."
+
+ value: class extends PureOp
+ pattern: any + key_type + any
+ type: (inputs) =>
+ { struct, key, val } = inputs
+ type = struct\type!
+ expected = type\get key.result!
+
+ if expected ~= val\type!
+ msg = string.format "expected value for key '%s' to be %s, not %s",
+ key.result!, expected, val\type!
+ error Error 'argument', msg
+
+ type
+
+ tick: =>
+ { struct, key, val } = @unwrap_all!
+
+ struct = {k,v for k,v in pairs struct}
+ struct[key] = val
+
+ @out\set struct
+
+insert = Constant.meta
+ meta:
+ name: 'insert'
+ summary: "Insert a new value into a struct."
+ examples: { '(insert struct key val)' }
+ description: "Insert `val` into `struct` at `key`.
+
+`key` has to be a constant expression. This is a pure op, so at most one of
+`struct` and `val` may be a !-stream."
+
+ value: class extends PureOp
+ pattern: any + key_type + any
+ type: (inputs) =>
+ { struct, key, val } = inputs
+ type = struct\type!
+ key = key.result!
+
+ if type.types[key]
+ msg = string.format "key '%s' already exists in value of type %s",
+ key, type
+ error Error 'argument', msg
+
+ types = {k,v for k,v in pairs type.types}
+ types[key] = val\type!
+ Struct types
+
+ tick: =>
+ { struct, key, val } = @unwrap_all!
+
+ struct = {k,v for k,v in pairs struct}
+ struct[key] = val
+
+ @out\set struct
+
+remove = Constant.meta
+ meta:
+ name: 'remove'
+ summary: "Remove values from a struct."
+ examples: { '(remove struct key)' }
+ description: "Removes the value at index `key` from `struct`.
+
+`key` has to be a constant expression."
+
+ value: class extends PureOp
+ pattern: any + key_type
+ type: (inputs) =>
+ { struct, key } = inputs
+ type = struct\type!
+ key = key.result!
+
+ -- check key exists
+ type\get key
+
+ types = {k,v for k,v in pairs type.types}
+ types[key] = nil
+ Struct types
+
+ tick: =>
+ { struct, key, val } = @unwrap_all!
+
+ struct = {k,v for k,v in pairs struct}
+ struct[key] = nil
+
+ @out\set struct
+
+{
+ :get, :set
+ :insert, :remove
+}
diff --git a/alv/builtins.moon b/alv/builtins.moon
index 1436962..a0a319a 100644
--- a/alv/builtins.moon
+++ b/alv/builtins.moon
@@ -507,180 +507,6 @@ This is a pure op, so at most one !-stream input is allowed."
pairs = @unwrap_all!
@out\set {key, val for {:key, :val} in *pairs}
-get = Constant.meta
- meta:
- name: 'get'
- summary: "Index into Arrays and Structs."
- examples: { '(get array [key])', '(get struct key [key2…])' }
- description: "Get the value for `key`.
-
-For arrays, `key` can be omitted to peek at the last element in the array.
-If multiple keys are specified, they are used to recursively index, i.e.
-
- (get struct 'a' 0 'note')
-
-is equivalent to
-
- (get (get (get struct 'a') 0) 'note')
-"
-
- value: class extends Op
- pattern = (sig! / evt!) + (const.str / const.sym / const.num)^0
- setup: (inputs) =>
- { val, keys } = pattern\match inputs
- super val: Input.hot val
-
- val_type = @inputs.val\type!
-
- if #keys > 0
- @state = [key.result! for key in *keys]
- elseif val_type.__class == Array
- assert val_type.size > 0, Error 'argument', "cannot (get) from empty Array"
- @state = { val_type.size - 1 }
- else
- error Error 'argument', "missing key"
-
- type = val\type!
- for key in *@state
- type = type\get key
-
- if val\metatype == '!'
- @out = type\mk_evt!
- else
- @out = type\mk_sig!
-
- tick: =>
- val = @inputs.val!
- for key in *@state
- if type(key) == 'number'
- key = key + 1
- val = val[key]
- @out\set val
-
-set = Constant.meta
- meta:
- name: 'set'
- summary: "Update values in Arrays and Structs."
- examples: { '(set array key val)', '(set struct key val)' }
- description: "Set the value for `key` to `val`.
-
-`key` has to be a constant expression. This is a pure op, so at most one of
-`array`/`struct` and `val` may be a !-stream."
-
- value: class extends PureOp
- pattern: (sig! / evt!) + (const.str / const.sym / const.num) + (sig! / evt!)
- type: (inputs) => inputs[1]\type!
-
- setup: (...) =>
- super ...
-
- { comp, key, val } = @inputs
-
- expected_val_typ = comp\type!\get key!
- got_val_typ = val\type!
- if expected_val_typ ~= got_val_typ
- msg = string.format "expected value for key '%s' to be %s, not %s",
- key!, expected_val_typ, got_val_typ
- error Error 'argument', msg
-
- tick: =>
- { comp, key, val } = @unwrap_all!
-
- if type(key) == 'number'
- key = key + 1
-
- comp = {k,v for k,v in pairs comp}
- comp[key] = val
-
- @out\set comp
-
-insert = Constant.meta
- meta:
- name: 'insert'
- summary: "Insert new values into Arrays and Structs."
- examples: { '(insert array key val)', '(insert struct key val)' }
- description: "Insert `val` into `array`/`struct` at `key`.
-
-`key` has to be a constant expression. This is a pure op, so at most one of
-`array`/`struct` and `val` may be a !-stream."
-
- value: class extends PureOp
- pattern: (sig! / evt!) + (const.str / const.sym / const.num) + (sig! / evt!)
- type: (inputs) =>
- { comp, key, val } = inputs
- before = comp\type!
-
- if before.__class == Array
- Array before.size + 1, before.type
- else
- types = {k,v for k,v in pairs before.types}
- types[key\const!!] = val\type!
- Struct types
-
- setup: (...) =>
- super ...
-
- { comp, key, val } = @inputs
- before = comp\type!
- key = key!
- if before.__class == Array and (key > before.size or key < 0)
- error Error 'argument', "index '#{key}' out of range!"
- else if before.__class == Struct and before.types[key]
- msg = string.format "key '%s' already exists in value of type %s",
- key, before
- error Error 'argument', msg
-
- tick: =>
- { comp, key, val } = @unwrap_all!
- comp = {k,v for k,v in pairs comp}
-
- if type(key) == 'number'
- table.insert comp, key + 1, val
- else
- comp[key] = val
-
- @out\set comp
-
-remove = Constant.meta
- meta:
- name: 'remove'
- summary: "Remove values from Arrays and Structs."
- examples: { '(remove array key)', '(remove struct key)' }
- description: "Remvoes the value for `key` from `array`/`struct`.
-
-`key` has to be a constant expression."
-
- value: class extends PureOp
- pattern: (sig! / evt!) + (const.str / const.sym / const.num)
- type: (inputs) =>
- { comp, key } = inputs
- before = comp\type!
-
- if before.__class == Array
- Array before.size - 1, before.type
- else
- types = {k,v for k,v in pairs before.types}
- types[key\const!!] = nil
- Struct types
-
- setup: (...) =>
- super ...
-
- { comp, key } = @inputs
- comp\type!\get key!
-
- tick: =>
- { comp, key, val } = @unwrap_all!
- comp = {k,v for k,v in pairs comp}
-
- if type(key) == 'number'
- table.remove comp, key + 1, val
- else
- comp[key] = nil
-
- @out\set comp
-
-
loop = Constant.meta
meta:
name: 'loop'
@@ -779,7 +605,6 @@ Scope.from_table {
'!': to_evt
:array, :struct
- :get, :set, :insert, :remove
:loop, :recur
diff --git a/spec/lang/struct_spec.moon b/spec/lang/struct_spec.moon
index 9d2286e..d0af6bc 100644
--- a/spec/lang/struct_spec.moon
+++ b/spec/lang/struct_spec.moon
@@ -2,7 +2,7 @@ import TestPilot from require 'spec.test_setup'
import T, Struct, Constant from require 'alv'
describe "struct", ->
- test = TestPilot ''
+ test = TestPilot '', '(import* struct)\n'
ab = Struct { a: T.num, b: T.bool }
diff --git a/spec/test_setup.moon b/spec/test_setup.moon
index 92756a8..16a3639 100644
--- a/spec/test_setup.moon
+++ b/spec/test_setup.moon
@@ -15,7 +15,7 @@ os.time = do
export COPILOT
class TestPilot extends Copilot
- new: (code, @preamble) =>
+ new: (code, @preamble='') =>
super!
COPILOT = @