#lang s-exp "../../../private/restricted-runtime-scheme.ss"
(define-struct stx:atom (datum loc context))
(define-struct stx:list (elts loc context))
(define-struct Loc (offset line column span id))
(define (stx? x)
(or (stx:atom? x)
(stx:list? x)))
(define (stx-e a-stx)
(cond
[(stx:atom? a-stx)
(stx:atom-datum a-stx)]
[(stx:list? a-stx)
(stx:list-elts a-stx)]))
(define (stx-context a-stx)
(cond
[(stx:atom? a-stx)
(stx:atom-context a-stx)]
[(stx:list? a-stx)
(stx:list-context a-stx)]))
(define (stx-update-context a-stx a-ctx)
(cond
[(stx:atom? a-stx)
(make-stx:atom (stx:atom-datum a-stx)
(stx:atom-loc a-stx)
a-ctx)]
[(stx:list? a-stx)
(make-stx:list (stx:list-elts a-stx)
(stx:list-loc a-stx)
a-ctx)]))
(define (stx-loc a-stx)
(cond
[(stx:atom? a-stx)
(stx:atom-loc a-stx)]
[(stx:list? a-stx)
(stx:list-loc a-stx)]))
(define (Loc->sexp a-loc)
`(make-Loc ,(Loc-offset a-loc)
,(Loc-line a-loc)
,(Loc-column a-loc)
,(Loc-span a-loc)
,(Loc-id a-loc)))
(define (sexp->Loc an-sexp)
(cond [(and (= 6 (length an-sexp))
(symbol? (list-ref an-sexp 0))
(number? (list-ref an-sexp 1))
(number? (list-ref an-sexp 2))
(number? (list-ref an-sexp 3))
(number? (list-ref an-sexp 4))
(string? (list-ref an-sexp 5)))
(make-Loc (list-ref an-sexp 1)
(list-ref an-sexp 2)
(list-ref an-sexp 3)
(list-ref an-sexp 4)
(list-ref an-sexp 5))]))
(define (stx-begins-with? a-stx a-sym)
(cond
[(stx:atom? a-stx)
#f]
[(stx:list? a-stx)
(and (not (empty? (stx:list-elts a-stx)))
(symbol? (stx-e (first (stx:list-elts a-stx))))
(symbol=? (stx-e (first (stx:list-elts a-stx)))
a-sym))]))
(define (datum->stx context-stx a-datum a-loc)
(cond
[(stx? a-datum)
a-datum]
[(or (pair? a-datum) (empty? a-datum))
(make-stx:list (map (lambda (x) (datum->stx context-stx x a-loc)) a-datum)
a-loc
(if (stx? context-stx)
(stx-context context-stx)
#f))]
[else
(make-stx:atom a-datum a-loc
(if (stx? context-stx)
(stx-context context-stx)
context-stx))]))
(define (stx->datum a-stx)
(cond
[(stx:atom? a-stx)
(stx:atom-datum a-stx)]
[(stx:list? a-stx)
(map stx->datum (stx:list-elts a-stx))]))
(define (stx->sexp a-stx)
(cond
[(stx:atom? a-stx)
`(make-stx:atom ,(stx:atom-datum a-stx)
,(Loc->sexp (stx:atom-loc a-stx))
#f)]
[(stx:list? a-stx)
`(make-stx:list ,(map stx->sexp (stx:list-elts a-stx))
,(Loc->sexp (stx:list-loc a-stx))
#f)]))
(define (sexp->stx sexp)
(cond
[(and (list? sexp)
(equal? 'make-stx:atom (first sexp))
(= (length sexp) 4)
(boolean? (fourth sexp)))
(make-stx:atom (second sexp)
(sexp->Loc (third sexp))
(fourth sexp))]
[(and (list? sexp)
(equal? 'make-stx:list (first sexp))
(= (length sexp) 4)
(boolean? (fourth sexp)))
(make-stx:list (map sexp->stx (second sexp))
(sexp->Loc (third sexp))
(fourth sexp))]))
(define (program->sexp a-program)
(map stx->sexp a-program))
(define (sexp->program an-sexp)
(map sexp->stx an-sexp))
(provide/contract [stx:atom? (any/c . -> . boolean?)]
[stx:list? (any/c . -> . boolean?)]
[struct Loc ([offset number?]
[line number?]
[column number?]
[span number?]
[id string?])]
[Loc->sexp (Loc? . -> . any/c)]
[sexp->Loc (any/c . -> . Loc?)]
[stx? (any/c . -> . boolean?)]
[stx-e (stx? . -> . any)]
[stx-loc (stx? . -> . any)]
[stx-context (stx? . -> . (or/c false/c any/c))]
[stx-begins-with? (stx? symbol? . -> . boolean?)]
[datum->stx ((or/c false? stx?) any/c Loc? . -> . stx?)]
[stx->datum (stx? . -> . any)]
[stx->sexp (stx? . -> . any)]
[sexp->stx (any/c . -> . stx?)]
[program->sexp ((listof stx?) . -> . any)]
[sexp->program (any/c . -> . (listof stx?))]
[stx-update-context (stx? any/c . -> . stx?)])