Parser, definitions, source-files refactoring work in progress

db4
Slava Pestov 2007-12-21 21:18:24 -05:00
parent 6636a75a8a
commit 07a4022d62
43 changed files with 436 additions and 499 deletions

View File

@ -7,8 +7,6 @@ generator command-line vocabs io prettyprint libc ;
"cpu." cpu append require "cpu." cpu append require
global [ { "compiler" } add-use ] bind
"-no-stack-traces" cli-args member? [ "-no-stack-traces" cli-args member? [
f compiled-stack-traces? set-global f compiled-stack-traces? set-global
0 profiler-prologue set-global 0 profiler-prologue set-global
@ -38,16 +36,22 @@ global [ { "compiler" } add-use ] bind
find-pair-next namestack* find-pair-next namestack*
bitand bitor bitxor bitnot bitand bitor bitxor bitnot
} compile-batch } compile
{ {
+ 1+ 1- 2/ < <= > >= shift min + 1+ 1- 2/ < <= > >= shift min
} compile
{
new nth push pop peek hashcode* = get set new nth push pop peek hashcode* = get set
} compile
{
. lines . lines
} compile
{
malloc free memcpy malloc free memcpy
} [ compile ] each } compile
[ recompile ] parse-hook set-global [ compile-batch ] recompile-hook set-global

View File

@ -444,7 +444,7 @@ PRIVATE>
: make-image ( arch -- ) : make-image ( arch -- )
[ [
parse-hook off [ drop ] recompile-hook set
prepare-image prepare-image
begin-image begin-image
"resource:/core/bootstrap/stage1.factor" run-file "resource:/core/bootstrap/stage1.factor" run-file

4
core/bootstrap/primitives.factor Normal file → Executable file
View File

@ -14,7 +14,6 @@ slots classes.union words.private ;
load-help? off load-help? off
crossref off crossref off
changed-words off
! Bring up a bare cross-compiling vocabulary. ! Bring up a bare cross-compiling vocabulary.
"syntax" vocab vocab-words bootstrap-syntax set "syntax" vocab vocab-words bootstrap-syntax set
@ -144,7 +143,6 @@ H{ } clone update-map set
{ "float>" "math.private" } { "float>" "math.private" }
{ "float>=" "math.private" } { "float>=" "math.private" }
{ "<word>" "words" } { "<word>" "words" }
{ "update-xt" "words" }
{ "word-xt" "words" } { "word-xt" "words" }
{ "drop" "kernel" } { "drop" "kernel" }
{ "2drop" "kernel" } { "2drop" "kernel" }
@ -189,7 +187,7 @@ H{ } clone update-map set
{ "tag" "kernel.private" } { "tag" "kernel.private" }
{ "cwd" "io.files" } { "cwd" "io.files" }
{ "cd" "io.files" } { "cd" "io.files" }
{ "modify-code-heap" "generator" } { "modify-code-heap" "words.private" }
{ "dlopen" "alien" } { "dlopen" "alien" }
{ "dlsym" "alien" } { "dlsym" "alien" }
{ "dlclose" "alien" } { "dlclose" "alien" }

View File

@ -19,8 +19,6 @@ IN: bootstrap.stage2
parse-command-line parse-command-line
all-words [ dup ] H{ } map>assoc changed-words set-global
"-no-crossref" cli-args member? [ "-no-crossref" cli-args member? [
"Cross-referencing..." print flush "Cross-referencing..." print flush
H{ } clone crossref set-global H{ } clone crossref set-global
@ -40,20 +38,14 @@ IN: bootstrap.stage2
"listener" use+ "listener" use+
] if ] if
f parse-hook [
"exclude" "include" "exclude" "include"
[ get-global " " split [ empty? not ] subset ] 2apply [ get-global " " split [ empty? not ] subset ] 2apply
seq-diff seq-diff
[ "bootstrap." swap append require ] each [ "bootstrap." swap append require ] each
] with-variable
do-parse-hook
init-io init-io
init-stdio init-stdio
changed-words get clear-assoc
"compile-errors" "generator" lookup [ "compile-errors" "generator" lookup [
f swap set-global f swap set-global
] when* ] when*

View File

@ -63,6 +63,8 @@ f swap set-vocab-source-loaded?
"{" "{"
"}" "}"
"CS{" "CS{"
"<<"
">>"
} [ "syntax" create drop ] each } [ "syntax" create drop ] each
"t" "syntax" lookup define-symbol "t" "syntax" lookup define-symbol

6
core/classes/classes.factor Normal file → Executable file
View File

@ -277,3 +277,9 @@ M: object class type type>class ;
2 slot { word } declare ; inline 2 slot { word } declare ; inline
PRIVATE> PRIVATE>
! A dummy
TUPLE: class-definition ;
: <class-definition> ( word -- defspec )
class-definition construct-delegate ;

View File

@ -7,7 +7,7 @@ ARTICLE: "compiler-usage" "Calling the optimizing compiler"
{ $subsection compile } { $subsection compile }
"The optimizing compiler can also compile a single quotation:" "The optimizing compiler can also compile a single quotation:"
{ $subsection compile-quot } { $subsection compile-quot }
{ $subsection compile-1 } { $subsection compile-call }
"Three utility words for bulk compilation:" "Three utility words for bulk compilation:"
{ $subsection compile-batch } { $subsection compile-batch }
{ $subsection compile-vocabs } { $subsection compile-vocabs }
@ -112,9 +112,6 @@ HELP: recompile
HELP: compile-all HELP: compile-all
{ $description "Recompiles all words." } ; { $description "Recompiles all words." } ;
HELP: changed-words
{ $var-description "Global variable holding words which need to be recompiled. Implemented as a hashtable where a key equals its value. This hashtable is updated by " { $link define } " when words are redefined, and inspected and cleared by " { $link recompile } "." } ;
HELP: compile-begins HELP: compile-begins
{ $values { "word" word } } { $values { "word" word } }
{ $description "Prints a message stating the word is being compiled, unless we are inside a " { $link compile-batch } "." } ; { $description "Prints a message stating the word is being compiled, unless we are inside a " { $link compile-batch } "." } ;

View File

@ -2,12 +2,9 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces arrays sequences io inference.backend USING: kernel namespaces arrays sequences io inference.backend
generator debugger math.parser prettyprint words continuations generator debugger math.parser prettyprint words continuations
vocabs assocs alien.compiler dlists optimizer ; vocabs assocs alien.compiler dlists optimizer definitions ;
IN: compiler IN: compiler
: finish-compilation-unit ( assoc -- )
[ swap add* ] { } assoc>map modify-code-heap ;
SYMBOL: compiler-hook SYMBOL: compiler-hook
: compile-begins ( word -- ) : compile-begins ( word -- )
@ -23,7 +20,7 @@ SYMBOL: compiler-hook
[ drop ] [ [ drop ] [
compiled-usage compiled-usage
[ "was-compiled" word-prop ] subset [ "was-compiled" word-prop ] subset
[ dup changed-word queue-compile ] each [ queue-compile ] each
] if ; ] if ;
: save-effect ( word effect -- ) : save-effect ( word effect -- )
@ -37,44 +34,25 @@ SYMBOL: compiler-hook
dup word-dataflow optimize >r over dup r> generate dup word-dataflow optimize >r over dup r> generate
] [ ] [
print-error print-error
dup update-xt dup unchanged-word f dup f compiled-xts get set-at f
] recover ] recover
2dup ripple-up save-effect 2dup ripple-up save-effect
] [ drop ] if ; ] [ drop ] if ;
: with-compilation-unit ( quot -- ) : compile ( words -- )
[ [
<dlist> compile-queue set <dlist> compile-queue set
H{ } clone compiled-xts set H{ } clone compiled-xts set
call [ queue-compile ] each
compile-queue get [ (compile) ] dlist-slurp compile-queue get [ (compile) ] dlist-slurp
compiled-xts get finish-compilation-unit compiled-xts get finish-compilation-unit
] with-scope ; inline ] with-scope ; inline
: compile-batch ( words -- )
[ [ queue-compile ] each ] with-compilation-unit ;
: compile ( word -- )
[ queue-compile ] with-compilation-unit ;
: compile-vocabs ( seq -- )
[ words ] map concat compile-batch ;
: compile-quot ( quot -- word ) : compile-quot ( quot -- word )
define-temp dup compile ; [ gensym dup rot define-compound ] with-compilation-unit ;
: compile-1 ( quot -- ) : compile-call ( quot -- )
compile-quot execute ; compile-quot execute ;
: recompile ( -- )
changed-words get [
dup keys compile-batch clear-assoc
] when* ;
: forget-errors ( seq -- )
[ f "no-effect" set-word-prop ] each ;
: compile-all ( -- ) : compile-all ( -- )
all-words all-words compile-batch ;
dup forget-errors [ changed-word ] each
recompile ;

View File

@ -3,6 +3,12 @@ namespaces parser tools.test words kernel sequences arrays io
effects tools.test.inference ; effects tools.test.inference ;
IN: temporary IN: temporary
[ t ] [
changed-words get assoc-size
[ ] define-temp drop
changed-words get assoc-size =
] unit-test
parse-hook get [ parse-hook get [
DEFER: foo \ foo reset-generic DEFER: foo \ foo reset-generic
DEFER: bar \ bar reset-generic DEFER: bar \ bar reset-generic

2
core/continuations/continuations-tests.factor Normal file → Executable file
View File

@ -41,7 +41,7 @@ IN: temporary
"!!! The following error is part of the test" print "!!! The following error is part of the test" print
[ [ "2 car" ] parse ] catch print-error [ [ "2 car" ] eval ] catch print-error
[ f throw ] unit-test-fails [ f throw ] unit-test-fails

7
core/debugger/debugger.factor Normal file → Executable file
View File

@ -221,3 +221,10 @@ M: condition error-help drop f ;
M: assert summary drop "Assertion failed" ; M: assert summary drop "Assertion failed" ;
M: immutable summary drop "Sequence is immutable" ; M: immutable summary drop "Sequence is immutable" ;
M: redefine-error error.
"Re-definition of " write
redefine-error-def . ;
M: forward-error error.
"Forward reference to " write forward-error-word . ;

27
core/definitions/definitions-docs.factor Normal file → Executable file
View File

@ -82,3 +82,30 @@ HELP: delete-xref
{ $description "Remove the vertex which represents the definition from the " { $link crossref } " graph." } { $description "Remove the vertex which represents the definition from the " { $link crossref } " graph." }
{ $notes "This word is called before a word is forgotten." } { $notes "This word is called before a word is forgotten." }
{ $see-also forget } ; { $see-also forget } ;
HELP: redefine-error
{ $values { "definition" "a definition specifier" } }
{ $description "Throws a " { $link redefine-error } "." }
{ $error-description "Indicates that a single source file contains two definitions for the same artifact, one of which shadows the other. This is an error since it indicates a likely mistake, such as two words accidentally named the same by the developer; the error is restartable." } ;
HELP: redefinition?
{ $values { "definition" "a definition specifier" } { "?" "a boolean" } }
{ $description "Tests if this definition is already present in the current source file." }
$parsing-note ;
HELP: (save-location)
{ $values { "definition" "a definition specifier" } { "loc" "a " { $snippet "{ path line# }" } " pair" } }
{ $description "Saves the location of a definition and associates this definition with the current source file."
$nl
"This is the book-keeping required to detect " { $link redefine-error } " and " { $link forward-error } "." } ;
HELP: old-definitions
{ $var-description "Stores an assoc where the keys form the set of definitions which were defined by " { $link file } " the most recent time it was loaded." } ;
HELP: new-definitions
{ $var-description "Stores an assoc where the keys form the set of definitions which were defined so far by the current parsing of " { $link file } "." } ;
HELP: forward-error
{ $values { "word" word } }
{ $description "Throws a " { $link forward-error } "." }
{ $description "Indicates a word is being referenced prior to the location of its most recent definition. This can only happen if a source file is loaded, and subsequently edited such that two dependent definitions are reversed." } ;

36
core/definitions/definitions.factor Normal file → Executable file
View File

@ -1,7 +1,7 @@
! Copyright (C) 2006, 2007 Slava Pestov. ! Copyright (C) 2006, 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: definitions IN: definitions
USING: kernel sequences namespaces assocs graphs ; USING: kernel sequences namespaces assocs graphs continuations ;
GENERIC: where ( defspec -- loc ) GENERIC: where ( defspec -- loc )
@ -43,3 +43,37 @@ M: object redefined* drop ;
: delete-xref ( defspec -- ) : delete-xref ( defspec -- )
dup unxref crossref get delete-at ; dup unxref crossref get delete-at ;
SYMBOL: changed-words
SYMBOL: old-definitions
SYMBOL: new-definitions
TUPLE: redefine-error def ;
: redefine-error ( definition -- )
\ redefine-error construct-boa
{ { "Continue" t } } throw-restarts drop ;
: redefinition? ( definition -- ? )
new-definitions get key? ;
: (save-location) ( definition loc -- )
over redefinition? [ over redefine-error ] when
over set-where
dup new-definitions get set-at ;
TUPLE: forward-error word ;
: forward-error ( word -- )
\ forward-error construct-boa throw ;
SYMBOL: recompile-hook
: with-compilation-unit ( quot -- new-defs )
[
H{ } clone changed-words set
H{ } clone new-definitions set
old-definitions off
call
changed-words get keys recompile-hook get call
] with-scope ; inline

View File

@ -26,10 +26,6 @@ HELP: compiling?
{ $values { "word" word } { "?" "a boolean" } } { $values { "word" word } { "?" "a boolean" } }
{ $description "Tests if a word is going to be or already is compiled." } ; { $description "Tests if a word is going to be or already is compiled." } ;
HELP: modify-code-heap ( array -- )
{ $values { "array" "an array of 6-element arrays having shape " { $snippet "{ word code labels rel words literals }" } } }
{ $description "Stores compiled code definitions in the code heap and updates words to point at those definitions." } ;
HELP: compiling-word HELP: compiling-word
{ $var-description "The word currently being compiled, set by " { $link generate-1 } "." } ; { $var-description "The word currently being compiled, set by " { $link generate-1 } "." } ;

View File

@ -17,7 +17,7 @@ SYMBOL: compiled-xts
f swap compiled-xts get set-at ; f swap compiled-xts get set-at ;
: finish-compiling ( word literals words rel labels code -- ) : finish-compiling ( word literals words rel labels code -- )
6array swap dup unchanged-word compiled-xts get set-at ; 6array swap compiled-xts get set-at ;
: compiling? ( word -- ? ) : compiling? ( word -- ? )
{ {

View File

@ -120,7 +120,7 @@ TUPLE: delegating ;
[ t ] [ \ + math-generic? ] unit-test [ t ] [ \ + math-generic? ] unit-test
[ "SYMBOL: not-a-class C: not-a-class ;" parse ] unit-test-fails [ "SYMBOL: not-a-class C: not-a-class ;" eval ] unit-test-fails
! Test math-combination ! Test math-combination
[ [ [ >float ] dip ] ] [ \ real \ float math-upgrade ] unit-test [ [ [ >float ] dip ] ] [ \ real \ float math-upgrade ] unit-test

3
core/inference/inference.factor Normal file → Executable file
View File

@ -25,3 +25,6 @@ M: callable dataflow-with
V{ } like meta-d set V{ } like meta-d set
f infer-quot f infer-quot
] with-infer nip ; ] with-infer nip ;
: forget-errors ( seq -- )
[ f "no-effect" set-word-prop ] each ;

2
core/inference/known-words/known-words.factor Normal file → Executable file
View File

@ -344,8 +344,6 @@ t over set-effect-terminated?
\ <word> { object object } { word } <effect> "inferred-effect" set-word-prop \ <word> { object object } { word } <effect> "inferred-effect" set-word-prop
\ <word> make-flushable \ <word> make-flushable
\ update-xt { word } { } <effect> "inferred-effect" set-word-prop
\ word-xt { word } { integer } <effect> "inferred-effect" set-word-prop \ word-xt { word } { integer } <effect> "inferred-effect" set-word-prop
\ word-xt make-flushable \ word-xt make-flushable

12
core/io/crc32/crc32.factor Normal file → Executable file
View File

@ -1,23 +1,19 @@
! Copyright (C) 2006 Doug Coleman ! Copyright (C) 2006 Doug Coleman
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel math sequences sequences.private namespaces USING: kernel math sequences sequences.private namespaces
words io io.binary io.files io.streams.string quotations ; words io io.binary io.files io.streams.string quotations
definitions ;
IN: io.crc32 IN: io.crc32
: crc32-polynomial HEX: edb88320 ; inline : crc32-polynomial HEX: edb88320 ; inline
! Generate the table at load time and define a new word with it, : crc32-table V{ } ; inline
! instead of using a variable, so that the compiler can inline
! the call to nth-unsafe
DEFER: crc32-table inline
\ crc32-table
256 [ 256 [
8 [ 8 [
dup even? >r 2/ r> [ crc32-polynomial bitxor ] unless dup even? >r 2/ r> [ crc32-polynomial bitxor ] unless
] times >bignum ] times >bignum
] map ] map 0 crc32-table copy
1quotation define-inline
: (crc32) ( crc ch -- crc ) : (crc32) ( crc ch -- crc )
>bignum dupd bitxor >bignum dupd bitxor

4
core/kernel/kernel-docs.factor Normal file → Executable file
View File

@ -552,3 +552,7 @@ $nl
"[ P ] [ Q ] [ ] while T" "[ P ] [ Q ] [ ] while T"
} }
"However, depending on the stack effects of " { $snippet "pred" } " and " { $snippet "quot" } ", the " { $snippet "tail" } " quotation might need to be non-empty in order to balance out the stack effect of branches for stack effect inference." } ; "However, depending on the stack effects of " { $snippet "pred" } " and " { $snippet "quot" } ", the " { $snippet "tail" } " quotation might need to be non-empty in order to balance out the stack effect of branches for stack effect inference." } ;
HELP: modify-code-heap ( array -- )
{ $values { "array" "an array of 6-element arrays having shape " { $snippet "{ word code labels rel words literals }" } } }
{ $description "Stores compiled code definitions in the code heap and updates words to point at those definitions." } ;

0
core/kernel/kernel.factor Normal file → Executable file
View File

View File

@ -3,7 +3,7 @@
USING: arrays hashtables io kernel math memory namespaces USING: arrays hashtables io kernel math memory namespaces
parser sequences strings io.styles io.streams.lines parser sequences strings io.styles io.streams.lines
io.streams.duplex vectors words generic system combinators io.streams.duplex vectors words generic system combinators
tuples continuations debugger ; tuples continuations debugger definitions ;
IN: listener IN: listener
SYMBOL: quit-flag SYMBOL: quit-flag
@ -12,31 +12,34 @@ SYMBOL: listener-hook
[ ] listener-hook set-global [ ] listener-hook set-global
GENERIC: parse-interactive ( stream -- quot/f ) GENERIC: stream-read-quot ( stream -- quot/f )
: parse-interactive-step ( lines -- quot/f ) : read-quot-step ( lines -- quot/f )
[ parse-lines ] catch { [ parse-lines ] catch {
{ [ dup delegate unexpected-eof? ] [ 2drop f ] } { [ dup delegate unexpected-eof? ] [ 2drop f ] }
{ [ dup not ] [ drop ] } { [ dup not ] [ drop ] }
{ [ t ] [ rethrow ] } { [ t ] [ rethrow ] }
} cond ; } cond ;
: parse-interactive-loop ( stream accum -- quot/f ) : read-quot-loop ( stream accum -- quot/f )
over stream-readln dup [ over stream-readln dup [
over push over push
dup parse-interactive-step dup dup read-quot-step dup
[ 2nip ] [ drop parse-interactive-loop ] if [ 2nip ] [ drop read-quot-loop ] if
] [ ] [
3drop f 3drop f
] if ; ] if ;
M: line-reader parse-interactive M: line-reader stream-read-quot
[ V{ } clone read-quot-loop ;
V{ } clone parse-interactive-loop in get
] with-scope in set ;
M: duplex-stream parse-interactive M: duplex-stream stream-read-quot
duplex-stream-in parse-interactive ; duplex-stream-in stream-read-quot ;
: read-quot ( -- quot )
[
stdio get stream-read-quot in get
] with-compilation-unit in set ;
: bye ( -- ) quit-flag on ; : bye ( -- ) quit-flag on ;
@ -46,10 +49,7 @@ M: duplex-stream parse-interactive
: listen ( -- ) : listen ( -- )
listener-hook get call prompt. listener-hook get call prompt.
[ [ read-quot [ call ] [ bye ] if* ] try ;
stdio get parse-interactive
[ call ] [ bye ] if*
] try ;
: until-quit ( -- ) : until-quit ( -- )
quit-flag get quit-flag get

View File

@ -231,22 +231,6 @@ HELP: location
{ $values { "loc" "a " { $snippet "{ path line# }" } " pair" } } { $values { "loc" "a " { $snippet "{ path line# }" } " pair" } }
{ $description "Outputs the current parser location. This value can be passed to " { $link set-where } " or " { $link (save-location) } "." } ; { $description "Outputs the current parser location. This value can be passed to " { $link set-where } " or " { $link (save-location) } "." } ;
HELP: redefine-error
{ $values { "definition" "a definition specifier" } }
{ $description "Throws a " { $link redefine-error } "." }
{ $error-description "Indicates that a single source file contains two definitions for the same artifact, one of which shadows the other. This is an error since it indicates a likely mistake, such as two words accidentally named the same by the developer; the error is restartable." } ;
HELP: redefinition?
{ $values { "definition" "a definition specifier" } { "?" "a boolean" } }
{ $description "Tests if this definition is already present in the current source file." }
$parsing-note ;
HELP: (save-location)
{ $values { "definition" "a definition specifier" } { "loc" "a " { $snippet "{ path line# }" } " pair" } }
{ $description "Saves the location of a definition and associates this definition with the current source file."
$nl
"This is the book-keeping required to detect " { $link redefine-error } " and " { $link forward-error } "." } ;
HELP: save-location HELP: save-location
{ $values { "definition" "a definition specifier" } } { $values { "definition" "a definition specifier" } }
{ $description "Saves the location of a definition and associates this definition with the current source file." { $description "Saves the location of a definition and associates this definition with the current source file."
@ -264,15 +248,6 @@ HELP: next-line
{ $values { "lexer" lexer } } { $values { "lexer" lexer } }
{ $description "Advances the lexer to the next input line, discarding the remainder of the current line." } ; { $description "Advances the lexer to the next input line, discarding the remainder of the current line." } ;
HELP: file
{ $var-description "Stores the " { $link source-file } " being parsed. The " { $link source-file-path } " of this object comes from the input parameter to " { $link parse-stream } "." } ;
HELP: old-definitions
{ $var-description "Stores an assoc where the keys form the set of definitions which were defined by " { $link file } " the most recent time it was loaded." } ;
HELP: new-definitions
{ $var-description "Stores an assoc where the keys form the set of definitions which were defined so far by the current parsing of " { $link file } "." } ;
HELP: parse-error HELP: parse-error
{ $error-description "Thrown when the parser encounters invalid input. A parse error wraps an underlying error and holds the file being parsed, line number, and column number." } ; { $error-description "Thrown when the parser encounters invalid input. A parse error wraps an underlying error and holds the file being parsed, line number, and column number." } ;
@ -417,11 +392,6 @@ HELP: search
{ $description "Searches for a word by name in the current vocabulary search path. If no such word could be found, throws a " { $link no-word } " error. If the search path does not contain a word with this name but other vocabularies do, the error will have restarts offering to add vocabularies to the search path." } { $description "Searches for a word by name in the current vocabulary search path. If no such word could be found, throws a " { $link no-word } " error. If the search path does not contain a word with this name but other vocabularies do, the error will have restarts offering to add vocabularies to the search path." }
$parsing-note ; $parsing-note ;
HELP: forward-error
{ $values { "word" word } }
{ $description "Throws a " { $link forward-error } "." }
{ $description "Indicates a word is being referenced prior to the location of its most recent definition. This can only happen if a source file is loaded, and subsequently edited such that two dependent definitions are reversed." } ;
HELP: scan-word HELP: scan-word
{ $values { "word/number/f" "a word, number or " { $link f } } } { $values { "word/number/f" "a word, number or " { $link f } } }
{ $description "Reads the next token from parser input. If the token is a valid number literal, it is converted to a number, otherwise the dictionary is searched for a word named by the token. Outputs " { $link f } " if the end of the input has been reached." } { $description "Reads the next token from parser input. If the token is a valid number literal, it is converted to a number, otherwise the dictionary is searched for a word named by the token. Outputs " { $link f } " if the end of the input has been reached." }
@ -510,11 +480,6 @@ HELP: bootstrap-syntax
HELP: file-vocabs HELP: file-vocabs
{ $description "Installs the initial the vocabulary search path for parsing a file. This consists of the " { $snippet "syntax" } " vocabulary together with the " { $snippet "scratchpad" } " vocabulary." } ; { $description "Installs the initial the vocabulary search path for parsing a file. This consists of the " { $snippet "syntax" } " vocabulary together with the " { $snippet "scratchpad" } " vocabulary." } ;
HELP: parse
{ $values { "str" string } { "quot" quotation } }
{ $description "Parses Factor source code from a string. The current vocabulary search path is used." }
{ $errors "Throws a parse error if the input is malformed." } ;
HELP: parse-fresh HELP: parse-fresh
{ $values { "lines" "a sequence of strings" } { "quot" quotation } } { $values { "lines" "a sequence of strings" } { "quot" quotation } }
{ $description "Parses Factor source code in a sequence of lines. The initial vocabulary search path is used (see " { $link file-vocabs } ")." } { $description "Parses Factor source code in a sequence of lines. The initial vocabulary search path is used (see " { $link file-vocabs } ")." }
@ -525,17 +490,6 @@ HELP: eval
{ $description "Parses Factor source code from a string, and calls the resulting quotation. The current vocabulary search path is used." } { $description "Parses Factor source code from a string, and calls the resulting quotation. The current vocabulary search path is used." }
{ $errors "Throws an error if the input is malformed, or if the quotation throws an error." } ; { $errors "Throws an error if the input is malformed, or if the quotation throws an error." } ;
HELP: parse-hook
{ $var-description "A quotation called by " { $link parse-stream } " after parsing the input stream. The default value recompiles new word definitions; see " { $link "recompile" } " for details." } ;
{ parse-hook do-parse-hook } related-words
HELP: start-parsing
{ $values { "stream" "an input stream" } { "name" "a pathname string" } }
{ $description "Prepares to parse a source file by reading the entire contents of the stream and setting some variables. The pathname identifies the stream for cross-referencing purposes." }
{ $errors "Throws an I/O error if there was an error reading from the stream." }
{ $notes "This is one of the factors of " { $link parse-stream } "." } ;
HELP: outside-usages HELP: outside-usages
{ $values { "seq" "a sequence of definitions" } { "usages" "an association list mapping definitions to sequences of definitions" } } { $values { "seq" "a sequence of definitions" } { "usages" "an association list mapping definitions to sequences of definitions" } }
{ $description "Outputs an association list mapping elements of " { $snippet "seq" } " to lists of usages which exclude the definitions in " { $snippet "seq" } " themselves." } ; { $description "Outputs an association list mapping elements of " { $snippet "seq" } " to lists of usages which exclude the definitions in " { $snippet "seq" } " themselves." } ;
@ -551,18 +505,11 @@ HELP: smudged-usage
HELP: forget-smudged HELP: forget-smudged
{ $description "Forgets removed definitions and prints a warning message if any of them are still referenced from other source files." } ; { $description "Forgets removed definitions and prints a warning message if any of them are still referenced from other source files." } ;
HELP: record-definitions
{ $values { "file" source-file } }
{ $description "Records that all " { $link new-definitions } " were defined in " { $snippet "file" } "." } ;
HELP: finish-parsing HELP: finish-parsing
{ $values { "quot" "the quotation just parsed" } } { $values { "quot" "the quotation just parsed" } }
{ $description "Records information to the current " { $link file } " and prints warnings about any removed definitions which are still in use." } { $description "Records information to the current " { $link file } " and prints warnings about any removed definitions which are still in use." }
{ $notes "This is one of the factors of " { $link parse-stream } "." } ; { $notes "This is one of the factors of " { $link parse-stream } "." } ;
HELP: undo-parsing
{ $description "Records information to the current " { $link file } " after an incomplete parse which ended with an error." } ;
HELP: parse-stream HELP: parse-stream
{ $values { "stream" "an input stream" } { "name" "a file name for error reporting and cross-referencing" } { "quot" quotation } } { $values { "stream" "an input stream" } { "name" "a file name for error reporting and cross-referencing" } { "quot" quotation } }
{ $description "Parses Factor source code read from the stream. The initial vocabulary search path is used." } { $description "Parses Factor source code read from the stream. The initial vocabulary search path is used." }
@ -582,20 +529,6 @@ HELP: ?run-file
{ $values { "path" "a pathname string" } } { $values { "path" "a pathname string" } }
{ $description "If the file exists, runs it with " { $link run-file } ", otherwise does nothing." } ; { $description "If the file exists, runs it with " { $link run-file } ", otherwise does nothing." } ;
HELP: reload
{ $values { "defspec" "a definition specifier" } }
{ $description "Reloads the source file containing the definition." }
{ $examples
"Reloading a word definition:"
{ $code "\\ foo reload" }
"A word's documentation:"
{ $code "\\ foo >link reload" }
"A method definition:"
{ $code "{ editor draw-gadget* } reload" }
"A help article:"
{ $code "\"handbook\" >link reload" }
} ;
HELP: bootstrap-file HELP: bootstrap-file
{ $values { "path" "a pathname string" } } { $values { "path" "a pathname string" } }
{ $description "If bootstrapping, parses the source file and adds its top level form to the quotation being constructed with " { $link make } "; the bootstrap code uses this to build up a boot quotation to be run on image startup. If not bootstrapping, just runs the file normally." } ; { $description "If bootstrapping, parses the source file and adds its top level form to the quotation being constructed with " { $link make } "; the bootstrap code uses this to build up a boot quotation to be run on image startup. If not bootstrapping, just runs the file normally." } ;

87
core/parser/parser-tests.factor Normal file → Executable file
View File

@ -19,46 +19,46 @@ IN: temporary
[ 6 CHAR: \s ] [ 6 CHAR: \s ]
[ 0 "\\u0020hello" next-char ] unit-test [ 0 "\\u0020hello" next-char ] unit-test
[ [ 1 [ 2 [ 3 ] 4 ] 5 ] ] [ 1 [ 2 [ 3 ] 4 ] 5 ]
[ "1\n[\n2\n[\n3\n]\n4\n]\n5" parse ] [ "1\n[\n2\n[\n3\n]\n4\n]\n5" eval ]
unit-test unit-test
[ [ t t f f ] ] [ t t f f ]
[ "t t f f" parse ] [ "t t f f" eval ]
unit-test unit-test
[ [ "hello world" ] ] [ "hello world" ]
[ "\"hello world\"" parse ] [ "\"hello world\"" eval ]
unit-test unit-test
[ [ "\n\r\t\\" ] ] [ "\n\r\t\\" ]
[ "\"\\n\\r\\t\\\\\"" parse ] [ "\"\\n\\r\\t\\\\\"" eval ]
unit-test unit-test
[ "hello world" ] [ "hello world" ]
[ [
"IN: temporary : hello \"hello world\" ;" "IN: temporary : hello \"hello world\" ;"
parse call "USE: scratchpad hello" eval eval "USE: temporary hello" eval
] unit-test ] unit-test
[ ] [ ]
[ "! This is a comment, people." parse call ] [ "! This is a comment, people." eval ]
unit-test unit-test
! Test escapes ! Test escapes
[ [ " " ] ] [ " " ]
[ "\"\\u0020\"" parse ] [ "\"\\u0020\"" eval ]
unit-test unit-test
[ [ "'" ] ] [ "'" ]
[ "\"\\u0027\"" parse ] [ "\"\\u0027\"" eval ]
unit-test unit-test
[ "\\u123" parse ] unit-test-fails [ "\\u123" eval ] unit-test-fails
! Test EOL comments in multiline strings. ! Test EOL comments in multiline strings.
[ [ "Hello" ] ] [ "#! This calls until-eol.\n\"Hello\"" parse ] unit-test [ "Hello" ] [ "#! This calls until-eol.\n\"Hello\"" eval ] unit-test
[ word ] [ \ f class ] unit-test [ word ] [ \ f class ] unit-test
@ -80,7 +80,7 @@ IN: temporary
[ \ baz "declared-effect" word-prop effect-terminated? ] [ \ baz "declared-effect" word-prop effect-terminated? ]
unit-test unit-test
[ [ ] ] [ "IN: temporary USE: math : effect-parsing-test ( a b -- d ) - ;" parse ] unit-test [ ] [ "IN: temporary USE: math : effect-parsing-test ( a b -- d ) - ;" eval ] unit-test
[ t ] [ [ t ] [
"effect-parsing-test" "temporary" lookup "effect-parsing-test" "temporary" lookup
@ -90,7 +90,7 @@ IN: temporary
[ T{ effect f { "a" "b" } { "d" } f } ] [ T{ effect f { "a" "b" } { "d" } f } ]
[ \ effect-parsing-test "declared-effect" word-prop ] unit-test [ \ effect-parsing-test "declared-effect" word-prop ] unit-test
[ [ ] ] [ "IN: temporary : effect-parsing-test ;" parse ] unit-test [ ] [ "IN: temporary : effect-parsing-test ;" eval ] unit-test
[ f ] [ \ effect-parsing-test "declared-effect" word-prop ] unit-test [ f ] [ \ effect-parsing-test "declared-effect" word-prop ] unit-test
@ -100,12 +100,12 @@ IN: temporary
[ "IN: temporary : missing-- ( a b ) ;" eval ] unit-test-fails [ "IN: temporary : missing-- ( a b ) ;" eval ] unit-test-fails
! These should throw errors ! These should throw errors
[ "HEX: zzz" parse ] unit-test-fails [ "HEX: zzz" eval ] unit-test-fails
[ "OCT: 999" parse ] unit-test-fails [ "OCT: 999" eval ] unit-test-fails
[ "BIN: --0" parse ] unit-test-fails [ "BIN: --0" eval ] unit-test-fails
[ f ] [ [ f ] [
"IN: temporary : foo ; TUPLE: foo ;" parse drop "IN: temporary : foo ; TUPLE: foo ;" eval
"foo" "temporary" lookup symbol? "foo" "temporary" lookup symbol?
] unit-test ] unit-test
@ -126,13 +126,13 @@ IN: temporary
"IN: temporary USING: math prettyprint ; : foo 2 2 + . ; parsing" eval "IN: temporary USING: math prettyprint ; : foo 2 2 + . ; parsing" eval
[ [ ] ] [ "USE: temporary foo" parse ] unit-test [ ] [ "USE: temporary foo" eval ] unit-test
"IN: temporary USING: math prettyprint ; : foo 2 2 + . ;" eval "IN: temporary USING: math prettyprint ; : foo 2 2 + . ;" eval
[ t ] [ [ t ] [
"USE: temporary foo" parse "USE: temporary \\ foo" eval
first "foo" "temporary" lookup eq? "foo" "temporary" lookup eq?
] unit-test ] unit-test
! Test smudging ! Test smudging
@ -323,12 +323,43 @@ IN: temporary
<string-reader> "removing-the-predicate" parse-stream <string-reader> "removing-the-predicate" parse-stream
] catch [ redefine-error? ] is? ] catch [ redefine-error? ] is?
] unit-test ] unit-test
[ t ] [
[
"IN: temporary TUPLE: class-redef-test ; TUPLE: class-redef-test ;"
<string-reader> "redefining-a-class-1" parse-stream
] catch [ redefine-error? ] is?
] unit-test
[ ] [
"IN: temporary TUPLE: class-redef-test ; SYMBOL: class-redef-test"
<string-reader> "redefining-a-class-2" parse-stream drop
] unit-test
[ t ] [
[
"IN: temporary TUPLE: class-redef-test ; SYMBOL: class-redef-test : class-redef-test ;"
<string-reader> "redefining-a-class-3" parse-stream drop
] catch [ redefine-error? ] is?
] unit-test
[ t ] [
[
"IN: temporary \\ class-fwd-test TUPLE: class-fwd-test ;"
<string-reader> "redefining-a-class-3" parse-stream drop
] catch [ forward-error? ] is?
] unit-test
[ t ] [
[
"IN: temporary \\ class-fwd-test TUPLE: class-fwd-test ; SYMBOL: class-fwd-test"
<string-reader> "redefining-a-class-3" parse-stream drop
] catch [ forward-error? ] is?
] unit-test
] with-scope ] with-scope
[ [
: FILE file get parsed ; parsing << file get parsed >> file set
FILE file set
: ~a ; : ~a ;
: ~b ~a ; : ~b ~a ;

View File

@ -8,8 +8,6 @@ io.files io.streams.string io.streams.lines vocabs
source-files classes hashtables ; source-files classes hashtables ;
IN: parser IN: parser
SYMBOL: file
TUPLE: lexer text line column ; TUPLE: lexer text line column ;
: <lexer> ( text -- lexer ) 1 0 lexer construct-boa ; : <lexer> ( text -- lexer ) 1 0 lexer construct-boa ;
@ -21,27 +19,6 @@ TUPLE: lexer text line column ;
file get lexer get lexer-line 2dup and file get lexer get lexer-line 2dup and
[ >r source-file-path r> 2array ] [ 2drop f ] if ; [ >r source-file-path r> 2array ] [ 2drop f ] if ;
SYMBOL: old-definitions
SYMBOL: new-definitions
TUPLE: redefine-error def ;
M: redefine-error error.
"Re-definition of " write
redefine-error-def . ;
: redefine-error ( definition -- )
\ redefine-error construct-boa
{ { "Continue" t } } throw-restarts drop ;
: redefinition? ( definition -- ? )
dup class? [ drop f ] [ new-definitions get key? ] if ;
: (save-location) ( definition loc -- )
over redefinition? [ over redefine-error ] when
over set-where
dup new-definitions get dup [ set-at ] [ 3drop ] if ;
: save-location ( definition -- ) : save-location ( definition -- )
location (save-location) ; location (save-location) ;
@ -119,7 +96,8 @@ M: lexer skip-word ( lexer -- )
TUPLE: bad-escape ; TUPLE: bad-escape ;
: bad-escape ( -- * ) \ bad-escape construct-empty throw ; : bad-escape ( -- * )
\ bad-escape construct-empty throw ;
M: bad-escape summary drop "Bad escape code" ; M: bad-escape summary drop "Bad escape code" ;
@ -238,7 +216,9 @@ PREDICATE: unexpected unexpected-eof
: CREATE ( -- word ) scan create-in ; : CREATE ( -- word ) scan create-in ;
: CREATE-CLASS ( -- word ) : CREATE-CLASS ( -- word )
scan create-in dup predicate-word save-location ; scan in get create
dup <class-definition> save-location
dup predicate-word save-location ;
: word-restarts ( possibilities -- restarts ) : word-restarts ( possibilities -- restarts )
natural-sort [ natural-sort [
@ -256,16 +236,12 @@ M: no-word summary
dup word-vocabulary (use+) ; dup word-vocabulary (use+) ;
: forward-reference? ( word -- ? ) : forward-reference? ( word -- ? )
dup old-definitions get key? {
swap new-definitions get key? not and ; { [ dup old-definitions get key? not ] [ f ] }
{ [ dup new-definitions get key? ] [ f ] }
TUPLE: forward-error word ; { [ dup <class-definition> new-definitions get key? ] [ f ] }
{ [ t ] [ t ] }
M: forward-error error. } cond nip ;
"Forward reference to " write forward-error-word . ;
: forward-error ( word -- )
\ forward-error construct-boa throw ;
: check-forward ( str word -- word ) : check-forward ( str word -- word )
dup forward-reference? [ dup forward-reference? [
@ -284,12 +260,25 @@ M: forward-error error.
: scan-word ( -- word/number/f ) : scan-word ( -- word/number/f )
scan dup [ dup string>number [ ] [ search ] ?if ] when ; scan dup [ dup string>number [ ] [ search ] ?if ] when ;
TUPLE: staging-violation word ;
: staging-violation ( word -- * )
\ staging-violation construct-boa throw ;
M: staging-violation summary
drop
"A parsing word cannot be used in the same file it is defined in." ;
: execute-parsing ( word -- )
dup new-definitions get key? [ staging-violation ] when
execute ;
: parse-step ( accum end -- accum ? ) : parse-step ( accum end -- accum ? )
scan-word { scan-word {
{ [ 2dup eq? ] [ 2drop f ] } { [ 2dup eq? ] [ 2drop f ] }
{ [ dup not ] [ drop unexpected-eof t ] } { [ dup not ] [ drop unexpected-eof t ] }
{ [ dup delimiter? ] [ unexpected t ] } { [ dup delimiter? ] [ unexpected t ] }
{ [ dup parsing? ] [ nip execute t ] } { [ dup parsing? ] [ nip execute-parsing t ] }
{ [ t ] [ pick push drop t ] } { [ t ] [ pick push drop t ] }
} cond ; } cond ;
@ -361,10 +350,6 @@ SYMBOL: bootstrap-syntax
: parse-fresh ( lines -- quot ) : parse-fresh ( lines -- quot )
[ file-vocabs parse-lines ] with-scope ; [ file-vocabs parse-lines ] with-scope ;
SYMBOL: parse-hook
: do-parse-hook ( -- ) parse-hook get [ call ] when* ;
: parsing-file ( file -- ) : parsing-file ( file -- )
"quiet" get [ "quiet" get [
drop drop
@ -372,15 +357,6 @@ SYMBOL: parse-hook
"Loading " write <pathname> . flush "Loading " write <pathname> . flush
] if ; ] if ;
: start-parsing ( stream name -- )
H{ } clone new-definitions set
dup [
source-file
dup file set
source-file-definitions clone old-definitions set
] [ drop ] if
contents \ contents set ;
: smudged-usage-warning ( usages removed -- ) : smudged-usage-warning ( usages removed -- )
parser-notes? [ parser-notes? [
"Warning: the following definitions were removed from sources," print "Warning: the following definitions were removed from sources," print
@ -416,35 +392,22 @@ SYMBOL: parse-hook
smudged-usage forget-all smudged-usage forget-all
over empty? [ 2dup smudged-usage-warning ] unless 2drop ; over empty? [ 2dup smudged-usage-warning ] unless 2drop ;
: record-definitions ( file -- ) : finish-parsing ( contents quot -- )
new-definitions get swap set-source-file-definitions ; file get
: finish-parsing ( quot -- )
file get dup [
[ record-form ] keep [ record-form ] keep
[ record-modified ] keep [ record-modified ] keep
[ \ contents get record-checksum ] keep [ record-definitions ] keep
record-definitions record-checksum ;
forget-smudged
] [
2drop
] if ;
: undo-parsing ( -- )
file get [
dup source-file-definitions new-definitions get union
swap set-source-file-definitions
] when* ;
: parse-stream ( stream name -- quot ) : parse-stream ( stream name -- quot )
[ [
[ [
start-parsing contents
\ contents get string-lines parse-fresh dup string-lines parse-fresh
dup finish-parsing tuck finish-parsing
do-parse-hook forget-smudged
] [ ] [ undo-parsing ] cleanup ] with-source-file
] with-scope ; ] with-compilation-unit ;
: parse-file-restarts ( file -- restarts ) : parse-file-restarts ( file -- restarts )
"Load " swap " again" 3append t 2array 1array ; "Load " swap " again" 3append t 2array 1array ;
@ -462,9 +425,6 @@ SYMBOL: parse-hook
: run-file ( file -- ) : run-file ( file -- )
[ [ parse-file call ] keep ] assert-depth drop ; [ [ parse-file call ] keep ] assert-depth drop ;
: reload ( defspec -- )
where first [ run-file ] when* ;
: ?run-file ( path -- ) : ?run-file ( path -- )
dup ?resource-path exists? [ run-file ] [ drop ] if ; dup ?resource-path exists? [ run-file ] [ drop ] if ;
@ -478,9 +438,8 @@ SYMBOL: parse-hook
: ?bootstrap-file ( path -- ) : ?bootstrap-file ( path -- )
dup ?resource-path exists? [ bootstrap-file ] [ drop ] if ; dup ?resource-path exists? [ bootstrap-file ] [ drop ] if ;
: parse ( str -- quot ) string-lines parse-lines ; : eval ( str -- )
[ string-lines parse-fresh ] with-compilation-unit call ;
: eval ( str -- ) parse call ;
: eval>string ( str -- output ) : eval>string ( str -- output )
[ [

View File

@ -53,10 +53,6 @@ unit-test
[ "W{ \\ + }" ] [ [ W{ \ + } ] first unparse ] unit-test [ "W{ \\ + }" ] [ [ W{ \ + } ] first unparse ] unit-test
[ t ] [
"[ >r \"alloc\" add 0 0 r> ]" dup parse first unparse =
] unit-test
[ ] [ \ fixnum see ] unit-test [ ] [ \ fixnum see ] unit-test
[ ] [ \ integer see ] unit-test [ ] [ \ integer see ] unit-test

11
core/source-files/source-files-docs.factor Normal file → Executable file
View File

@ -80,3 +80,14 @@ HELP: reset-checksums
HELP: forget-source HELP: forget-source
{ $values { "path" "a pathname string" } } { $values { "path" "a pathname string" } }
{ $description "Forgets all information known about a source file." } ; { $description "Forgets all information known about a source file." } ;
HELP: record-definitions
{ $values { "file" source-file } }
{ $description "Records that all " { $link new-definitions } " were defined in " { $snippet "file" } "." } ;
HELP: rollback-source-file
{ $values { "file" source-file } }
{ $description "Records information to the source file after an incomplete parse which ended with an error." } ;
HELP: file
{ $var-description "Stores the " { $link source-file } " being parsed. The " { $link source-file-path } " of this object comes from the input parameter to " { $link with-source-file } "." } ;

22
core/source-files/source-files.factor Normal file → Executable file
View File

@ -33,8 +33,8 @@ uses definitions ;
dup source-file-path ?resource-path file-modified dup source-file-path ?resource-path file-modified
swap set-source-file-modified ; swap set-source-file-modified ;
: record-checksum ( source-file contents -- ) : record-checksum ( contents source-file -- )
crc32 swap set-source-file-checksum ; >r crc32 r> set-source-file-checksum ;
: (xref-source) ( source-file -- pathname uses ) : (xref-source) ( source-file -- pathname uses )
dup source-file-path <pathname> swap source-file-uses dup source-file-path <pathname> swap source-file-uses
@ -54,6 +54,9 @@ uses definitions ;
swap quot-uses keys over set-source-file-uses swap quot-uses keys over set-source-file-uses
xref-source ; xref-source ;
: record-definitions ( file -- )
new-definitions get swap set-source-file-definitions ;
: <source-file> ( path -- source-file ) : <source-file> ( path -- source-file )
{ set-source-file-path } \ source-file construct ; { set-source-file-path } \ source-file construct ;
@ -75,3 +78,18 @@ M: pathname where pathname-string 1 2array ;
source-files get delete-at ; source-files get delete-at ;
M: pathname forget pathname-string forget-source ; M: pathname forget pathname-string forget-source ;
: rollback-source-file ( source-file -- )
dup source-file-definitions new-definitions get union
swap set-source-file-definitions ;
SYMBOL: file
: with-source-file ( name quot -- )
#! Should be called from inside with-compilation-unit.
[
swap source-file
dup file set
source-file-definitions old-definitions set
[ ] [ file get rollback-source-file ] cleanup
] with-scope ; inline

View File

@ -22,145 +22,149 @@ IN: bootstrap.syntax
>r "syntax" lookup dup r> define-compound >r "syntax" lookup dup r> define-compound
t "parsing" set-word-prop ; t "parsing" set-word-prop ;
{ "]" "}" ";" } [ define-delimiter ] each [
{ "]" "}" ";" ">>" } [ define-delimiter ] each
"PRIMITIVE:" [ "PRIMITIVE:" [
"Primitive definition is not supported" throw "Primitive definition is not supported" throw
] define-syntax ] define-syntax
"CS{" [ "CS{" [
"Call stack literals are not supported" throw "Call stack literals are not supported" throw
] define-syntax ] define-syntax
"!" [ lexer get next-line ] define-syntax "!" [ lexer get next-line ] define-syntax
"#!" [ POSTPONE: ! ] define-syntax "#!" [ POSTPONE: ! ] define-syntax
"IN:" [ scan set-in ] define-syntax "IN:" [ scan set-in ] define-syntax
"PRIVATE>" [ in get ".private" ?tail drop set-in ] define-syntax "PRIVATE>" [ in get ".private" ?tail drop set-in ] define-syntax
"<PRIVATE" [ "<PRIVATE" [
POSTPONE: PRIVATE> in get ".private" append set-in POSTPONE: PRIVATE> in get ".private" append set-in
] define-syntax ] define-syntax
"USE:" [ scan use+ ] define-syntax "USE:" [ scan use+ ] define-syntax
"USE-IF:" [ "USE-IF:" [
scan-word scan swap execute [ use+ ] [ drop ] if scan-word scan swap execute [ use+ ] [ drop ] if
] define-syntax ] define-syntax
"USING:" [ ";" parse-tokens add-use ] define-syntax "USING:" [ ";" parse-tokens add-use ] define-syntax
"HEX:" [ 16 parse-base ] define-syntax "HEX:" [ 16 parse-base ] define-syntax
"OCT:" [ 8 parse-base ] define-syntax "OCT:" [ 8 parse-base ] define-syntax
"BIN:" [ 2 parse-base ] define-syntax "BIN:" [ 2 parse-base ] define-syntax
"f" [ f parsed ] define-syntax "f" [ f parsed ] define-syntax
"t" "syntax" lookup define-symbol "t" "syntax" lookup define-symbol
"CHAR:" [ 0 scan next-char nip parsed ] define-syntax "CHAR:" [ 0 scan next-char nip parsed ] define-syntax
"\"" [ parse-string parsed ] define-syntax "\"" [ parse-string parsed ] define-syntax
"SBUF\"" [ "SBUF\"" [
lexer get skip-blank parse-string >sbuf parsed lexer get skip-blank parse-string >sbuf parsed
] define-syntax ] define-syntax
"P\"" [ "P\"" [
lexer get skip-blank parse-string <pathname> parsed lexer get skip-blank parse-string <pathname> parsed
] define-syntax ] define-syntax
"[" [ \ ] [ >quotation ] parse-literal ] define-syntax "[" [ \ ] [ >quotation ] parse-literal ] define-syntax
"{" [ \ } [ >array ] parse-literal ] define-syntax "{" [ \ } [ >array ] parse-literal ] define-syntax
"V{" [ \ } [ >vector ] parse-literal ] define-syntax "V{" [ \ } [ >vector ] parse-literal ] define-syntax
"B{" [ \ } [ >byte-array ] parse-literal ] define-syntax "B{" [ \ } [ >byte-array ] parse-literal ] define-syntax
"?{" [ \ } [ >bit-array ] parse-literal ] define-syntax "?{" [ \ } [ >bit-array ] parse-literal ] define-syntax
"F{" [ \ } [ >float-array ] parse-literal ] define-syntax "F{" [ \ } [ >float-array ] parse-literal ] define-syntax
"H{" [ \ } [ >hashtable ] parse-literal ] define-syntax "H{" [ \ } [ >hashtable ] parse-literal ] define-syntax
"T{" [ \ } [ >tuple ] parse-literal ] define-syntax "T{" [ \ } [ >tuple ] parse-literal ] define-syntax
"W{" [ \ } [ first <wrapper> ] parse-literal ] define-syntax "W{" [ \ } [ first <wrapper> ] parse-literal ] define-syntax
"POSTPONE:" [ scan-word parsed ] define-syntax "POSTPONE:" [ scan-word parsed ] define-syntax
"\\" [ scan-word literalize parsed ] define-syntax "\\" [ scan-word literalize parsed ] define-syntax
"inline" [ word make-inline ] define-syntax "inline" [ word make-inline ] define-syntax
"foldable" [ word make-foldable ] define-syntax "foldable" [ word make-foldable ] define-syntax
"flushable" [ word make-flushable ] define-syntax "flushable" [ word make-flushable ] define-syntax
"delimiter" [ word t "delimiter" set-word-prop ] define-syntax "delimiter" [ word t "delimiter" set-word-prop ] define-syntax
"parsing" [ word t "parsing" set-word-prop ] define-syntax "parsing" [ word t "parsing" set-word-prop ] define-syntax
"SYMBOL:" [ "SYMBOL:" [
CREATE dup reset-generic define-symbol CREATE dup reset-generic define-symbol
] define-syntax ] define-syntax
"DEFER:" [ "DEFER:" [
scan in get create scan in get create
dup old-definitions get delete-at dup old-definitions get delete-at
set-word set-word
] define-syntax ] define-syntax
":" [ ":" [
CREATE dup reset-generic parse-definition define-compound CREATE dup reset-generic parse-definition define-compound
] define-syntax ] define-syntax
"GENERIC:" [ "GENERIC:" [
CREATE dup reset-word CREATE dup reset-word
define-simple-generic define-simple-generic
] define-syntax ] define-syntax
"GENERIC#" [ "GENERIC#" [
CREATE dup reset-word CREATE dup reset-word
scan-word <standard-combination> define-generic scan-word <standard-combination> define-generic
] define-syntax ] define-syntax
"MATH:" [ "MATH:" [
CREATE dup reset-word CREATE dup reset-word
T{ math-combination } define-generic T{ math-combination } define-generic
] define-syntax ] define-syntax
"HOOK:" [ "HOOK:" [
CREATE dup reset-word scan-word CREATE dup reset-word scan-word
<hook-combination> define-generic <hook-combination> define-generic
] define-syntax ] define-syntax
"M:" [ "M:" [
f set-word f set-word
location >r location >r
scan-word bootstrap-word scan-word scan-word bootstrap-word scan-word
[ parse-definition <method> -rot define-method ] 2keep [ parse-definition <method> -rot define-method ] 2keep
2array r> (save-location) 2array r> (save-location)
] define-syntax ] define-syntax
"UNION:" [ "UNION:" [
CREATE-CLASS parse-definition define-union-class CREATE-CLASS parse-definition define-union-class
] define-syntax ] define-syntax
"MIXIN:" [ "MIXIN:" [
CREATE-CLASS define-mixin-class CREATE-CLASS define-mixin-class
] define-syntax ] define-syntax
"INSTANCE:" [ scan-word scan-word add-mixin-instance ] define-syntax "INSTANCE:" [ scan-word scan-word add-mixin-instance ] define-syntax
"PREDICATE:" [ "PREDICATE:" [
scan-word scan-word
CREATE-CLASS CREATE-CLASS
parse-definition define-predicate-class parse-definition define-predicate-class
] define-syntax ] define-syntax
"TUPLE:" [ "TUPLE:" [
CREATE-CLASS ";" parse-tokens define-tuple-class CREATE-CLASS ";" parse-tokens define-tuple-class
] define-syntax ] define-syntax
"C:" [ "C:" [
CREATE dup reset-generic CREATE dup reset-generic
scan-word dup check-tuple scan-word dup check-tuple
[ construct-boa ] curry define-inline [ construct-boa ] curry define-inline
] define-syntax ] define-syntax
"FORGET:" [ scan use get assoc-stack forget ] define-syntax "FORGET:" [ scan use get assoc-stack forget ] define-syntax
"(" [ "(" [
parse-effect word parse-effect word
[ swap "declared-effect" set-word-prop ] [ drop ] if* [ swap "declared-effect" set-word-prop ] [ drop ] if*
] define-syntax ] define-syntax
"MAIN:" [ scan-word in get vocab set-vocab-main ] define-syntax "MAIN:" [ scan-word in get vocab set-vocab-main ] define-syntax
"<<" [ \ >> parse-until >quotation call ] define-syntax
] with-compilation-unit

31
core/words/words-docs.factor Normal file → Executable file
View File

@ -143,8 +143,7 @@ ARTICLE: "word.private" "Word implementation details"
{ $subsection word-def } { $subsection word-def }
{ $subsection set-word-def } { $subsection set-word-def }
"An " { $emphasis "XT" } " (execution token) is the machine code address of a word:" "An " { $emphasis "XT" } " (execution token) is the machine code address of a word:"
{ $subsection word-xt } { $subsection word-xt } ;
{ $subsection update-xt } ;
ARTICLE: "words" "Words" ARTICLE: "words" "Words"
"Words are the Factor equivalent of functions or procedures; a word is a body of code with a unique name and some additional meta-data. Words are defined in the " { $vocab-link "words" } " vocabulary." "Words are the Factor equivalent of functions or procedures; a word is a body of code with a unique name and some additional meta-data. Words are defined in the " { $vocab-link "words" } " vocabulary."
@ -278,15 +277,6 @@ HELP: gensym
{ $examples { $unchecked-example "gensym ." "G:260561" } } { $examples { $unchecked-example "gensym ." "G:260561" } }
{ $notes "Gensyms are often used as placeholder values that have no meaning of their own but must be unique. For example, the compiler uses gensyms to label sections of code." } ; { $notes "Gensyms are often used as placeholder values that have no meaning of their own but must be unique. For example, the compiler uses gensyms to label sections of code." } ;
HELP: define-temp
{ $values { "quot" quotation } { "word" word } }
{ $description "Creates an uninterned word that will call " { $snippet "quot" } " when executed." }
{ $notes
"The following phrases are equivalent:"
{ $code "[ 2 2 + . ] call" }
{ $code "[ 2 2 + . ] define-temp execute" }
} ;
HELP: bootstrapping? HELP: bootstrapping?
{ $var-description "Set by the library while bootstrap is in progress. Some parsing words need to behave differently during bootstrap." } ; { $var-description "Set by the library while bootstrap is in progress. Some parsing words need to behave differently during bootstrap." } ;
@ -337,30 +327,11 @@ HELP: bootstrap-word
{ $values { "word" word } { "target" word } } { $values { "word" word } { "target" word } }
{ $description "Looks up a word with the same name and vocabulary as the given word, performing a transformation to handle parsing words in the target dictionary. Used during bootstrap to transfer host words to the target dictionary." } ; { $description "Looks up a word with the same name and vocabulary as the given word, performing a transformation to handle parsing words in the target dictionary. Used during bootstrap to transfer host words to the target dictionary." } ;
HELP: update-xt ( word -- )
{ $values { "word" word } }
{ $description "Updates a word's execution token based on the value of the " { $link word-def } " slot. If the word was compiled by the optimizing compiler, this forces the word to revert to its unoptimized definition." }
{ $side-effects "word" } ;
HELP: parsing? HELP: parsing?
{ $values { "obj" object } { "?" "a boolean" } } { $values { "obj" object } { "?" "a boolean" } }
{ $description "Tests if an object is a parsing word declared by " { $link POSTPONE: parsing } "." } { $description "Tests if an object is a parsing word declared by " { $link POSTPONE: parsing } "." }
{ $notes "Outputs " { $link f } " if the object is not a word." } ; { $notes "Outputs " { $link f } " if the object is not a word." } ;
HELP: word-changed?
{ $values { "word" word } { "?" "a boolean" } }
{ $description "Tests if a word needs to be recompiled." } ;
HELP: changed-word
{ $values { "word" word } }
{ $description "Marks a word as needing recompilation by adding it to the " { $link changed-words } " assoc." }
$low-level-note ;
HELP: unchanged-word
{ $values { "word" word } }
{ $description "Marks a word as no longer needing recompilation by removing it from the " { $link changed-words } " assoc." }
$low-level-note ;
HELP: define-declared HELP: define-declared
{ $values { "word" word } { "def" quotation } { "effect" effect } } { $values { "word" word } { "def" quotation } { "effect" effect } }
{ $description "Defines a compound word and declares its stack effect." } { $description "Defines a compound word and declares its stack effect." }

6
core/words/words-tests.factor Normal file → Executable file
View File

@ -126,12 +126,6 @@ DEFER: x
[ ] [ "IN: temporary : test-last ( -- ) ;" eval ] unit-test [ ] [ "IN: temporary : test-last ( -- ) ;" eval ] unit-test
[ "test-last" ] [ word word-name ] unit-test [ "test-last" ] [ word word-name ] unit-test
[ t ] [
changed-words get assoc-size
[ ] define-temp drop
changed-words get assoc-size =
] unit-test
! regression ! regression
SYMBOL: quot-uses-a SYMBOL: quot-uses-a
SYMBOL: quot-uses-b SYMBOL: quot-uses-b

35
core/words/words.factor Normal file → Executable file
View File

@ -14,18 +14,6 @@ GENERIC: execute ( word -- )
M: word execute (execute) ; M: word execute (execute) ;
! Used by the compiler
SYMBOL: changed-words
: word-changed? ( word -- ? )
changed-words get [ key? ] [ drop f ] if* ;
: changed-word ( word -- )
dup changed-words get [ set-at ] [ 2drop ] if* ;
: unchanged-word ( word -- )
changed-words get [ delete-at ] [ drop ] if* ;
M: word <=> M: word <=>
[ dup word-name swap word-vocabulary 2array ] compare ; [ dup word-name swap word-vocabulary 2array ] compare ;
@ -98,21 +86,14 @@ M: compound redefined* ( word -- )
<PRIVATE <PRIVATE
: definition-changed? ( word def -- ? ) : changed-word ( word -- ) dup changed-words get set-at ;
swap word-def = not ;
: define ( word def -- ) : define ( word def -- )
2dup definition-changed? [
over redefined
over unxref over unxref
over redefined
over set-word-def over set-word-def
dup update-xt dup changed-word
dup word-vocabulary [ dup word-vocabulary [ dup xref ] when drop ;
dup changed-word dup xref
] when drop
] [
2drop
] if ;
PRIVATE> PRIVATE>
@ -154,9 +135,6 @@ PRIVATE>
: gensym ( -- word ) : gensym ( -- word )
"G:" \ gensym counter number>string append f <word> ; "G:" \ gensym counter number>string append f <word> ;
: define-temp ( quot -- word )
gensym [ swap define-compound ] keep ;
: reveal ( word -- ) : reveal ( word -- )
dup word-name over word-vocabulary vocab-words set-at ; dup word-name over word-vocabulary vocab-words set-at ;
@ -201,7 +179,6 @@ M: word (forget-word)
: forget-word ( word -- ) : forget-word ( word -- )
dup delete-xref dup delete-xref
dup unchanged-word
(forget-word) ; (forget-word) ;
M: word forget forget-word ; M: word forget forget-word ;
@ -214,3 +191,7 @@ M: word literalize <wrapper> ;
: ?word-name dup word? [ word-name ] when ; : ?word-name dup word? [ word-name ] when ;
: xref-words ( -- ) all-words [ xref ] each ; : xref-words ( -- ) all-words [ xref ] each ;
recompile-hook global
[ [ [ f ] { } map>assoc modify-code-heap ] or ]
change-at

2
extra/cocoa/cocoa.factor Normal file → Executable file
View File

@ -32,7 +32,7 @@ SYMBOL: super-sent-messages
{ {
"cocoa" "cocoa.runtime" "cocoa.messages" "cocoa.subclassing" "cocoa" "cocoa.runtime" "cocoa.messages" "cocoa.subclassing"
} compile-vocabs } [ words ] map concat compile-batch
"Importing Cocoa classes..." print "Importing Cocoa classes..." print
{ {

0
extra/cocoa/subclassing/subclassing.factor Normal file → Executable file
View File

12
extra/shuffle/shuffle-tests.factor Normal file → Executable file
View File

@ -1,25 +1,25 @@
USING: arrays shuffle kernel math tools.test compiler words ; USING: arrays shuffle kernel math tools.test inference words ;
[ 8 ] [ 5 6 7 8 3nip ] unit-test [ 8 ] [ 5 6 7 8 3nip ] unit-test
{ 1 2 3 4 1 } [ 1 2 3 4 4 npick ] unit-test { 1 2 3 4 1 } [ 1 2 3 4 4 npick ] unit-test
{ 1 2 3 4 2 } [ 1 2 3 4 3 npick ] unit-test { 1 2 3 4 2 } [ 1 2 3 4 3 npick ] unit-test
{ 1 2 3 4 3 } [ 1 2 3 4 2 npick ] unit-test { 1 2 3 4 3 } [ 1 2 3 4 2 npick ] unit-test
{ 1 2 3 4 4 } [ 1 2 3 4 1 npick ] unit-test { 1 2 3 4 4 } [ 1 2 3 4 1 npick ] unit-test
{ t } [ [ 1 1 ndup ] compile-quot compiled? ] unit-test { t } [ [ 1 1 ndup ] infer >boolean ] unit-test
{ 1 1 } [ 1 1 ndup ] unit-test { 1 1 } [ 1 1 ndup ] unit-test
{ 1 2 1 2 } [ 1 2 2 ndup ] unit-test { 1 2 1 2 } [ 1 2 2 ndup ] unit-test
{ 1 2 3 1 2 3 } [ 1 2 3 3 ndup ] unit-test { 1 2 3 1 2 3 } [ 1 2 3 3 ndup ] unit-test
{ 1 2 3 4 1 2 3 4 } [ 1 2 3 4 4 ndup ] unit-test { 1 2 3 4 1 2 3 4 } [ 1 2 3 4 4 ndup ] unit-test
{ t } [ [ 1 2 2 nrot ] compile-quot compiled? ] unit-test { t } [ [ 1 2 2 nrot ] infer >boolean ] unit-test
{ 2 1 } [ 1 2 2 nrot ] unit-test { 2 1 } [ 1 2 2 nrot ] unit-test
{ 2 3 1 } [ 1 2 3 3 nrot ] unit-test { 2 3 1 } [ 1 2 3 3 nrot ] unit-test
{ 2 3 4 1 } [ 1 2 3 4 4 nrot ] unit-test { 2 3 4 1 } [ 1 2 3 4 4 nrot ] unit-test
{ t } [ [ 1 2 2 -nrot ] compile-quot compiled? ] unit-test { t } [ [ 1 2 2 -nrot ] infer >boolean ] unit-test
{ 2 1 } [ 1 2 2 -nrot ] unit-test { 2 1 } [ 1 2 2 -nrot ] unit-test
{ 3 1 2 } [ 1 2 3 3 -nrot ] unit-test { 3 1 2 } [ 1 2 3 3 -nrot ] unit-test
{ 4 1 2 3 } [ 1 2 3 4 4 -nrot ] unit-test { 4 1 2 3 } [ 1 2 3 4 4 -nrot ] unit-test
{ t } [ [ 1 2 3 4 3 nnip ] compile-quot compiled? ] unit-test { t } [ [ 1 2 3 4 3 nnip ] infer >boolean ] unit-test
{ 4 } [ 1 2 3 4 3 nnip ] unit-test { 4 } [ 1 2 3 4 3 nnip ] unit-test
{ t } [ [ 1 2 3 4 4 ndrop ] compile-quot compiled? ] unit-test { t } [ [ 1 2 3 4 4 ndrop ] infer >boolean ] unit-test
{ 0 } [ 0 1 2 3 4 4 ndrop ] unit-test { 0 } [ 0 1 2 3 4 4 ndrop ] unit-test
[ 3 1 2 3 ] [ 1 2 3 tuckd ] unit-test [ 3 1 2 3 ] [ 1 2 3 tuckd ] unit-test

2
extra/tools/annotations/annotations-docs.factor Normal file → Executable file
View File

@ -2,7 +2,7 @@ USING: help.markup help.syntax words parser ;
IN: tools.annotations IN: tools.annotations
ARTICLE: "tools.annotations" "Word annotations" ARTICLE: "tools.annotations" "Word annotations"
"The word annotation feature modifies word definitions to add debugging code. You can restore the old definition by calling " { $link reload } " on the word in question." "The word annotation feature modifies word definitions to add debugging code. You can restore the old definition by calling " { $link reset } " on the word in question."
{ $subsection watch } { $subsection watch }
{ $subsection breakpoint } { $subsection breakpoint }
{ $subsection breakpoint-if } { $subsection breakpoint-if }

2
extra/tools/annotations/annotations.factor Normal file → Executable file
View File

@ -4,6 +4,8 @@ USING: kernel words parser io inspector quotations sequences
prettyprint continuations effects ; prettyprint continuations effects ;
IN: tools.annotations IN: tools.annotations
: reset "not implemented yet" throw ;
: annotate ( word quot -- ) : annotate ( word quot -- )
over >r >r word-def r> call r> over >r >r word-def r> call r>
swap define-compound do-parse-hook ; swap define-compound do-parse-hook ;

6
extra/tools/deploy/shaker/strip-cocoa.factor Normal file → Executable file
View File

@ -22,9 +22,5 @@ global [
! We need this for strip-stack-traces to work fully ! We need this for strip-stack-traces to work fully
{ message-senders super-message-senders } { message-senders super-message-senders }
[ [ get values compile ] each
get values [
dup update-xt compile
] each
] each
] bind ] bind

View File

@ -67,24 +67,14 @@ V{ } clone operations set-global
{ +listener+ t } { +listener+ t }
} define-operation } define-operation
UNION: definition word method-spec link ; UNION: definition word method-spec link vocab vocab-link ;
UNION: editable-definition definition vocab vocab-link ; [ definition? ] \ edit H{
[ editable-definition? ] \ edit H{
{ +keyboard+ T{ key-down f { C+ } "E" } } { +keyboard+ T{ key-down f { C+ } "E" } }
{ +listener+ t } { +listener+ t }
} define-operation } define-operation
UNION: reloadable-definition definition pathname ; [ definition? ] \ forget H{ } define-operation
[ reloadable-definition? ] \ reload H{
{ +keyboard+ T{ key-down f { C+ } "R" } }
{ +listener+ t }
} define-operation
[ dup reloadable-definition? swap vocab-spec? or ] \ forget
H{ } define-operation
! Words ! Words
[ word? ] \ insert-word H{ [ word? ] \ insert-word H{

View File

@ -348,15 +348,26 @@ DEFINE_PRIMITIVE(modify_code_heap)
CELL i; CELL i;
for(i = 0; i < count; i++) for(i = 0; i < count; i++)
{ {
F_ARRAY *data = untag_array(array_nth(alist,i)); F_ARRAY *pair = untag_array(array_nth(alist,i));
F_WORD *word = untag_word(array_nth(data,0)); F_WORD *word = untag_word(array_nth(pair,0));
CELL profiler_prologue = to_cell(array_nth(data,1)); CELL data = array_nth(pair,1);
F_ARRAY *literals = untag_array(array_nth(data,2));
F_ARRAY *words = untag_array(array_nth(data,3)); if(data == F)
F_ARRAY *rel = untag_array(array_nth(data,4)); {
F_ARRAY *labels = untag_array(array_nth(data,5)); word->compiledp = F;
F_ARRAY *code = untag_array(array_nth(data,6)); word->xt = default_word_xt(word);
}
else
{
F_ARRAY *compiled_code = untag_array(data);
CELL profiler_prologue = to_cell(array_nth(compiled_code,0));
F_ARRAY *literals = untag_array(array_nth(compiled_code,1));
F_ARRAY *words = untag_array(array_nth(compiled_code,2));
F_ARRAY *rel = untag_array(array_nth(compiled_code,3));
F_ARRAY *labels = untag_array(array_nth(compiled_code,4));
F_ARRAY *code = untag_array(array_nth(compiled_code,5));
REGISTER_UNTAGGED(alist); REGISTER_UNTAGGED(alist);
REGISTER_UNTAGGED(word); REGISTER_UNTAGGED(word);
@ -375,6 +386,7 @@ DEFINE_PRIMITIVE(modify_code_heap)
set_word_xt(word,compiled); set_word_xt(word,compiled);
} }
}
if(count != 0) if(count != 0)
iterate_code_heap(finalize_code_block); iterate_code_heap(finalize_code_block);

1
vm/primitives.c Normal file → Executable file
View File

@ -67,7 +67,6 @@ void *primitives[] = {
primitive_float_greater, primitive_float_greater,
primitive_float_greatereq, primitive_float_greatereq,
primitive_word, primitive_word,
primitive_update_xt,
primitive_word_xt, primitive_word_xt,
primitive_drop, primitive_drop,
primitive_2drop, primitive_2drop,

View File

@ -474,13 +474,6 @@ DEFINE_PRIMITIVE(word)
dpush(tag_object(allot_word(vocab,name))); dpush(tag_object(allot_word(vocab,name)));
} }
DEFINE_PRIMITIVE(update_xt)
{
F_WORD *word = untag_word(dpop());
word->compiledp = F;
word->xt = default_word_xt(word);
}
DEFINE_PRIMITIVE(word_xt) DEFINE_PRIMITIVE(word_xt)
{ {
F_WORD *word = untag_word(dpeek()); F_WORD *word = untag_word(dpeek());

1
vm/types.h Normal file → Executable file
View File

@ -187,7 +187,6 @@ DECLARE_PRIMITIVE(hashtable);
F_WORD *allot_word(CELL vocab, CELL name); F_WORD *allot_word(CELL vocab, CELL name);
DECLARE_PRIMITIVE(word); DECLARE_PRIMITIVE(word);
DECLARE_PRIMITIVE(update_xt);
DECLARE_PRIMITIVE(word_xt); DECLARE_PRIMITIVE(word_xt);
DECLARE_PRIMITIVE(wrapper); DECLARE_PRIMITIVE(wrapper);