From 33188f943329296ff4c19ad3fcf717194e3b237e Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Sat, 14 Jan 2023 02:29:20 -0400 Subject: Added compilation of definitions for C++. --- lux-c++/commands.md | 4 + lux-c++/source/program.lux | 196 ++++++++++++++++----- lux-js/source/program.lux | 4 +- lux-jvm/source/program.lux | 4 +- .../library/lux/math/arithmetic/fixed_point.lux | 2 +- .../language/lux/phase/translation/c++.lux | 104 +++++++++++ .../language/lux/phase/translation/c++/runtime.lux | 34 +++- .../language/lux/phase/translation/jvm.lux | 64 +++---- .../language/lux/phase/translation/jvm/program.lux | 3 +- .../language/lux/phase/translation/reference.lux | 4 +- .../library/lux/meta/compiler/meta/context.lux | 1 + stdlib/source/library/lux/meta/compiler/target.lux | 1 + .../library/lux/meta/compiler/target/c++.lux | 6 + stdlib/source/test/lux/meta.lux | 127 +++++++------ stdlib/source/test/lux/world/environment.lux | 4 +- 15 files changed, 404 insertions(+), 154 deletions(-) create mode 100644 stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++.lux diff --git a/lux-c++/commands.md b/lux-c++/commands.md index 53ad68455..af26bf44e 100644 --- a/lux-c++/commands.md +++ b/lux-c++/commands.md @@ -37,6 +37,10 @@ cd ~/lux/lux-c++/ \ && conda activate WORK \ && python3 target/program.py +cd ~/lux/lux-c++/ \ +&& conda activate WORK \ +&& python3 target/program.py build --source ~/lux/stdlib/source --target ~/lux/stdlib/target --module test/lux --program _ + ## Compile Lux's Standard Library's tests using a c++/Node-based compiler. cd ~/lux/stdlib/ \ && lux clean \ diff --git a/lux-c++/source/program.lux b/lux-c++/source/program.lux index 67c5fb26d..4d669f5d5 100644 --- a/lux-c++/source/program.lux +++ b/lux-c++/source/program.lux @@ -14,10 +14,12 @@ ["[0]" maybe (.use "[1]#[0]" monad)] ["[0]" try (.only Try)] ["[0]" exception (.only Exception)] - ["[0]" io (.only IO io)]] + ["[0]" io (.only IO io)] + [concurrency + ["[0]" async (.only Async)]]] [data ["[0]" product] - [text + ["[0]" text (.only) ["%" \\format (.only format)] [encoding ["[0]" utf8]]] @@ -30,7 +32,7 @@ ["[0]" i64]]] ["[0]" world ["[0]" file] - ["[1]/[0]" environment]] + ["[0]" environment]] [meta [macro ["^" pattern] @@ -55,7 +57,7 @@ ["[1]" js]]] [translation ["[0]" reference] - [c++ + ["[0]" c++ (.only) ["[0]" runtime] ["[0]" type] ["[0]" primitive] @@ -70,46 +72,158 @@ ["[0]" packager ["[1]" script]]]]]]] [program - ["/" compositor]]) + ["[0]" compositor]]) (import cppyy "[1]::[0]" ("static" cppdef [Text] "io" Bit) ("static" gbl (ffi.Object Any))) -(def standard_out (_.global [_.standard "cout"] (list))) -(def \n (_.global [_.standard "endl"] (list))) - -(def (print it) - (-> _.Expression - _.Statement) - (|> standard_out - (_.<< it) - (_.<< \n) - _.;)) - -(with_expansions [ "say_hello"] - (def _ - (program [] - (do io.monad - [? (cppyy::cppdef [(_.code (all _.then - runtime.declaration - - (_.include "iostream") - (_.function (_.local ) - (list) - (list) - :.void - (all _.then - (print (_.deref (runtime.host_value type.bit (runtime.simple type.bit (primitive.bit true))))) - (print (_.deref (runtime.host_value type.i64 (runtime.simple type.i64 (primitive.i64 +123))))) - (print (_.deref (runtime.host_value type.f64 (runtime.simple type.f64 (primitive.f64 -456.789))))) - ... (print (_.deref (runtime.host_value type.text (runtime.simple type.text (primitive.text "YOLO"))))) - ))))]) - .let [_ (debug.log! (%.format "BEFORE " (%.bit ?)))] - global (cppyy::gbl) - .let [say_hello (as ffi.Function - (.python_object_get# global)) - _ (debug.log! "AFTER") - _ (.python_apply# say_hello [])]] - (in (debug.log! "Hello, C++")))))) +... (def standard_out (_.global [_.standard "cout"] (list))) +... (def \n (_.global [_.standard "endl"] (list))) + +... (def (print it) +... (-> _.Expression +... _.Statement) +... (|> standard_out +... (_.<< it) +... (_.<< \n) +... _.;)) + +... (with_expansions [ "say_hello"] +... (def _ +... (program [] +... (do io.monad +... [? (cppyy::cppdef [(_.code (all _.then +... runtime.declaration + +... (_.include "iostream") +... (_.function (_.local ) +... (list) +... (list) +... :.void +... (all _.then +... (print (_.deref (runtime.host_value type.bit (runtime.simple type.bit (primitive.bit true))))) +... (print (_.deref (runtime.host_value type.i64 (runtime.simple type.i64 (primitive.i64 +123))))) +... (print (_.deref (runtime.host_value type.f64 (runtime.simple type.f64 (primitive.f64 -456.789))))) +... ... (print (_.deref (runtime.host_value type.text (runtime.simple type.text (primitive.text "YOLO"))))) +... ))))]) +... .let [_ (debug.log! (%.format "BEFORE " (%.bit ?)))] +... global (cppyy::gbl) +... .let [say_hello (as ffi.Function +... (.python_object_get# global)) +... _ (debug.log! "AFTER") +... _ (.python_apply# say_hello [])]] +... (in (debug.log! "Hello, C++")))))) + +(ffi.import (getattr [(ffi.Object Any) Text] Any)) + +(def host + (IO (Host runtime.Value runtime.Declaration)) + (io (let [\n\t (%.format text.\n text.\t) + evaluate! (is (-> unit.ID [(Maybe unit.ID) runtime.Value] (Try Any)) + (function (evaluate! context [_ input]) + (let [global (reference.artifact context) + definition (_.constant (_.local global) type.value input)] + (if (io.run! (cppyy::cppdef (_.code definition))) + {try.#Success (getattr (io.run! (cppyy::gbl)) global)} + {try.#Failure "Cannot evaluate!"})))) + execute! (is (-> runtime.Declaration + (Try Any)) + (function (execute! input) + (if (io.run! (cppyy::cppdef (_.code input))) + {try.#Success []} + {try.#Failure "Cannot execute!"})))] + (is (Host runtime.Value runtime.Declaration) + (implementation + (def evaluate evaluate!) + (def execute execute!) + (def (define context custom [@def input]) + (let [global (maybe.else (reference.artifact context) + custom) + @global (_.local global)] + (do try.monad + [.let [definition (_.constant @global type.value input)] + _ (execute! definition) + value (evaluate! context [@def @global])] + (in [global value definition])))) + + (def (ingest context content) + (|> content + (of utf8.codec decoded) + try.trusted + (as runtime.Declaration))) + + (def (re_learn context custom content) + (execute! content)) + + (def (re_load context custom content) + (do try.monad + [_ (execute! content)] + (evaluate! context [{.#None} (_.local (reference.artifact context))])))))))) + +(def (phase_wrapper _) + phase.Wrapper + (undefined)) + +(def .public platform + (IO [runtime.Host + (Platform runtime.Anchor runtime.Value runtime.Declaration)]) + (do io.monad + [host ..host] + (in [host + [platform.#file_system (file.async file.default) + platform.#host host + + platform.#phase c++.translation + platform.#runtime runtime.translation + + platform.#phase_wrapper ..phase_wrapper + platform.#write (|>> _.code (of utf8.codec encoded))]]))) + +(def (extender _) + Extender + (undefined)) + +(def reference_system + (reference.System runtime.Value) + (implementation + (def constant' _.local) + (def variable' _.local))) + +(def (expander macro inputs lux) + Expander + (undefined)) + +(def (c++_program name it) + (Program runtime.Value runtime.Declaration) + (undefined)) + +(def (declare_success! _) + (-> Any (Async Any)) + (async.future (of environment.default exit +0))) + +(def _ + (program [service cli.service] + (let [context (context.jvm (cli.target service))] + (exec + (do async.monad + [[host platform] (async.future ..platform) + _ (compositor.compiler (|>> (as platform.Custom)) + context + ..expander + extension.empty + (io.io platform) + extension.empty + extension.empty + ..c++_program + (reference.constant reference_system) + ..extender + service + [(packager.package (is runtime.Declaration (_.manual "")) + _.code + _.also + (_.namespace "lux_program")) + "program.cpp"])] + (..declare_success! [])) + (io.io []))))) diff --git a/lux-js/source/program.lux b/lux-js/source/program.lux index bbd328b6b..f896219f8 100644 --- a/lux-js/source/program.lux +++ b/lux-js/source/program.lux @@ -32,7 +32,7 @@ ["[0]" i64]]] ["[0]" world ["[0]" file] - ["[1]/[0]" environment]] + ["[0]" environment]] [meta ["@" target (.only) ["_" js]] @@ -709,7 +709,7 @@ (def (declare_success! _) (-> Any (Async Any)) - (async.future (of world/environment.default exit +0))) + (async.future (of environment.default exit +0))) (def (scope body) (-> _.Statement _.Statement) diff --git a/lux-jvm/source/program.lux b/lux-jvm/source/program.lux index 1ce1ea0d2..351c132ff 100644 --- a/lux-jvm/source/program.lux +++ b/lux-jvm/source/program.lux @@ -55,7 +55,7 @@ ["[1][0]" reference]]]]]]]] ["[0]" world ["[0]" file] - ["[1]/[0]" environment]]]] + ["[0]" environment]]]] [program ["[0]" compositor]]) @@ -158,7 +158,7 @@ (def (declare_success! _) (-> Any (Async Any)) - (async.future (of world/environment.default exit +0))) + (async.future (of environment.default exit +0))) (def _ (program [service cli.service] diff --git a/stdlib/source/library/lux/math/arithmetic/fixed_point.lux b/stdlib/source/library/lux/math/arithmetic/fixed_point.lux index 4498bce85..560068499 100644 --- a/stdlib/source/library/lux/math/arithmetic/fixed_point.lux +++ b/stdlib/source/library/lux/math/arithmetic/fixed_point.lux @@ -77,7 +77,7 @@ (I64 Any))) (|> it .i64 - (i.right_shifted (n.- (nominal.representation Point @) i64.width))))) + (i64.right_shifted (n.- (nominal.representation Point @) i64.width))))) (def .public (fixed @ units sub_units) (All (_ @) diff --git a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++.lux b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++.lux new file mode 100644 index 000000000..519863128 --- /dev/null +++ b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++.lux @@ -0,0 +1,104 @@ +... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +(.require + [library + [lux (.except Synthesis) + [abstract + [monad (.only do)]] + [control + ["[0]" try] + ["[0]" exception (.only Exception)]] + [data + ["[0]" text (.use "[1]#[0]" equivalence) + ["%" \\format]]] + ["[0]" meta (.only) + [macro + ["^" pattern]] + [type + ["[0]" check]] + [compiler + [meta + ["[0]" archive (.only Archive)] + ["[0]" cache + [dependency + ["[1]/[0]" artifact]]]]]]]] + ["[0]" / + [runtime (.only Operation Phase Handler)] + ["[1][0]" primitive] + ["[1][0]" complex] + ... ["[1][0]" reference] + ... ["[1][0]" function] + ... ["[1][0]" when] + ... ["[1][0]" loop] + ["//[1]" /// + ["[0]" extension] + [// + ["[0]" phase (.use "[1]#[0]" monad)] + ["[0]" synthesis (.only Synthesis)] + ["[0]" translation] + [/// + ["[0]" reference]]]]]) + +(def .public (translation extender lux) + (-> extension.Extender Lux + Phase) + (function (phase archive it) + (when it + (^.with_template [ ] + [( @ it) + (phase#in ( it))]) + ([synthesis.bit /primitive.bit] + [synthesis.i64 /primitive.i64] + [synthesis.f64 /primitive.f64] + [synthesis.text /primitive.text]) + + (synthesis.variant @ it) + (/complex.variant phase archive it) + + (synthesis.tuple @ it) + (/complex.tuple phase archive it) + + ... [@ {synthesis.#Reference reference}] + ... (when reference + ... {reference.#Variable variable} + ... (/reference.variable archive variable) + + ... {reference.#Constant constant} + ... (/reference.constant archive constant)) + + ... (synthesis.branch/when @ [valueS pathS]) + ... (/when.when phase archive [valueS pathS]) + + ... (synthesis.branch/exec @ [this that]) + ... (/when.exec phase archive [this that]) + + ... (synthesis.branch/let @ [inputS register bodyS]) + ... (/when.let phase archive [inputS register bodyS]) + + ... (synthesis.branch/if @ [conditionS thenS elseS]) + ... (/when.if phase archive [conditionS thenS elseS]) + + ... (synthesis.branch/get @ [path recordS]) + ... (/when.get phase archive [path recordS]) + + ... (synthesis.loop/scope @ scope) + ... (/loop.scope phase archive scope) + + ... (synthesis.loop/again @ updates) + ... (/loop.again phase archive updates) + + ... (synthesis.function/abstraction @ abstraction) + ... (/function.abstraction phase archive abstraction) + + ... (synthesis.function/apply @ application) + ... (/function.apply phase archive application) + + ... [@ {synthesis.#Extension [name parameters]}] + ... (extension.application extender lux phase archive .Translation false name parameters + ... (|>>) + ... (function (_ _) {.#None})) + + _ + (undefined) + ))) diff --git a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++/runtime.lux b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++/runtime.lux index 4e488a289..461b0ead8 100644 --- a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++/runtime.lux +++ b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/c++/runtime.lux @@ -4,11 +4,17 @@ (.require [library [lux (.except Declaration Translation) + [abstract + ["[0]" monad (.only do)]] [data + ["[0]" product] [text - ["%" \\format]] + ["%" \\format] + [encoding + ["[0]" utf8]]] [collection - ["[0]" list]]] + ["[0]" list] + ["[0]" sequence]]] ["[0]" meta (.use "[1]#[0]" functor) ["[0]" code] [macro @@ -20,10 +26,13 @@ ["[0]" // ["[1][0]" type]] [///// + ["[0]" phase] ["[0]" translation] [/// [meta - [archive (.only Archive)]]]]) + [archive (.only Output Archive) + ["[0]" registry (.only Registry)] + ["[0]" unit]]]]]) (type .public Anchor Any) @@ -32,7 +41,7 @@ _.Expression) (type .public Declaration - _.Statement) + _.Declaration) (with_template [ ] [(type .public @@ -44,6 +53,9 @@ [Bundle translation.Bundle] ) +(type .public Host + (translation.Host Value Declaration)) + (type .public (Translation of) (-> Phase Archive of (Operation Value))) @@ -156,3 +168,17 @@ _.Expression (_.global [..namespace ] (list))) ) + +(def artifact_id + 0) + +(def .public translation + (Operation [Registry Output]) + (do phase.monad + [_ (translation.execute! ..declaration) + _ (translation.save! ..artifact_id {.#None} ..declaration)] + (in [(|> registry.empty + (registry.resource .true unit.none) + product.right) + (sequence.sequence [..artifact_id {.#None} + (of utf8.codec encoded (_.code ..declaration))])]))) diff --git a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm.lux b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm.lux index 15a4a8057..4e47ca19b 100644 --- a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm.lux +++ b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm.lux @@ -60,69 +60,69 @@ (def .public (translate extender lux) (-> extension.Extender Lux Phase) - (function (phase archive synthesis) - (when synthesis + (function (phase archive it) + (when it (^.with_template [ ] - [( @ value) + [( @ it) (with_source_mapping @ - (phase#in ( value)))]) + (phase#in ( it)))]) ([synthesis.bit /primitive.bit] [synthesis.i64 /primitive.i64] [synthesis.f64 /primitive.f64] [synthesis.text /primitive.text]) - (synthesis.variant @ variantS) + (synthesis.variant @ it) (with_source_mapping @ - (/complex.variant phase archive variantS)) + (/complex.variant phase archive it)) - (synthesis.tuple @ members) + (synthesis.tuple @ it) (with_source_mapping @ - (/complex.tuple phase archive members)) + (/complex.tuple phase archive it)) - [@ {synthesis.#Reference reference}] + [@ {synthesis.#Reference it}] (with_source_mapping @ - (when reference - {reference.#Variable variable} - (/reference.variable archive variable) + (when it + {reference.#Variable it} + (/reference.variable archive it) - {reference.#Constant constant} - (/reference.constant archive constant))) + {reference.#Constant it} + (/reference.constant archive it))) - (synthesis.branch/when @ [valueS pathS]) + (synthesis.branch/when @ it) (with_source_mapping @ - (/when.when phase archive [valueS pathS])) + (/when.when phase archive it)) - (synthesis.branch/exec @ [this that]) + (synthesis.branch/exec @ it) (with_source_mapping @ - (/when.exec phase archive [this that])) + (/when.exec phase archive it)) - (synthesis.branch/let @ [inputS register bodyS]) + (synthesis.branch/let @ it) (with_source_mapping @ - (/when.let phase archive [inputS register bodyS])) + (/when.let phase archive it)) - (synthesis.branch/if @ [conditionS thenS elseS]) + (synthesis.branch/if @ it) (with_source_mapping @ - (/when.if phase archive [conditionS thenS elseS])) + (/when.if phase archive it)) - (synthesis.branch/get @ [path recordS]) + (synthesis.branch/get @ it) (with_source_mapping @ - (/when.get phase archive [path recordS])) + (/when.get phase archive it)) - (synthesis.loop/scope @ scope) + (synthesis.loop/scope @ it) (with_source_mapping @ - (/loop.scope phase archive scope)) + (/loop.scope phase archive it)) - (synthesis.loop/again @ updates) + (synthesis.loop/again @ it) (with_source_mapping @ - (/loop.again phase archive updates)) + (/loop.again phase archive it)) - (synthesis.function/abstraction @ abstraction) + (synthesis.function/abstraction @ it) (with_source_mapping @ - (/function.abstraction phase archive abstraction)) + (/function.abstraction phase archive it)) - (synthesis.function/apply @ application) + (synthesis.function/apply @ it) (with_source_mapping @ - (/function.apply phase archive application)) + (/function.apply phase archive it)) [@ {synthesis.#Extension [name parameters]}] (with_source_mapping @ diff --git a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm/program.lux b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm/program.lux index 43d0cb6b6..80a700340 100644 --- a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm/program.lux +++ b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/jvm/program.lux @@ -146,7 +146,8 @@ //runtime.apply)) (def .public (program artifact_name context program) - (-> (-> unit.ID Text) (Program (Bytecode Any) Definition)) + (-> (-> unit.ID Text) + (Program (Bytecode Any) Definition)) (let [super_class (|> ..^Object type.reflection reflection.reflection name.internal) main (method.method ..main::modifier "main" false ..main::type diff --git a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/reference.lux b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/reference.lux index 1cd97d325..9c7a0aa24 100644 --- a/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/reference.lux +++ b/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/reference.lux @@ -8,7 +8,6 @@ [text ["%" \\format (.only format)]]] [meta - ["[0]" version] [compiler ["@" target]]]]] [//// @@ -54,8 +53,7 @@ (def .public (artifact [module artifact]) (-> unit.ID Text) - (format "l" (%.nat version.latest) - ..universe_label + (format ..universe_label "m" (%.nat module) "a" (%.nat artifact))) diff --git a/stdlib/source/library/lux/meta/compiler/meta/context.lux b/stdlib/source/library/lux/meta/compiler/meta/context.lux index ccd7fe4ea..d2c76f8dc 100644 --- a/stdlib/source/library/lux/meta/compiler/meta/context.lux +++ b/stdlib/source/library/lux/meta/compiler/meta/context.lux @@ -33,4 +33,5 @@ [lua @.lua ".lua" ".lua"] [python @.python ".py" ".py"] [ruby @.ruby ".rb" ".rb"] + [c++ @.c++ ".cpp" ".cpp"] ) diff --git a/stdlib/source/library/lux/meta/compiler/target.lux b/stdlib/source/library/lux/meta/compiler/target.lux index 82f1c4b53..ee3bbedc2 100644 --- a/stdlib/source/library/lux/meta/compiler/target.lux +++ b/stdlib/source/library/lux/meta/compiler/target.lux @@ -21,6 +21,7 @@ [lua "Lua"] [python "Python"] [ruby "Ruby"] + [c++ "C++"] ... Not available yet. [common_lisp "Common Lisp"] [php "PHP"] diff --git a/stdlib/source/library/lux/meta/compiler/target/c++.lux b/stdlib/source/library/lux/meta/compiler/target/c++.lux index d2cde8f5b..eda5a1440 100644 --- a/stdlib/source/library/lux/meta/compiler/target/c++.lux +++ b/stdlib/source/library/lux/meta/compiler/target/c++.lux @@ -43,6 +43,12 @@ (text#= (%> refererence) (%> it))))) + (def .public manual + (All (_ of) + (-> Text + (Code of))) + (|>> <%)) + (def .public code (-> (Code Any) Text) diff --git a/stdlib/source/test/lux/meta.lux b/stdlib/source/test/lux/meta.lux index 8fd22359c..1b037cb8a 100644 --- a/stdlib/source/test/lux/meta.lux +++ b/stdlib/source/test/lux/meta.lux @@ -856,24 +856,34 @@ (list#each (|>> [label_module]) {.#Item tags_0})) last (-- (list.size cohort)) - right? (n.= last)] + right? (n.= last) + lefts (is (-> Nat Nat) + (function (_ index) + (if (right? index) + (-- index) + index)))] (|> {.#Item tags_0} list.enumeration (list#each (function (_ [index short]) [short [true {.#Definition [.Tag - (|> [{.#Some [index (right? index) cohort]} type_0] + (|> [{.#Some [(lefts index) (right? index) cohort]} type_0] (is Label) (as .Tag))]}]])))) (let [cohort (is (List Symbol) (list#each (|>> [label_module]) {.#Item tags_1})) last (-- (list.size cohort)) - right? (n.= last)] + right? (n.= last) + lefts (is (-> Nat Nat) + (function (_ index) + (if (right? index) + (-- index) + index)))] (|> {.#Item tags_1} list.enumeration (list#each (function (_ [index short]) [short [true {.#Definition [.Slot - (|> [{.#Some [index (right? index) cohort]} type_1] + (|> [{.#Some [(lefts index) (right? index) cohort]} type_1] (is Label) (as .Slot))]}]])))))) .#imports (list) @@ -888,72 +898,55 @@ .#extensions [] .#eval (as (-> Type Code (Meta Any)) []) .#host []])]] - (all _.and - (_.coverage [/.tag_lists] - (let [equivalence (list.equivalence - (product.equivalence - (list.equivalence symbol.equivalence) - type.equivalence))] - (|> (/.tag_lists label_module) - (/.result expected_lux) - (try#each (of equivalence = (list [(list#each (|>> [label_module]) {.#Item tags_1}) - type_1]))) - (try.else false)))) - (_.coverage [/.tags_of] - (|> (/.tags_of [label_module name_1]) - (/.result expected_lux) - (try#each (of (maybe.equivalence (list.equivalence symbol.equivalence)) = - {.#Some (list#each (|>> [label_module]) {.#Item tags_1})})) - (try.else false))) - ... (_.coverage [/.tag] - ... (|> {.#Item tags_0} - ... list.enumeration - ... (list.every? (function (_ [expected_index label]) - ... (|> [label_module label] - ... /.tag - ... (/.result expected_lux) - ... (!expect (^.multi {try.#Success [actual_index actual_tags actual_type]} - ... (let [correct_index! - ... (n.= expected_index - ... actual_index) - - ... correct_tags! - ... (of (list.equivalence symbol.equivalence) = - ... (list#each (|>> [label_module]) {.#Item tags_0}) - ... actual_tags) + (`` (all _.and + (_.coverage [/.tag_lists] + (let [equivalence (list.equivalence + (product.equivalence + (list.equivalence symbol.equivalence) + type.equivalence))] + (|> (/.tag_lists label_module) + (/.result expected_lux) + (try#each (of equivalence = (list [(list#each (|>> [label_module]) {.#Item tags_1}) + type_1]))) + (try.else false)))) + (_.coverage [/.tags_of] + (|> (/.tags_of [label_module name_1]) + (/.result expected_lux) + (try#each (of (maybe.equivalence (list.equivalence symbol.equivalence)) = + {.#Some (list#each (|>> [label_module]) {.#Item tags_1})})) + (try.else false))) + (,, (with_template [