Seeing the great response to previous competitions, I thought that I'd 
start one too.

As part of a test framework I'm working on, I want to evaluate the test 
code in a separate context to avoid clashes between the code being 
tested and the test framework code.

I found it wasn't as easy as simply binding the block to a different 
context.  I've come up with a method based on adding new words in the 
code to be evaluated to the context before binding them. It seems to 
work (I haven't tested it extensively yet) but it's complicated and 
uses recursion.

I'm sure many of you can come up with simpler and non-recursive 
solutions?

My code:

  eval-ctx: make object! [
   anchor: none
   eval: function [code-block [block!]] [
     result
   ][
     bind code-block 'anchor
     if error? set/any 'result try code-block [
       result: disarm result
     ]
     result
   ]
]


evaluate: function [code-block [block!]] [
   words-to-add
   find-words-to-add
   p
   w
][
   words-to-add: copy []
   find-words-to-add: func [code-block [block!]][
     parse code-block [
       any [
         set w block! (
           find-words-to-add w             ;; recursive call
         )
         |
         set w set-word! (
           if not in eval-ctx to word! w [
             insert insert words-to-add reduce w none
           ]
         )
         |
         'set set w lit-word! (
           if not in eval-ctx w [
             insert insert words-to-add to set-word! w none
           ]
         )
         |
         set p path! set w lit-word! (
           if 'set = first p [
             if not in eval-ctx w [
               insert insert words-to-add to set-word! w none
             ]
           ]
         )
         |
         skip
       ]
     ]
   ]
   find-words-to-add code-block
   if words-to-add <> [] [
     eval-ctx: make eval-ctx words-to-add
   ]
   eval-ctx/eval code-block
]

A sample:

 >> evaluate [test1: "peter"]
[test1: "peter"]
== "peter"
 >> test1
** Script Error: test1 has no value
** Near: test1
 >> probe eval-ctx
make object! [
     anchor: none
     eval: func [code-block [block!] /local
         result
     ][
         bind code-block 'anchor
         if error? set/any 'result try code-block [
             result: disarm result
         ]
         result
     ]
     test1: "peter"
]

Regards

Peter

-- 
To unsubscribe from the list, just send an email to 
lists at rebol.com with unsubscribe as the subject.

Reply via email to