]> gitweb.factorcode.org Git - factor.git/commitdiff
locals.parser: new word with-lambda-scope to handle lexical variables
authorBjörn Lindqvist <bjourne@gmail.com>
Mon, 22 Jun 2015 08:53:03 +0000 (10:53 +0200)
committerBjörn Lindqvist <bjourne@gmail.com>
Mon, 22 Jun 2015 09:15:47 +0000 (11:15 +0200)
better, fixes #1338

By cloning the relevant parts of the manifest, you ensure that the
quotation with-lambda-scope runs can't "leak" local names in case of
restartable errors.

basis/functors/functors.factor
basis/locals/parser/parser-tests.factor
basis/locals/parser/parser.factor
core/vocabs/parser/parser-docs.factor
core/vocabs/parser/parser.factor

index 5f7eabe0404cc1f33bcc5a928e78c5470ac6661c..104e4666ec1f041b841f379fe1e1c7064be4ece2 100644 (file)
@@ -141,12 +141,6 @@ DEFER: ;FUNCTOR delimiter
 
 <PRIVATE
 
-: push-functor-words ( -- )
-    functor-words use-words ;
-
-: pop-functor-words ( -- )
-    functor-words unuse-words ;
-
 : (parse-bindings) ( end -- words )
     [ dup parse-binding dup ]
     [ first2 [ make-local ] dip 2array ]
@@ -159,16 +153,14 @@ DEFER: ;FUNCTOR delimiter
     [
         building get use-words
         (parse-bindings)
-        building get unuse-words
     ] with-bindings ;
 
 : parse-functor-body ( -- form )
-    push-functor-words
+    functor-words use-words
     "WHERE" parse-bindings
     [ [ swap <def> suffix ] { } assoc>map concat ]
-    [ [ \ ;FUNCTOR parse-until >quotation ] ((parse-lambda)) ] bi*
-    [ ] append-as
-    pop-functor-words ;
+    [ [ \ ;FUNCTOR parse-until >quotation ] with-lambda-scope ] bi*
+    [ ] append-as ;
 
 : (FUNCTOR:) ( -- word def effect )
     scan-new-word [ parse-functor-body ] parse-locals-definition ;
index 316715f92686a06097fd630e455e41d22178ecee..dca8a9bff7c3c8ee1956270a77849dfe96224f65 100644 (file)
@@ -4,18 +4,6 @@ tools.test vocabs vocabs.parser ;
 IN: locals.parser.tests
 
 <<
-! ((parse-lambda))
-{
-    "V{ 99 :> kkk kkk }"
-} [
-    [
-        "locals" use-vocab
-        { "99 :> kkk kkk ;" } <lexer> [
-            H{ } clone [ \ ; parse-until ] ((parse-lambda))
-        ] with-lexer
-    ] with-compilation-unit unparse
-] unit-test
-
 ! (::)
 {
     "dobiedoo"
@@ -67,3 +55,25 @@ IN: locals.parser.tests
     ] with-compilation-unit
     [ locals>> [ name>> ] map ] [ keys ] bi*
 ] unit-test
+
+<<
+! with-lambda-scope
+{ t } [
+    qualified-vocabs length
+    H{ } clone [
+        "hey there!" qualified-vocabs push [ ]
+    ] with-lambda-scope drop
+    qualified-vocabs length =
+] unit-test
+
+{
+    "V{ 99 :> kkk kkk }"
+} [
+    [
+        "locals" use-vocab
+        { "99 :> kkk kkk ;" } <lexer> [
+            H{ } clone [ \ ; parse-until ] with-lambda-scope
+        ] with-lexer
+    ] with-compilation-unit unparse
+] unit-test
+>>
index ba7c89110d40db48901e25246d5ad13716741eea..84ca8da4c66ed8ccebbe29cfbbbd3397e8993fe8 100644 (file)
@@ -31,15 +31,16 @@ ERROR: invalid-local-name name ;
 
 SINGLETON: lambda-parser
 
-: ((parse-lambda)) ( assoc reader-quot: ( -- quot ) -- quot )
+: with-lambda-scope ( assoc reader-quot: ( -- quot ) -- quot )
     '[
         in-lambda? on
         lambda-parser quotation-parser set
-        [ use-words @ ] [ unuse-words ] bi
+        manifest [ clone [ clone ] change-qualified-vocabs ] change
+        use-words @
     ] with-scope ; inline
 
 : (parse-lambda) ( assoc -- quot )
-    [ \ ] parse-until >quotation ] ((parse-lambda)) ;
+    [ \ ] parse-until >quotation ] with-lambda-scope ;
 
 : parse-lambda ( -- lambda )
     parse-local-defs
@@ -76,7 +77,7 @@ M: lambda-parser parse-quotation ( -- quotation )
     in>> [ dup pair? [ first ] when ] map make-locals ;
 
 : (parse-locals-definition) ( effect vars assoc reader-quot -- word quot effect )
-    ((parse-lambda)) <lambda>
+    with-lambda-scope <lambda>
     [ nip "lambda" set-word-prop ]
     [ nip rewrite-closures dup length 1 = [ first ] [ bad-rewrite ] if ]
     [ drop nip ] 3tri ; inline
index 9f60f790479de189f247d7d9e1b18c972ad05d91..95e1c81095d974bafd29fed4acd4d2364fef2980 100644 (file)
@@ -155,11 +155,6 @@ HELP: use-words
 { $description "Adds an assoc mapping word names to words to the current manifest." }
 { $notes "This word is used by " { $link "locals" } " to implement lexically-scoped names." } ;
 
-HELP: unuse-words
-{ $values { "assoc" assoc } }
-{ $description "Removes an assoc mapping word names to words from the current manifest." }
-{ $notes "This word is used by " { $link "locals" } " to implement lexically-scoped names." } ;
-
 HELP: ambiguous-use-error
 { $error-description "Thrown when a word name referenced in source file is available in more than one vocabulary in the manifest. Such cases must be explicitly disambiguated using " { $link POSTPONE: FROM: } ", " { $link POSTPONE: EXCLUDE: } ", " { $link POSTPONE: QUALIFIED: } ", or " { $link POSTPONE: QUALIFIED-WITH: } "." } ;
 
index 3751db3fba33f654b6652703263a06294ecd9ef9..a4f59bdc61b9e64cfdfe1dfbcff4259bd69b6c7e 100644 (file)
@@ -170,9 +170,6 @@ TUPLE: rename word vocab words ;
 : use-words ( assoc -- )
     <extra-words> qualified-vocabs push ;
 
-: unuse-words ( assoc -- )
-    <extra-words> qualified-vocabs remove! drop ;
-
 TUPLE: ambiguous-use-error words ;
 
 : <ambiguous-use-error> ( words -- error restarts )