#lang scheme/base
(require "../base.ss"
"struct.ss")
(define (quotable? val)
(or (boolean? val)
(number? val)
(string? val)
(symbol? val)
(bytes? val)
(url? val)))
(define (javascript+quotable? val)
(or (SourceElement? val)
(Expression? val)
(quotable? val)))
(define (statement+quotable? val)
(or (Statement? val)
(Expression? val)
(Identifier? val)
(quotable? val)))
(define (expression+quotable? val)
(or (Expression? val)
(Identifier? val)
(quotable? val)))
(define (identifier+quotable? val)
(or (Identifier? val)
(symbol? val)))
(define (quote-identifier id)
(cond [(Identifier? id) id]
[(symbol? id) (make-Identifier #f id)]
[else (contract-error "Expected (U symbol id), received ~a" id)]))
(define (quote-expression val)
(cond [(Expression? val) val]
[(Identifier? val) (make-VarReference #f val)]
[(boolean? val) (make-BooleanLiteral #f val)]
[(number? val) (make-NumericLiteral #f val)]
[(string? val) (make-StringLiteral #f val)]
[(symbol? val) (make-StringLiteral #f (symbol->string val))]
[(bytes? val) (make-StringLiteral #f (bytes->string/utf-8 val))]
[(url? val) (make-StringLiteral #f (url->string val))]
[else (contract-error "Expected (U term boolean number string symbol bytes url), received ~a" val)]))
(define (quote-statement val)
(cond [(Expression? val) (make-ExpressionStatement #f val)]
[(Statement? val) val]
[else (quote-statement (quote-expression val))]))
(define (quote-javascript val)
(cond [(Expression? val) (make-ExpressionStatement #f val)]
[(SourceElement? val) val]
[else (quote-statement (quote-expression val))]))
(define (wrap-begin items)
(cond [(null? items) (make-BeginStatement #f null)]
[(null? (cdr items)) (quote-javascript (car items))]
[else (make-BeginStatement #f (map quote-javascript items))]))
(define (wrap-block items)
(make-BlockStatement #f (map quote-javascript items))
(cond [(null? items) (make-BlockStatement #f (list (make-EmptyStatement #f)))]
[(null? (cdr items)) (quote-javascript (car items))]
[else (make-BlockStatement #f (map quote-javascript items))]))
(define (parenthesize-anonymous-function item)
(if (FunctionExpression? item)
(make-ParenExpression #f item)
item))
(define (contract-error format-string . args)
(raise-exn exn:fail:contract
(apply format format-string args)))
(provide/contract
[quotable? procedure?]
[javascript+quotable? procedure?]
[statement+quotable? procedure?]
[expression+quotable? procedure?]
[identifier+quotable? procedure?]
[quote-identifier (-> identifier+quotable? Identifier?)]
[quote-expression (-> expression+quotable? Expression?)]
[quote-statement (-> statement+quotable? Statement?)]
[quote-javascript (-> javascript+quotable? SourceElement?)]
[wrap-begin (-> (listof javascript+quotable?) SourceElement?)]
[wrap-block (-> (listof javascript+quotable?) SourceElement?)]
[parenthesize-anonymous-function (-> Expression? Expression?)])