diff --git a/remix/data0.rkt b/remix/data0.rkt new file mode 100644 index 0000000..dd16637 --- /dev/null +++ b/remix/data0.rkt @@ -0,0 +1,55 @@ +#lang racket/base +(require (for-syntax + racket/base + syntax/parse + racket/syntax + (prefix-in remix: remix/stx0) + remix/stx/singleton-struct0 + (for-syntax racket/base + syntax/parse)) + (prefix-in remix: remix/stx0)) + +(begin-for-syntax + (define-syntax (static-interface stx) + (syntax-parse stx + #:literals (remix:#%brackets) + [(_si (remix:#%brackets lhs:id rhs:id) ...) + (with-syntax ([int-name (syntax-local-name)]) + (syntax/loc stx + (let () + (define int-id->orig-id + (make-immutable-hasheq + (list (cons 'lhs #'rhs) + ...))) + (define available-ids + (sort (hash-keys int-id->orig-id) + string<=? + #:key symbol->string)) + (define (get-binding stx x) + (define xv (syntax->datum x)) + (hash-ref int-id->orig-id + xv + (λ () + (raise-syntax-error + 'int-name + (format "Unknown component ~v, expected one of ~v" + xv + available-ids) + stx + x)))) + (singleton-struct + #:property prop:procedure + (λ (_ stx) + (raise-syntax-error 'int-name "Illegal in expression context" stx)) + #:methods remix:gen:dot-transformer + [(define (dot-transform _ stx) + (syntax-parse stx + [(_dot me:id x:id) + (get-binding stx #'x)] + [(_dot me:id x:id . more:expr) + (with-syntax ([xb (get-binding stx #'x)]) + (syntax/loc stx + (let-syntax ([x (make-rename-transformer #'xb)]) + (remix:#%dot x . more))))]))]))))]))) + +(provide (for-syntax static-interface)) diff --git a/remix/stx0.rkt b/remix/stx0.rkt index 570c248..0cb57d0 100644 --- a/remix/stx0.rkt +++ b/remix/stx0.rkt @@ -293,6 +293,7 @@ [remix-cond cond] [remix-cut-$ $]) #%rest + (rename-out [remix-block block]) #%brackets #%braces (for-syntax gen:binary-operator diff --git a/remix/tests/simple.rkt b/remix/tests/simple.rkt index 3954e72..db60702 100644 --- a/remix/tests/simple.rkt +++ b/remix/tests/simple.rkt @@ -35,6 +35,14 @@ (module+ test {(f x x) ≡ 126}) +;; That's the same as just 'block' if you want to be specific +(def (other-f x y) + (+ (block (def z (+ x x)) + z) + y)) +(module+ test + {(other-f x x) ≡ 126}) + ;; cond requires []s for the question-answer pairs. It uses this to ;; make any code in between clauses go in between the `if`s that pop ;; out of the cond macro. finally, cond REQUIRES a #:else clause. @@ -210,3 +218,31 @@ (f y x …)) (module+ test {(flipper - 5 9 0) ≡ (- 0 5 9)}) + +;; data gives us data structures and that sort of thing +(require remix/data0) + +;; First, we can define static interfaces, which associate dot-terms +;; with particular functions. +(def (example-f x y) x) +(def (example-g x y) y) +(def [stx example^] + (static-interface + [f example-f] + [g example-g])) +(module+ test + {(example^.f 1 2) ≡ 1} + {(example^.g 1 2) ≡ 2}) + +;; These static interfaces allow nesting +(def example2-h 19) +(def [stx example2^] + (static-interface + [fg example^] + [h example2-h])) +(module+ test + {(example2^.fg.f 1 2) ≡ 1} + {(example2^.fg.g 1 2) ≡ 2} + {example2^.h ≡ 19}) + +