aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/math/infix.lux
blob: 145b8f579aff93fa20b133245ca94a04b8e6f3f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
(.module: {#.doc "Common mathematical constants and functions."}
  [lux #*
   [control
    monad
    ["p" parser ("parser/." Functor<Parser>)]]
   [data
    ["." product]
    [collection
     [list ("list/." Fold<List>)]]]
   [macro
    ["s" syntax (#+ syntax: Syntax)]
    ["." code]]])

(type: #rec Infix
  (#Const Code)
  (#Call (List Code))
  (#Unary Code Infix)
  (#Binary Infix Code Infix))

(def: infix^
  (Syntax Infix)
  (<| p.rec (function (_ infix^))
      ($_ p.or
          ($_ p.either
              (parser/map code.bit s.bit)
              (parser/map code.nat s.nat)
              (parser/map code.int s.int)
              (parser/map code.rev s.rev)
              (parser/map code.frac s.frac)
              (parser/map code.text s.text)
              (parser/map code.identifier s.identifier)
              (parser/map code.tag s.tag))
          (s.form (p.many s.any))
          (s.tuple (p.and s.any infix^))
          (s.tuple ($_ p.either
                       (do p.Monad<Parser>
                         [_ (s.this (' #and))
                          init-subject infix^
                          init-op s.any
                          init-param infix^
                          steps (p.some (p.and s.any infix^))]
                         (wrap (product.right (list/fold (function (_ [op param] [subject [_subject _op _param]])
                                                           [param [(#Binary _subject _op _param)
                                                                   (` and)
                                                                   (#Binary subject op param)]])
                                                         [init-param [init-subject init-op init-param]]
                                                         steps))))
                       (do p.Monad<Parser>
                         [init-subject infix^
                          init-op s.any
                          init-param infix^
                          steps (p.some (p.and s.any infix^))]
                         (wrap (list/fold (function (_ [op param] [_subject _op _param])
                                            [(#Binary _subject _op _param) op param])
                                          [init-subject init-op init-param]
                                          steps)))
                       ))
          )))

(def: (infix-to-prefix infix)
  (-> Infix Code)
  (case infix
    (#Const value)
    value
    
    (#Call parts)
    (code.form parts)

    (#Unary op subject)
    (` ((~ op) (~ (infix-to-prefix subject))))
    
    (#Binary left op right)
    (` ((~ op) (~ (infix-to-prefix right)) (~ (infix-to-prefix left))))
    ))

(syntax: #export (infix {expr infix^})
  {#.doc (doc "Infix math syntax."
              (infix [x i/* +10])
              (infix [[x i/+ y] i/* [x i/- y]])
              (infix [sin [x i/+ y]])
              (infix [[x n/< y] and [y n/< z]])
              (infix [#and x n/< y n/< z])
              (infix [(n/* 3 9) gcd 450])

              "The rules for infix syntax are simple."
              "If you want your binary function to work well with it."
              "Then take the argument to the right (y) as your first argument,"
              "and take the argument to the left (x) as your second argument.")}
  (wrap (list (infix-to-prefix expr))))