(.using [library [lux {"-" Alias} ["@" target] ["[0]" meta] [abstract [monad {"+" do}]] [control ["[0]" io] ["[0]" maybe] ["<>" parser ("[1]#[0]" monad) ["<[0]>" code {"+" Parser}]]] [data ["[0]" product] ["[0]" text ["%" format]] [collection ["[0]" list ("[1]#[0]" functor)]]] [type abstract] [macro {"+" with_symbols} [syntax {"+" syntax:}] ["[0]" code] ["[0]" template]]]]) (abstract: .public (Object brand) Any) (template [] [(with_expansions [ (template.symbol [ "'"])] (abstract: Any) (type: .public (..Object )))] [Nil] [Function] ) (template [ ] [(type: .public )] [Boolean Bit] [Integer Int] [Float Frac] [String Text] ) (type: Nilable [Bit Code]) (def: nilable (Parser Nilable) (let [token (' "?")] (<| (<>.and (<>.parses? (.this! token))) (<>.after (<>.not (.this! token))) .any))) (type: Alias Text) (def: alias (Parser Alias) (<>.after (.this! (' "as")) .local_symbol)) (type: Field [Bit Text (Maybe Alias) Nilable]) (def: static! (Parser Any) (.this! (' "static"))) (def: field (Parser Field) (.form ($_ <>.and (<>.parses? ..static!) .local_symbol (<>.maybe ..alias) ..nilable))) (def: constant (Parser Field) (.form ($_ <>.and (<>#in true) .local_symbol (<>.maybe ..alias) ..nilable))) (type: Common_Method (Record [#name Text #alias (Maybe Alias) #inputs (List Nilable) #io? Bit #try? Bit #output Nilable])) (type: Static_Method Common_Method) (type: Virtual_Method Common_Method) (type: Method (Variant {#Static Static_Method} {#Virtual Virtual_Method})) (def: common_method (Parser Common_Method) ($_ <>.and .local_symbol (<>.maybe ..alias) (.tuple (<>.some ..nilable)) (<>.parses? (.this! (' "io"))) (<>.parses? (.this! (' "try"))) ..nilable)) (def: static_method (<>.after ..static! ..common_method)) (def: method (Parser Method) (.form (<>.or ..static_method ..common_method))) (type: Member (Variant {#Field Field} {#Method Method})) (def: member (Parser Member) ($_ <>.or ..field ..method )) (def: input_variables (-> (List Nilable) (List [Bit Code])) (|>> list.enumeration (list#each (function (_ [idx [nilable? type]]) [nilable? (|> idx %.nat code.local_symbol)])))) (def: (nilable_type [nilable? type]) (-> Nilable Code) (if nilable? (` (.Maybe (~ type))) type)) (def: (with_nil g!temp [nilable? input]) (-> Code [Bit Code] Code) (if nilable? (` (case (~ input) {.#Some (~ g!temp)} (~ g!temp) {.#None} ("ruby object nil"))) input)) (def: (without_nil g!temp [nilable? outputT] output) (-> Code Nilable Code Code) (if nilable? (` (let [(~ g!temp) (~ output)] (if ("ruby object nil?" (~ g!temp)) {.#None} {.#Some (~ g!temp)}))) (` (let [(~ g!temp) (~ output)] (if (not ("ruby object nil?" (~ g!temp))) (~ g!temp) (.panic! "Nil is an invalid value!")))))) (type: Import (Variant {#Class Text (Maybe Alias) Text (List Member)} {#Function Static_Method} {#Constant Field})) (def: import (Parser [(Maybe Text) Import]) ($_ <>.and (<>.maybe .text) ($_ <>.or ($_ <>.and .local_symbol (<>.maybe ..alias) (<>.else ["" (list)] (.tuple (<>.and .text (<>.some member))))) (.form ..common_method) ..constant ))) (def: (with_io with? without) (-> Bit Code Code) (if with? (` (io.io (~ without))) without)) (def: (io_type io? rawT) (-> Bit Code Code) (if io? (` (io.IO (~ rawT))) rawT)) (def: (with_try with? without_try) (-> Bit Code Code) (if with? (` (.try (~ without_try))) without_try)) (def: (try_type try? rawT) (-> Bit Code Code) (if try? (` (.Either .Text (~ rawT))) rawT)) (def: (make_function g!method g!temp source inputsT io? try? outputT) (-> Code Code Code (List Nilable) Bit Bit Nilable Code) (let [g!inputs (input_variables inputsT)] (` (def: ((~ g!method) [(~+ (list#each product.right g!inputs))]) (-> [(~+ (list#each nilable_type inputsT))] (~ (|> (nilable_type outputT) (try_type try?) (io_type io?)))) (:expected (~ (<| (with_io io?) (with_try try?) (without_nil g!temp outputT) (` ("ruby apply" (:as ..Function (~ source)) (~+ (list#each (with_nil g!temp) g!inputs))))))))))) (syntax: .public (import: [[?module import] ..import]) (with_symbols [g!temp] (case import {#Class [class alias format members]} (with_symbols [g!object] (let [qualify (: (-> Text Code) (function (_ member_name) (|> format (text.replaced "[1]" (maybe.else class alias)) (text.replaced "[0]" member_name) code.local_symbol))) g!type (code.local_symbol (maybe.else class alias)) module_import (: (List Code) (case ?module {.#Some module} (list (` ("ruby import" (~ (code.text module))))) {.#None} (list))) class_import (` ("ruby constant" (~ (code.text class))))] (in (list& (` (type: (~ g!type) (..Object (Primitive (~ (code.text class)))))) (list#each (function (_ member) (case member {#Field [static? field alias fieldT]} (if static? (` ((~! syntax:) ((~ (qualify (maybe.else field alias))) []) (# (~! meta.monad) (~' in) (list (` (.:as (~ (nilable_type fieldT)) (.exec (~+ module_import) ("ruby constant" (~ (code.text (%.format class "::" field))))))))))) (` (def: ((~ (qualify field)) (~ g!object)) (-> (~ g!type) (~ (nilable_type fieldT))) (:expected (~ (without_nil g!temp fieldT (` ("ruby object get" (~ (code.text field)) (:as (..Object .Any) (~ g!object)))))))))) {#Method method} (case method {#Static [method alias inputsT io? try? outputT]} (..make_function (qualify (maybe.else method alias)) g!temp (` ("ruby object get" (~ (code.text method)) (:as (..Object .Any) (.exec (~+ module_import) ("ruby constant" (~ (code.text (%.format class "::" method)))))))) inputsT io? try? outputT) {#Virtual [method alias inputsT io? try? outputT]} (let [g!inputs (input_variables inputsT)] (` (def: ((~ (qualify (maybe.else method alias))) [(~+ (list#each product.right g!inputs))] (~ g!object)) (-> [(~+ (list#each nilable_type inputsT))] (~ g!type) (~ (|> (nilable_type outputT) (try_type try?) (io_type io?)))) (:expected (~ (<| (with_io io?) (with_try try?) (without_nil g!temp outputT) (` ("ruby object do" (~ (code.text method)) (~ g!object) (~+ (list#each (with_nil g!temp) g!inputs))))))))))))) members))))) {#Function [name alias inputsT io? try? outputT]} (let [imported (` (.exec (~+ (case ?module {.#Some module} (list (` ("ruby import" (~ (code.text module))))) {.#None} (list))) ("ruby constant" (~ (code.text name)))))] (in (list (..make_function (code.local_symbol (maybe.else name alias)) g!temp imported inputsT io? try? outputT)))) {#Constant [_ name alias fieldT]} (let [imported (` (.exec (~+ (case ?module {.#Some module} (list (` ("ruby import" (~ (code.text module))))) {.#None} (list))) ("ruby constant" (~ (code.text name)))))] (in (list (` ((~! syntax:) ((~ (code.local_symbol (maybe.else name alias))) []) (# (~! meta.monad) (~' in) (list (` (.:as (~ (nilable_type fieldT)) (~ imported)))))))))) )))