diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a8dba3f..ed6aca7 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -177,6 +177,7 @@ June 2019. - add PasteToSprunge.forth - add retro-extend.forth - add retro-embedimage.forth +- add Sandboxed-Dictionary.forth - add SaveAndRestoreStack.forth - add share.forth and shared.forth - add strip-html.forth diff --git a/example/Sandboxed-Dictionary.forth b/example/Sandboxed-Dictionary.forth new file mode 100644 index 0000000..bfcfc79 --- /dev/null +++ b/example/Sandboxed-Dictionary.forth @@ -0,0 +1,65 @@ +# Sandboxed Dictionaries + +This implements some words to create a sandboxed dictionary and +to execute a word or quotation within the sandbox. + +# Making A Sandboxed Dictionary + +The dictionary is structured as a linked list. To make a new one, +I take an array with the names from the global dictionary, extract +the header fields for each, and make a new list using them. + +The `make-dict` will return a pointer to the last entry in the new +dictionary. + +~~~ +{{ + 'D var + :unpack (d-saa) + d:lookup [ d:name ] [ d:class fetch ] [ d:xt fetch ] tri ; + :add-header (saa-) + here [ @D , , , s, ] dip !D ; +---reveal--- + :make-dict (a-a) + #0 !D [ unpack add-header ] array:for-each @D ; +}} +~~~ + +The `{ ... } make-dict` can be wrapped in something to make this +a little more obvious. + +~~~ + :dict{ (-) |{ ; immediate + :}dict (-a) |} |make-dict ; immediate +~~~ + +# Using The Sandboxed Dictionary + +I implement a very simple `d:with` to run a quote with a +sandboxed dictionary. This works by temporarily replacing +the global dictionary with the sandboxed one. + +~~~ +:d:with (qa-) + &Dictionary [ !Dictionary call ] v:preserve ; +~~~ + +# A Test Case + +This will expose a dictionary with just two words that can be +used with a new `%` prefix. + +``` +{{ + :swap $A ; + :dup $B ; + dict{ 'swap 'dup }dict 'SANDBOX const +---reveal--- + :prefix:% (s) [ s:evaluate c:put ] SANDBOX d:with ; +}} + +#70 dup swap +%swap %dup +n:put n:put +nl bye +```