#lang scheme/base
(require
"../ns-tx.ss"
"../tools.ss"
"../op/static.ss"
scheme/pretty
(for-template
scheme/base
"../op.ss"
"../tools.ss"
"../scat.ss"
"../ns.ss"
"pattern-runtime.ss"
"rep.ss"
scheme/match
))
(provide
asm-pattern-tx
asm-template-tx
asm-lambda-tx
asm-transforms-tx
with-asm-transforms-tx
)
(define (syntax->warning stx)
(let ((src (syntax-source stx))
(line (syntax-line stx))
(col (syntax-column stx)))
(or
(and src line col
(format "~a:~a:~a" src line col)) "<???>")))
(define (check-ins type ins)
(syntax-case ins ()
((rator rand ...)
(if (not (identifier? #'rator))
(when #f (printf "~a: parametric ~a ~a\n"
(syntax->warning ins)
type
(syntax->datum ins)))
(op-check-syntax ins)))))
(define (srcloc stx)
#`(make-pattern-srcloc
#,(syntax-source stx)
#,(syntax-line stx)
#,(syntax-column stx)))
(define (asm-pattern-tx stx)
(map
(lambda (ins)
(syntax-case ins (unquote)
(,instruction #'instruction)
((,tag arg ...) #`(list tag arg ...))
((,tag arg ... . args) #`(list-rest tag arg ... args))
((tag arg ...) (begin
(check-ins "pattern" ins)
#`(list (? (ns (op ?) tag))
arg ...)))))
(syntax->list stx)))
(define (asm-template-tx stx)
(syntax-case stx (macro:)
(((rator rand ...) ...)
(begin
(for ((_ins (syntax->list stx))) (check-ins "template" _ins))
#`(list
#,@(for/list ((ins (syntax->list stx)))
(syntax-case ins (unquote)
(((unquote rator) rand ...) #`(list rator rand ...))
((rator rand ...) #`(op: rator rand ...))
)))
))
(_ stx)))
(define (spec->name/match-clause stx)
(syntax-case stx ()
(((asm-pattern ... name) expr)
(values
(name->identifier #'name) (let ((pattern-lst
(reverse (asm-pattern-tx
#'(asm-pattern ...))))
(template
#`(macro/append-reverse #,(asm-template-tx #'expr)
rest)))
(if (null? pattern-lst)
#`(rest #,template)
#`((list-rest #,@pattern-lst rest) #,template)
))))))
(define (specs->clause-dict specs)
(map*
(lambda (name . orig/clause)
(list name
(map first orig/clause)
(map second orig/clause)))
(collect
free-identifier=?
(map
(lambda (orig)
(let-values
(((name clause)
(spec->name/match-clause orig)))
(cons name (list orig clause)))) (syntax->list specs)))))
(define (clauses->word name clauses)
#`(pattern-tx->macro
'#,name
#,(quasisyntax/loc
name
(match-lambda
#,@clauses
(else (error 'patterns "Mismatch at: ~a" 'clauses))
))))
(define (transform-bindings specs)
(map*
(lambda (name origs clauses)
#`(#,name
(make-primitive-macro #,(clauses->word name clauses)
'#,origs)))
(specs->clause-dict specs)))
(define (asm-transforms-tx namespace specs)
#`(ns #,namespace
#,(syntax-case (transform-bindings specs) ()
(((name expr) ...)
#'(define-values (name ...) (values expr ...))))))
(define (with-asm-transforms-tx namespace specs)
#`(lambda (thunk)
(parameterize-words-ns! #,namespace
#,(transform-bindings specs)
(thunk))))
(define (asm-lambda-tx specs)
(let* ((clause-dict
(specs->clause-dict specs)))
(apply
(lambda (origs clauses)
#`(make-word
#,(clauses->word #'<anonymous> clauses)
'((pattern . #,origs))
))
(list
(apply append (map second clause-dict))
(apply append (map third clause-dict))))))