modular/interface.ss
#lang scheme/base

(require scheme/stxparam
         "keywords.ss"
         "dynamic-rep.ss"
         "../private/planet.ss")

(require (for-syntax scheme/base
                     (cce syntax)
                     "static-rep.ss"
                     "syntax-meta.ss"))

(provide interface-macro)

(define-for-syntax (spec->static stx)
  (syntax-case stx (fun sig con mv include)
    [(fun f (x ...) body)
     (syntax/loc stx (make-ind/static #'f (list #'x ...) #'body))]
    [(sig f (x ...) (y ...))
     (syntax/loc stx (make-sig/static #'f (list #'x ...) (list #'y ...)))]
    [(sig f (x ...))
     (syntax/loc stx (make-sig/static #'f (list #'x ...) #f))]
    [(con f e options ...)
     (syntax/loc stx (make-con/static #'f #'e #'(options ...)))]
    [(include i)
     (syntax/loc stx
       (make-include/static
        (syntax->meta #:message "not an interface" #'i)))]))

(define-for-syntax (expand-interface stx)
  (parameterize ([current-syntax stx])
    (syntax-case stx ()
      [(_ name spec ...)
       (with-syntax ([(spec/static ...)
                      (map spec->static (syntax->list #'(spec ...)))])
         (syntax/loc stx
           (define-syntax name
             (make-syntax-meta
              (make-interface/static #'name (list spec/static ...))
              (expand-keyword "cannot be used as an expression")))))])))

(define-syntax interface-macro expand-interface)