diff --git a/remix/README b/remix/README index 946a54a..e251262 100644 --- a/remix/README +++ b/remix/README @@ -1,3 +1,10 @@ +TODO add ; as #%semicolon that adds ()s between occurrences + +TODO add syntax property for def transformer on RHS (for function call +results, alloc, etc) + +TODO maybe add , as special + TODO #%dot is extensible transformer (struct posn ((complex x) y)) @@ -39,6 +46,8 @@ TODO robby's request TODO (define+ (f case) body) +TODO facts/properties macro + TODO No set! (use data-structure mutation and :=) (def (var x) 5) @@ -147,6 +156,22 @@ transformer (can change define to define-syntax/etc) vs expander functions! --- See https://mail.google.com/mail/u/0/#inbox/1513f480b3313fb2 +;; def+'s default is to use match (while def/def*'s default is to not +;; use match) + +(def+ (length '()) + 0) +(def+ (length (cons x xs)) + {(length xs) + 1}) +(def+ [contract length] (-> list? nat?)) +(def+ [doc (length l)] + @{A most excellent function + for discovering the length of lists.}) +(def+ [examples length] + {(length '()) \defs 0} + {(length '(a b c)) \defs 3}) +(def+ [provide length]) + TODO how to make sure cases of cond/etc are complete? A bare minimum dynamic solution is to do a module-lift to a test diff --git a/remix/core.rkt b/remix/core.rkt index ad21edb..12bcdeb 100644 --- a/remix/core.rkt +++ b/remix/core.rkt @@ -1,3 +1,19 @@ #lang racket/base -(provide #%module-begin +(require (for-syntax racket/base + syntax/parse)) + +(define-syntax (#%semi stx) + (raise-syntax-error '#%semi "illegal outside of block" stx)) + +(define-syntax (remix-module-begin stx) + (syntax-parse stx + #:literals (#%semi) + [(_ (~seq (~and semi-form (~not #%semi)) ... #%semi) ... + (~and tail-form (~not #%semi)) ...) + (syntax/loc stx + (#%module-begin (semi-form ...) ... tail-form ...))])) + +(provide (rename-out + [remix-module-begin #%module-begin]) + #%semi require) diff --git a/remix/lang/reader.rkt b/remix/lang/reader.rkt index c7a2ba0..dea06e3 100644 --- a/remix/lang/reader.rkt +++ b/remix/lang/reader.rkt @@ -10,6 +10,18 @@ [read-curly-brace-with-tag #t] [read-accept-dot #f] [read-accept-infix-dot #f] - [read-cdot #t]) + [read-cdot #t] + [current-readtable + (make-readtable + #f #\; 'terminating-macro + (λ (ch port [src #f] [line #f] [col #f] [pos #f]) + (define next-ch (peek-char port)) + (cond + [(eq? #\; next-ch) + (if src + (read-syntax/recursive src port ch #f) + (read/recursive port ch #f))] + [else + (datum->syntax #f '#%semi (list src line col pos (add1 pos)))])))]) (t))) (require (prefix-in at: scribble/reader))) diff --git a/remix/tests/simple.rkt b/remix/tests/simple.rkt index 5592000..94b767e 100644 --- a/remix/tests/simple.rkt +++ b/remix/tests/simple.rkt @@ -2,8 +2,9 @@ ;; #lang remix only contains two bindings: #%module-begin and require ;; ;; We use require to get everything else. most of it comes from stx0 -(require remix/stx0 - remix/num/gen0) +require remix/stx0 + remix/num/gen0; + (module+ test ;; This introduces ≡ as a testing form @@ -155,6 +156,7 @@ {v11 ≡ 11}) (def v11b + ;; ((#%dot λ (+ 10 1)) 'ignored) (λ.(+ 10 1) 'ignored)) (module+ test {v11b ≡ 11}) @@ -198,10 +200,12 @@ ;; otherwise. (def (f-no-args) 42) (def (f-one-arg x) x) +;; => (def f-one-arg (λ (x1) (def x x1) x)) (def (f-kw-arg #:x x) x) (def (f-kw-args #:x x y) (+ x y)) (def (f-def-arg (x 20) (y 22)) (+ x y)) (def (f-two-arg x y) (+ x y)) +;; (f-rest-args . x) => ((#%dot f-rest-args x)) (def (f-rest-args #%rest x) 42) (module+ test {(f-no-args) ≡ 42} @@ -234,7 +238,9 @@ (module+ test {(flip - 5 0) ≡ (- 0 5)}) +;; ... => (#%dot #%dot #%dot) ;; … (\ldots) is ... (because that doesn't work with cdots) +;; or dotdotdot or ooo or *** (def [mac (flipper f x … y)] (f y x …)) (module+ test @@ -273,8 +279,11 @@ ;; implicitly pass the binding on as the first argument to functions ;; when used. (def [example^ ee] 1) +;; => (begin (define real-ee 1) (define-syntax ee ...magic...)) (module+ test {(ee.f 2) ≡ 1} + ;; => {(example^.f real-ee 2) ≡ 2} + ;; => {(example^.f 1 2) ≡ 1} {(ee.g 2) ≡ 2}) ;; This is especially useful inside of functions @@ -321,6 +330,8 @@ ;; layout is a def-transformer (XXX I wish I could make it phase1 ;; macro also but it needs to define some functions that could be ;; called) +;; +;; XXX maybe I can expand to a submodule and local-require ;; The most basic syntax is a list of fields, which are identifiers. (def [layout posn] @@ -328,6 +339,7 @@ (module+ test ;; You will get an allocation function named #:alloc (def [posn p1] (posn.#:alloc [x 5] [y 7])) + ;; XXX (def [posn p1] #:alloc [x 5] [y 7]) ;; And accessors {p1.x ≡ 5} {p1.y ≡ 7} @@ -372,6 +384,8 @@ {qpq1.y ≡ 2} {qpq1.z ≡ 3}) +;; XXX Does it do the "right thing" for copying? + ;; A layout's fields may be specified as other layouts. When the first ;; field is a layout, this is not necessarily the same thing as a ;; parent (like C structs) but it may be. (No matter what, you'd never @@ -402,9 +416,10 @@ ;; ;; I expect to produce a few more ;; -;; (XXX) layout-c : Compatible with C -;; (XXX) layout-optimize : Optimize for removing padding and have -;; cache-line-aligned accesses +;; (XXX) layout-c : Compatible with C +;; (XXX) layout-optimize : Optimize for removing padding and have +;; cache-line-aligned accesses +;; (XXX) layout-enumerate : Use data/enumerate ;; ;; It would be possible to make layout-c right now, but define-cstruct ;; is really slow. It is trivial to have layout-optimize if you have