#lang scheme
(require "constants.ss"
"declare.ss"
"../private/planet.ss"
"../private/define-below.ss")
(require (for-syntax "t-or-nil.ss"
"checking-proc.ss"
(cce function)))
(provide defun
defstub
mutual-recursion)
(define-for-syntax (enforce-valid-name! stx v)
(unless (identifier? v)
(raise-syntax-error #f "expected an identifier" stx v))
(when (t-or-nil? v)
(raise-syntax-error #f "cannot bind reserved name" stx v)))
(define-for-syntax (expand-funs orig-stx funs-stx)
(case (syntax-local-context)
[( expression )
(raise-syntax-error #f "may not be used as an expression" orig-stx)]
[else
(syntax-case funs-stx ()
[((function (arg ...) body) ...)
(begin
(for-each (papply enforce-valid-name! orig-stx)
(syntax->list #'(function ... arg ... ...)))
(with-syntax ([(checked ...)
(generate-temporaries #'(function ...))])
(syntax/loc orig-stx
(begin
(define-syntaxes (function ...)
(values (checking-proc checked (arg ...)) ...))
(define-values-below (checked ...)
(let ([function (lambda (arg ...) body)] ...)
(values function ...)))))))])]))
(define-syntax (defstub stx)
(syntax-case stx ()
[(ds function (arg ...) dummy)
(expand-funs
stx
#'((function (arg ...)
(raise-user-error 'function "cannot execute a stub"))))]))
(define-syntax (defun stx)
(syntax-case stx ()
[(df function (arg ...) doc/declare ... body)
(expand-funs stx #'((function (arg ...) body)))]))
(define-syntax (mutual-recursion stx)
(syntax-case stx ()
[(mr (defun function (arg ...) doc/declare ... body) ...)
(expand-funs stx #'((function (arg ...) body) ...))]))