import with_dev from require "spec.helpers" describe "moonscript.transform.destructure", -> local extract_assign_names, split_assign, Block with_dev -> { :extract_assign_names, :split_assign } = require "moonscript.transform.destructure" {:Block} = require "moonscript.compile" describe "split_assign #fff", -> -- {:hello} = world it "simple assignment", -> node = { "assign" { { "table", { {{"key_literal", "hello"}, {"ref", "hello"}} } } } { {"ref", "world"} } } out = split_assign Block!, node assert.same { "group", { { "group", { { "declare", { {"ref", "hello"} } } { "assign", { {"ref", "hello"} }, { {"chain", {"ref", "world"}, {"dot", "hello"}} } } }} }}, out -- {:a, :b} = world! -- a complex value should never be repeated to avoid double execution it "complex value", -> node = { "assign" { { "table", { {{"key_literal", "a"}, {"ref", "a"}} {{"key_literal", "b"}, {"ref", "b"}} } } } { {"chain", {"ref", "world"}, {"call", {}}} } } out = split_assign Block!, node -- the temp name the result is stored into tmp = {"temp_name", prefix: "obj"} assert.same { "group", { { "group", { { "declare", { {"ref", "a"}, {"ref", "b"} } } { "do", { {"assign", { tmp }, { {"chain", {"ref", "world"}, {"call", {}}} } } {"assign", { {"ref", "a"}, {"ref", "b"} }, { {"chain", tmp, {"dot", "a"}}, {"chain", tmp, {"dot", "b"}} } } }} }} }}, out -- a, {:hello} = one, two it "multiple assigns", -> node = { "assign" { {"ref", "a"} { "table", { {{"key_literal", "hello"}, {"ref", "hello"}} } } } { {"ref", "one"} {"ref", "two"} } } out = split_assign Block!, node assert.same { "group", { {"assign", { {"ref", "a"} }, { {"ref", "one"} }} { "group", { { "declare", { {"ref", "hello"} } } { "assign", { {"ref", "hello"} }, { {"chain", {"ref", "two"}, {"dot", "hello"}} } } }} }}, out -- {:hello}, a = one, two it "multiple assigns swapped", -> node = { "assign" { { "table", { {{"key_literal", "hello"}, {"ref", "hello"}} } } {"ref", "a"} } { {"ref", "one"} {"ref", "two"} } } out = split_assign Block!, node assert.same { "group", { { "group", { { "declare", { {"ref", "hello"} } } { "assign", { {"ref", "hello"} }, { {"chain", {"ref", "one"}, {"dot", "hello"}} } } }} {"assign", { {"ref", "a"} }, { {"ref", "two"} }} }}, out it "extracts names from table destructure", -> des = { "table" { {{"key_literal", "hi"}, {"ref", "hi"}} {{"key_literal", "world"}, {"ref", "world"}} } } assert.same { { {"ref", "hi"} -- target { {"dot", "hi"} } -- chain suffix } { {"ref", "world"} { {"dot", "world"} } } }, extract_assign_names des it "extracts names from array destructure", -> des = { "table" { {{"ref", "hi"}} } } assert.same { { {"ref", "hi"} { {"index", {"number", 1}} } } }, extract_assign_names des describe "moonscript.transform.statements", -> local last_stm, transform_last_stm, Run with_dev -> { :last_stm, :transform_last_stm, :Run } = require "moonscript.transform.statements" describe "last_stm", -> it "gets last statement from empty list", -> assert.same nil, (last_stm {}) it "gets last statement", -> stms = { {"ref", "butt_world"} {"ref", "hello_world"} } stm, idx, t = last_stm stms assert stms[2] == stm assert.same 2, idx assert stms == t it "gets last statement ignoring run", -> stms = { {"ref", "butt_world"} {"ref", "hello_world"} Run => print "hi" } stm, idx, t = last_stm stms assert stms[2] == stm assert.same 2, idx assert stms == t it "gets last from within group", -> stms = { {"ref", "butt_world"} {"group", { {"ref", "hello_world"} {"ref", "cool_world"} }} } last = stms[2][2][2] stm, idx, t = last_stm stms assert stm == last, "should get last" assert.same 2, idx assert t == stms[2][2], "should get correct table" describe "transform_last_stm", -> it "transforms empty stms", -> before = {} after = transform_last_stm before, (n) -> {"wrapped", n} assert.same before, after assert before != after it "transforms stms", -> before = { {"ref", "butt_world"} {"ref", "hello_world"} } transformer = (n) -> n after = transform_last_stm before, transformer assert.same { {"ref", "butt_world"} {"transform", {"ref", "hello_world"}, transformer} }, after it "transforms empty stms ignoring runs", -> before = { {"ref", "butt_world"} {"ref", "hello_world"} Run => print "hi" } transformer = (n) -> n after = transform_last_stm before, transformer assert.same { {"ref", "butt_world"} {"transform", {"ref", "hello_world"}, transformer} before[3] }, after