Arc Forumnew | comments | leaders | submitlogin
4 points by rocketnia 4502 days ago | link | parent

I've made a prototype for you as a DSL in Arc 3.1. Since I didn't want to call it Blub, I'm calling it Whacky, but feel free to change it. ^_^;

  (mac $ (x)
    `(cdr `(0 . ,,x)))
  
  (def whacky-call (a b)
    (let call-fn
           (fn (f arg)
             ; Get the maximum Racket arity, treating varargs arities as
             ; though the rest arg is absent.
             (caselet arity
                        (apply max
                          (map [if $.arity-at-least?._
                                 $.arity-at-least-value._
                                 _]
                            (let arity $.procedure-arity.f
                              (if (or $.procedure-arity?.arity
                                      (isa arity 'int))
                                list.arity
                                arity))))
               0  (err "Can't use a 0-arity fn in whacky.")
                  ( (afn (rev-args n)
                      (if (is n arity)
                        (apply f rev.rev-args)
                        [self (cons _ rev-args) inc.n]))
                    list.arg 1)))
      (if (isa a 'fn)               (call-fn a b)
          (in type.a 'cons 'table)  a.b
          (isa b 'fn)               (call-fn b a)
          (in type.b 'cons 'table)  b.a
        (err "Neither part of a whacky-call was a fn."))))
  
  (def whacky-compile (expr)
    (if (~acons expr)
      expr
      (let (first . rest) expr
        (zap whacky-compile first)
        (if no.rest
          first
          (reduce
            (fn (op arg)
              (if (and op (isa op 'sym) (~ssyntax op)
                       (isa (bound&eval op) 'mac))
                `(,op ,arg)
                `(',whacky-call ,op ,whacky-compile.arg)))
            (cons first rest))))))
  
  (mac wh code
    whacky-compile.code)
This uses Arc procedures, tables, and lists as procedures, uses Arc macros as macros, and resolves variables in the Arc local environment.

When a call is made using a procedure and a procedure, the first procedure is called with the second as its argument. If the first procedure has arity 0 (after ignoring varargs), this results in an error. Note that lists and tables are treated as procedures here.

When calling a procedure, varargs arguments are never passed in. If you must use a varargs Arc procedure, define a non-varargs Arc procedure that proxies it.

When calling an Arc macro, only one argument is passed in, and that argument doesn't go through whacky-compile, so its exact parentheses are significant. Notably, this means you can use "do (...)" to get back to regular Arc code.

Ssyntax isn't processed, except to protect against evaluating an ssyntax symbol when checking whether it's a macro name.

As in Arc 3.1, a global macro shadows a local procedure. If you use this code in a variant of Arc where this shadowing bug has been fixed (e.g. Anarki), there's probably no way to make this code behave properly, since the 'wh macro can't look up the local environment to see if some macro is shadowed. Instead, this implementation will compile the expression as though it's a macro call (i.e. without compiling the body), and the local function shadowing the macro will be called instead.

  arc> (wh 1)
  1
  arc> (wh ((1)))
  1
  arc> (wh 1 cons 2)
  (1 . 2)
  arc> (wh obj a)
  #hash()
  arc> (let w- (fn (a b) (- a b)) (wh - 1 w- 2))
  -3
  arc> (wh map1 list (do '(1 2 3)))
  ((1) (2) (3))
  arc> (wh list map1 (do '(1 2 3)))
  Error: "Can't use a 0-arity fn in whacky."
  arc> (wh (3 cons (1 cons 2)))
  (3 1 . 2)
  arc> (wh ((1 cons 2) cons 3))
  Error: "list-ref: expects type <non-negative exact integer> as 2nd argument, given: #<procedure:cons>; other arguments were: '(1 . 2)"
  arc> (wh (cons (1 cons 2) 3))
  ((1 . 2) . 3)
  arc> (wh len (10 cons nil))
  1
  arc> (wh (10 cons nil) 0)
  10
  arc> (wh 0 (10 cons nil))
  10
  arc> (wh 10 cons nil 0)
  10
  arc> (wh 1 - sqrt)
  0+1i
The "0-arity fn" error is due to 'list, whose varargs parameters are ignored. The 'list-ref error is due to the fact that the cons cell (1 . 2) counts as a Whacky procedure.


2 points by akkartik 4502 days ago | link

Oh this is awesome.

I spent a week thinking I should be able to crank it out with a few hours of work, but unable to actually do so. Finally I gave up and just threw the idea out there without any code, and boy am I glad I did!

Part of the problem was that hacking on wart I've forgotten that I have a mature lisp available to me.

-----

3 points by rocketnia 4502 days ago | link

You're welcome!

One thing Arc's good for is cobbled-together Arc Forum examples. ;) I'll start a thread about that, actually....

Here it is: http://arclanguage.org/item?id=16610

-----