works better

dev-elider-3
Matthew Butterick 8 years ago
parent 0f6334c005
commit 2bd78a0595

@ -1,13 +1,11 @@
#lang br/demo/hdl
CHIP Not {
IN a, b, c, d;
OUT x, y, z;
IN in;
OUT out;
PARTS:
Nand(a=a, b=a, out=x);
Nand(a=a, b=a, out=y);
Nand(a=a, b=a, out=z);
Nand(a=in, b=in, out=out);
}

@ -0,0 +1,32 @@
#lang br
(provide #%top-interaction (rename-out [mb #%module-begin]))
(define #'(mb _arg ...)
#'(#%module-begin
(module treemod br/demo/hdl/expander
_arg ...)
(require 'treemod)
(chip parse-tree)))
(define #'(chip _Chip
(_input-pin ...)
(_output-pin ...)
((_Part [_pin-in _val-id] ... [out _pin-out]) ...))
#'(begin
(provide _Chip)
(define _Chip
(make-keyword-procedure
(λ (kws kw-args . rest)
(define kw-pairs (map cons kws kw-args))
(let ([_input-pin (cdr (assq (string->keyword (format "~a" '_input-pin)) kw-pairs))] ...)
(define _pin-out (call-part _Part [_pin-in _val-id] ...)) ...
(values _output-pin ...)))))))
(define #'(call-part _Part [_pin-in _val-id] ...)
(with-syntax ([part-path (format "~a.hdl" (syntax->datum #'_Part))]
[(kw ...) (map (λ(pi) (string->keyword (format "~a" (syntax->datum pi)))) (syntax->list #'(_pin-in ...)))])
#'(let ()
(local-require (rename-in part-path [_Part local-name]))
(keyword-apply local-name '(kw ...) (list _val-id ...) null))))

@ -1,54 +1,66 @@
#lang br
(provide (all-from-out br) (all-defined-out))
(require "expander0.rkt")
#|
Be your own binding procedure.
Part parser should generate inner `define`.
input-pin-spec parser should generate kw procedure.
chip-name parser should generate outer define/provide form.
(chip Not
(x)
(y))
|#
(define-for-syntax (remove-commas stx-expr)
(filter (λ(i)
(not (equal? "," (syntax->datum i)))) (syntax->list stx-expr)))
(define #'(make-kw-procedure
(pin-spec-in "IN" _pinin-or-comma ... ";")
(pin-spec-out "OUT" _pinout-or-comma ... ";")
_part-spec)
(inject-syntax ([#'(_pinin ...) (remove-commas #'(_pinin-or-comma ...))]
[#'(_pinout ...) (remove-commas #'(_pinout-or-comma ...))])
#'(make-keyword-procedure
(λ (kws kw-args . rest)
(define kw-pairs (map cons kws kw-args))
(let ([_pinin (cdr (assq (string->keyword (format "~a" '_pinin)) kw-pairs))] ...)
#;_part-spec
(define _pinout (list _pinin ...)) ...
(list _pinout ...))))))
;; next: make part-spec work
#;(define #'(part-spec "PARTS:" _part ...))
(define #'(chip-program "CHIP" _topid "{" _pin-spec-in _pin-spec-out _part-spec "}")
#`(begin
(provide _topid)
(define _topid
(make-kw-procedure _pin-spec-in _pin-spec-out _part-spec)
)
(require rackunit)
(check-equal? (_topid #:a 1 #:b 2 #:c 3 #:d 4) '((1 2 3 4)(1 2 3 4)(1 2 3 4)))))
#|
PARTS:
Nand(a=a, b=a, out=x);
|#
(provide #%top-interaction #%module-begin #%datum #%top #%app)
(provide chip-program)
(define #'(chip-program "CHIP" _arg ...)
#'(chip _arg ...))
(provide pin-spec-in)
(define #'(pin-spec-in "IN" _pin-list ";")
#'_pin-list)
(provide pin-spec-out)
(define #'(pin-spec-out "OUT" _pin-list ";")
#'_pin-list)
(require (for-syntax sugar/debug))
(provide pin-list)
(define #'(pin-list . _pin-or-commas)
(for/list ([stx (in-list (syntax->list #'_pin-or-commas))]
#:when (not (equal? "," (report (syntax->datum stx)))))
stx))
(begin-for-syntax
(define (expand-macro mac)
(syntax-disarm (report (local-expand mac 'expression #f)) #f)))
(provide part-spec)
(define #'(part-spec "PARTS:" _part-list)
#'_part-list)
(provide part-list)
(define #'(part-list _part ";")
#'_part)
(provide part)
(define #'(part _partname "(" _pin-in "=" _val-id "," _pin-in2 "=" _val-id2 "," out "=" _pin-out ")")
#'(begin
(define _pin-out (call-part _partname [_pin-in _val-id][_pin-in2 _val-id2]))))
(define #'(chip _chipname "{"
_input-pins
_output-pins
_part-spec "}")
(inject-syntax ([#'(_input-pin ...) (expand-macro #'_input-pins)]
[#'(_output-pin ...) (expand-macro #'_output-pins)]
[#'_part (expand-macro #'_part-spec)])
#'(begin
(provide _chipname)
(define _chipname
(make-keyword-procedure
(λ (kws kw-args . rest)
(define kw-pairs (map cons kws kw-args))
(let ([_input-pin (cdr (assq (string->keyword (format "~a" '_input-pin)) kw-pairs))] ...)
_part
(values _output-pin ...))))))))
(provide call-part)
(define #'(call-part _Part [_pin-in _val-id] ...)
(with-syntax ([part-path (format "~a.hdl" (syntax->datum #'_Part))]
[(kw ...) (map (λ(pi) (string->keyword (format "~a" (syntax->datum pi)))) (syntax->list #'(_pin-in ...)))])
#'(let ()
(local-require (rename-in part-path [_Part local-name]))
(keyword-apply local-name '(kw ...) (list _val-id ...) null))))

@ -2,9 +2,14 @@
chip-program : "CHIP" ID "{" pin-spec-in pin-spec-out part-spec "}"
pin-spec-in : "IN" ID ["," ID]* ";"
pin-spec-in : "IN" pin-list ";"
pin-spec-out : "OUT" ID ["," ID]* ";"
pin-spec-out : "OUT" pin-list ";"
pin-list : ID ["," ID]*
part-spec : "PARTS:" [ID "(" ID "=" ID "," [ ID "=" ID ","]* "out" "=" ID ")" ";"]+
part-spec : "PARTS:" part-list
part-list : [part ";"]+
part : ID "(" ID "=" ID ["," ID "=" ID]* ")"

@ -10,7 +10,7 @@
(lexer
[(eof) eof]
[(union #\tab #\space #\newline) (get-token input-port)]
[(union "CHIP" "IN" "OUT" "PARTS:" "out") lexeme]
[(union "CHIP" "IN" "OUT" "PARTS:") lexeme]
[(char-set "{}(),;=") lexeme]
[(repetition 1 +inf.0 (union alphabetic numeric)) (token 'ID (string->symbol lexeme))]))
(get-token input-port))

Loading…
Cancel
Save