(.module: [library [lux "*" ["." meta] ["@" target] [abstract [monad {"+" [do]}]] [control ["." io] ["." maybe] ["<>" parser ["<.>" code {"+" [Parser]}]]] [data ["." product] ["." text ["%" format]] [collection ["." list ("#\." functor mix)]]] [type abstract] [macro {"+" [with_identifiers]} [syntax {"+" [syntax:]}] ["." code] ["." template]]]]) (abstract: .public (Object brand) {} Any) (template [] [(with_expansions [ (template.identifier [ "'"])] (abstract: {} Any) (type: .public (..Object )))] [None] [Dict] [Function] ) (template [ ] [(type: .public )] [Boolean Bit] [Integer Int] [Float Frac] [String Text] ) (type: Noneable [Bit Code]) (def: noneable (Parser Noneable) (let [token (' "?")] (<| (<>.and (<>.parses? (.this! token))) (<>.after (<>.not (.this! token))) .any))) (type: Constructor (List Noneable)) (def: constructor (Parser Constructor) (.form (<>.after (.this! (' new)) (.tuple (<>.some ..noneable))))) (type: Field [Bit Text Noneable]) (def: static! (Parser Any) (.this! (' "static"))) (def: field (Parser Field) (.form ($_ <>.and (<>.parses? ..static!) .local_identifier ..noneable))) (type: Common_Method (Record [#name Text #alias (Maybe Text) #inputs (List Noneable) #io? Bit #try? Bit #output Noneable])) (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_identifier (<>.maybe (<>.after (.this! (' "as")) .local_identifier)) (.tuple (<>.some ..noneable)) (<>.parses? (.this! (' "io"))) (<>.parses? (.this! (' "try"))) ..noneable)) (def: static_method (<>.after ..static! ..common_method)) (def: method (Parser Method) (.form (<>.or ..static_method ..common_method))) (type: Member (Variant (#Constructor Constructor) (#Field Field) (#Method Method))) (def: member (Parser Member) ($_ <>.or ..constructor ..field ..method )) (def: input_variables (-> (List Noneable) (List [Bit Code])) (|>> list.enumeration (list\each (function (_ [idx [noneable? type]]) [noneable? (|> idx %.nat code.local_identifier)])))) (def: (noneable_type [noneable? type]) (-> Noneable Code) (if noneable? (` (.Maybe (~ type))) type)) (def: (with_none g!temp [noneable? input]) (-> Code [Bit Code] Code) (if noneable? (` (case (~ input) (#.Some (~ g!temp)) (~ g!temp) #.None ("python object none"))) input)) (def: (without_none g!temp [noneable? outputT] output) (-> Code Noneable Code Code) (if noneable? (` (let [(~ g!temp) (~ output)] (if ("python object none?" (~ g!temp)) #.None (#.Some (~ g!temp))))) (` (let [(~ g!temp) (~ output)] (if (not ("python object none?" (~ g!temp))) (~ g!temp) (.panic! "None is an invalid value!")))))) (type: Import (Variant (#Class [Text Text (List Member)]) (#Function Static_Method))) (def: import (Parser Import) (<>.or (<>.and .local_identifier (<>.else ["" (list)] (.tuple (<>.and .text (<>.some member))))) (.form ..common_method))) (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 Noneable) Bit Bit Noneable Code) (let [g!inputs (input_variables inputsT)] (` (def: ((~ g!method) [(~+ (list\each product.right g!inputs))]) (-> [(~+ (list\each noneable_type inputsT))] (~ (|> (noneable_type outputT) (try_type try?) (io_type io?)))) (:expected (~ (<| (with_io io?) (with_try try?) (without_none g!temp outputT) (` ("python apply" (:as ..Function (~ source)) (~+ (list\each (with_none g!temp) g!inputs))))))))))) (syntax: .public (import: [import ..import]) {#.doc (example "Easily import types, methods, functions and constants." (import: os ["#::." ("static" F_OK ..Integer) ("static" R_OK ..Integer) ("static" W_OK ..Integer) ("static" X_OK ..Integer) ("static" mkdir [..String] "io" "try" "?" Any) ("static" access [..String ..Integer] "io" "try" ..Boolean) ("static" remove [..String] "io" "try" "?" Any) ("static" rmdir [..String] "io" "try" "?" Any) ("static" rename [..String ..String] "io" "try" "?" Any) ("static" listdir [..String] "io" "try" (Array ..String))]) (import: os/path ["#::." ("static" isfile [..String] "io" "try" ..Boolean) ("static" isdir [..String] "io" "try" ..Boolean) ("static" sep ..String) ("static" getsize [..String] "io" "try" ..Integer) ("static" getmtime [..String] "io" "try" ..Float)]))} (with_identifiers [g!temp] (case import (#Class [class format members]) (with_identifiers [g!object] (let [qualify (: (-> Text Code) (function (_ member_name) (|> format (text.replaced "#" class) (text.replaced "." member_name) code.local_identifier))) g!type (code.local_identifier class) real_class (text.replaced "/" "." class) imported (case (text.all_split_by "/" class) (#.Item head tail) (list\mix (function (_ sub super) (` ("python object get" (~ (code.text sub)) (:as (..Object .Any) (~ super))))) (` ("python import" (~ (code.text head)))) tail) #.End (` ("python import" (~ (code.text class)))))] (in (list& (` (type: (~ g!type) (..Object (primitive (~ (code.text real_class)))))) (list\each (function (_ member) (case member (#Constructor inputsT) (let [g!inputs (input_variables inputsT)] (` (def: ((~ (qualify "new")) [(~+ (list\each product.right g!inputs))]) (-> [(~+ (list\each noneable_type inputsT))] (~ g!type)) (:expected ("python apply" (:as ..Function (~ imported)) (~+ (list\each (with_none g!temp) g!inputs))))))) (#Field [static? field fieldT]) (if static? (` ((~! syntax:) ((~ (qualify field)) []) (\ (~! meta.monad) (~' in) (list (` (.:as (~ (noneable_type fieldT)) ("python object get" (~ (code.text field)) (:as (..Object .Any) (~ imported))))))))) (` (def: ((~ (qualify field)) (~ g!object)) (-> (~ g!type) (~ (noneable_type fieldT))) (:expected (~ (without_none g!temp fieldT (` ("python 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 (` ("python object get" (~ (code.text method)) (:as (..Object .Any) (~ imported)))) 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 noneable_type inputsT))] (~ g!type) (~ (|> (noneable_type outputT) (try_type try?) (io_type io?)))) (:expected (~ (<| (with_io io?) (with_try try?) (without_none g!temp outputT) (` ("python object do" (~ (code.text method)) (~ g!object) (~+ (list\each (with_none g!temp) g!inputs))))))))))))) members))))) (#Function [name alias inputsT io? try? outputT]) (in (list (..make_function (code.local_identifier (maybe.else name alias)) g!temp (` ("python constant" (~ (code.text name)))) inputsT io? try? outputT))) ))) (template: .public (lambda ) {#.doc (example "Allows defining closures/anonymous-functions in the form that Python expects." "This is useful for adapting Lux functions for usage by Python code." (: ..Function (lambda [left right] (do_something (:as Foo left) (:as Bar right)))))} [(.:as ..Function (`` ("python function" (~~ (template.amount )) (.function (_ []) ))))])