[math] initial checkpoint
This commit is contained in:
parent
23fccba081
commit
13f44e3d78
59
math.rkt
Normal file
59
math.rkt
Normal file
|
@ -0,0 +1,59 @@
|
|||
#lang typed/racket/base
|
||||
|
||||
(provide
|
||||
+: ;-: *: /:
|
||||
;; Fold syntactic constants
|
||||
)
|
||||
|
||||
(require (for-syntax
|
||||
racket/base
|
||||
(only-in racket/format ~a)
|
||||
racket/syntax
|
||||
syntax/id-table
|
||||
syntax/parse
|
||||
trivial/private/common
|
||||
))
|
||||
|
||||
;; =============================================================================
|
||||
|
||||
(define-syntax make-numeric-operator
|
||||
(syntax-parser
|
||||
[(_ f:id)
|
||||
#:with f: (format-id #'f "~a:" (syntax-e #'f))
|
||||
#'(define-syntax f:
|
||||
(syntax-parser
|
||||
[g:id
|
||||
(syntax/loc #'g f)]
|
||||
[(g e* (... ...))
|
||||
#:with e+* (for/list ([e (in-list (syntax->list #'(e* (... ...))))])
|
||||
(expand-expr e))
|
||||
#:with e++ (reduce/op f (syntax->list #'e+*) #:src #'g)
|
||||
(syntax/loc #'g e++)]
|
||||
[(g e* (... ...))
|
||||
(syntax/loc #'g (f e* (... ...)))]))]))
|
||||
|
||||
(make-numeric-operator +)
|
||||
|
||||
;; -----------------------------------------------------------------------------
|
||||
|
||||
(define-for-syntax (reduce/op op e* #:src stx)
|
||||
(let loop ([prev #f]
|
||||
[acc '()]
|
||||
[e* e*])
|
||||
(if (null? e*)
|
||||
;; then: combine `prev` and `acc` into a list or single number
|
||||
(cond
|
||||
[(null? acc)
|
||||
(quasisyntax/loc stx #,prev)]
|
||||
[else
|
||||
(let ([acc+ (reverse (if prev (cons prev acc) acc))])
|
||||
(quasisyntax/loc stx (#,op #,@acc+)))])
|
||||
;; else: pop the next argument from e*, fold if it's a constant
|
||||
(syntax-parse (car e*)
|
||||
[n:number
|
||||
(if prev
|
||||
;; eval?
|
||||
(loop (op prev (car e*)) acc (cdr e*))
|
||||
(loop (car e*) acc (cdr e*)))]
|
||||
[e
|
||||
(loop #f (cons (car e*) (if prev (cons prev acc) acc)) (cdr e*))]))))
|
Loading…
Reference in New Issue
Block a user