diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-03-10 17:05:34 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-03-10 17:14:29 +0000 |
| commit | 7b75041acdef0a60af408f83bec37aec0127941c (patch) | |
| tree | fe038f92d3619887487dbd9230751c052c7111f5 /spec/core | |
| parent | bugfixes (diff) | |
| download | alive-7b75041acdef0a60af408f83bec37aec0127941c.tar.gz alive-7b75041acdef0a60af408f83bec37aec0127941c.zip | |
add Result spec
Close #10
Diffstat (limited to 'spec/core')
| -rw-r--r-- | spec/core/cell_spec.moon | 64 | ||||
| -rw-r--r-- | spec/core/result_spec.moon | 185 | ||||
| -rw-r--r-- | spec/core/tag_spec.moon | 36 | ||||
| -rw-r--r-- | spec/core/value_spec.moon | 8 |
4 files changed, 263 insertions, 30 deletions
diff --git a/spec/core/cell_spec.moon b/spec/core/cell_spec.moon index 8b6d68b..710b252 100644 --- a/spec/core/cell_spec.moon +++ b/spec/core/cell_spec.moon @@ -1,34 +1,74 @@ import Cell, RootCell from require 'core.cell' -import Value, Scope, Registry, globals from require 'core' +import Value, Scope, Tag, SimpleRegistry, globals from require 'core' import Logger from require 'logger' Logger.init 'silent' -hello_world = Cell nil, { (Value.sym 'hello'), (Value.str 'world') } -two_plus_two = Cell nil, { (Value.sym '+'), (Value.num 2), (Value.num 2) } +hello_world = Cell.parse (Tag.parse '2'), { '', (Value.sym 'hello'), ' ', (Value.str 'world'), '' } +two_plus_two = Cell.parse (Tag.parse '3'), { '', (Value.sym '+'), ' ', (Value.num 2), ' ', (Value.num 2), '' } + +reg = SimpleRegistry! +setup -> reg\grab! +teardown -> reg\release! describe 'Cell', -> - it 'supports quoting', -> + describe 'when quoted', -> with hello_world\quote! - assert.is.equal Cell, .__class - assert.is.equal (Value.sym 'hello'), \head! - assert.is.same { Value.str 'world' }, \tail! + it 'stays equal', -> + assert.is.equal Cell, .__class + assert.is.equal (Value.sym 'hello'), \head! + assert.is.same { Value.str 'world' }, \tail! + + it 'shares the tag', -> + assert.is.equal hello_world.tag, .tag with two_plus_two\quote! - assert.is.equal Cell, .__class - assert.is.equal (Value.sym '+'), \head! - assert.is.same { (Value.num 2), (Value.num 2) }, \tail! + it 'stays equal', -> + assert.is.equal Cell, .__class + assert.is.equal (Value.sym '+'), \head! + assert.is.same { (Value.num 2), (Value.num 2) }, \tail! + + it 'shares the tag', -> + assert.is.equal two_plus_two.tag, .tag + + describe 'when cloned', -> + parent = Tag.blank '1' + with hello_world\clone parent + it 'keeps children', -> + assert.is.equal Cell, .__class + assert.is.equal (Value.sym 'hello'), \head! + assert.is.same { Value.str 'world' }, \tail! + it 'clones the tag', -> + assert.is.equal hello_world.tag, .tag.original + assert.is.equal parent, .tag.parent + + describe 'when evaluated', -> + it 'errors when empty', -> + cell = Cell.parse {''} + assert.has.error -> cell\eval globals + + it 'evaluates its head', -> + head = Value.sym 'trace' + cell = Cell.parse { '', head, ' ', (Value.sym 'true'), '' } + + s = spy.on head, 'eval' + cell\eval globals + assert.spy(s).was_called_with (match.is_ref head), (match.is_ref globals) describe 'RootCell', -> + test 'tag is always [0]', -> + cell = Cell.parse_root {} + assert.is.equal '[0]', cell.tag\stringify! + test 'head is always "do"', -> - cell = Cell\parse_root {} + cell = Cell.parse_root {} assert.is.equal (Value.sym 'do'), cell\head! cell = RootCell nil, { hello_world, two_plus_two } assert.is.equal (Value.sym 'do'), cell\head! test 'tail is all children', -> - cell = Cell\parse_root {} + cell = Cell.parse_root {} assert.is.same {}, cell\tail! cell = RootCell nil, { hello_world, two_plus_two } diff --git a/spec/core/result_spec.moon b/spec/core/result_spec.moon new file mode 100644 index 0000000..cc7cd71 --- /dev/null +++ b/spec/core/result_spec.moon @@ -0,0 +1,185 @@ +import Result, Value, Scope, SimpleRegistry from require 'core' +import Input, Op, IO from require 'core.base' +import Logger from require 'logger' +Logger.init 'silent' + +op_with_inputs = (inputs) -> + with Op! + \setup inputs if inputs + +result_with_sideinput = (value, input) -> + with Result :value + .side_inputs = { [value]: input } + +reg = SimpleRegistry! +setup -> reg\grab! +teardown -> reg\release! + +class DirtyIO extends IO + tick: => + dirty: => true + +describe 'Result', -> + it 'wraps value, children', -> + value = Value.num 3 + + a = Result! + b = Result! + children = { a, b } + + result = Result :value, :children + + assert.is.equal value, result.value + assert.is.same children, result.children + + it ':type gets type and assets value', -> + result = Result value: Value.num 2 + assert.is.equal 'num', result\type! + + result = Result! + assert.has.error -> result\type! + + it ':is_const', -> + value = Value.num 2 + pure = Result :value + impure = result_with_sideinput value, {} + + assert.is.true pure\is_const! + assert.is.false impure\is_const! + + assert.is.equal value, pure\const! + assert.has.error -> impure\const! + assert.has.error (-> impure\const 'test'), 'test' + + it ':make_ref', -> + value = Value.num 2 + input = Input.value value + op = op_with_inputs { input } + thick = Result :value, :op, children: { Result!, Result! } + ref = thick\make_ref! + + assert ref + assert.is.equal thick.value, ref.value + assert.is.same thick.side_inputs, ref.side_inputs + assert.is.same {}, ref.children + assert.is.nil ref.op + + it 'lifts up inputs from op', -> + event = Value 'bang', false + event_input = Input.event event + + value = Value 'num', 4 + value_input = Input.value value + + op = op_with_inputs { event_input, value_input } + result = Result op: op, :value + + assert.is.equal op, result.op + assert.is.same { [event]: event_input, [value]: value_input }, + result.side_inputs + + it 'does not lift up op inputs that are also child values', -> + event = Value 'bang', false + event_input = Input.event event + + value = Value 'num', 4 + value_input = Input.value value + + op = op_with_inputs { event_input, value_input } + result = Result op: op, :value, children: { Result :value } + + assert.is.same { [event]: event_input }, result.side_inputs + + it 'lifts up side_inputs from children', -> + event_value = Value 'bang', false + event_input = Input.event event_value + event = Result op: op_with_inputs { event_input } + assert.is.same { [event_value]: event_input }, event.side_inputs + + value_value = Value 'num', 4 + value_input = Input.value value_value + value = Result op: op_with_inputs { value_input } + assert.is.same { [value_value]: value_input }, value.side_inputs + + result = Result children: { event, value } + assert.is.same { [event_value]: event_input, [value_value]: value_input }, + result.side_inputs + + describe ':tick', -> + local a_value, a_child, a_input + local b_value, b_child, b_input + before_each -> + a_value = Value 'num' + a_input = Input.event a_value + a_child = result_with_sideinput a_value, a_input + + b_value = Value 'num' + b_input = Input.event b_value + b_child = result_with_sideinput b_value, b_input + + it 'updates children when a side_input is dirty', -> + a_value\set 1 + assert.is.true a_input\dirty! + assert.is.false b_input\dirty! + + a = spy.on a_child, 'tick' + b = spy.on b_child, 'tick' + + result = Result children: { a_child, b_child } + result\tick! + + assert.spy(a).was_called_with match.ref a_child + assert.spy(b).was_called_with match.ref b_child + + it 'early-outs when no side_inputs are dirty', -> + assert.is.false a_input\dirty! + assert.is.false b_input\dirty! + + a = spy.on a_child, 'tick' + b = spy.on b_child, 'tick' + + result = Result children: { a_child, b_child } + result\tick! + + assert.spy(a).was_not_called! + assert.spy(b).was_not_called! + + it 'updates op when any op-inputs are dirty', -> + a_value\set 1 + assert.is.true a_input\dirty! + assert.is.false b_input\dirty! + + op = op_with_inputs a: Input.event a_value + s = spy.on op, 'tick' + + result = Result :op, children: { a_child, b_child } + result\tick! + + assert.spy(s).was_called_with match.ref op + + it 'early-outs when no op-inputs are dirty', -> + a_value\set 1 + assert.is.true a_input\dirty! + assert.is.false b_input\dirty! + + op = op_with_inputs { Input.event b_value } + s = spy.on op, 'tick' + + result = Result :op, children: { a_child, b_child } + result\tick! + + assert.spy(s).was_not_called! + + describe ':tick_io', -> + it 'ticks IOs referenced in side_inputs', -> + io = DirtyIO! + value = Value 'an_io', io + input = Input.io value + op = op_with_inputs { input } + result = Result :op + + s = spy.on io, 'tick' + assert.is.same { [value]: input }, result.side_inputs + result\tick_io! + + assert.spy(s).was_called_with match.ref io diff --git a/spec/core/tag_spec.moon b/spec/core/tag_spec.moon index 7855fd6..a4491b0 100644 --- a/spec/core/tag_spec.moon +++ b/spec/core/tag_spec.moon @@ -16,14 +16,14 @@ do_reg = (fn) -> describe 'Tag', -> describe 'should be constructable', -> it 'by parsing', -> - tag = Tag\parse '2' + tag = Tag.parse '2' assert tag assert.is.equal 2, tag.value assert.is.equal '[2]', tag\stringify! assert.is.equal '2', tostring tag it 'as blank Tags', -> - tag = Tag\blank! + tag = Tag.blank! assert tag assert.is.nil tag.value assert.is.equal '', tag\stringify! @@ -37,49 +37,49 @@ describe 'Tag', -> assert.has.error tag\stringify it 'from parsed tags', with_reg -> - parent = Tag\parse '1' - original = Tag\parse '2' + parent = Tag.parse '1' + original = Tag.parse '2' tag = original\clone parent do_asserts tag, '1.2' it 'but not from blank tags', with_reg -> - parent = Tag\parse '1' - original = Tag\blank! + parent = Tag.parse '1' + original = Tag.blank! tag = original\clone parent do_asserts tag, '1.?' it 'with blank parent', with_reg -> - parent = Tag\blank! - original = Tag\parse '2' + parent = Tag.blank! + original = Tag.parse '2' tag = original\clone parent do_asserts tag, '?.2' it 'completely blank', with_reg -> - parent = Tag\blank! - original = Tag\blank! + parent = Tag.blank! + original = Tag.blank! tag = original\clone parent do_asserts tag, '?.?' describe 'should be set-able', -> it 'only if blank', with_reg -> - tag = Tag\parse '42' + tag = Tag.parse '42' assert.has.error -> tag\set 43 - clone = tag\clone Tag\parse '3' + clone = tag\clone Tag.parse '3' assert.has.error -> clone\set 42 - clone = tag\clone Tag\blank! + clone = tag\clone Tag.blank! assert.has.error -> clone\set 42 it 'and stores the value', with_reg -> - blank = Tag\blank! + blank = Tag.blank! blank\set 12 assert.is.equal blank.value, 12 it 'sets the original if cloned', with_reg -> - original = Tag\blank! - parent = Tag\parse '7' + original = Tag.blank! + parent = Tag.parse '7' o_set = spy.on original, 'set' p_set = spy.on parent, 'set' @@ -93,8 +93,8 @@ describe 'Tag', -> assert.is.equal original.value, 11 it 'requires the parent to be registered if cloned', with_reg -> - original = Tag\blank! - parent = Tag\blank! + original = Tag.blank! + parent = Tag.blank! clone = original\clone parent assert.has.error -> clone\set 11 diff --git a/spec/core/value_spec.moon b/spec/core/value_spec.moon index 4e56c31..2436371 100644 --- a/spec/core/value_spec.moon +++ b/spec/core/value_spec.moon @@ -122,3 +122,11 @@ describe 'Value', -> assert_noop Value.num 2 assert_noop Value.str 'hello' assert_noop Value.sym 'world' + + describe 'clones literals', -> + test 'as themselves', -> + assert_noop = (val) -> assert.is.equal val, val\clone! + + assert_noop Value.num 2 + assert_noop Value.str 'hello' + assert_noop Value.sym 'world' |
