diff --git a/core/classes/tuple/tuple-tests.factor b/core/classes/tuple/tuple-tests.factor index 729997d3b2..2575570d2f 100755 --- a/core/classes/tuple/tuple-tests.factor +++ b/core/classes/tuple/tuple-tests.factor @@ -529,3 +529,12 @@ TUPLE: another-forget-accessors-test ; ] unit-test [ t ] [ \ another-forget-accessors-test class? ] unit-test + +! Shadowing test +[ f ] [ + t parser-notes? [ + [ + "IN: classes.tuple.tests TUPLE: shadow-1 a b ; TUPLE: shadow-2 < shadow-1 a b ;" eval + ] with-string-writer empty? + ] with-variable +] unit-test diff --git a/core/classes/tuple/tuple.factor b/core/classes/tuple/tuple.factor index 608fb8cf6c..aa8ef6cdb7 100755 --- a/core/classes/tuple/tuple.factor +++ b/core/classes/tuple/tuple.factor @@ -55,6 +55,9 @@ PRIVATE> "slot-names" word-prop [ dup array? [ second ] when ] map ; +: all-slot-names ( class -- slots ) + superclasses [ slot-names ] map concat \ class prefix ; + : define-tuple-layout ( class -- ) dup make-tuple-layout "layout" set-word-prop ; -: all-slot-names ( class -- slots ) - superclasses [ slot-names ] map concat \ class prefix ; - : compute-slot-permutation ( class old-slot-names -- permutation ) >r all-slot-names r> [ index ] curry map ; diff --git a/core/combinators/combinators.factor b/core/combinators/combinators.factor index 139c6d8fdf..96c4009ba9 100755 --- a/core/combinators/combinators.factor +++ b/core/combinators/combinators.factor @@ -59,6 +59,10 @@ ERROR: no-case ; M: sequence hashcode* [ sequence-hashcode ] recursive-hashcode ; +M: reversed hashcode* [ sequence-hashcode ] recursive-hashcode ; + +M: slice hashcode* [ sequence-hashcode ] recursive-hashcode ; + M: hashtable hashcode* [ dup assoc-size 1 number= diff --git a/core/compiler/compiler.factor b/core/compiler/compiler.factor index a0599f79a1..6f75ca873d 100755 --- a/core/compiler/compiler.factor +++ b/core/compiler/compiler.factor @@ -1,10 +1,10 @@ ! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel namespaces arrays sequences io inference.backend -inference.state generator debugger math.parser prettyprint words -compiler.units continuations vocabs assocs alien.compiler dlists -optimizer definitions math compiler.errors threads graphs -generic inference ; +inference.state generator debugger words compiler.units +continuations vocabs assocs alien.compiler dlists optimizer +definitions math compiler.errors threads graphs generic +inference ; IN: compiler : ripple-up ( word -- ) diff --git a/core/optimizer/optimizer-tests.factor b/core/optimizer/optimizer-tests.factor index 6c6adfa3e6..c8d7a0a0a0 100755 --- a/core/optimizer/optimizer-tests.factor +++ b/core/optimizer/optimizer-tests.factor @@ -370,4 +370,7 @@ HINTS: recursive-inline-hang-2 array ; HINTS: recursive-inline-hang-3 array ; +! Regression +USE: sequences.private +[ ] [ { (3append) } compile ] unit-test diff --git a/core/parser/parser-docs.factor b/core/parser/parser-docs.factor index d11f036445..e7984f7ec3 100755 --- a/core/parser/parser-docs.factor +++ b/core/parser/parser-docs.factor @@ -153,6 +153,8 @@ ARTICLE: "parser-files" "Parsing source files" { $subsection parse-file } { $subsection bootstrap-file } "The parser cross-references source files and definitions. This allows it to keep track of removed definitions, and prevent forward references and accidental redefinitions." +$nl +"While the above words are useful for one-off experiments, real programs should be written to use the vocabulary system instead; see " { $link "vocabs.loader" } "." { $see-also "source-files" } ; ARTICLE: "parser-usage" "Reflective parser usage" @@ -161,6 +163,13 @@ ARTICLE: "parser-usage" "Reflective parser usage" "The parser can also parse from a stream:" { $subsection parse-stream } ; +ARTICLE: "top-level-forms" "Top level forms" +"Any code outside of a definition is known as a " { $emphasis "top-level form" } "; top-level forms are run after the entire source file has been parsed, regardless of their position in the file." +$nl +"Top-level forms do not have access to the " { $link in } " and " { $link use } " variables that were set at parse time, nor do they run inside " { $link with-compilation-unit } "; so meta-programming might require extra work in a top-level form compared with a parsing word." +$nl +"Also, top-level forms run in a new dynamic scope, so using " { $link set } " to store values is almost always wrong, since the values will be lost after the top-level form completes. To save values computed by a top-level form, either use " { $link set-global } " or define a new word with the value." ; + ARTICLE: "parser" "The parser" "This parser is a general facility for reading textual representations of objects and definitions. The parser is implemented in the " { $vocab-link "parser" } " and " { $vocab-link "syntax" } " vocabularies." $nl @@ -168,6 +177,7 @@ $nl { $subsection "vocabulary-search" } { $subsection "parser-files" } { $subsection "parser-usage" } +{ $subsection "top-level-forms" } "The parser can be extended." { $subsection "parsing-words" } { $subsection "parser-lexer" } diff --git a/core/parser/parser.factor b/core/parser/parser.factor index 6d091fd1c0..6c09e08f84 100755 --- a/core/parser/parser.factor +++ b/core/parser/parser.factor @@ -1,12 +1,11 @@ ! Copyright (C) 2005, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: arrays definitions generic assocs kernel math -namespaces prettyprint sequences strings vectors words -quotations inspector io.styles io combinators sorting -splitting math.parser effects continuations debugger -io.files io.streams.string vocabs io.encodings.utf8 -source-files classes hashtables compiler.errors compiler.units -accessors ; +USING: arrays definitions generic assocs kernel math namespaces +prettyprint sequences strings vectors words quotations inspector +io.styles io combinators sorting splitting math.parser effects +continuations debugger io.files io.streams.string vocabs +io.encodings.utf8 source-files classes classes.tuple hashtables +compiler.errors compiler.units accessors ; IN: parser TUPLE: lexer text line line-text line-length column ; @@ -285,13 +284,27 @@ M: no-word-error summary : CREATE-METHOD ( -- method ) scan-word bootstrap-word scan-word create-method-in ; +: shadowed-slots ( superclass slots -- shadowed ) + >r all-slot-names r> seq-intersect ; + +: check-slot-shadowing ( class superclass slots -- ) + shadowed-slots [ + [ + "Definition of slot ``" % + % + "'' in class ``" % + word-name % + "'' shadows a superclass slot" % + ] "" make note. + ] with each ; + : parse-tuple-definition ( -- class superclass slots ) CREATE-CLASS scan { { ";" [ tuple f ] } { "<" [ scan-word ";" parse-tokens ] } [ >r tuple ";" parse-tokens r> prefix ] - } case ; + } case 3dup check-slot-shadowing ; ERROR: staging-violation word ; diff --git a/core/sequences/sequences-tests.factor b/core/sequences/sequences-tests.factor index 3a30824084..281b27d540 100755 --- a/core/sequences/sequences-tests.factor +++ b/core/sequences/sequences-tests.factor @@ -1,6 +1,6 @@ USING: arrays kernel math namespaces sequences kernel.private sequences.private strings sbufs tools.test vectors bit-arrays -generic ; +generic vocabs.loader ; IN: sequences.tests [ V{ 1 2 3 4 } ] [ 1 5 dup >vector ] unit-test @@ -100,6 +100,16 @@ unit-test [ [ ] ] [ [ 1 2 3 ] 3 tail ] unit-test [ [ 3 ] ] [ [ 1 2 3 ] 2 tail ] unit-test +[ "blah" ] [ "blahxx" 2 head* ] unit-test + +[ "xx" ] [ "blahxx" 2 tail* ] unit-test + +[ t ] [ "xxfoo" 2 head-slice "xxbar" 2 head-slice = ] unit-test +[ t ] [ "xxfoo" 2 head-slice "xxbar" 2 head-slice [ hashcode ] bi@ = ] unit-test + +[ t ] [ "xxfoo" 2 head-slice SBUF" barxx" 2 tail-slice* = ] unit-test +[ t ] [ "xxfoo" 2 head-slice SBUF" barxx" 2 tail-slice* [ hashcode ] bi@ = ] unit-test + [ t ] [ [ 1 2 3 ] [ 1 2 3 ] sequence= ] unit-test [ t ] [ [ 1 2 3 ] { 1 2 3 } sequence= ] unit-test [ t ] [ { 1 2 3 } [ 1 2 3 ] sequence= ] unit-test @@ -195,6 +205,12 @@ unit-test ! Pathological case [ "ihbye" ] [ "hi" "bye" append ] unit-test +[ t ] [ "hi" SBUF" hi" = ] unit-test + +[ t ] [ "hi" SBUF" hi" = ] unit-test + +[ t ] [ "hi" SBUF" hi" [ hashcode ] bi@ = ] unit-test + [ -10 "hi" "bye" copy ] must-fail [ 10 "hi" "bye" copy ] must-fail @@ -244,3 +260,5 @@ unit-test [ "asdf " ] [ " asdf " [ CHAR: \s = ] left-trim ] unit-test [ " asdf" ] [ " asdf " [ CHAR: \s = ] right-trim ] unit-test +! Hardcore +[ ] [ "sequences" reload ] unit-test diff --git a/core/sequences/sequences.factor b/core/sequences/sequences.factor index 01a1cb9b6a..996aba8e6e 100755 --- a/core/sequences/sequences.factor +++ b/core/sequences/sequences.factor @@ -172,7 +172,9 @@ TUPLE: reversed seq ; C: reversed M: reversed virtual-seq reversed-seq ; + M: reversed virtual@ reversed-seq [ length swap - 1- ] keep ; + M: reversed length reversed-seq length ; INSTANCE: reversed virtual-sequence @@ -198,7 +200,9 @@ ERROR: slice-error reason ; slice construct-boa ; inline M: slice virtual-seq slice-seq ; + M: slice virtual@ [ slice-from + ] keep slice-seq ; + M: slice length dup slice-to swap slice-from - ; : head-slice ( seq n -- slice ) (head) ; @@ -466,6 +470,21 @@ M: sequence <=> 2dup [ length ] bi@ number= [ mismatch not ] [ 2drop f ] if ; inline +: sequence-hashcode-step ( oldhash newpart -- newhash ) + swap [ + dup -2 fixnum-shift-fast swap 5 fixnum-shift-fast + fixnum+fast fixnum+fast + ] keep fixnum-bitxor ; inline + +: sequence-hashcode ( n seq -- x ) + 0 -rot [ + hashcode* >fixnum sequence-hashcode-step + ] with each ; inline + +M: reversed equal? over reversed? [ sequence= ] [ 2drop f ] if ; + +M: slice equal? over slice? [ sequence= ] [ 2drop f ] if ; + : move ( to from seq -- ) 2over number= [ 3drop ] [ [ nth swap ] keep set-nth ] if ; inline @@ -692,14 +711,3 @@ PRIVATE> dup [ length ] map infimum [ dup like ] with map ] unless ; - -: sequence-hashcode-step ( oldhash newpart -- newhash ) - swap [ - dup -2 fixnum-shift-fast swap 5 fixnum-shift-fast - fixnum+fast fixnum+fast - ] keep fixnum-bitxor ; inline - -: sequence-hashcode ( n seq -- x ) - 0 -rot [ - hashcode* >fixnum sequence-hashcode-step - ] with each ; inline