func apply_closure (params t, args t, body t, env t) t { for ;; { if atom(params) { break; } if atom(args) { panic("Too few arguments"); } param := car (params); if !symbolp (param) { yerror ("Bad parameter", param); } env = cons (cons (car (params), car (args)), env); params = cdr (params); args = cdr (args); } if null (params) { if !null (args) { panic("Too many arguments"); } } else { if !symbolp (params) { yerror ("Bad parameter", params); } env = cons (cons (params, args), env); } return evbody (body, env); } func evbody (body t, env t) t { res := qNIL; for ;consp (body); body = cdr(body) { res = eval (car (body), env); } return res; } var catchstack t = qNIL; func evcatch (tag t, body t, env t) t { var res t; oldcatchstack := catchstack; cell := cons (tag, catchstack); catchstack = cell; defer func() { catchstack = oldcatchstack; }(); func () { defer func () { q := recover(); if q != nil { if q == cell { res = car (q); } else { panic (q); }}}(); res = evbody (body, env); }(); return res; } func throw (tag t, val t) t { for q := catchstack; consp (q); q = cdr (q) { if eq (car (q), tag) { rplaca (q, val); panic (q); }} yerror ("Throw tag not found", tag); for ;; {}} // NOTREACHED func init () { set (intern ("THROW"), throw); }