--- a/ac.scm 2009-11-21 10:39:51.000000000 -0500 +++ b/ac.scm 2009-11-21 10:38:31.000000000 -0500 @@ -9,6 +9,23 @@ (require (lib "foreign.ss")) (unsafe!) +(define (ac-global-name s) + (string->symbol (string-append "_" (symbol->string s)))) + +(define-syntax defarc + (syntax-rules () + ((defarc (name . args) body ...) + (defarc name (name . args) body ...)) + ((defarc arc-name (scheme-name . args) body ...) + (begin + (xdef arc-name (lambda args body ...)) + (defarc arc-name scheme-name))) + ((defarc arc-name scheme-name) + (define (scheme-name . args) + (apply (namespace-variable-value (ac-global-name 'arc-name)) args))) + ((defarc name) + (defarc name name)))) + ; compile an Arc expression into a Scheme expression, ; both represented as s-expressions. ; env is a list of lexically bound variables, which we @@ -209,9 +226,6 @@ acc keepsep?)))) -(define (ac-global-name s) - (string->symbol (string-append "_" (symbol->string s)))) - (define (ac-var-ref s env) (if (lex? s env) s
Some extensions to the Arc compiler are more fun to write in Arc than in Scheme, so this patch allows a Scheme function in ac.scm
to be implemented with Arc code.
Inside of ac.scm
:
(defarc foo)
Defines in Scheme a function foo
, that when called, calls the Arc function foo
. Note that there’s no automatic translation between Scheme and Arc values in the function arguments or return value, so you may need to call ac-denil
or ac-niltree
etc. on one side or the other.
(defarc foo bar)
Defines in Scheme a function bar
, that when called, calls the Arc function foo
. (This is useful if you want to call a function in Arc when there's already a Scheme function with the same name).
(defarc (foo . args) body...)
Defines in Scheme a function foo
that calls foo
in Arc, and also provides (like xdef
) an initial definition of the Arc function in Scheme, that can be later redefined or extended in Arc.
This syntax matches that of Scheme’s define
, so that you can replace a define
with a defarc
to allow that Scheme function to be hacked in Arc.
For example, in arc3 ac.scm
, the definition of literal?
reads:
(define (literal? x) (or (boolean? x) (char? x) (string? x) (number? x) (eq? x '())))
Change the “define
” to a “defarc
”:
(defarc (literal? x) (or (boolean? x) (char? x) (string? x) (number? x) (eq? x '())))
And in Arc:
arc> literal? #<procedure:literal?>
arc> (literal? 3) #t
arc> (literal? '(a b c)) #f
(note how we’re getting Scheme true and false values here).
This is different than
(xdef literal? literal?)
because calls in the Arc compiler to the Scheme version of literal?
are actually calling the Arc literal?
version. Thus changes to literal?
in Arc will change how the Arc compiler operates. For example, suppose we wanted a byte string to be treated by Arc as a literal value (which it currently isn't):
arc> #"hello"Bad object in expression #"hello"
We can extend Arc to do that by changing the definition of literal?
in Arc:
arc> (extend literal? (x) (ac-scheme (bytes? x)) #t) #<procedure: literal?>
arc> #"hello" #"hello"
(ac-scheme
from ac lets us call Scheme code from Arc, and extend provides a convenient way of extending an Arc function).
(defarc foo (bar . args) body...)
Defines in Scheme a function bar
that calls the Arc function foo
, providing an initial definition in Scheme for the Arc function.
This is useful when we want to have the function to have a different name in Arc than in the Scheme. For example, we might prefer to have literal?
be called ac-literal
in Arc:
(defarc ac-literal (literal? x) (or (boolean? x) (char? x) (string? x) (number? x) (eq? x '())))
arc> (extend ac-literal (x) (ac-scheme (bytes? x)) #t) #<procedure: ac-literal>
arc> #"hello" #"hello"
Download defarc0.patch.
Or, using the hackinator:
hack ycombinator.com/arc/arc3.1.tar \ awwx.ws/defarc0.patch
This patch is in the public domain. The combination of this patch and Arc may be redistributed or modified under the same terms as Arc itself.