(.require [library [lux (.except let local symbol macro) ["[0]" meta] [abstract ["[0]" monad (.only do)]] [control ["[0]" try (.only Try)] ["[0]" exception (.only exception)] ["<>" parser (.use "[1]#[0]" functor) ["<[0]>" code (.only Parser)]]] [data ["[0]" bit (.use "[1]#[0]" codec)] ["[0]" text] [collection ["[0]" list (.use "[1]#[0]" monad)] ["[0]" dictionary (.only Dictionary)]]] [macro ["^" pattern]] [math [number ["[0]" nat (.use "[1]#[0]" decimal)] ["[0]" int (.use "[1]#[0]" decimal)] ["[0]" rev (.use "[1]#[0]" decimal)] ["[0]" frac (.use "[1]#[0]" decimal)]]]]] ["[0]" // (.only) [syntax (.only syntax)] ["[0]" code] ["[0]" local]]) (def .public spliced (syntax (_ [parts (.tuple (<>.some .any))]) (in parts))) (def .public amount (syntax (_ [parts (.tuple (<>.some .any))]) (in (list (code.nat (list.size parts)))))) (def .public with_locals (syntax (_ [locals (.tuple (<>.some .local)) body .any]) (do [! meta.monad] [g!locals (|> locals (list#each //.symbol) (monad.all !))] (in (list (` (.with_expansions [(~+ (|> (list.zipped_2 locals g!locals) (list#each (function (_ [name symbol]) (list (code.local name) symbol))) list#conjoint))] (~ body)))))))) (def (symbol_side module_side? parser) (-> Bit (Parser Symbol) (Parser Text)) (do <>.monad [[module short] parser] (in (if module_side? (case module "" short _ module) short)))) (def (snippet module_side?) (-> Bit (Parser Text)) (.let [full_symbol (..symbol_side module_side? .symbol)] (all <>.either .text (if module_side? full_symbol (<>.either .local full_symbol)) (<>#each bit#encoded .bit) (<>#each nat#encoded .nat) (<>#each int#encoded .int) (<>#each rev#encoded .rev) (<>#each frac#encoded .frac) ))) (def (part module_side?) (-> Bit (Parser (List Text))) (.tuple (<>.many (..snippet module_side?)))) (def .public text (syntax (_ [simple (..part false)]) (in (list (|> simple (text.interposed "") code.text))))) (with_template [ ] [(def .public (syntax (_ [name (<>.or (<>.and (..part true) (..part false)) (..part false))]) (case name {.#Left [simple complex]} (in (list ( [(text.interposed "" simple) (text.interposed "" complex)]))) {.#Right simple} (in (list (|> simple (text.interposed "") ))))))] [symbol code.local code.symbol] ) (type Environment (Dictionary Text Code)) (def (applied env template) (-> Environment Code Code) (case template [_ {.#Symbol "" name}] (case (dictionary.value name env) {.#Some substitute} substitute {.#None} template) (^.with_template [] [[meta { elems}] [meta { (list#each (applied env) elems)}]]) ([.#Form] [.#Variant] [.#Tuple]) _ template)) (type Local (Record [#name Text #parameters (List Text) #template (List Code)])) (exception .public (irregular_arguments [expected Nat actual Nat]) (exception.report "Expected" (at nat.decimal encoded expected) "Actual" (at nat.decimal encoded actual))) (def (macro (open "_[0]")) (-> Local Macro) ("lux macro" (function (_ inputs compiler) (.let [parameters_amount (list.size _#parameters) inputs_amount (list.size inputs)] (if (nat.= parameters_amount inputs_amount) (.let [environment (is Environment (|> (list.zipped_2 _#parameters inputs) (dictionary.of_list text.hash)))] {.#Right [compiler (list#each (..applied environment) _#template)]}) (exception.except ..irregular_arguments [parameters_amount inputs_amount])))))) (def local (Parser Local) (do <>.monad [[name parameters] (.form (<>.and .local (<>.many .local))) template (.tuple (<>.some .any))] (in [#name name #parameters parameters #template template]))) ... TODO: Get rid of this (and any local definitions it depends on) once the bootstrapping compiler is gone. (def .public let (syntax (_ [locals (.tuple (<>.some ..local)) body .any]) (do meta.monad [here_name meta.current_module_name expression? (is (Meta Bit) (function (_ lux) {try.#Success [lux (case (the .#expected lux) {.#None} false {.#Some _} true)]})) g!pop (local.push (list#each (function (_ local) [[here_name (the #name local)] (..macro local)]) locals))] (if expression? (//.with_symbols [g!body] (in (list (` (.let [(~ g!body) (~ body)] (exec (~ g!pop) (~ g!body))))))) (in (list body g!pop))))))