diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-08-21 11:54:42 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-02 14:24:49 +0000 |
| commit | f9a0ea48bf5be4fb6963e174317bd117914f10ef (patch) | |
| tree | aab5341beb75ae42bbd4df3bb5cc054a11d23735 | |
| parent | move array ops into library, implement concat and size (diff) | |
| download | alive-f9a0ea48bf5be4fb6963e174317bd117914f10ef.tar.gz alive-f9a0ea48bf5be4fb6963e174317bd117914f10ef.zip | |
move struct ops into library
| -rw-r--r-- | alv-lib/array.moon | 32 | ||||
| -rw-r--r-- | alv-lib/struct.moon | 125 | ||||
| -rw-r--r-- | alv/builtins.moon | 175 | ||||
| -rw-r--r-- | spec/lang/struct_spec.moon | 2 | ||||
| -rw-r--r-- | spec/test_setup.moon | 2 |
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 = @ |
