[honu] honu forms implemented in racket must call honu->racket on the parsed output. add an example to do ocaml style pattern matching

This commit is contained in:
Jon Rafkind 2012-02-14 10:43:10 -07:00
parent 549a7522e3
commit 782664316d
11 changed files with 144 additions and 34 deletions

View File

@ -76,6 +76,7 @@
[literal:semicolon %semicolon] [literal:semicolon %semicolon]
[literal:honu-comma %comma] [literal:honu-comma %comma]
[literal:honu-comma %comma] [literal:honu-comma %comma]
[literal:honu-$ $]
[literal:honu-<- <-] [literal:honu-<- <-]
[literal:honu-in-lines inLines] [literal:honu-in-lines inLines]
[literal:#%brackets #%brackets] [literal:#%brackets #%brackets]

View File

@ -1,14 +1,20 @@
#lang racket/base #lang racket/base
(require syntax/parse (require syntax/parse
(for-syntax racket/base "debug.rkt" syntax/parse)
"literals.rkt") "literals.rkt")
;; to get syntax as a literal
(require (for-template racket/base))
(provide (all-defined-out)) (provide (all-defined-out))
(define (honu->racket forms) (define (honu->racket forms)
(define-literal-set literals (%racket)) (define-literal-set literals (%racket))
(syntax-parse forms #:literal-sets (literals) (syntax-parse forms #:literal-sets (literals)
#:literals ([literal-syntax syntax])
[(%racket x) (honu->racket #'x)] [(%racket x) (honu->racket #'x)]
[(literal-syntax form) #'#'form]
[(form ...) [(form ...)
(datum->syntax forms (datum->syntax forms
(map honu->racket (syntax->list #'(form ...))) (map honu->racket (syntax->list #'(form ...)))
@ -26,3 +32,31 @@
(syntax-parse code (syntax-parse code
[(x:stopper rest ...) (strip-stops #'(rest ...))] [(x:stopper rest ...) (strip-stops #'(rest ...))]
[else code])) [else code]))
(define-syntax repeat$ (lambda (stx) (raise-syntax-error 'repeat$ "dont use this")))
(define-syntax (unexpand-honu-syntax stx)
(define (remove-repeats input)
(debug "Remove repeats from ~a\n" (syntax->datum input))
(define-literal-set locals (repeat$))
(syntax-parse input #:literal-sets (locals)
[(out ... (repeat$ stuff ...) rest ...)
(debug " Found a repeat\n")
(with-syntax ([(out* ...) (map remove-repeats (syntax->list #'(out ...)))]
[(rest* ...) (map remove-repeats (syntax->list #'(rest ...)))])
(remove-repeats #'(out* ... stuff ... rest* ...)))]
[(normal ...) (with-syntax ([(normal* ...) (map remove-repeats (syntax->list #'(normal ...)))])
(datum->syntax input
#'(normal* ...)
input input))]
[x #'x]
[else (raise-syntax-error 'repeats "unhandled case" input)]))
(syntax-case stx ()
[(_ expr)
(begin
(debug "Expand honu syntax at phase ~a\n" (syntax-local-phase-level))
(debug " Is ~a expanded ~a\n" (syntax->datum #'expr) (syntax->datum #'#'expr))
(define removed (remove-repeats #'expr))
(debug "Cleansed ~a\n" (syntax->datum removed))
removed)]))

View File

@ -475,7 +475,10 @@ Then, in the pattern above for 'if', 'then' would be bound to the following synt
;; if parsed is #f then we don't want to expand to anything that will print ;; if parsed is #f then we don't want to expand to anything that will print
;; so use an empty form, begin, `parsed' could be #f becuase there was no expression ;; so use an empty form, begin, `parsed' could be #f becuase there was no expression
;; in the input such as parsing just ";". ;; in the input such as parsing just ";".
(with-syntax ([parsed (if (not parsed) #'(begin) (honu->racket parsed))] (with-syntax ([parsed (if (not parsed) #'(begin)
parsed
#;
(honu->racket parsed))]
[(unparsed ...) unparsed]) [(unparsed ...) unparsed])
(debug "Final parsed syntax\n~a\n" (pretty-format (syntax->datum #'parsed))) (debug "Final parsed syntax\n~a\n" (pretty-format (syntax->datum #'parsed)))
(if (null? (syntax->datum #'(unparsed ...))) (if (null? (syntax->datum #'(unparsed ...)))

View File

@ -333,7 +333,9 @@
(lambda (code context) (lambda (code context)
(syntax-parse code #:literal-sets (cruft) (syntax-parse code #:literal-sets (cruft)
[(var:honu-declaration . rest) [(var:honu-declaration . rest)
(define result #'(%racket (define-values (var.name ...) var.expression))) (define result
(with-syntax ([var.expression (honu->racket #'var.expression)])
#'(%racket (define-values (var.name ...) var.expression))))
(values result #'rest #t)]))) (values result #'rest #t)])))
(provide (rename-out [honu-with-syntax withSyntax])) (provide (rename-out [honu-with-syntax withSyntax]))

View File

@ -31,6 +31,7 @@
honu-for-syntax honu-for-syntax
honu-for-template honu-for-template
honu-prefix honu-prefix
honu-$
;; FIXME: in-lines should probably not be here ;; FIXME: in-lines should probably not be here
honu-in-lines honu-in-lines
%racket) %racket)

View File

@ -8,6 +8,7 @@
"literals.rkt" "literals.rkt"
"parse2.rkt" "parse2.rkt"
"debug.rkt" "debug.rkt"
"compile.rkt"
racket/base) racket/base)
(for-meta 2 syntax/parse (for-meta 2 syntax/parse
racket/base racket/base
@ -15,6 +16,7 @@
"compile.rkt") "compile.rkt")
"literals.rkt" "literals.rkt"
"syntax.rkt" "syntax.rkt"
(for-meta -1 "literals.rkt" "compile.rkt" "parse2.rkt" "parse-helper.rkt")
#; #;
(for-syntax "honu-typed-scheme.rkt") (for-syntax "honu-typed-scheme.rkt")
syntax/parse) syntax/parse)
@ -155,14 +157,29 @@
;; Do any honu-specific expansion here ;; Do any honu-specific expansion here
(define-honu-syntax honu-syntax (define-honu-syntax honu-syntax
(lambda (code context) (lambda (code context)
(define (compress-dollars stx)
(define-literal-set local-literals (honu-$))
(syntax-parse stx #:literal-sets (local-literals)
[(honu-$ x ... honu-$ rest ...)
(with-syntax ([(rest* ...) (compress-dollars #'(rest ...))])
#'((repeat$ x ...) rest* ...))]
[(x rest ...)
(with-syntax ([x* (compress-dollars #'x)]
[(rest* ...) (compress-dollars #'(rest ...))])
#'(x* rest* ...))]
[x #'x]))
(syntax-parse code #:literal-sets (cruft) (syntax-parse code #:literal-sets (cruft)
[(_ (#%parens stuff ...) . rest) [(_ (#%parens stuff ...) . rest)
(define context (stx-car #'(stuff ...))) (define context (stx-car #'(stuff ...)))
(define compressed (compress-dollars #'(stuff ...)))
(values (values
(with-syntax ([stuff* (datum->syntax context (with-syntax ([stuff* (datum->syntax context
(syntax->list #'(stuff ...)) (syntax->list compressed)
context context)]) context context)])
#'(%racket #'stuff*)) ;; (debug "Stuff is ~a\n" (syntax->datum #'stuff*))
;; (debug "Stuff syntaxed is ~a\n" (syntax->datum #'#'stuff*))
(with-syntax ([(out ...) #'stuff*])
#'(%racket #'(%racket (unexpand-honu-syntax (do-parse-rest-macro out ...))))))
#; #'(%racket-expression (parse-stuff stuff ...)) #; #'(%racket-expression (parse-stuff stuff ...))
#'rest #'rest
#f)]))) #f)])))
@ -179,17 +196,7 @@
(provide honu-pattern) (provide honu-pattern)
(define-honu-syntax honu-pattern (define-honu-syntax honu-pattern
(lambda (code context) (lambda (code context)
(define (bind-to-results pattern) (define (generate-pattern name literals original-pattern maybe-out)
(with-syntax ([((pattern-variable.name pattern-variable.result) ...)
(find-pattern-variables pattern)])
(with-syntax ([(each ...)
(for/list ([name (syntax->list #'(pattern-variable.name ...))]
[result (syntax->list #'(pattern-variable.result ...))])
(with-syntax ([name name]
[result result])
#'(#:with result result)))])
#'(each ...))))
(define (generate-pattern name literals original-pattern)
(define variables (find-pattern-variables original-pattern)) (define variables (find-pattern-variables original-pattern))
(define use (generate-temporaries variables)) (define use (generate-temporaries variables))
(define mapping (make-hash)) (define mapping (make-hash))
@ -206,8 +213,10 @@
[(literal ...) literals] [(literal ...) literals]
[(new-pattern ...) (convert-pattern original-pattern mapping)] [(new-pattern ...) (convert-pattern original-pattern mapping)]
[((withs ...) ...) withs] [((withs ...) ...) withs]
#; [(result-with ...) (if maybe-out
[((bindings ...) ...) (bind-to-results original-pattern)]) (with-syntax ([(out ...) maybe-out])
#'(#:with result (syntax out ...)))
#'())])
#'(%racket (begin-for-syntax #'(%racket (begin-for-syntax
(define-literal-set local-literals (literal ...)) (define-literal-set local-literals (literal ...))
(define-splicing-syntax-class name (define-splicing-syntax-class name
@ -215,12 +224,15 @@
[local-literals #:at name]) [local-literals #:at name])
[pattern (~seq new-pattern ...) [pattern (~seq new-pattern ...)
withs ... ... withs ... ...
; bindings ... ... result-with ...
]))))) ])))))
(syntax-parse code #:literal-sets (cruft) (syntax-parse code #:literal-sets (cruft)
[(_ name (#%parens literal ...) [(_ name (#%parens literal ...)
(#%braces pattern ...) (#%braces pattern ...)
(~optional (#%braces out ...))
. rest) . rest)
(values (generate-pattern #'name #'(literal ...) #'(pattern ...)) (values (generate-pattern #'name #'(literal ...)
#'(pattern ...)
(attribute out))
#'rest #'rest
#f)]))) #f)])))

View File

@ -0,0 +1,11 @@
#lang racket/base
(require (for-syntax racket/base
"parse2.rkt"))
(provide (all-defined-out))
(define-syntax (do-parse-rest-macro stx)
(syntax-case stx ()
[(_ stuff ...)
(do-parse-rest #'(stuff ...) #'do-parse-rest-macro)]))

View File

@ -154,13 +154,16 @@
(debug 2 "Comma? ~a ~a\n" what is) (debug 2 "Comma? ~a ~a\n" what is)
is) is)
(provide do-parse-rest)
(define (do-parse-rest stx parse-more) (define (do-parse-rest stx parse-more)
(syntax-parse stx (syntax-parse stx
[(_ stuff ...) [(stuff ...)
(define-values (parsed unparsed) (define-values (parsed unparsed)
(parse (strip-stops #'(stuff ...)))) (parse (strip-stops #'(stuff ...))))
(debug "Parse more: ~a unparsed ~a\n" parsed unparsed) (debug "Parse more: ~a unparsed ~a\n" parsed unparsed)
(define output (if parsed (define output (if parsed
parsed
#;
(honu->racket parsed) (honu->racket parsed)
#'(void))) #'(void)))
(debug "Output ~a\n" output) (debug "Output ~a\n" output)
@ -169,20 +172,29 @@
[parse-more parse-more]) [parse-more parse-more])
(if (null? (syntax->datum #'(unparsed-out ...))) (if (null? (syntax->datum #'(unparsed-out ...)))
#'output #'output
#'(begin output (parse-more unparsed-out ...))))])) #'(begin output (parse-more unparsed-out ...))))]
[() #'(begin)]))
(define (do-parse-rest/local stx) (define (do-parse-rest/local stx)
(define name (gensym 'local-parser)) (define name (gensym 'local-parser))
(define local-parser (with-syntax ([name name]) (define local-parser (with-syntax ([name name])
#'(define-syntax (name stx) #'(define-syntax (name stx)
(do-parse-rest stx #'name)))) (syntax-case stx ()
[(_ stuff (... ...))
(do-parse-rest #'(stuff (... ...)) #'name)]))))
(with-syntax ([local local-parser] (with-syntax ([local local-parser]
[parsed (do-parse-rest stx name)]) [parsed (do-parse-rest stx name)])
#'(begin local parsed))) (with-syntax ([(stx ...) stx]
[name name])
#'(begin local (name stx ...)))))
#|
(provide do-parse-rest-macro)
(define-syntax (do-parse-rest-macro stx) (define-syntax (do-parse-rest-macro stx)
(with-syntax ([stx stx]) (syntax-case stx ()
#'(do-parse-rest stx #'do-parse-rest-macro))) [(_ stuff ...)
(do-parse-rest #'(stuff ...) #'do-parse-rest-macro)]))
|#
(provide honu-body) (provide honu-body)
(define-syntax-class honu-body (define-syntax-class honu-body
@ -259,7 +271,7 @@
precedence left current) precedence left current)
(define re-parse (define re-parse
(with-syntax ([(x ...) #'parsed]) (with-syntax ([(x ...) #'parsed])
(do-parse-rest/local #'(nothing x ...)))) (do-parse-rest/local #'(x ...))))
(debug "Reparsed ~a\n" (pretty-format (syntax->datum re-parse))) (debug "Reparsed ~a\n" (pretty-format (syntax->datum re-parse)))
#; #;
(define re-parse (let-values ([(re-parse re-unparse) (define re-parse (let-values ([(re-parse re-unparse)
@ -287,7 +299,8 @@
[pattern x:str] [pattern x:str]
[pattern x:number]) [pattern x:number])
(debug "parse ~a precedence ~a left ~a current ~a\n" (syntax->datum stream) precedence left current) (debug "parse ~a precedence ~a left ~a current ~a\n"
(syntax->datum stream) precedence left current)
(define final (if current current #f)) (define final (if current current #f))
(syntax-parse stream #:literal-sets (cruft) (syntax-parse stream #:literal-sets (cruft)
#; #;
@ -299,7 +312,7 @@
(debug "Native racket expression ~a\n" #'racket) (debug "Native racket expression ~a\n" #'racket)
(if current (if current
(values (left current) stream) (values (left current) stream)
(values (left stream) #'())) (values (left #'racket) #'()))
#; #;
(if current (if current
(values (left current) stream) (values (left current) stream)
@ -325,7 +338,6 @@
[(honu-macro? #'head) [(honu-macro? #'head)
(debug "Macro ~a\n" #'head) (debug "Macro ~a\n" #'head)
(do-macro #'head #'(rest ...) precedence left current stream)] (do-macro #'head #'(rest ...) precedence left current stream)]
#;
[(parsed-syntax? #'head) [(parsed-syntax? #'head)
(debug "Parsed syntax ~a\n" #'head) (debug "Parsed syntax ~a\n" #'head)
(do-parse #'(rest ...) precedence left #'head)] (do-parse #'(rest ...) precedence left #'head)]

View File

@ -37,8 +37,8 @@
(:~ #\"))) (:~ #\")))
(define-lex-abbrev string (:: #\" (:* string-character) #\")) (define-lex-abbrev string (:: #\" (:* string-character) #\"))
(define-lex-abbrev operator (:or "+=" "-=" "*=" "/=" (define-lex-abbrev operator (:or "+=" "-=" "*=" "/="
"+" "!=" "=" "==" "*" "/" "-" "^" "||" "|" "&&" "<=" "+" "!=" "=>" "=" "==" "*" "/" "-" "^" "||" "|" "&&" "<="
">=" "<-" "<" ">" "!" "::" ":=" "%")) ">=" "<-" "<" ">" "!" "::" ":=" "%" "$"))
(define-lex-abbrev block-comment (:: "/*" (define-lex-abbrev block-comment (:: "/*"
(complement (:: any-string "*/" any-string)) (complement (:: any-string "*/" any-string))
"*/")) "*/"))

View File

@ -5,6 +5,7 @@
(for-syntax syntax/parse (for-syntax syntax/parse
racket/base racket/base
honu/core/private/literals honu/core/private/literals
honu/core/private/compile
honu/core/private/parse2)) honu/core/private/parse2))
(provide sqr) (provide sqr)
@ -22,8 +23,10 @@
[(_ (~seq clause:honu-expression colon body:honu-expression (~optional honu-comma)) ... [(_ (~seq clause:honu-expression colon body:honu-expression (~optional honu-comma)) ...
. rest) . rest)
(values (values
(with-syntax ([(clause.result ...) (map honu->racket (syntax->list #'(clause.result ...)))]
[(body.result ...) (map honu->racket (syntax->list #'(body.result ...)))])
#'(%racket (cond #'(%racket (cond
[clause.result body.result] [clause.result body.result]
...)) ...)))
#'rest #'rest
#t)]))) #t)])))

View File

@ -0,0 +1,31 @@
#lang honu
var => = 0
pattern match_pattern (){ [element:expression] } { [element] }
pattern match_clause (| =>){ | pattern:match_pattern => out:expression , }
macro mymatch(with){
thing:expression with
clause:match_clause ...
} {
syntax(
cond
$ clause_pattern == thing: clause_out, $ ...
else: -2
/*
if (clause_pattern == thing){
clause_out
} else {
-2
}
*/)
}
mymatch [1] with
| [1] => 5,
| [2] => 6,
// mymatch [1] with | [2] => 5