 ! Copyright (C) 2008 James Cash
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel peg sequences arrays strings combinators.lib
-namespaces combinators math bake locals.private accessors vectors syntax lisp.parser ;
+namespaces combinators math bake locals locals.private accessors
+vectors syntax lisp.parser assocs parser sequences.lib ;
 IN: lisp
 
 DEFER: convert-form

  
: lisp-string>factor ( str -- quot )
  lisp-expr parse-result-ast convert-form ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

SYMBOL: lisp-env  

H{ } clone lisp-env set

: define-lisp-word ( name body -- )
  lisp-env get set-at ;
  
: get-lisp-word ( name -- word )  
  lisp-env get at ;
  
: funcall ( quot sym -- * )  
  name>> get-lisp-word call ;
! Functions to convert s-exps to quotations
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: convert-body ( s-exp -- quot )
  [ convert-form ] map [ ] [ compose ] reduce ; inline
  
: convert-if ( s-exp -- quot )
  rest [ convert-form ] map reverse first3  [ % , , if ] bake ;
  
: convert-begin ( s-exp -- quot )  
  rest convert-form ;
  
: convert-cond ( s-exp -- quot )  
  rest [ [ convert-form map ] map ] [ % cond ] bake ;
  
: convert-general-form ( s-exp -- quot )
  unclip convert-form swap convert-body [ , % funcall ] bake ;
  
<PRIVATE  
: localize-body ( vars body -- newbody )  
  [ dup lisp-symbol? [ tuck name>> swap member? [ name>> make-local ] [ ] if ]
                     [ dup s-exp? [ body>> localize-body <s-exp> ] [ nip ] if ] if
                   ] with map ;
  
: localize-lambda ( body vars -- newbody newvars )
  dup make-locals dup push-locals [ swap localize-body <s-exp> convert-form ] dipd
  pop-locals swap ;
  
PRIVATE>
                   
: split-lambda ( s-exp -- body vars )                   
  first3 -rot nip [ body>> ] bi@ [ name>> ] map ; inline                 
  
: rest-lambda-vars ( seq -- n newseq )  
  "&rest" swap [ remove ] [ index ] 2bi ;
  
: convert-lambda ( s-exp -- quot )  
  split-lambda dup "&rest"  swap member? [ rest-lambda-vars ] [ dup length ] if
  [ localize-lambda <lambda> ] dip
  [ , cut [ dup length firstn ] dip dup empty? [ drop ] when  , with-locals ] bake ;
  
: convert-quoted ( s-exp -- quot )  
  second [ , ] bake ;
