Merge branch 'master' of git://factorcode.org/git/factor
commit
a13c5d173d
|
@ -19,15 +19,19 @@ ARTICLE: "compiler-usage" "Calling the optimizing compiler"
|
|||
"Higher-level words can be found in " { $link "compilation-units" } "." ;
|
||||
|
||||
ARTICLE: "compiler" "Optimizing compiler"
|
||||
"Factor is a fully compiled language implementation with two distinct compilers:"
|
||||
"Factor includes two compilers which work behind the scenes. Words are always compiled, and the compilers do not have to be invoked explicitly. For the most part, compilation is fully transparent. However, there are a few things worth knowing about the compilation process."
|
||||
$nl
|
||||
"The two compilers differ in the level of analysis they perform:"
|
||||
{ $list
|
||||
{ "The " { $emphasis "non-optimizing quotation compiler" } " compiles quotations to naive machine code very quickly. The non-optimizing quotation compiler is part of the VM." }
|
||||
{ "The " { $emphasis "optimizing word compiler" } " compiles whole words at a time while performing extensive data and control flow analysis. This provides greater performance for generated code, but incurs a much longer compile time. The optimizing compiler is written in Factor." }
|
||||
}
|
||||
"The optimizing compiler only compiles words which have a static stack effect. This means that methods defined on fundamental generic words such as " { $link nth } " should have a static stack effect; for otherwise, most of the system would be compiled with the non-optimizing compiler. See " { $link "inference" } " and " { $link "cookbook-pitfalls" } "."
|
||||
{ $subsection "compiler-usage" }
|
||||
"The optimizing compiler only compiles words which have a static stack effect. This means that methods defined on fundamental generic words such as " { $link nth } " should have a static stack effect. See " { $link "inference" } " and " { $link "cookbook-pitfalls" } "."
|
||||
$nl
|
||||
"The optimizing compiler also trades off compile time for performance of generated code, so loading certain vocabularies might take a while. Saving the image after loading vocabularies can save you a lot of time that you would spend waiting for the same code to load in every coding session; see " { $link "images" } " for information."
|
||||
{ $subsection "compiler-errors" }
|
||||
{ $subsection "hints" } ;
|
||||
{ $subsection "hints" }
|
||||
{ $subsection "compiler-usage" } ;
|
||||
|
||||
ABOUT: "compiler"
|
||||
|
||||
|
|
|
@ -5,8 +5,7 @@ namespaces sequences db.sqlite.ffi db combinators
|
|||
continuations db.types calendar.format serialize
|
||||
io.streams.byte-array byte-arrays io.encodings.binary
|
||||
io.backend db.errors present urls io.encodings.utf8
|
||||
io.encodings.string accessors shuffle io prettyprint
|
||||
db.private ;
|
||||
io.encodings.string accessors shuffle io db.private ;
|
||||
IN: db.sqlite.lib
|
||||
|
||||
ERROR: sqlite-error < db-error n string ;
|
||||
|
@ -125,8 +124,7 @@ ERROR: sqlite-sql-error < sql-error n string ;
|
|||
] if* (sqlite-bind-type) ;
|
||||
|
||||
: sqlite-finalize ( handle -- ) sqlite3_finalize sqlite-check-result ;
|
||||
: sqlite-reset ( handle -- )
|
||||
"resetting: " write dup . sqlite3_reset sqlite-check-result ;
|
||||
: sqlite-reset ( handle -- ) sqlite3_reset sqlite-check-result ;
|
||||
: sqlite-clear-bindings ( handle -- )
|
||||
sqlite3_clear_bindings sqlite-check-result ;
|
||||
: sqlite-#columns ( query -- int ) sqlite3_column_count ;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
USING: io io.files io.files.temp io.directories io.launcher
|
||||
kernel namespaces prettyprint tools.test db.sqlite db sequences
|
||||
continuations db.types db.tuples unicode.case ;
|
||||
continuations db.types db.tuples unicode.case accessors arrays
|
||||
sorting ;
|
||||
IN: db.sqlite.tests
|
||||
|
||||
: db-path ( -- path ) "test.db" temp-file ;
|
||||
|
@ -74,8 +75,9 @@ IN: db.sqlite.tests
|
|||
] with-db
|
||||
] unit-test
|
||||
|
||||
[ \ swap ensure-table ] must-fail
|
||||
|
||||
! You don't need a primary key
|
||||
USING: accessors arrays sorting ;
|
||||
TUPLE: things one two ;
|
||||
|
||||
things "THINGS" {
|
||||
|
@ -115,7 +117,7 @@ hi "HELLO" {
|
|||
1 <foo> insert-tuple
|
||||
f <foo> select-tuple
|
||||
1 1 <hi> insert-tuple
|
||||
f <hi> select-tuple
|
||||
f f <hi> select-tuple
|
||||
hi drop-table
|
||||
foo drop-table
|
||||
] with-db
|
||||
|
@ -158,10 +160,9 @@ watch "WATCH" {
|
|||
show new insert-tuple
|
||||
show new select-tuple
|
||||
"littledan" f user boa select-tuple
|
||||
swap [ username>> ] [ id>> ] bi*
|
||||
watch boa insert-tuple
|
||||
watch new select-tuple
|
||||
user>> f user boa select-tuple
|
||||
] with-db
|
||||
] unit-test
|
||||
|
||||
[ \ swap ensure-table ] must-fail
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
! Copyright (C) 2005, 2008 Chris Double, Doug Coleman.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: alien arrays assocs classes compiler db hashtables
|
||||
io.files kernel math math.parser namespaces prettyprint
|
||||
io.files kernel math math.parser namespaces prettyprint fry
|
||||
sequences strings classes.tuple alien.c-types continuations
|
||||
db.sqlite.lib db.sqlite.ffi db.tuples words db.types combinators
|
||||
math.intervals io nmake accessors vectors math.ranges random
|
||||
math.bitwise db.queries destructors db.tuples.private interpolate
|
||||
io.streams.string multiline make db.private ;
|
||||
io.streams.string multiline make db.private sequences.deep ;
|
||||
IN: db.sqlite
|
||||
|
||||
TUPLE: sqlite-db path ;
|
||||
|
@ -126,30 +126,6 @@ M: sqlite-statement query-results ( query -- result-set )
|
|||
dup handle>> sqlite-result-set new-result-set
|
||||
dup advance-row ;
|
||||
|
||||
M: sqlite-db-connection create-sql-statement ( class -- statement )
|
||||
[
|
||||
dupd
|
||||
"create table " 0% 0%
|
||||
"(" 0% [ ", " 0% ] [
|
||||
dup "sql-spec" set
|
||||
dup column-name>> [ "table-id" set ] [ 0% ] bi
|
||||
" " 0%
|
||||
dup type>> lookup-create-type 0%
|
||||
modifiers 0%
|
||||
] interleave
|
||||
|
||||
find-primary-key [
|
||||
", " 0%
|
||||
"primary key(" 0%
|
||||
[ "," 0% ] [ column-name>> 0% ] interleave
|
||||
")" 0%
|
||||
] unless-empty
|
||||
");" 0%
|
||||
] query-make ;
|
||||
|
||||
M: sqlite-db-connection drop-sql-statement ( class -- statement )
|
||||
[ "drop table " 0% 0% ";" 0% drop ] query-make ;
|
||||
|
||||
M: sqlite-db-connection <insert-db-assigned-statement> ( tuple -- statement )
|
||||
[
|
||||
"insert into " 0% 0%
|
||||
|
@ -225,7 +201,7 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
: insert-trigger ( -- string )
|
||||
[
|
||||
<"
|
||||
CREATE TRIGGER fki_${table-name}_${foreign-table-name}_id
|
||||
CREATE TRIGGER fki_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id
|
||||
BEFORE INSERT ON ${table-name}
|
||||
FOR EACH ROW BEGIN
|
||||
SELECT RAISE(ROLLBACK, 'insert on table "${table-name}" violates foreign key constraint "fk_${foreign-table-name}_id"')
|
||||
|
@ -237,7 +213,7 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
: insert-trigger-not-null ( -- string )
|
||||
[
|
||||
<"
|
||||
CREATE TRIGGER fki_${table-name}_${foreign-table-name}_id
|
||||
CREATE TRIGGER fki_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id
|
||||
BEFORE INSERT ON ${table-name}
|
||||
FOR EACH ROW BEGIN
|
||||
SELECT RAISE(ROLLBACK, 'insert on table "${table-name}" violates foreign key constraint "fk_${foreign-table-name}_id"')
|
||||
|
@ -247,10 +223,17 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: drop-insert-trigger ( -- string )
|
||||
[
|
||||
<"
|
||||
DROP TRIGGER fki_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id;
|
||||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: update-trigger ( -- string )
|
||||
[
|
||||
<"
|
||||
CREATE TRIGGER fku_${table-name}_${foreign-table-name}_id
|
||||
CREATE TRIGGER fku_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id
|
||||
BEFORE UPDATE ON ${table-name}
|
||||
FOR EACH ROW BEGIN
|
||||
SELECT RAISE(ROLLBACK, 'update on table "${table-name}" violates foreign key constraint "fk_${foreign-table-name}_id"')
|
||||
|
@ -262,7 +245,7 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
: update-trigger-not-null ( -- string )
|
||||
[
|
||||
<"
|
||||
CREATE TRIGGER fku_${table-name}_${foreign-table-name}_id
|
||||
CREATE TRIGGER fku_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id
|
||||
BEFORE UPDATE ON ${table-name}
|
||||
FOR EACH ROW BEGIN
|
||||
SELECT RAISE(ROLLBACK, 'update on table "${table-name}" violates foreign key constraint "fk_${foreign-table-name}_id"')
|
||||
|
@ -272,10 +255,17 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: drop-update-trigger ( -- string )
|
||||
[
|
||||
<"
|
||||
DROP TRIGGER fku_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id;
|
||||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: delete-trigger-restrict ( -- string )
|
||||
[
|
||||
<"
|
||||
CREATE TRIGGER fkd_${table-name}_${foreign-table-name}_id
|
||||
CREATE TRIGGER fkd_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id
|
||||
BEFORE DELETE ON ${foreign-table-name}
|
||||
FOR EACH ROW BEGIN
|
||||
SELECT RAISE(ROLLBACK, 'delete on table "${foreign-table-name}" violates foreign key constraint "fk_${foreign-table-name}_id"')
|
||||
|
@ -284,10 +274,17 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: drop-delete-trigger-restrict ( -- string )
|
||||
[
|
||||
<"
|
||||
DROP TRIGGER fkd_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id;
|
||||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: delete-trigger-cascade ( -- string )
|
||||
[
|
||||
<"
|
||||
CREATE TRIGGER fkd_${table-name}_${foreign-table-name}_id
|
||||
CREATE TRIGGER fkd_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id
|
||||
BEFORE DELETE ON ${foreign-table-name}
|
||||
FOR EACH ROW BEGIN
|
||||
DELETE from ${table-name} WHERE ${table-id} = OLD.${foreign-table-id};
|
||||
|
@ -295,6 +292,13 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: drop-delete-trigger-cascade ( -- string )
|
||||
[
|
||||
<"
|
||||
DROP TRIGGER fkd_${table-name}_${table-id}_${foreign-table-name}_${foreign-table-id}_id;
|
||||
"> interpolate
|
||||
] with-string-writer ;
|
||||
|
||||
: can-be-null? ( -- ? )
|
||||
"sql-spec" get modifiers>> [ +not-null+ = ] any? not ;
|
||||
|
||||
|
@ -318,14 +322,69 @@ M: sqlite-db-connection persistent-table ( -- assoc )
|
|||
delete-trigger-restrict sqlite-trigger,
|
||||
] if ;
|
||||
|
||||
: drop-sqlite-triggers ( -- )
|
||||
drop-insert-trigger sqlite-trigger,
|
||||
drop-update-trigger sqlite-trigger,
|
||||
delete-cascade? [
|
||||
drop-delete-trigger-cascade sqlite-trigger,
|
||||
] [
|
||||
drop-delete-trigger-restrict sqlite-trigger,
|
||||
] if ;
|
||||
|
||||
: db-triggers ( sql-specs word -- )
|
||||
'[
|
||||
[ modifiers>> [ +foreign-id+ = ] deep-any? ] filter
|
||||
[
|
||||
[ class>> db-table-name "db-table" set ]
|
||||
[ column-name>> "table-id" set ]
|
||||
[
|
||||
modifiers>> [ [ +foreign-id+ = ] deep-any? ] filter
|
||||
[
|
||||
[ second db-table-name "foreign-table-name" set ]
|
||||
[ third "foreign-table-id" set ] bi
|
||||
_ execute
|
||||
] each
|
||||
] tri
|
||||
] each
|
||||
] call ;
|
||||
|
||||
: sqlite-create-table ( sql-specs class-name -- )
|
||||
[
|
||||
"create table " 0% 0%
|
||||
"(" 0% [ ", " 0% ] [
|
||||
dup "sql-spec" set
|
||||
dup column-name>> [ "table-id" set ] [ 0% ] bi
|
||||
" " 0%
|
||||
dup type>> lookup-create-type 0%
|
||||
modifiers 0%
|
||||
] interleave
|
||||
] [
|
||||
drop
|
||||
find-primary-key [
|
||||
", " 0%
|
||||
"primary key(" 0%
|
||||
[ "," 0% ] [ column-name>> 0% ] interleave
|
||||
")" 0%
|
||||
] unless-empty
|
||||
");" 0%
|
||||
] 2bi ;
|
||||
|
||||
M: sqlite-db-connection create-sql-statement ( class -- statement )
|
||||
[
|
||||
! specs name
|
||||
[ sqlite-create-table ]
|
||||
[ drop \ create-sqlite-triggers db-triggers ] 2bi
|
||||
] query-make ;
|
||||
|
||||
M: sqlite-db-connection drop-sql-statement ( class -- statements )
|
||||
[
|
||||
[ nip "drop table " 0% 0% ";" 0% ]
|
||||
[ drop \ drop-sqlite-triggers db-triggers ] 2bi
|
||||
] query-make ;
|
||||
|
||||
M: sqlite-db-connection compound ( string seq -- new-string )
|
||||
over {
|
||||
{ "default" [ first number>string " " glue ] }
|
||||
{ "references" [
|
||||
[ >reference-string ] keep
|
||||
first2 [ db-table-name "foreign-table-name" set ]
|
||||
[ "foreign-table-id" set ] bi*
|
||||
create-sqlite-triggers
|
||||
] }
|
||||
{ "references" [ >reference-string ] }
|
||||
[ 2drop ]
|
||||
} case ;
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
USING: arrays assocs classes db kernel namespaces
|
||||
classes.tuple words sequences slots math accessors
|
||||
math.parser io prettyprint db.types continuations
|
||||
destructors mirrors sets db.types db.private ;
|
||||
destructors mirrors sets db.types db.private fry
|
||||
combinators.short-circuit ;
|
||||
IN: db.tuples
|
||||
|
||||
HOOK: create-sql-statement db-connection ( class -- object )
|
||||
|
@ -29,7 +30,7 @@ GENERIC: eval-generator ( singleton -- object )
|
|||
|
||||
: resulting-tuple ( exemplar-tuple row out-params -- tuple )
|
||||
rot class new [
|
||||
[ [ slot-name>> ] dip set-slot-named ] curry 2each
|
||||
'[ slot-name>> _ set-slot-named ] 2each
|
||||
] keep ;
|
||||
|
||||
: query-tuples ( exemplar-tuple statement -- seq )
|
||||
|
@ -98,33 +99,49 @@ M: query >query clone ;
|
|||
|
||||
M: tuple >query <query> swap >>tuple ;
|
||||
|
||||
ERROR: no-defined-persistent object ;
|
||||
|
||||
: ensure-defined-persistent ( object -- object )
|
||||
dup { [ class? ] [ "db-table" word-prop ] } 1&& [
|
||||
no-defined-persistent
|
||||
] unless ;
|
||||
|
||||
: create-table ( class -- )
|
||||
ensure-defined-persistent
|
||||
create-sql-statement [ execute-statement ] with-disposals ;
|
||||
|
||||
: drop-table ( class -- )
|
||||
ensure-defined-persistent
|
||||
drop-sql-statement [ execute-statement ] with-disposals ;
|
||||
|
||||
: recreate-table ( class -- )
|
||||
ensure-defined-persistent
|
||||
[
|
||||
[ drop-sql-statement [ execute-statement ] with-disposals
|
||||
] curry ignore-errors
|
||||
'[
|
||||
_ drop-sql-statement [ execute-statement ] with-disposals
|
||||
] ignore-errors
|
||||
] [ create-table ] bi ;
|
||||
|
||||
: ensure-table ( class -- ) [ create-table ] curry ignore-errors ;
|
||||
: ensure-table ( class -- )
|
||||
ensure-defined-persistent
|
||||
'[ _ create-table ] ignore-errors ;
|
||||
|
||||
: ensure-tables ( classes -- ) [ ensure-table ] each ;
|
||||
|
||||
: insert-tuple ( tuple -- )
|
||||
dup class db-columns find-primary-key db-assigned-id-spec?
|
||||
dup class ensure-defined-persistent
|
||||
db-columns find-primary-key db-assigned-id-spec?
|
||||
[ insert-db-assigned-statement ] [ insert-user-assigned-statement ] if ;
|
||||
|
||||
: update-tuple ( tuple -- )
|
||||
dup class
|
||||
dup class ensure-defined-persistent
|
||||
db-connection get update-statements>> [ <update-tuple-statement> ] cache
|
||||
[ bind-tuple ] keep execute-statement ;
|
||||
|
||||
: delete-tuples ( tuple -- )
|
||||
dup dup class <delete-tuples-statement> [
|
||||
dup
|
||||
dup class ensure-defined-persistent
|
||||
<delete-tuples-statement> [
|
||||
[ bind-tuple ] keep execute-statement
|
||||
] with-disposal ;
|
||||
|
||||
|
@ -132,8 +149,8 @@ M: tuple >query <query> swap >>tuple ;
|
|||
>query [ tuple>> ] [ query>statement ] bi do-select ;
|
||||
|
||||
: select-tuple ( query/tuple -- tuple/f )
|
||||
>query 1 >>limit [ tuple>> ] [ query>statement ] bi do-select
|
||||
[ f ] [ first ] if-empty ;
|
||||
>query 1 >>limit [ tuple>> ] [ query>statement ] bi
|
||||
do-select [ f ] [ first ] if-empty ;
|
||||
|
||||
: count-tuples ( query/tuple -- n )
|
||||
>query [ tuple>> ] [ <count-statement> ] bi do-count
|
||||
|
|
|
@ -220,24 +220,6 @@ ARTICLE: "cookbook-io" "Input and output cookbook"
|
|||
"io"
|
||||
} ;
|
||||
|
||||
ARTICLE: "cookbook-compiler" "Compiler cookbook"
|
||||
"Factor includes two compilers which work behind the scenes. Words are always compiled, and the compilers do not have to be invoked explicitly. For the most part, compilation is a fully transparent process. However, there are a few things worth knowing about the compilation process."
|
||||
$nl
|
||||
"The optimizing compiler trades off compile time for performance of generated code, so loading certain vocabularies might take a while. Saving the image after loading vocabularies can save you a lot of time that you would spend waiting for the same code to load in every coding session; see " { $link "images" } " for information."
|
||||
$nl
|
||||
"After loading a vocabulary, you might see messages like:"
|
||||
{ $code
|
||||
":errors - print 2 compiler errors."
|
||||
":warnings - print 50 compiler warnings."
|
||||
}
|
||||
"These warnings arise from the compiler's stack effect checker. Warnings are non-fatal conditions -- not all code has a static stack effect, so you try to minimize warnings but understand that in many cases they cannot be eliminated. Errors indicate programming mistakes, such as erroneous stack effect declarations."
|
||||
{ $references
|
||||
"To learn more about the compiler and static stack effect inference, read these articles:"
|
||||
"compiler"
|
||||
"compiler-errors"
|
||||
"inference"
|
||||
} ;
|
||||
|
||||
ARTICLE: "cookbook-application" "Application cookbook"
|
||||
"Vocabularies can define a main entry point:"
|
||||
{ $code "IN: game-of-life"
|
||||
|
@ -396,7 +378,6 @@ ARTICLE: "cookbook" "Factor cookbook"
|
|||
{ $subsection "cookbook-io" }
|
||||
{ $subsection "cookbook-application" }
|
||||
{ $subsection "cookbook-scripts" }
|
||||
{ $subsection "cookbook-compiler" }
|
||||
{ $subsection "cookbook-philosophy" }
|
||||
{ $subsection "cookbook-pitfalls" }
|
||||
{ $subsection "cookbook-next" } ;
|
||||
|
|
|
@ -33,8 +33,8 @@ $nl
|
|||
{ { $snippet { $emphasis "foo" } "*" } { "alternative form of " { $snippet "foo" } ", or a generic word called by " { $snippet "foo" } } { { $links at* pprint* } } }
|
||||
{ { $snippet "(" { $emphasis "foo" } ")" } { "implementation detail word used by " { $snippet "foo" } } { { $link (clone) } } }
|
||||
{ { $snippet "set-" { $emphasis "foo" } } { "sets " { $snippet "foo" } " to a new value" } { $links set-length } }
|
||||
{ { $snippet { $emphasis "foo" } ">>" } { "gets the " { $snippet "foo" } " slot of the tuple at the top of the stack; see " { $link "accessors" } } { { $link >>name } } }
|
||||
{ { $snippet ">>" { $emphasis "foo" } } { "sets the " { $snippet "foo" } " slot of the tuple at the top of the stack; see " { $link "accessors" } } { { $link name>> } } }
|
||||
{ { $snippet { $emphasis "foo" } ">>" } { "gets the " { $snippet "foo" } " slot of the tuple at the top of the stack; see " { $link "accessors" } } { { $link name>> } } }
|
||||
{ { $snippet ">>" { $emphasis "foo" } } { "sets the " { $snippet "foo" } " slot of the tuple at the top of the stack; see " { $link "accessors" } } { { $link >>name } } }
|
||||
{ { $snippet "with-" { $emphasis "foo" } } { "performs some kind of initialization and cleanup related to " { $snippet "foo" } ", usually in a new dynamic scope" } { $links with-scope with-input-stream with-output-stream } }
|
||||
{ { $snippet "$" { $emphasis "foo" } } { "help markup" } { $links $heading $emphasis } }
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ HELP: arg
|
|||
|
||||
HELP: >polar
|
||||
{ $values { "z" number } { "abs" "a non-negative real number" } { "arg" "a number in the interval " { $snippet "(-pi,pi]" } } }
|
||||
{ $description "Creates a complex number from an absolute value and argument (polar form)." } ;
|
||||
{ $description "Converts a complex number into an absolute value and argument (polar form)." } ;
|
||||
|
||||
HELP: cis
|
||||
{ $values { "arg" "a real number" } { "z" "a complex number on the unit circle" } }
|
||||
|
|
|
@ -252,14 +252,10 @@ M: real tanh ftanh ;
|
|||
|
||||
: -i* ( x -- y ) >rect swap neg rect> ;
|
||||
|
||||
GENERIC: asin ( x -- y ) foldable
|
||||
|
||||
M: number asin
|
||||
: asin ( x -- y )
|
||||
dup [-1,1]? [ fasin ] [ i* asinh -i* ] if ; inline
|
||||
|
||||
GENERIC: acos ( x -- y ) foldable
|
||||
|
||||
M: number acos
|
||||
: acos ( x -- y )
|
||||
dup [-1,1]? [ facos ] [ asin pi 2 / swap - ] if ;
|
||||
inline
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@ HELP: inconsistent-recursive-call-error
|
|||
} ;
|
||||
|
||||
ARTICLE: "inference-errors" "Inference warnings and errors"
|
||||
"These conditions are thrown by " { $link "inference" } ", as well as the " { $link "compiler" } "."
|
||||
$nl
|
||||
"Main wrapper for all inference warnings and errors:"
|
||||
{ $subsection inference-error }
|
||||
"Inference warnings:"
|
||||
|
|
|
@ -22,7 +22,7 @@ ARTICLE: "slot-class-declaration" "Slot class declarations"
|
|||
ARTICLE: "slot-class-coercion" "Coercive slot declarations"
|
||||
"If the class of a slot is declared to be one of " { $link fixnum } " or " { $link float } ", then rather than testing values with the class predicate, writer words coerce values to the relevant type with " { $link >fixnum } " or " { $link >float } ". This may still result in error, but permits a wider range of values than a class predicate test. It also results in a possible loss of precision; for example, storing a large integer into a " { $link fixnum } " slot will silently overflow and discard high bits, and storing a ratio into a " { $link float } " slot may lose precision if the ratio is one which cannot be represented exactly with floating-point."
|
||||
$nl
|
||||
"This feature is mostly intended as an optimization for low-level code designed to avoid integer overflow, or where floating point precision is sufficient. Most code needs to work transparently with large integers, and thus hsould avoid the coercion behavior by using " { $link integer } " and " { $link real } " in place of " { $link fixnum } " and " { $link float } "." ;
|
||||
"This feature is mostly intended as an optimization for low-level code designed to avoid integer overflow, or where floating point precision is sufficient. Most code needs to work transparently with large integers, and thus should avoid the coercion behavior by using " { $link integer } " and " { $link real } " in place of " { $link fixnum } " and " { $link float } "." ;
|
||||
|
||||
ARTICLE: "tuple-declarations" "Tuple slot declarations"
|
||||
"The slot specifier syntax of the " { $link POSTPONE: TUPLE: } " parsing word understands the following slot attributes:"
|
||||
|
|
|
@ -3,9 +3,16 @@ USING: help.markup help.syntax vocabs.loader words io
|
|||
quotations words.symbol ;
|
||||
|
||||
ARTICLE: "compiler-errors" "Compiler warnings and errors"
|
||||
"The compiler saves " { $link "inference-errors" } " in a global variable:"
|
||||
{ $subsection compiler-errors }
|
||||
"These notifications can be viewed later:"
|
||||
"After loading a vocabulary, you might see messages like:"
|
||||
{ $code
|
||||
":errors - print 2 compiler errors."
|
||||
":warnings - print 50 compiler warnings."
|
||||
}
|
||||
"These warnings arise from the compiler's stack effect checker. Warnings are non-fatal conditions -- not all code has a static stack effect, so you try to minimize warnings but understand that in many cases they cannot be eliminated. Errors indicate programming mistakes, such as erroneous stack effect declarations."
|
||||
$nl
|
||||
"The precise warning and error conditions are documented in " { $link "inference-errors" } "."
|
||||
$nl
|
||||
"Words to view warnings and errors:"
|
||||
{ $subsection :errors }
|
||||
{ $subsection :warnings }
|
||||
{ $subsection :linkage }
|
||||
|
|
|
@ -34,13 +34,20 @@ $nl
|
|||
{ $subsection "vocabs.roots" }
|
||||
"Vocabulary names map directly to source files. A vocabulary named " { $snippet "foo.bar" } " must be defined in a " { $snippet "bar" } " directory nested inside a " { $snippet "foo" } " directory of a vocabulary root. Any level of vocabulary nesting is permitted."
|
||||
$nl
|
||||
"The vocabulary directory - " { $snippet "bar" } " in our example - can contain the following files; the first is required while the rest are optional:"
|
||||
"The vocabulary directory - " { $snippet "bar" } " in our example - contains a source file:"
|
||||
{ $list
|
||||
{ { $snippet "foo/bar/bar.factor" } " - the source file, must define words in the " { $snippet "foo.bar" } " vocabulary with an " { $snippet "IN: foo.bar" } " form" }
|
||||
}
|
||||
"Two other Factor source files, storing documentation and tests, respectively, are optional:"
|
||||
{ $list
|
||||
{ { $snippet "foo/bar/bar.factor" } " - the source file, defines words in the " { $snippet "foo.bar" } " vocabulary" }
|
||||
{ { $snippet "foo/bar/bar-docs.factor" } " - documentation, see " { $link "writing-help" } }
|
||||
{ { $snippet "foo/bar/bar-tests.factor" } " - unit tests, see " { $link "tools.test" } }
|
||||
}
|
||||
"Finally, three text files can contain meta-data:"
|
||||
{ $list
|
||||
{ { $snippet "foo/bar/authors.txt" } " - a series of lines, with one author name per line. These are listed under " { $link "vocab-authors" } }
|
||||
{ { $snippet "foo/bar/summary.txt" } " - a one-line description" }
|
||||
{ { $snippet "foo/bar/tags.txt" } " - a whitespace-separated list of tags which classify the vocabulary" }
|
||||
{ { $snippet "foo/bar/tags.txt" } " - a whitespace-separated list of tags which classify the vocabulary. Consult " { $link "vocab-tags" } " for a list of existing tags you can re-use" }
|
||||
}
|
||||
"While " { $link POSTPONE: USE: } " and " { $link POSTPONE: USING: } " load vocabularies which have not been loaded before adding them to the search path, it is also possible to load a vocabulary without adding it to the search path:"
|
||||
{ $subsection require }
|
||||
|
|
|
@ -92,8 +92,8 @@ PRIVATE>
|
|||
|
||||
: (fuel-word-synopsis) ( word usings -- str/f )
|
||||
[
|
||||
[ vocab ] filter interactive-vocabs get append interactive-vocabs set
|
||||
fuel-find-word [ synopsis ] when*
|
||||
[ vocab ] filter interactive-vocabs [ append ] change
|
||||
fuel-find-word [ synopsis ] [ f ] if*
|
||||
] with-scope ;
|
||||
|
||||
: (fuel-word-see) ( word -- elem )
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
! Copyright (C) 2009 Jason W. Merrill.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: tools.test automatic-differentiation.derivatives ;
|
||||
IN: automatic-differentiation.derivatives.tests
|
|
@ -88,14 +88,14 @@ HELP: drecip
|
|||
}
|
||||
{ $description "Reciprocal of a dual number." } ;
|
||||
|
||||
HELP: define-dual-method
|
||||
HELP: define-dual
|
||||
{ $values
|
||||
{ "word" word }
|
||||
}
|
||||
{ $description "Defines a method on the dual numbers for generic word." }
|
||||
{ $description "Defines a word " { $snippet "d[word]" } " in the " { $vocab-link "math.dual" } " vocabulary that operates on dual numbers." }
|
||||
{ $notes "Uses the derivative word-prop, which holds a list of quotations giving the partial derivatives of the word with respect to each of its arguments. This can be set using " { $link POSTPONE: DERIVATIVE: } "." } ;
|
||||
|
||||
{ define-dual-method dual-op POSTPONE: DERIVATIVE: } related-words
|
||||
{ define-dual dual-op POSTPONE: DERIVATIVE: } related-words
|
||||
|
||||
HELP: dual
|
||||
{ $class-description "The class of dual numbers with non-zero epsilon part." } ;
|
||||
|
|
|
@ -4,13 +4,13 @@ USING: tools.test math.dual kernel accessors math math.functions
|
|||
math.constants ;
|
||||
IN: math.dual.tests
|
||||
|
||||
[ 0.0 1.0 ] [ 0 1 <dual> sin unpack-dual ] unit-test
|
||||
[ 1.0 0.0 ] [ 0 1 <dual> cos unpack-dual ] unit-test
|
||||
[ 0.0 1.0 ] [ 0 1 <dual> dsin unpack-dual ] unit-test
|
||||
[ 1.0 0.0 ] [ 0 1 <dual> dcos unpack-dual ] unit-test
|
||||
[ 3 5 ] [ 1 5 <dual> 2 d+ unpack-dual ] unit-test
|
||||
[ 0 -1 ] [ 1 5 <dual> 1 6 <dual> d- unpack-dual ] unit-test
|
||||
[ 2 1 ] [ 2 3 <dual> 1 -1 <dual> d* unpack-dual ] unit-test
|
||||
[ 1/2 -1/4 ] [ 2 1 <dual> 1 swap d/ unpack-dual ] unit-test
|
||||
[ 2 ] [ 1 1 <dual> 2 d^ epsilon-part>> ] unit-test
|
||||
[ 2.0 .25 ] [ 4 1 <dual> sqrt unpack-dual ] unit-test
|
||||
[ 2.0 .25 ] [ 4 1 <dual> dsqrt unpack-dual ] unit-test
|
||||
[ 2 -1 ] [ -2 1 <dual> dabs unpack-dual ] unit-test
|
||||
[ -2 -1 ] [ 2 1 <dual> dneg unpack-dual ] unit-test
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2009 Jason W. Merrill.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel math math.functions math.derivatives accessors
|
||||
macros words effects sequences generalizations fry
|
||||
macros words effects vocabs sequences generalizations fry
|
||||
combinators.smart generic compiler.units ;
|
||||
|
||||
IN: math.dual
|
||||
|
@ -57,36 +57,15 @@ MACRO: dual-op ( word -- )
|
|||
tri
|
||||
'[ _ @ @ <dual> ] ;
|
||||
|
||||
: define-dual-method ( word -- )
|
||||
[ \ dual swap create-method ] keep '[ _ dual-op ] define ;
|
||||
: define-dual ( word -- )
|
||||
[
|
||||
[ stack-effect ]
|
||||
[ name>> "d" prepend "math.dual" create ]
|
||||
bi [ set-stack-effect ] keep
|
||||
]
|
||||
keep
|
||||
'[ _ dual-op ] define ;
|
||||
|
||||
! Specialize math functions to operate on dual numbers.
|
||||
[ { sqrt exp log sin cos tan sinh cosh tanh acos asin atan }
|
||||
[ define-dual-method ] each ] with-compilation-unit
|
||||
|
||||
! Inverse methods { asinh, acosh, atanh } are not generic, so
|
||||
! there is no way to specialize them for dual numbers. However,
|
||||
! they are defined in terms of functions that can operate on
|
||||
! dual numbers and arithmetic methods, so if it becomes
|
||||
! possible to make arithmetic operators work directly on dual
|
||||
! numbers, we will get these for free.
|
||||
|
||||
! Arithmetic words are not generic (yet?), so we have to
|
||||
! define special versions of them to operate on dual numbers.
|
||||
: d+ ( x y -- x+y ) \ + dual-op ;
|
||||
: d- ( x y -- x-y ) \ - dual-op ;
|
||||
: d* ( x y -- x*y ) \ * dual-op ;
|
||||
: d/ ( x y -- x/y ) \ / dual-op ;
|
||||
: d^ ( x y -- x^y ) \ ^ dual-op ;
|
||||
|
||||
: dabs ( x -- |x| ) \ abs dual-op ;
|
||||
|
||||
! The following words are also not generic, but are defined in
|
||||
! terms of words that can operate on dual numbers and
|
||||
! arithmetic. If it becomes possible to implement arithmetic on
|
||||
! dual numbers directly, these functions can be deleted.
|
||||
: dneg ( x -- -x ) \ neg dual-op ;
|
||||
: drecip ( x -- 1/x ) \ recip dual-op ;
|
||||
: dasinh ( x -- y ) \ asinh dual-op ;
|
||||
: dacosh ( x -- y ) \ acosh dual-op ;
|
||||
: datanh ( x -- y ) \ atanh dual-op ;
|
||||
[ all-words [ "derivative" word-prop ] filter
|
||||
[ define-dual ] each ] with-compilation-unit
|
Loading…
Reference in New Issue