local cosmo = require"cosmo" local grammar = require"cosmo.grammar" values = { rank="Ace", suit="Spades" } template = "$rank of $suit" result = cosmo.fill(template, values) assert(result== "Ace of Spades") mycards = { {rank="Ace", suit="Spades"}, {rank="Queen", suit="Diamonds"}, {rank="10", suit="Hearts"} } template = "$do_cards[[$rank of $suit, ]]" result = cosmo.fill(template, {do_cards = mycards}) assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, ") result= cosmo.f(template){do_cards = mycards} assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, ") mycards = { {"Ace", "Spades"}, {"Queen", "Diamonds"}, {"10", "Hearts"} } result = cosmo.f(template){ do_cards = function() for i,v in ipairs(mycards) do cosmo.yield{rank=v[1], suit=v[2]} end end } assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, ") table.insert(mycards, {"2", "Clubs"}) template = "You have: $do_cards[[$rank of $suit]],[[, $rank of $suit]],[[, and $rank of $suit]]" result = cosmo.f(template){ do_cards = function() for i,v in ipairs(mycards) do local template if i == #mycards then -- for the last item use the third template (with "and") template = 3 elseif i~=1 then -- use the second template for items 2...n-1 template = 2 end cosmo.yield{rank=v[1], suit=v[2], _template=template} end end } assert(result=="You have: Ace of Spades, Queen of Diamonds, 10 of Hearts, and 2 of Clubs") template = "$do_cards[[$1 of $2]]" result= cosmo.f(template){do_cards = cosmo.make_concat(mycards)} assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, 2 of Clubs") template = "$concat{cards}[[$1 of $2]]" result= cosmo.f(template){cards = mycards, concat = cosmo.concat} assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, 2 of Clubs") result= cosmo.f(template){cards = mycards, concat = cosmo.concat} assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, 2 of Clubs") template = "$do_cards[[$it]]" result= cosmo.f(template){do_cards = cosmo.make_concat{ "Ace of Spades", "Queen of Diamonds", "10 of Hearts" } } assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts") result= cosmo.f(template){do_cards = cosmo.make_concat{ "Ace of Spades", "Queen of Diamonds", "10 of Hearts" } } assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts") template = "$do_cards[[$it]]" result= cosmo.f(template){do_cards = cosmo.make_concat{ "Ace of Spades" } } assert(result=="Ace of Spades") result= cosmo.f(template){do_cards = cosmo.make_concat{ "Ace of Spades" } } assert(result=="Ace of Spades") template = "$concat{cards}[[$it]]" result= cosmo.f(template){ cards = { "Ace of Spades", "Queen of Diamonds", "10 of Hearts" }, concat = cosmo.concat } assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts") result= cosmo.f(template){ cards = { "Ace of Spades", "Queen of Diamonds", "10 of Hearts" }, concat = cosmo.concat } assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts") template = "$concat{cards}[[$1 of $2]]" result= cosmo.f(template){cards = mycards, concat = cosmo.concat} assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, 2 of Clubs") result= cosmo.f(template){cards = mycards, concat = cosmo.concat} assert(result=="Ace of Spades, Queen of Diamonds, 10 of Hearts, 2 of Clubs") template = "$do_cards{'; '}[[$1 of $2]]" result= cosmo.f(template){do_cards = cosmo.make_concat(mycards)} assert(result=="Ace of Spades; Queen of Diamonds; 10 of Hearts; 2 of Clubs") result= cosmo.f(template){do_cards = cosmo.make_concat(mycards)} assert(result=="Ace of Spades; Queen of Diamonds; 10 of Hearts; 2 of Clubs") template = "$concat{cards, '; '}[[$1 of $2]]" result= cosmo.f(template){cards = mycards, concat = cosmo.concat} assert(result=="Ace of Spades; Queen of Diamonds; 10 of Hearts; 2 of Clubs") result= cosmo.f(template){cards = mycards, concat = cosmo.concat} assert(result=="Ace of Spades; Queen of Diamonds; 10 of Hearts; 2 of Clubs") template = [====[You have: $do_cards[[$rank of $suit]], [[, $rank of $suit]], [[, and $rank of $suit]]]====] result = cosmo.f(template){ do_cards = function() for i,v in ipairs(mycards) do local template if i == #mycards then -- for the last item use the third template (with "and") template = 3 elseif i~=1 then -- use the second template for items 2...n-1 template = 2 end cosmo.yield{rank=v[1], suit=v[2], _template=template} end end } assert(result=="You have: Ace of Spades, Queen of Diamonds, 10 of Hearts, and 2 of Clubs") players = {"John", "João"} cards = {} cards["John"] = mycards cards["João"] = { {"Ace", "Diamonds"} } template = "$do_players[=[$player has $do_cards[[$rank of $suit]],[[, $rank of $suit]],[[, and $rank of $suit]]\n]=]" result = cosmo.f(template){ do_players = function() for i,p in ipairs(players) do cosmo.yield { player = p, do_cards = function() for i,v in ipairs(cards[p]) do local template if i == #mycards then -- for the last item use the third template (with "and") template = 3 elseif i~=1 then -- use the second template for items 2...n-1 template = 2 end cosmo.yield{rank=v[1], suit=v[2], _template=template} end end } end end } assert(result=="John has Ace of Spades, Queen of Diamonds, 10 of Hearts, and 2 of Clubs\nJoão has Ace of Diamonds\n") players = {"John", "João"} cards = {} cards["John"] = mycards cards["João"] = { {"Ace", "Diamonds"} } template = "$do_players[[$player has $do_cards[[$rank of $suit]],[=[, $rank of $suit]=],[[, and $rank of $suit]]\n]]" result = cosmo.f(template){ do_players = function() for i,p in ipairs(players) do cosmo.yield { player = p, do_cards = function() for i,v in ipairs(cards[p]) do local template if i == #mycards then -- for the last item use the third template (with "and") template = 3 elseif i~=1 then -- use the second template for items 2...n-1 template = 2 end cosmo.yield{rank=v[1], suit=v[2], _template=template} end end } end end } assert(result=="John has Ace of Spades, Queen of Diamonds, 10 of Hearts, and 2 of Clubs\nJoão has Ace of Diamonds\n") template = "$do_players[=[$player$if_john[[$mark]] has $do_cards[[$rank of $suit, ]]\n]=]" result = cosmo.f(template){ do_players = function() for i,p in ipairs(players) do cosmo.yield { player = p, do_cards = function() for i,v in ipairs(cards[p]) do cosmo.yield{rank=v[1], suit=v[2]} end end, if_john = cosmo.c(p=="John"){mark="*"} } end end } assert(result=="John* has Ace of Spades, Queen of Diamonds, 10 of Hearts, 2 of Clubs, \nJoão has Ace of Diamonds, \n") template = "$do_players[=[$do_cards[[$rank of $suit ($player), ]]]=]" result = cosmo.f(template){ do_players = function() for i,p in ipairs(players) do cosmo.yield { player = p, do_cards = function() for i,v in ipairs(cards[p]) do cosmo.yield{rank=v[1], suit=v[2]} end end, } end end } assert(result=="Ace of Spades (John), Queen of Diamonds (John), 10 of Hearts (John), 2 of Clubs (John), Ace of Diamonds (João), ") template = "$do_players[=[$player: $n card$if_plural[[s]] $if_needs_more[[(needs $n more)]]\n]=]" result = cosmo.f(template){ do_players = function() for i,p in ipairs(players) do cosmo.yield { player = p, n = #cards[p], if_plural = cosmo.cond(#cards[p] > 1, {}), if_needs_more = cosmo.cond(#cards[p] < 3, { n = 3-#cards[p] }) } end end } assert(result=="John: 4 cards \nJoão: 1 card (needs 2 more)\n") result = cosmo.f(template){ do_players = function() for i,p in ipairs(players) do cosmo.yield { player = p, n = #cards[p], if_plural = cosmo.c(#cards[p] > 1){}, if_needs_more = cosmo.c(#cards[p] < 3){ n = 3-#cards[p] } } end end } assert(result=="John: 4 cards \nJoão: 1 card (needs 2 more)\n") template = " $foo|bar $foo|1|baz " result = cosmo.fill(template, { foo = { { baz = "World!" }, bar = "Hello" } }) assert(result==" Hello World! ") template = " $(foo.bar) $(foo[1].baz) " result = cosmo.fill(template, { foo = { { baz = "World!" }, bar = "Hello" } }) assert(result==" Hello World! ") template = " $[foo.bar] $[foo[1].baz] " result = cosmo.fill(template, { foo = { { baz = "World!" }, bar = "Hello" } }, { parser = grammar.new("[", "]") }) assert(result==" Hello World! ") template = " $(foo.bar) $(foo[1].baz) " result = cosmo.fill(template, { foo = { { baz = "World!" }, bar = "Hello" } }) assert(result==" Hello World! ") template = " Hello $message{ 'World!' } " result = cosmo.fill(template, { message = function (arg) return arg[1] end }) assert(result==" Hello World! ") template = " Hello $(message){ 'World!' } " result = cosmo.fill(template, { message = function (arg) return arg[1] end }) assert(result==" Hello World! ") template = " Hello $(message){ 'World!' } " result = cosmo.fill(template, { message = function (arg) return arg[1] end }) assert(result==" Hello World! ") template = " Hello $message{ $msg } " result = cosmo.fill(template, { msg = "World!", message = function (arg) return arg[1] end }) assert(result==" Hello World! ") template = " Hello $message{ $(msg) } " result = cosmo.fill(template, { msg = "World!", message = function (arg) return arg[1] end }) assert(result==" Hello World! ") template = " Hello $message{ $(msg) } " result = cosmo.fill(template, { msg = "World!", message = function (arg) return arg[1] end }) assert(result==" Hello World! ") template = " Hello $message{ $msg }[[$it]] " result = cosmo.fill(template, { msg = "World!", message = function (arg) cosmo.yield{ it = arg[1] } end }) assert(result==" Hello World! ") template = " $foo|bar $foo|1|baz " result = cosmo.f(template){ foo = { { baz = "World!" }, bar = "Hello" } } assert(result==" Hello World! ") template = " Hello $message{ 'World!' } " result = cosmo.f(template){ message = function (arg) return arg[1] end } assert(result==" Hello World! ") template = " Hello $message{ $msg } " result = cosmo.f(template){ msg = "World!", message = function (arg) return arg[1] end } assert(result==" Hello World! ") template = " Hello $message{ $msg }[[$it]] " result = cosmo.f(template){ msg = "World!", message = function (arg) cosmo.yield{ it = arg[1] } end } assert(result==" Hello World! ") template = " Hello $message{ $msg } " result = cosmo.f(template){ msg = "World!", message = function (arg, has_block) if has_block then cosmo.yield{ it = arg[1] } else return arg[1] end end } assert(result==" Hello World! ") template = " Hello $message{ $msg }[[$it]] " result = cosmo.f(template){ msg = "World!", message = function (arg, has_block) if has_block then cosmo.yield{ it = arg[1] } else return arg[1] end end } assert(result==" Hello World! ") template = " Hello $message{ $msg } " result = cosmo.fill(template, { msg = "World!", message = function (arg, has_block) if has_block then cosmo.yield{ it = arg[1] } else return arg[1] end end }) assert(result==" Hello World! ") template = " Hello $message{ msg } " result = cosmo.fill(template, { msg = "World!", message = function (arg, has_block) if has_block then cosmo.yield{ it = arg[1] } else return arg[1] end end }) assert(result==" Hello World! ") template = " Hello $message{ msg } " result = cosmo.fill(template, { msg = "World!", message = function (arg, has_block) if has_block then cosmo.yield{ it = arg[1] } else return arg[1] end end }) assert(result==" Hello World! ") template = " Hello $message{ $msg }[[$it]] " result = cosmo.fill(template, { msg = "World!", message = function (arg, has_block) if has_block then cosmo.yield{ it = arg[1] } else return arg[1] end end }) assert(result==" Hello World! ") template = " $message{ greeting = 'Hello', target = 'World' } " result = cosmo.fill(template, { message = function(arg, has_block) if has_block then cosmo.yield{ grt = arg.greeting, tgt = arg.target } else return arg.greeting .. " " .. arg.target .. "!" end end }) assert(result==" Hello World! ") template = " $message{ greeting = 'Hello', target = 'World' } " result = cosmo.f(template){ message = function(arg, has_block) if has_block then cosmo.yield{ grt = arg.greeting, tgt = arg.target } else return arg.greeting .. " " .. arg.target .. "!" end end } assert(result==" Hello World! ") template = " $message{ greeting = 'Hello', target = 'World' }[[$grt $tgt]] " result = cosmo.fill(template, { message = function(arg, has_block) if has_block then cosmo.yield{ grt = arg.greeting, tgt = arg.target } else return arg.greeting .. " " .. arg.target .. "!" end end }) assert(result==" Hello World ") template = " $message{ greeting = 'Hello', target = 'World'}[[$grt $tgt]] " result = cosmo.f(template){ message = function(arg, has_block) if has_block then cosmo.yield{ grt = arg.greeting, tgt = arg.target } else return arg.greeting .. " " .. arg.target .. "!" end end } assert(result==" Hello World ") local env = {} setmetatable(env, { __index = { text = "Hello World!" } }) template = " $show[[$text]] " result = cosmo.fill(template, { show = function () cosmo.yield(env) end }) assert(result == " Hello World! ") result = cosmo.f(template){ show = function () cosmo.yield(env) end } assert(result == " Hello World! ") template = " $map{ 1, 2, 3, 4, 5}[[$it]] " result = cosmo.fill(template, { map = cosmo.map }) assert(result == " 12345 ") result = cosmo.f(template){ map = cosmo.map } assert(result == " 12345 ") template = " $map{ 1, [[foo]], 3, 4, 5}[[$it]] " result = cosmo.fill(template, { map = cosmo.map }) assert(result == " 1foo345 ") result = cosmo.f(template){ map = cosmo.map } assert(result == " 1foo345 ") template = " $map{ 1, 2, 3, 4, 5} " result = cosmo.fill(template, { map = cosmo.map }) assert(result == " 12345 ") result = cosmo.f(template){ map = cosmo.map } assert(result == " 12345 ") template = "$inject{ msg = 'Hello', target = 'World' }[[ $msg $target! ]]" result = cosmo.fill(template, { inject = cosmo.inject }) assert(result == " Hello World! ") result = cosmo.f(template){ inject = cosmo.inject } assert(result == " Hello World! ") template = "$if{ $x + 3 > 4, target = 'World' }[[ Hello $target! ]],[[ Hi $target! ]]" result = cosmo.fill(template, { x = 0, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ x = 0, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { x = 2, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ x = 2, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ $x + 3 > 4, target = 'World' }[[ Hello $target! ]]" result = cosmo.fill(template, { x = 0, ["if"] = cosmo.cif }) assert(result == "") result = cosmo.f(template){ x = 0, ["if"] = cosmo.cif } assert(result == "") result = cosmo.fill(template, { x = 2, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ x = 2, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ $x + 3 > 4, target = 'World' }[[ Hello $target! ]][[ Hi $target! ]]" result = cosmo.fill(template, { x = 0, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ x = 0, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { x = 2, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ x = 2, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ $x + 3 > 4, target = 'World' }[[ Hello $target! ]][[ Hi $target! ]]" result = cosmo.fill(template, { x = 0, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ x = 0, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { x = 2, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ x = 2, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ x + 3 > 4, target = 'World' }[[ Hello $target! ]],[[ Hi $target! ]]" result = cosmo.fill(template, { x = 0, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ x = 0, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { x = 2, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ x = 2, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ $mod($x, 4) == 0, target = 'World' }[[ Hello $target! ]],[[ Hi $target! ]]" result = cosmo.fill(template, { mod = math.fmod, x = 2, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ mod = math.fmod, x = 2, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { mod = math.fmod, x = 4, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ mod = math.fmod, x = 4, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ math.fmod(x, 4) == 0, target = 'World' }[[ Hello $target! ]],[[ Hi $target! ]]" result = cosmo.fill(template, { math = math, x = 2, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ math = math, x = 2, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { math = math, x = 4, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ math = math, x = 4, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ x == 0, target = 'World' }[[ Hello $target! ]],[[ Hi $target! ]]" result = cosmo.fill(template, { math = math, x = 4, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ math = math, x = 4, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { math = math, x = 0, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ math = math, x = 0, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$if{ x(), target = 'World' }[[ Hello $target! ]],[[ Hi $target! ]]" result = cosmo.fill(template, { math = math, x = function () return false end, ["if"] = cosmo.cif }) assert(result == " Hi World! ") result = cosmo.f(template){ math = math, x = function () return false end, ["if"] = cosmo.cif } assert(result == " Hi World! ") result = cosmo.fill(template, { math = math, x = function () return true end, ["if"] = cosmo.cif }) assert(result == " Hello World! ") result = cosmo.f(template){ math = math, x = function () return true end, ["if"] = cosmo.cif } assert(result == " Hello World! ") template = "$lit[[ $msg]]" result = cosmo.fill(template, { lit = function () cosmo.yield("Hello", true) cosmo.yield({ msg = "World" }) cosmo.yield("!", true) end }) assert(result == "Hello World!") result = cosmo.fill(template, { lit = function () cosmo.yield("Hello", true) cosmo.yield({ msg = "World" }) cosmo.yield("!", true) end }) assert(result == "Hello World!") template = "$if{ math.fmod(x, 4) == 0, target = 'World' }[[ Hello $target! ]]" result = cosmo.fill(template, { math = math, x = 2, ["if"] = cosmo.cif }, { fallback = true }) assert(result == " Hello World! ") result = cosmo.f(template)({ math = math, x = 2, ["if"] = cosmo.cif }, { fallback = true }) assert(result == " Hello World! ") template = " $foo " result = cosmo.fill(template, {}) assert(result == " ") result = cosmo.f(template){} assert(result == " ") template = " $bar " result = cosmo.fill(template, {}, { passthrough = true }) assert(result == " $bar ") result = cosmo.f(template)({}, { passthrough = true }) assert(result == " $bar ")