[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:
parent
549a7522e3
commit
782664316d
|
@ -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]
|
||||||
|
|
|
@ -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)]))
|
||||||
|
|
|
@ -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 ...)))
|
||||||
|
|
|
@ -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]))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)])))
|
||||||
|
|
11
collects/honu/core/private/parse-helper.rkt
Normal file
11
collects/honu/core/private/parse-helper.rkt
Normal 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)]))
|
|
@ -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)]
|
||||||
|
|
|
@ -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))
|
||||||
"*/"))
|
"*/"))
|
||||||
|
|
|
@ -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)])))
|
||||||
|
|
31
collects/tests/honu/match.honu
Normal file
31
collects/tests/honu/match.honu
Normal 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
|
Loading…
Reference in New Issue
Block a user