(.module: [lux (#- Code not or and list if cond int comment) [control [pipe (#+ new> case> cond>)] [parser ["s" code]]] [data [number ["f" frac]] ["." text ["%" format (#+ format)]] [collection ["." list ("#@." functor fold)]]] [macro ["." template] ["." code] [syntax (#+ syntax:)]] [type abstract]]) (def: expression (-> Text Text) (text.enclose ["(" ")"])) (def: nest (-> Text Text) (|>> (format text.new-line) (text.replace-all text.new-line (format text.new-line text.tab)))) (abstract: #export (Code brand) {} Text (def: #export manual (-> Text Code) (|>> :abstraction)) (def: #export code (-> (Code Any) Text) (|>> :representation)) (template [ ] [(with-expansions [ (template.identifier [ "'"])] (`` (abstract: #export ( brand) {} Any)) (`` (type: #export ( brand) ( ( brand)))))] [Expression Code] [Computation Expression] [Location Computation] [Var Location] [Statement Code] ) (template [ ] [(with-expansions [ (template.identifier [ "'"])] (`` (abstract: #export {} Any)) (`` (type: #export ( ))))] [Literal Computation] [Access Location] [Loop Statement] [Label Code] ) (template [ ] [(abstract: #export {} Any) (type: #export (Var ))] [SVar Single] [PVar Poly] [KVar Keyword] ) (def: #export var (-> Text SVar) (|>> :abstraction)) (template [ ] [(def: #export (-> SVar (Var )) (|>> :representation (format ) :abstraction))] [poly Poly "*"] [keyword Keyword "**"] ) (def: #export none Literal (:abstraction "None")) (def: #export bool (-> Bit Literal) (|>> (case> #0 "False" #1 "True") :abstraction)) (def: #export int (-> Int Literal) (|>> %.int :abstraction)) (def: #export (long value) (-> Int Literal) (:abstraction (format (%.int value) "L"))) (def: #export float (-> Frac Literal) (`` (|>> (cond> (~~ (template [ ] [[(f.= )] [(new> (format "float(" text.double-quote text.double-quote ")") [])]] [f.positive-infinity "inf"] [f.negative-infinity "-inf"] [f.not-a-number "nan"] )) ## else [%.frac]) :abstraction))) (def: sanitize (-> Text Text) (`` (|>> (~~ (template [ ] [(text.replace-all )] ["\" "\\"] [text.tab "\t"] [text.vertical-tab "\v"] [text.null "\0"] [text.back-space "\b"] [text.form-feed "\f"] [text.new-line "\n"] [text.carriage-return "\r"] [text.double-quote (format "\" text.double-quote)] )) ))) (def: #export string (-> Text Literal) (|>> ..sanitize (text.enclose [text.double-quote text.double-quote]) :abstraction)) (def: (composite-literal left-delimiter right-delimiter entry-serializer) (All [a] (-> Text Text (-> a Text) (-> (List a) Literal))) (function (_ entries) (<| :abstraction ..expression (format left-delimiter (|> entries (list@map entry-serializer) (text.join-with ", ")) right-delimiter)))) (template [
 ]
    [(def: #export 
       (-> (List (Expression Any)) Literal)
       (composite-literal 
  ..code))]

    [tuple "(" ")"]
    [list  "[" "]"]
    )

  (def: #export (slice from to list)
    (-> (Expression Any) (Expression Any) (Expression Any) Access)
    (<| :abstraction
        ..expression
        (format (:representation list) "[" (:representation from) ":" (:representation to) "]")))

  (def: #export (slice-from from list)
    (-> (Expression Any) (Expression Any) Access)
    (<| :abstraction
        ..expression
        (format (:representation list) "[" (:representation from) ":]")))

  (def: #export dict
    (-> (List [(Expression Any) (Expression Any)]) (Computation Any))
    (composite-literal "{" "}" (.function (_ [k v]) (format (:representation k) " : " (:representation v)))))

  (def: #export (apply/* func args)
    (-> (Expression Any) (List (Expression Any)) (Computation Any))
    (<| :abstraction
        ..expression
        (format (:representation func) "(" (text.join-with ", " (list@map ..code args)) ")")))

  (template [  ]
    [(def: ( var)
       (-> (Expression Any) Text)
       (format  (:representation var)))]

    [splat-poly    Poly    "*"]
    [splat-keyword Keyword "**"]
    )

  (template [ ]
    [(def: #export ( args extra func)
       (-> (List (Expression Any)) (Expression Any) (Expression Any) (Computation Any))
       (<| :abstraction
           ..expression
           (format (:representation func)
                   (format "(" (|> args
                                   (list@map (function (_ arg) (format (:representation arg) ", ")))
                                   (text.join-with ""))
                           ( extra) ")"))))]

    [apply-poly    splat-poly]
    [apply-keyword splat-keyword]
    )

  (def: #export (the name object)
    (-> Text (Expression Any) (Computation Any))
    (:abstraction (format (:representation object) "." name)))

  (def: #export (do method args object)
    (-> Text (List (Expression Any)) (Expression Any) (Computation Any))
    (..apply/* (..the method object) args))

  (template [ ]
    [(def: #export ( args extra method)
       (-> (List (Expression Any)) (Expression Any) Text
           (-> (Expression Any) (Computation Any)))
       (|>> (..the method) ( args extra)))]

    [do-poly    apply-poly]
    [do-keyword apply-keyword]
    )

  (def: #export (nth idx array)
    (-> (Expression Any) (Expression Any) Location)
    (:abstraction (format (:representation array) "[" (:representation idx) "]")))

  (def: #export (? test then else)
    (-> (Expression Any) (Expression Any) (Expression Any) (Computation Any))
    (<| :abstraction
        ..expression
        (format (:representation then) " if " (:representation test) " else " (:representation else))))

  (template [ ]
    [(def: #export ( param subject)
       (-> (Expression Any) (Expression Any) (Computation Any))
       (<| :abstraction
           ..expression
           (format (:representation subject) " "  " " (:representation param))))]

    [is      "is"]
    [=       "=="]
    [<       "<"]
    [<=      "<="]
    [>       ">"]
    [>=      ">="]
    [+       "+"]
    [-       "-"]
    [*       "*"]
    [/       "/"]
    [%       "%"]
    [**      "**"]
    [bit-or  "|"]
    [bit-and "&"]
    [bit-xor "^"]
    [bit-shl "<<"]
    [bit-shr ">>"]

    [or      "or"]
    [and     "and"]
    )

  (def: #export (not subject)
    (-> (Expression Any) (Computation Any))
    (<| :abstraction
        ..expression
        (format "not " (:representation subject))))

  (def: #export (lambda arguments body)
    (-> (List (Var Any)) (Expression Any) (Computation Any))
    (<| :abstraction
        ..expression
        (format "lambda " (|> arguments (list@map ..code) (text.join-with ", ")) ": "
                (:representation body))))

  (def: #export (set vars value)
    (-> (List (Location Any)) (Expression Any) (Statement Any))
    (:abstraction
     (format (|> vars (list@map ..code) (text.join-with ", "))
             " = "
             (:representation value))))

  (def: #export (delete where)
    (-> (Location Any) (Statement Any))
    (:abstraction (format "del " (:representation where))))

  (def: #export (if test then! else!)
    (-> (Expression Any) (Statement Any) (Statement Any) (Statement Any))
    (:abstraction
     (format "if " (:representation test) ":"
             (..nest (:representation then!))
             text.new-line "else:"
             (..nest (:representation else!)))))

  (def: #export (when test then!)
    (-> (Expression Any) (Statement Any) (Statement Any))
    (:abstraction
     (format "if " (:representation test) ":"
             (..nest (:representation then!)))))

  (def: #export (then pre! post!)
    (-> (Statement Any) (Statement Any) (Statement Any))
    (:abstraction
     (format (:representation pre!)
             text.new-line
             (:representation post!))))

  (template [ <0>]
    [(def: #export <0>
       Statement
       (:abstraction ))]

    ["break"    break]
    ["continue" continue]
    )

  (def: #export (while test body!)
    (-> (Expression Any) (Statement Any) Loop)
    (:abstraction
     (format "while " (:representation test) ":"
             (..nest (:representation body!)))))

  (def: #export (for-in var inputs body!)
    (-> SVar (Expression Any) (Statement Any) Loop)
    (:abstraction
     (format "for " (:representation var) " in " (:representation inputs) ":"
             (..nest (:representation body!)))))

  (def: #export statement
    (-> (Expression Any) (Statement Any))
    (|>> :transmutation))

  (def: #export pass
    (Statement Any)
    (:abstraction "pass"))

  (type: #export Except
    {#classes (List SVar)
     #exception SVar
     #handler (Statement Any)})
  
  (def: #export (try body! excepts)
    (-> (Statement Any) (List Except) (Statement Any))
    (:abstraction
     (format "try:"
             (..nest (:representation body!))
             (|> excepts
                 (list@map (function (_ [classes exception catch!])
                             (format text.new-line "except (" (text.join-with ", " (list@map ..code classes))
                                     ") as " (:representation exception) ":"
                                     (..nest (:representation catch!)))))
                 (text.join-with "")))))

  (template [ ]
    [(def: #export ( message)
       (-> (Expression Any) (Statement Any))
       (:abstraction
        (format  " " (:representation message))))]

    [raise  "raise"]
    [return "return"]
    [print  "print"]
    )
  
  (def: #export (def name args body)
    (-> SVar (List (Ex [k] (Var k))) (Statement Any) (Statement Any))
    (:abstraction
     (format "def " (:representation name)
             "(" (|> args (list@map ..code) (text.join-with ", ")) "):"
             (..nest (:representation body)))))

  (def: #export (import module-name)
    (-> Text (Statement Any))
    (:abstraction (format "import " module-name)))

  (def: #export (comment commentary on)
    (All [brand] (-> Text (Code brand) (Code brand)))
    (:abstraction (format "# "  (..sanitize commentary) text.new-line
                          (:representation on))))
  )

(def: #export (cond clauses else!)
  (-> (List [(Expression Any) (Statement Any)]) (Statement Any) (Statement Any))
  (list@fold (.function (_ [test then!] next!)
               (..if test then! next!))
             else!
             (list.reverse clauses)))

(syntax: (arity-inputs {arity s.nat})
  (wrap (case arity
          0 (.list)
          _ (|> (dec arity)
                (list.n/range 0)
                (list@map (|>> %.nat code.local-identifier))))))

(syntax: (arity-types {arity s.nat})
  (wrap (list.repeat arity (` (Expression Any)))))

(template [ +]
  [(with-expansions [ (template.identifier ["apply/" ])
                      (arity-inputs )
                      (arity-types )
                      (template.splice +)]
     (def: #export ( function )
       (-> (Expression Any)  (Computation Any))
       (..apply/* function (.list )))

     (template []
       [(`` (def: #export (~~ (template.identifier [ "/" ]))
              ( (..var ))))]

       ))]

  [1
   [["str"]
    ["ord"]
    ["float"]
    ["int"]
    ["len"]
    ["chr"]
    ["repr"]
    ["Exception"]]]

  [2
   []]

  [3
   []]
  )