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 ...) decl ... body)
     (syntax/loc stx
       (list (make-ind/static #'f (list #'x ...) (list #'decl ...) #'body)))]
    [(sig f (x ...) (y ...))
     (syntax/loc stx
       (list (make-sig/static #'f (list #'x ...) (list #'y ...))))]
    [(sig f (x ...))
     (syntax/loc stx
       (list (make-sig/static #'f (list #'x ...) #f)))]
    [(con f e options ...)
     (syntax/loc stx
       (list (make-con/static #'f #'e #'(options ...))))]
    [(include i ...)
     (syntax/loc stx
       (list
        (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 (append spec/static ...))
              (expand-keyword "cannot be used as an expression")))))])))

(define-syntax interface-macro expand-interface)