Merge branch 'master' into unicode

db4
Daniel Ehrenberg 2008-02-11 18:42:08 -06:00
commit 8c63311a0f
552 changed files with 9684 additions and 5964 deletions

View File

@ -63,8 +63,9 @@ default:
@echo "macosx-ppc" @echo "macosx-ppc"
@echo "solaris-x86-32" @echo "solaris-x86-32"
@echo "solaris-x86-64" @echo "solaris-x86-64"
@echo "windows-ce-arm" @echo "wince-arm"
@echo "windows-nt-x86-32" @echo "winnt-x86-32"
@echo "winnt-x86-64"
@echo "" @echo ""
@echo "Additional modifiers:" @echo "Additional modifiers:"
@echo "" @echo ""
@ -122,10 +123,21 @@ solaris-x86-32:
solaris-x86-64: solaris-x86-64:
$(MAKE) $(EXECUTABLE) CONFIG=vm/Config.solaris.x86.64 $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.solaris.x86.64
windows-nt-x86-32: freetype6.dll:
wget http://factorcode.org/dlls/freetype6.dll
chmod 755 freetype6.dll
zlib1.dll:
wget http://factorcode.org/dlls/zlib1.dll
chmod 755 zlib1.dll
winnt-x86-32: freetype6.dll zlib1.dll
$(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.nt.x86.32 $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.nt.x86.32
windows-ce-arm: winnt-x86-64:
$(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.nt.x86.64
wince-arm:
$(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.ce.arm $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.ce.arm
macosx.app: factor macosx.app: factor
@ -151,7 +163,7 @@ clean:
rm -f factor*.dll libfactor*.* rm -f factor*.dll libfactor*.*
vm/resources.o: vm/resources.o:
windres vm/factor.rs vm/resources.o $(WINDRES) vm/factor.rs vm/resources.o
.c.o: .c.o:
$(CC) -c $(CFLAGS) -o $@ $< $(CC) -c $(CFLAGS) -o $@ $<

View File

@ -14,7 +14,7 @@ prettyprint ;
! Testing the various bignum accessor ! Testing the various bignum accessor
10 <byte-array> "dump" set 10 <byte-array> "dump" set
[ "dump" get alien-address ] unit-test-fails [ "dump" get alien-address ] must-fail
[ 123 ] [ [ 123 ] [
123 "dump" get 0 set-alien-signed-1 123 "dump" get 0 set-alien-signed-1
@ -61,9 +61,9 @@ cell 8 = [
[ ] [ 0 F{ 1 2 3 } <displaced-alien> drop ] unit-test [ ] [ 0 F{ 1 2 3 } <displaced-alien> drop ] unit-test
[ ] [ 0 ?{ t f t } <displaced-alien> drop ] unit-test [ ] [ 0 ?{ t f t } <displaced-alien> drop ] unit-test
[ 0 B{ 1 2 3 } <displaced-alien> alien-address ] unit-test-fails [ 0 B{ 1 2 3 } <displaced-alien> alien-address ] must-fail
[ 1 1 <displaced-alien> ] unit-test-fails [ 1 1 <displaced-alien> ] must-fail
[ f ] [ 0 B{ 1 2 3 } <displaced-alien> pinned-c-ptr? ] unit-test [ f ] [ 0 B{ 1 2 3 } <displaced-alien> pinned-c-ptr? ] unit-test

View File

@ -34,6 +34,10 @@ HELP: stack-size
{ $description "Outputs the number of bytes to reserve on the C stack by a value of this C type. In most cases this is equal to " { $link heap-size } ", except on some platforms where C structs are passed by invisible reference, in which case a C struct type only uses as much space as a pointer on the C stack." } { $description "Outputs the number of bytes to reserve on the C stack by a value of this C type. In most cases this is equal to " { $link heap-size } ", except on some platforms where C structs are passed by invisible reference, in which case a C struct type only uses as much space as a pointer on the C stack." }
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ; { $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
HELP: byte-length
{ $values { "seq" "A byte array or float array" } { "n" "a non-negative integer" } }
{ $contract "Outputs the size of the byte array or float array data in bytes as presented to the C library interface." } ;
HELP: c-getter HELP: c-getter
{ $values { "name" string } { "quot" "a quotation with stack effect " { $snippet "( c-ptr n -- obj )" } } } { $values { "name" string } { "quot" "a quotation with stack effect " { $snippet "( c-ptr n -- obj )" } } }
{ $description "Outputs a quotation which reads values of this C type from a C structure." } { $description "Outputs a quotation which reads values of this C type from a C structure." }

View File

@ -71,4 +71,4 @@ TYPEDEF: uchar* MyLPBYTE
[ [
0 B{ 1 2 3 4 } <displaced-alien> <void*> 0 B{ 1 2 3 4 } <displaced-alien> <void*>
] unit-test-fails ] must-fail

View File

@ -1,11 +1,17 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: byte-arrays arrays generator.registers assocs USING: bit-arrays byte-arrays float-arrays arrays
kernel kernel.private libc math namespaces parser sequences generator.registers assocs kernel kernel.private libc math
strings words assocs splitting math.parser cpu.architecture namespaces parser sequences strings words assocs splitting
alien alien.accessors quotations system compiler.units ; math.parser cpu.architecture alien alien.accessors quotations
system compiler.units ;
IN: alien.c-types IN: alien.c-types
DEFER: <int>
DEFER: *char
: little-endian? ( -- ? ) 1 <int> *char 1 = ; foldable
TUPLE: c-type TUPLE: c-type
boxer prep unboxer boxer prep unboxer
getter setter getter setter
@ -107,6 +113,14 @@ M: string stack-size c-type stack-size ;
M: c-type stack-size c-type-size ; M: c-type stack-size c-type-size ;
GENERIC: byte-length ( seq -- n ) flushable
M: bit-array byte-length length 7 + -3 shift ;
M: byte-array byte-length length ;
M: float-array byte-length length "double" heap-size * ;
: c-getter ( name -- quot ) : c-getter ( name -- quot )
c-type c-type-getter [ c-type c-type-getter [
[ "Cannot read struct fields with type" throw ] [ "Cannot read struct fields with type" throw ]
@ -205,6 +219,9 @@ M: long-long-type box-return ( type -- )
over [ <c-object> tuck 0 ] over c-setter append swap over [ <c-object> tuck 0 ] over c-setter append swap
>r >r constructor-word r> r> add* define-inline ; >r >r constructor-word r> r> add* define-inline ;
: c-bool> ( int -- ? )
zero? not ;
: >c-array ( seq type word -- ) : >c-array ( seq type word -- )
>r >r dup length dup r> <c-array> dup -roll r> >r >r dup length dup r> <c-array> dup -roll r>
[ execute ] 2curry 2each ; inline [ execute ] 2curry 2each ; inline

View File

@ -1,346 +1,356 @@
IN: temporary IN: temporary
USING: alien alien.c-types alien.syntax compiler kernel USING: alien alien.c-types alien.syntax compiler kernel
namespaces namespaces tools.test sequences inference words namespaces namespaces tools.test sequences inference words
arrays parser quotations continuations inference.backend effects arrays parser quotations continuations inference.backend effects
namespaces.private io io.streams.string memory system threads namespaces.private io io.streams.string memory system threads
tools.test.inference ; tools.test ;
FUNCTION: void ffi_test_0 ; FUNCTION: void ffi_test_0 ;
[ ] [ ffi_test_0 ] unit-test [ ] [ ffi_test_0 ] unit-test
FUNCTION: int ffi_test_1 ; FUNCTION: int ffi_test_1 ;
[ 3 ] [ ffi_test_1 ] unit-test [ 3 ] [ ffi_test_1 ] unit-test
FUNCTION: int ffi_test_2 int x int y ; FUNCTION: int ffi_test_2 int x int y ;
[ 5 ] [ 2 3 ffi_test_2 ] unit-test [ 5 ] [ 2 3 ffi_test_2 ] unit-test
[ "hi" 3 ffi_test_2 ] unit-test-fails [ "hi" 3 ffi_test_2 ] must-fail
FUNCTION: int ffi_test_3 int x int y int z int t ; FUNCTION: int ffi_test_3 int x int y int z int t ;
[ 25 ] [ 2 3 4 5 ffi_test_3 ] unit-test [ 25 ] [ 2 3 4 5 ffi_test_3 ] unit-test
FUNCTION: float ffi_test_4 ; FUNCTION: float ffi_test_4 ;
[ 1.5 ] [ ffi_test_4 ] unit-test [ 1.5 ] [ ffi_test_4 ] unit-test
FUNCTION: double ffi_test_5 ; FUNCTION: double ffi_test_5 ;
[ 1.5 ] [ ffi_test_5 ] unit-test [ 1.5 ] [ ffi_test_5 ] unit-test
FUNCTION: int ffi_test_9 int a int b int c int d int e int f int g ; FUNCTION: int ffi_test_9 int a int b int c int d int e int f int g ;
[ 28 ] [ 1 2 3 4 5 6 7 ffi_test_9 ] unit-test [ 28 ] [ 1 2 3 4 5 6 7 ffi_test_9 ] unit-test
[ "a" 2 3 4 5 6 7 ffi_test_9 ] unit-test-fails [ "a" 2 3 4 5 6 7 ffi_test_9 ] must-fail
[ 1 2 3 4 5 6 "a" ffi_test_9 ] unit-test-fails [ 1 2 3 4 5 6 "a" ffi_test_9 ] must-fail
C-STRUCT: foo C-STRUCT: foo
{ "int" "x" } { "int" "x" }
{ "int" "y" } { "int" "y" }
; ;
: make-foo ( x y -- foo ) : make-foo ( x y -- foo )
"foo" <c-object> [ set-foo-y ] keep [ set-foo-x ] keep ; "foo" <c-object> [ set-foo-y ] keep [ set-foo-x ] keep ;
FUNCTION: int ffi_test_11 int a foo b int c ; FUNCTION: int ffi_test_11 int a foo b int c ;
[ 14 ] [ 1 2 3 make-foo 4 ffi_test_11 ] unit-test [ 14 ] [ 1 2 3 make-foo 4 ffi_test_11 ] unit-test
FUNCTION: int ffi_test_13 int a int b int c int d int e int f int g int h int i int j int k ; FUNCTION: int ffi_test_13 int a int b int c int d int e int f int g int h int i int j int k ;
[ 66 ] [ 1 2 3 4 5 6 7 8 9 10 11 ffi_test_13 ] unit-test [ 66 ] [ 1 2 3 4 5 6 7 8 9 10 11 ffi_test_13 ] unit-test
FUNCTION: foo ffi_test_14 int x int y ; FUNCTION: foo ffi_test_14 int x int y ;
[ 11 6 ] [ 11 6 ffi_test_14 dup foo-x swap foo-y ] unit-test [ 11 6 ] [ 11 6 ffi_test_14 dup foo-x swap foo-y ] unit-test
FUNCTION: char* ffi_test_15 char* x char* y ; FUNCTION: char* ffi_test_15 char* x char* y ;
[ "foo" ] [ "xy" "zt" ffi_test_15 ] unit-test [ "foo" ] [ "xy" "zt" ffi_test_15 ] unit-test
[ "bar" ] [ "xy" "xy" ffi_test_15 ] unit-test [ "bar" ] [ "xy" "xy" ffi_test_15 ] unit-test
[ 1 2 ffi_test_15 ] unit-test-fails [ 1 2 ffi_test_15 ] must-fail
C-STRUCT: bar C-STRUCT: bar
{ "long" "x" } { "long" "x" }
{ "long" "y" } { "long" "y" }
{ "long" "z" } { "long" "z" }
; ;
FUNCTION: bar ffi_test_16 long x long y long z ; FUNCTION: bar ffi_test_16 long x long y long z ;
[ 11 6 -7 ] [ [ 11 6 -7 ] [
11 6 -7 ffi_test_16 dup bar-x over bar-y rot bar-z 11 6 -7 ffi_test_16 dup bar-x over bar-y rot bar-z
] unit-test ] unit-test
C-STRUCT: tiny C-STRUCT: tiny
{ "int" "x" } { "int" "x" }
; ;
FUNCTION: tiny ffi_test_17 int x ; FUNCTION: tiny ffi_test_17 int x ;
[ 11 ] [ 11 ffi_test_17 tiny-x ] unit-test [ 11 ] [ 11 ffi_test_17 tiny-x ] unit-test
[ t ] [ [ [ alien-indirect ] infer ] catch inference-error? ] unit-test [ [ alien-indirect ] infer ] [ inference-error? ] must-fail-with
: indirect-test-1 : indirect-test-1
"int" { } "cdecl" alien-indirect ; "int" { } "cdecl" alien-indirect ;
{ 1 1 } [ indirect-test-1 ] unit-test-effect { 1 1 } [ indirect-test-1 ] must-infer-as
[ 3 ] [ "ffi_test_1" f dlsym indirect-test-1 ] unit-test [ 3 ] [ "ffi_test_1" f dlsym indirect-test-1 ] unit-test
[ -1 indirect-test-1 ] unit-test-fails [ -1 indirect-test-1 ] must-fail
: indirect-test-2 : indirect-test-2
"int" { "int" "int" } "cdecl" alien-indirect data-gc ; "int" { "int" "int" } "cdecl" alien-indirect data-gc ;
{ 3 1 } [ indirect-test-2 ] unit-test-effect { 3 1 } [ indirect-test-2 ] must-infer-as
[ 5 ] [ 5 ]
[ 2 3 "ffi_test_2" f dlsym indirect-test-2 ] [ 2 3 "ffi_test_2" f dlsym indirect-test-2 ]
unit-test unit-test
: indirect-test-3 : indirect-test-3
"int" { "int" "int" "int" "int" } "stdcall" alien-indirect "int" { "int" "int" "int" "int" } "stdcall" alien-indirect
data-gc ; data-gc ;
<< "f-stdcall" f "stdcall" add-library >> << "f-stdcall" f "stdcall" add-library >>
[ f ] [ "f-stdcall" load-library ] unit-test [ f ] [ "f-stdcall" load-library ] unit-test
[ "stdcall" ] [ "f-stdcall" library library-abi ] unit-test [ "stdcall" ] [ "f-stdcall" library library-abi ] unit-test
: ffi_test_18 ( w x y z -- int ) : ffi_test_18 ( w x y z -- int )
"int" "f-stdcall" "ffi_test_18" { "int" "int" "int" "int" } "int" "f-stdcall" "ffi_test_18" { "int" "int" "int" "int" }
alien-invoke data-gc ; alien-invoke data-gc ;
[ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test [ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test
: ffi_test_19 ( x y z -- bar ) : ffi_test_19 ( x y z -- bar )
"bar" "f-stdcall" "ffi_test_19" { "long" "long" "long" } "bar" "f-stdcall" "ffi_test_19" { "long" "long" "long" }
alien-invoke data-gc ; alien-invoke data-gc ;
[ 11 6 -7 ] [ [ 11 6 -7 ] [
11 6 -7 ffi_test_19 dup bar-x over bar-y rot bar-z 11 6 -7 ffi_test_19 dup bar-x over bar-y rot bar-z
] unit-test ] unit-test
FUNCTION: double ffi_test_6 float x float y ; FUNCTION: double ffi_test_6 float x float y ;
[ 6.0 ] [ 3.0 2.0 ffi_test_6 ] unit-test [ 6.0 ] [ 3.0 2.0 ffi_test_6 ] unit-test
[ "a" "b" ffi_test_6 ] unit-test-fails [ "a" "b" ffi_test_6 ] must-fail
FUNCTION: double ffi_test_7 double x double y ; FUNCTION: double ffi_test_7 double x double y ;
[ 6.0 ] [ 3.0 2.0 ffi_test_7 ] unit-test [ 6.0 ] [ 3.0 2.0 ffi_test_7 ] unit-test
FUNCTION: double ffi_test_8 double x float y double z float t int w ; FUNCTION: double ffi_test_8 double x float y double z float t int w ;
[ 19.0 ] [ 3.0 2.0 1.0 6.0 7 ffi_test_8 ] unit-test [ 19.0 ] [ 3.0 2.0 1.0 6.0 7 ffi_test_8 ] unit-test
FUNCTION: int ffi_test_10 int a int b double c int d float e int f int g int h ; FUNCTION: int ffi_test_10 int a int b double c int d float e int f int g int h ;
[ -34 ] [ 1 2 3.0 4 5.0 6 7 8 ffi_test_10 ] unit-test [ -34 ] [ 1 2 3.0 4 5.0 6 7 8 ffi_test_10 ] unit-test
FUNCTION: void ffi_test_20 double x1, double x2, double x3, FUNCTION: void ffi_test_20 double x1, double x2, double x3,
double y1, double y2, double y3, double y1, double y2, double y3,
double z1, double z2, double z3 ; double z1, double z2, double z3 ;
[ ] [ 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 ffi_test_20 ] unit-test [ ] [ 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 ffi_test_20 ] unit-test
! Make sure XT doesn't get clobbered in stack frame ! Make sure XT doesn't get clobbered in stack frame
: ffi_test_31 : ffi_test_31
"void" "void"
f "ffi_test_31" f "ffi_test_31"
{ "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" } { "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" }
alien-invoke code-gc 3 ; alien-invoke code-gc 3 ;
[ 3 ] [ 42 [ ] each ffi_test_31 ] unit-test [ 3 ] [ 42 [ ] each ffi_test_31 ] unit-test
FUNCTION: longlong ffi_test_21 long x long y ; FUNCTION: longlong ffi_test_21 long x long y ;
[ 121932631112635269 ] [ 121932631112635269 ]
[ 123456789 987654321 ffi_test_21 ] unit-test [ 123456789 987654321 ffi_test_21 ] unit-test
FUNCTION: long ffi_test_22 long x longlong y longlong z ; FUNCTION: long ffi_test_22 long x longlong y longlong z ;
[ 987655432 ] [ 987655432 ]
[ 1111 121932631112635269 123456789 ffi_test_22 ] unit-test [ 1111 121932631112635269 123456789 ffi_test_22 ] unit-test
[ 1111 f 123456789 ffi_test_22 ] unit-test-fails [ 1111 f 123456789 ffi_test_22 ] must-fail
C-STRUCT: rect C-STRUCT: rect
{ "float" "x" } { "float" "x" }
{ "float" "y" } { "float" "y" }
{ "float" "w" } { "float" "w" }
{ "float" "h" } { "float" "h" }
; ;
: <rect> : <rect>
"rect" <c-object> "rect" <c-object>
[ set-rect-h ] keep [ set-rect-h ] keep
[ set-rect-w ] keep [ set-rect-w ] keep
[ set-rect-y ] keep [ set-rect-y ] keep
[ set-rect-x ] keep ; [ set-rect-x ] keep ;
FUNCTION: int ffi_test_12 int a int b rect c int d int e int f ; FUNCTION: int ffi_test_12 int a int b rect c int d int e int f ;
[ 45 ] [ 1 2 3.0 4.0 5.0 6.0 <rect> 7 8 9 ffi_test_12 ] unit-test [ 45 ] [ 1 2 3.0 4.0 5.0 6.0 <rect> 7 8 9 ffi_test_12 ] unit-test
[ 1 2 { 1 2 3 } 7 8 9 ffi_test_12 ] unit-test-fails [ 1 2 { 1 2 3 } 7 8 9 ffi_test_12 ] must-fail
FUNCTION: float ffi_test_23 ( float[3] x, float[3] y ) ; FUNCTION: float ffi_test_23 ( float[3] x, float[3] y ) ;
[ 32.0 ] [ { 1.0 2.0 3.0 } >c-float-array { 4.0 5.0 6.0 } >c-float-array ffi_test_23 ] unit-test [ 32.0 ] [ { 1.0 2.0 3.0 } >c-float-array { 4.0 5.0 6.0 } >c-float-array ffi_test_23 ] unit-test
! Test odd-size structs ! Test odd-size structs
C-STRUCT: test-struct-1 { { "char" 1 } "x" } ; C-STRUCT: test-struct-1 { { "char" 1 } "x" } ;
FUNCTION: test-struct-1 ffi_test_24 ; FUNCTION: test-struct-1 ffi_test_24 ;
[ B{ 1 } ] [ ffi_test_24 ] unit-test [ B{ 1 } ] [ ffi_test_24 ] unit-test
C-STRUCT: test-struct-2 { { "char" 2 } "x" } ; C-STRUCT: test-struct-2 { { "char" 2 } "x" } ;
FUNCTION: test-struct-2 ffi_test_25 ; FUNCTION: test-struct-2 ffi_test_25 ;
[ B{ 1 2 } ] [ ffi_test_25 ] unit-test [ B{ 1 2 } ] [ ffi_test_25 ] unit-test
C-STRUCT: test-struct-3 { { "char" 3 } "x" } ; C-STRUCT: test-struct-3 { { "char" 3 } "x" } ;
FUNCTION: test-struct-3 ffi_test_26 ; FUNCTION: test-struct-3 ffi_test_26 ;
[ B{ 1 2 3 } ] [ ffi_test_26 ] unit-test [ B{ 1 2 3 } ] [ ffi_test_26 ] unit-test
C-STRUCT: test-struct-4 { { "char" 4 } "x" } ; C-STRUCT: test-struct-4 { { "char" 4 } "x" } ;
FUNCTION: test-struct-4 ffi_test_27 ; FUNCTION: test-struct-4 ffi_test_27 ;
[ B{ 1 2 3 4 } ] [ ffi_test_27 ] unit-test [ B{ 1 2 3 4 } ] [ ffi_test_27 ] unit-test
C-STRUCT: test-struct-5 { { "char" 5 } "x" } ; C-STRUCT: test-struct-5 { { "char" 5 } "x" } ;
FUNCTION: test-struct-5 ffi_test_28 ; FUNCTION: test-struct-5 ffi_test_28 ;
[ B{ 1 2 3 4 5 } ] [ ffi_test_28 ] unit-test [ B{ 1 2 3 4 5 } ] [ ffi_test_28 ] unit-test
C-STRUCT: test-struct-6 { { "char" 6 } "x" } ; C-STRUCT: test-struct-6 { { "char" 6 } "x" } ;
FUNCTION: test-struct-6 ffi_test_29 ; FUNCTION: test-struct-6 ffi_test_29 ;
[ B{ 1 2 3 4 5 6 } ] [ ffi_test_29 ] unit-test [ B{ 1 2 3 4 5 6 } ] [ ffi_test_29 ] unit-test
C-STRUCT: test-struct-7 { { "char" 7 } "x" } ; C-STRUCT: test-struct-7 { { "char" 7 } "x" } ;
FUNCTION: test-struct-7 ffi_test_30 ; FUNCTION: test-struct-7 ffi_test_30 ;
[ B{ 1 2 3 4 5 6 7 } ] [ ffi_test_30 ] unit-test [ B{ 1 2 3 4 5 6 7 } ] [ ffi_test_30 ] unit-test
C-STRUCT: test-struct-8 { "double" "x" } { "double" "y" } ; C-STRUCT: test-struct-8 { "double" "x" } { "double" "y" } ;
FUNCTION: double ffi_test_32 test-struct-8 x int y ; FUNCTION: double ffi_test_32 test-struct-8 x int y ;
[ 9.0 ] [ [ 9.0 ] [
"test-struct-8" <c-object> "test-struct-8" <c-object>
1.0 over set-test-struct-8-x 1.0 over set-test-struct-8-x
2.0 over set-test-struct-8-y 2.0 over set-test-struct-8-y
3 ffi_test_32 3 ffi_test_32
] unit-test ] unit-test
C-STRUCT: test-struct-9 { "float" "x" } { "float" "y" } ; C-STRUCT: test-struct-9 { "float" "x" } { "float" "y" } ;
FUNCTION: double ffi_test_33 test-struct-9 x int y ; FUNCTION: double ffi_test_33 test-struct-9 x int y ;
[ 9.0 ] [ [ 9.0 ] [
"test-struct-9" <c-object> "test-struct-9" <c-object>
1.0 over set-test-struct-9-x 1.0 over set-test-struct-9-x
2.0 over set-test-struct-9-y 2.0 over set-test-struct-9-y
3 ffi_test_33 3 ffi_test_33
] unit-test ] unit-test
C-STRUCT: test-struct-10 { "float" "x" } { "int" "y" } ; C-STRUCT: test-struct-10 { "float" "x" } { "int" "y" } ;
FUNCTION: double ffi_test_34 test-struct-10 x int y ; FUNCTION: double ffi_test_34 test-struct-10 x int y ;
[ 9.0 ] [ [ 9.0 ] [
"test-struct-10" <c-object> "test-struct-10" <c-object>
1.0 over set-test-struct-10-x 1.0 over set-test-struct-10-x
2 over set-test-struct-10-y 2 over set-test-struct-10-y
3 ffi_test_34 3 ffi_test_34
] unit-test ] unit-test
C-STRUCT: test-struct-11 { "int" "x" } { "int" "y" } ; C-STRUCT: test-struct-11 { "int" "x" } { "int" "y" } ;
FUNCTION: double ffi_test_35 test-struct-11 x int y ; FUNCTION: double ffi_test_35 test-struct-11 x int y ;
[ 9.0 ] [ [ 9.0 ] [
"test-struct-11" <c-object> "test-struct-11" <c-object>
1 over set-test-struct-11-x 1 over set-test-struct-11-x
2 over set-test-struct-11-y 2 over set-test-struct-11-y
3 ffi_test_35 3 ffi_test_35
] unit-test ] unit-test
! Test callbacks C-STRUCT: test-struct-12 { "int" "a" } { "double" "x" } ;
: callback-1 "void" { } "cdecl" [ ] alien-callback ; : make-struct-12
"test-struct-12" <c-object>
[ 0 1 ] [ [ callback-1 ] infer dup effect-in swap effect-out ] unit-test [ set-test-struct-12-x ] keep ;
[ t ] [ callback-1 alien? ] unit-test FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
: callback_test_1 "void" { } "cdecl" alien-indirect ; [ 1.23456 ] [ 1.23456 make-struct-12 ffi_test_36 ] unit-test
[ ] [ callback-1 callback_test_1 ] unit-test ! Test callbacks
: callback-2 "void" { } "cdecl" [ [ 5 throw ] catch drop ] alien-callback ; : callback-1 "void" { } "cdecl" [ ] alien-callback ;
[ ] [ callback-2 callback_test_1 ] unit-test [ 0 1 ] [ [ callback-1 ] infer dup effect-in swap effect-out ] unit-test
: callback-3 "void" { } "cdecl" [ 5 "x" set ] alien-callback ; [ t ] [ callback-1 alien? ] unit-test
[ t ] [ : callback_test_1 "void" { } "cdecl" alien-indirect ;
namestack*
3 "x" set callback-3 callback_test_1 [ ] [ callback-1 callback_test_1 ] unit-test
namestack* eq?
] unit-test : callback-2 "void" { } "cdecl" [ [ 5 throw ] ignore-errors ] alien-callback ;
[ 5 ] [ [ ] [ callback-2 callback_test_1 ] unit-test
[
3 "x" set callback-3 callback_test_1 "x" get : callback-3 "void" { } "cdecl" [ 5 "x" set ] alien-callback ;
] with-scope
] unit-test [ t ] [
namestack*
: callback-4 3 "x" set callback-3 callback_test_1
"void" { } "cdecl" [ "Hello world" write ] alien-callback namestack* eq?
data-gc ; ] unit-test
[ "Hello world" ] [ [ 5 ] [
[ callback-4 callback_test_1 ] string-out [
] unit-test 3 "x" set callback-3 callback_test_1 "x" get
] with-scope
: callback-5 ] unit-test
"void" { } "cdecl" [ data-gc ] alien-callback ;
: callback-4
[ "testing" ] [ "void" { } "cdecl" [ "Hello world" write ] alien-callback
"testing" callback-5 callback_test_1 data-gc ;
] unit-test
[ "Hello world" ] [
: callback-5a [ callback-4 callback_test_1 ] string-out
"void" { } "cdecl" [ 8000000 f <array> drop ] alien-callback ; ] unit-test
! Hack; if we're on ARM, we probably don't have much RAM, so : callback-5
! skip this test. "void" { } "cdecl" [ data-gc ] alien-callback ;
cpu "arm" = [
[ "testing" ] [ [ "testing" ] [
"testing" callback-5a callback_test_1 "testing" callback-5 callback_test_1
] unit-test ] unit-test
] unless
: callback-5a
: callback-6 "void" { } "cdecl" [ 8000000 f <array> drop ] alien-callback ;
"void" { } "cdecl" [ [ continue ] callcc0 ] alien-callback ;
! Hack; if we're on ARM, we probably don't have much RAM, so
[ 1 2 3 ] [ callback-6 callback_test_1 1 2 3 ] unit-test ! skip this test.
cpu "arm" = [
: callback-7 [ "testing" ] [
"void" { } "cdecl" [ 1000 sleep ] alien-callback ; "testing" callback-5a callback_test_1
] unit-test
[ 1 2 3 ] [ callback-7 callback_test_1 1 2 3 ] unit-test ] unless
[ f ] [ namespace global eq? ] unit-test : callback-6
"void" { } "cdecl" [ [ continue ] callcc0 ] alien-callback ;
: callback-8
"void" { } "cdecl" [ [ 1 2 3 ] [ callback-6 callback_test_1 1 2 3 ] unit-test
[ continue ] callcc0
] alien-callback ; : callback-7
"void" { } "cdecl" [ 1000 sleep ] alien-callback ;
[ ] [ callback-8 callback_test_1 ] unit-test
[ 1 2 3 ] [ callback-7 callback_test_1 1 2 3 ] unit-test
[ f ] [ namespace global eq? ] unit-test
: callback-8
"void" { } "cdecl" [
[ continue ] callcc0
] alien-callback ;
[ ] [ callback-8 callback_test_1 ] unit-test

View File

@ -5,7 +5,8 @@ hashtables kernel math namespaces sequences words
inference.state inference.backend inference.dataflow system inference.state inference.backend inference.dataflow system
math.parser classes alien.arrays alien.c-types alien.structs math.parser classes alien.arrays alien.c-types alien.structs
alien.syntax cpu.architecture alien inspector quotations assocs alien.syntax cpu.architecture alien inspector quotations assocs
kernel.private threads continuations.private libc combinators ; kernel.private threads continuations.private libc combinators
compiler.errors continuations ;
IN: alien.compiler IN: alien.compiler
! Common protocol for alien-invoke/alien-callback/alien-indirect ! Common protocol for alien-invoke/alien-callback/alien-indirect
@ -207,9 +208,21 @@ M: alien-invoke-error summary
swap alien-node-parameters parameter-sizes drop swap alien-node-parameters parameter-sizes drop
number>string 3append ; number>string 3append ;
TUPLE: no-such-library name ;
M: no-such-library summary
drop "Library not found" ;
: no-such-library ( name -- )
\ no-such-library +linkage+ (inference-error) ;
: (alien-invoke-dlsym) ( node -- symbol dll ) : (alien-invoke-dlsym) ( node -- symbol dll )
dup alien-invoke-function dup alien-invoke-function
swap alien-invoke-library load-library ; swap alien-invoke-library [
load-library
] [
2drop no-such-library
] recover ;
TUPLE: no-such-symbol ; TUPLE: no-such-symbol ;
@ -217,7 +230,7 @@ M: no-such-symbol summary
drop "Symbol not found" ; drop "Symbol not found" ;
: no-such-symbol ( -- ) : no-such-symbol ( -- )
\ no-such-symbol inference-error ; \ no-such-symbol +linkage+ (inference-error) ;
: alien-invoke-dlsym ( node -- symbol dll ) : alien-invoke-dlsym ( node -- symbol dll )
dup (alien-invoke-dlsym) 2dup dlsym [ dup (alien-invoke-dlsym) 2dup dlsym [

View File

@ -2,10 +2,10 @@ USING: arrays kernel sequences sequences.private growable
tools.test vectors layouts system math vectors.private ; tools.test vectors layouts system math vectors.private ;
IN: temporary IN: temporary
[ -2 { "a" "b" "c" } nth ] unit-test-fails [ -2 { "a" "b" "c" } nth ] must-fail
[ 10 { "a" "b" "c" } nth ] unit-test-fails [ 10 { "a" "b" "c" } nth ] must-fail
[ "hi" -2 { "a" "b" "c" } set-nth ] unit-test-fails [ "hi" -2 { "a" "b" "c" } set-nth ] must-fail
[ "hi" 10 { "a" "b" "c" } set-nth ] unit-test-fails [ "hi" 10 { "a" "b" "c" } set-nth ] must-fail
[ f ] [ { "a" "b" "c" } dup clone eq? ] unit-test [ f ] [ { "a" "b" "c" } dup clone eq? ] unit-test
[ "hi" ] [ "hi" 1 { "a" "b" "c" } clone [ set-nth ] keep second ] unit-test [ "hi" ] [ "hi" 1 { "a" "b" "c" } clone [ set-nth ] keep second ] unit-test
[ V{ "a" "b" "c" } ] [ { "a" "b" "c" } >vector ] unit-test [ V{ "a" "b" "c" } ] [ { "a" "b" "c" } >vector ] unit-test
@ -17,5 +17,5 @@ IN: temporary
[ { "a" "b" "c" "d" "e" } ] [ { "a" "b" "c" "d" "e" } ]
[ { "a" } { "b" "c" } { "d" "e" } 3append ] unit-test [ { "a" } { "b" "c" } { "d" "e" } 3append ] unit-test
[ -1 f <array> ] unit-test-fails [ -1 f <array> ] must-fail
[ cell-bits cell log2 - 2^ f <array> ] unit-test-fails [ cell-bits cell log2 - 2^ f <array> ] must-fail

View File

@ -51,4 +51,4 @@ IN: temporary
[ ?{ t t } ] [ 2 ?{ t t f t f t f t t t f t } resize-bit-array ] unit-test [ ?{ t t } ] [ 2 ?{ t t f t f t f t t t f t } resize-bit-array ] unit-test
[ -10 ?{ } resize-bit-array ] unit-test-fails [ -10 ?{ } resize-bit-array ] must-fail

View File

@ -1,6 +1,5 @@
IN: temporary IN: temporary
USING: bootstrap.image bootstrap.image.private USING: bootstrap.image bootstrap.image.private tools.test ;
tools.test.inference ;
\ ' must-infer \ ' must-infer
\ write-image must-infer \ write-image must-infer

View File

@ -7,9 +7,26 @@ strings sbufs vectors words quotations assocs system layouts
splitting growable classes tuples words.private splitting growable classes tuples words.private
io.binary io.files vocabs vocabs.loader source-files io.binary io.files vocabs vocabs.loader source-files
definitions debugger float-arrays quotations.private definitions debugger float-arrays quotations.private
combinators.private combinators ; sequences.private combinators ;
IN: bootstrap.image IN: bootstrap.image
: my-arch ( -- arch )
cpu dup "ppc" = [ os "-" rot 3append ] when ;
: boot-image-name ( arch -- string )
"boot." swap ".image" 3append ;
: my-boot-image-name ( -- string )
my-arch boot-image-name ;
: images ( -- seq )
{
"x86.32"
"x86.64"
"linux-ppc" "macosx-ppc"
! "arm"
} ;
<PRIVATE <PRIVATE
! Constants ! Constants
@ -119,7 +136,7 @@ SYMBOL: undefined-quot
: here-as ( tag -- pointer ) here swap bitor ; : here-as ( tag -- pointer ) here swap bitor ;
: align-here ( -- ) : align-here ( -- )
here 8 mod 4 = [ 0 emit ] when ; here 8 mod 4 = [ heap-size drop 0 emit ] when ;
: emit-fixnum ( n -- ) tag-fixnum emit ; : emit-fixnum ( n -- ) tag-fixnum emit ;
@ -160,6 +177,7 @@ GENERIC: ' ( obj -- ptr )
[ dup bignum-bits neg shift swap bignum-radix bitand ] [ dup bignum-bits neg shift swap bignum-radix bitand ]
[ ] unfold nip ; [ ] unfold nip ;
USE: continuations
: emit-bignum ( n -- ) : emit-bignum ( n -- )
dup 0 < [ 1 swap neg ] [ 0 swap ] if bignum>seq dup 0 < [ 1 swap neg ] [ 0 swap ] if bignum>seq
dup length 1+ emit-fixnum dup length 1+ emit-fixnum
@ -197,13 +215,10 @@ M: f '
: 1, 1 >bignum ' 1-offset fixup ; : 1, 1 >bignum ' 1-offset fixup ;
: -1, -1 >bignum ' -1-offset fixup ; : -1, -1 >bignum ' -1-offset fixup ;
! Beginning of the image
: begin-image ( -- ) emit-header t, 0, 1, -1, ;
! Words ! Words
: emit-word ( word -- ) : emit-word ( word -- )
dup subwords [ emit-word ] each
[ [
dup hashcode ' , dup hashcode ' ,
dup word-name ' , dup word-name ' ,
@ -224,7 +239,7 @@ M: f '
[ % dup word-vocabulary % " " % word-name % ] "" make throw ; [ % dup word-vocabulary % " " % word-name % ] "" make throw ;
: transfer-word ( word -- word ) : transfer-word ( word -- word )
dup target-word [ ] [ word-name no-word ] ?if ; dup target-word swap or ;
: fixup-word ( word -- offset ) : fixup-word ( word -- offset )
transfer-word dup objects get at transfer-word dup objects get at
@ -248,7 +263,7 @@ M: wrapper '
emit-seq ; emit-seq ;
: pack-string ( string -- newstr ) : pack-string ( string -- newstr )
dup length 1+ bootstrap-cell align 0 pad-right ; dup length bootstrap-cell align 0 pad-right ;
: emit-string ( string -- ptr ) : emit-string ( string -- ptr )
string type-number object tag-number [ string type-number object tag-number [
@ -285,17 +300,20 @@ M: float-array ' float-array emit-dummy-array ;
] emit-object ; ] emit-object ;
: emit-tuple ( obj -- pointer ) : emit-tuple ( obj -- pointer )
objects get [ [
[ tuple>array unclip transfer-word , % ] { } make [ tuple>array unclip transfer-word , % ] { } make
tuple type-number dup emit-array tuple type-number dup emit-array
] cache ; inline ]
! Hack
over class word-name "tombstone" =
[ objects get swap cache ] [ call ] if ;
M: tuple ' emit-tuple ; M: tuple ' emit-tuple ;
M: tombstone ' M: tombstone '
delegate delegate
"((tombstone))" "((empty))" ? "hashtables.private" lookup "((tombstone))" "((empty))" ? "hashtables.private" lookup
word-def first emit-tuple ; word-def first objects get [ emit-tuple ] cache ;
M: array ' M: array '
array type-number object tag-number emit-array ; array type-number object tag-number emit-array ;
@ -313,41 +331,6 @@ M: quotation '
] emit-object ] emit-object
] cache ; ] cache ;
! Vectors and sbufs
M: vector '
dup length swap underlying '
tuple type-number tuple tag-number [
4 emit-fixnum
vector ' emit
f ' emit
emit ! array ptr
emit-fixnum ! length
] emit-object ;
M: sbuf '
dup length swap underlying '
tuple type-number tuple tag-number [
4 emit-fixnum
sbuf ' emit
f ' emit
emit ! array ptr
emit-fixnum ! length
] emit-object ;
! Hashes
M: hashtable '
[ hash-array ' ] keep
tuple type-number tuple tag-number [
5 emit-fixnum
hashtable ' emit
f ' emit
dup hash-count emit-fixnum
hash-deleted emit-fixnum
emit ! array ptr
] emit-object ;
! Curries ! Curries
M: curry ' M: curry '
@ -399,7 +382,10 @@ M: curry '
: fixup-header ( -- ) : fixup-header ( -- )
heap-size data-heap-size-offset fixup ; heap-size data-heap-size-offset fixup ;
: end-image ( -- ) : build-image ( -- image )
800000 <vector> image set
20000 <hashtable> objects set
emit-header t, 0, 1, -1,
"Serializing words..." print flush "Serializing words..." print flush
emit-words emit-words
"Serializing JIT data..." print flush "Serializing JIT data..." print flush
@ -414,7 +400,8 @@ M: curry '
fixup-header fixup-header
"Image length: " write image get length . "Image length: " write image get length .
"Object cache size: " write objects get assoc-size . "Object cache size: " write objects get assoc-size .
\ word global delete-at ; \ word global delete-at
image get ;
! Image output ! Image output
@ -425,37 +412,23 @@ M: curry '
[ >le write ] curry each [ >le write ] curry each
] if ; ] if ;
: image-name : write-image ( image -- )
"boot." architecture get ".image" 3append resource-path ; "Writing image to " write
architecture get boot-image-name resource-path
: write-image ( image filename -- ) dup write "..." print flush
"Writing image to " write dup write "..." print flush
<file-writer> [ (write-image) ] with-stream ; <file-writer> [ (write-image) ] with-stream ;
: prepare-image ( -- )
bootstrapping? on
load-help? off
800000 <vector> image set
20000 <hashtable> objects set ;
PRIVATE> PRIVATE>
: make-image ( arch -- ) : make-image ( arch -- )
architecture [ [
prepare-image architecture set
begin-image bootstrapping? on
load-help? off
"resource:/core/bootstrap/stage1.factor" run-file "resource:/core/bootstrap/stage1.factor" run-file
end-image build-image
image get image-name write-image write-image
] with-variable ; ] with-scope ;
: my-arch ( -- arch )
cpu dup "ppc" = [ os "-" rot 3append ] when ;
: make-images ( -- ) : make-images ( -- )
{ images [ make-image ] each ;
"x86.32"
"x86.64"
"linux-ppc" "macosx-ppc"
! "arm"
} [ make-image ] each ;

View File

@ -1,4 +1,4 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2007, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces math words kernel alien byte-arrays USING: namespaces math words kernel alien byte-arrays
hashtables vectors strings sbufs arrays bit-arrays hashtables vectors strings sbufs arrays bit-arrays
@ -8,7 +8,7 @@ BIN: 111 tag-mask set
8 num-tags set 8 num-tags set
3 tag-bits set 3 tag-bits set
20 num-types set 19 num-types set
H{ H{
{ fixnum BIN: 000 } { fixnum BIN: 000 }
@ -27,11 +27,10 @@ tag-numbers get H{
{ float-array 10 } { float-array 10 }
{ callstack 11 } { callstack 11 }
{ string 12 } { string 12 }
{ curry 13 } { bit-array 13 }
{ quotation 14 } { quotation 14 }
{ dll 15 } { dll 15 }
{ alien 16 } { alien 16 }
{ word 17 } { word 17 }
{ byte-array 18 } { byte-array 18 }
{ bit-array 19 }
} union type-numbers set } union type-numbers set

View File

@ -118,11 +118,11 @@ H{ } clone update-map set
H{ } clone typemap set H{ } clone typemap set
num-types get f <array> builtins set num-types get f <array> builtins set
! These symbols are needed by the code that executes below ! Forward definitions
{ "object" "kernel" create t "class" set-word-prop
{ "object" "kernel" } "object" "kernel" create union-class "metaclass" set-word-prop
{ "null" "kernel" }
} [ create drop ] assoc-each "null" "kernel" create drop
"fixnum" "math" create "fixnum?" "math" create { } define-builtin "fixnum" "math" create "fixnum?" "math" create { } define-builtin
"fixnum" "math" create ">fixnum" "math" create 1quotation "coercer" set-word-prop "fixnum" "math" create ">fixnum" "math" create 1quotation "coercer" set-word-prop
@ -295,23 +295,6 @@ define-builtin
"float-array?" "float-arrays" create "float-array?" "float-arrays" create
{ } define-builtin { } define-builtin
"curry" "kernel" create
"curry?" "kernel" create
{
{
{ "object" "kernel" }
"obj"
{ "curry-obj" "kernel" }
f
}
{
{ "object" "kernel" }
"obj"
{ "curry-quot" "kernel" }
f
}
} define-builtin
"callstack" "kernel" create "callstack?" "kernel" create "callstack" "kernel" create "callstack?" "kernel" create
{ } define-builtin { } define-builtin
@ -440,14 +423,44 @@ builtins get num-tags get tail f union-class define-class
} }
} define-tuple-class } define-tuple-class
"curry" "kernel" create
{
{
{ "object" "kernel" }
"obj"
{ "curry-obj" "kernel" }
f
} {
{ "object" "kernel" }
"quot"
{ "curry-quot" "kernel" }
f
}
} define-tuple-class
"compose" "kernel" create
{
{
{ "object" "kernel" }
"first"
{ "compose-first" "kernel" }
f
} {
{ "object" "kernel" }
"second"
{ "compose-second" "kernel" }
f
}
} define-tuple-class
! Primitive words ! Primitive words
: make-primitive ( word vocab n -- ) : make-primitive ( word vocab n -- )
>r create dup reset-word r> [ do-primitive ] curry [ ] like define ; >r create dup reset-word r>
[ do-primitive ] curry [ ] like define ;
{ {
{ "(execute)" "words.private" } { "(execute)" "words.private" }
{ "(call)" "kernel.private" } { "(call)" "kernel.private" }
{ "uncurry" "kernel.private" }
{ "bignum>fixnum" "math.private" } { "bignum>fixnum" "math.private" }
{ "float>fixnum" "math.private" } { "float>fixnum" "math.private" }
{ "fixnum>bignum" "math.private" } { "fixnum>bignum" "math.private" }
@ -553,8 +566,6 @@ builtins get num-tags get tail f union-class define-class
{ "millis" "system" } { "millis" "system" }
{ "type" "kernel.private" } { "type" "kernel.private" }
{ "tag" "kernel.private" } { "tag" "kernel.private" }
{ "cwd" "io.files" }
{ "cd" "io.files" }
{ "modify-code-heap" "compiler.units" } { "modify-code-heap" "compiler.units" }
{ "dlopen" "alien" } { "dlopen" "alien" }
{ "dlsym" "alien" } { "dlsym" "alien" }
@ -624,7 +635,6 @@ builtins get num-tags get tail f union-class define-class
{ "become" "kernel.private" } { "become" "kernel.private" }
{ "(sleep)" "threads.private" } { "(sleep)" "threads.private" }
{ "<float-array>" "float-arrays" } { "<float-array>" "float-arrays" }
{ "curry" "kernel" }
{ "<tuple-boa>" "tuples.private" } { "<tuple-boa>" "tuples.private" }
{ "class-hash" "kernel.private" } { "class-hash" "kernel.private" }
{ "callstack>array" "kernel" } { "callstack>array" "kernel" }

View File

@ -32,12 +32,13 @@ vocabs.loader system ;
"io.streams.c" require "io.streams.c" require
"vocabs.loader" require "vocabs.loader" require
"syntax" require "syntax" require
"bootstrap.layouts" require "bootstrap.layouts" require
[ [
"resource:core/bootstrap/stage2.factor" "resource:core/bootstrap/stage2.factor"
dup ?resource-path exists? [ dup resource-exists? [
run-file run-file
] [ ] [
"Cannot find " write write "." print "Cannot find " write write "." print

View File

@ -1,31 +1,70 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: init command-line namespaces words debugger io USING: init command-line namespaces words debugger io
kernel.private math memory continuations kernel io.files kernel.private math memory continuations kernel io.files
io.backend system parser vocabs sequences prettyprint io.backend system parser vocabs sequences prettyprint
vocabs.loader combinators splitting source-files strings vocabs.loader combinators splitting source-files strings
definitions assocs compiler.errors compiler.units definitions assocs compiler.errors compiler.units
math.parser ; math.parser generic ;
IN: bootstrap.stage2 IN: bootstrap.stage2
SYMBOL: bootstrap-time
: default-image-name ( -- string )
vm file-name windows? [ "." split1 drop ] when
".image" append ;
: do-crossref ( -- )
"Cross-referencing..." print flush
H{ } clone crossref set-global
xref-words
xref-generics
xref-sources ;
: load-components ( -- )
"exclude" "include"
[ get-global " " split [ empty? not ] subset ] 2apply
seq-diff
[ "bootstrap." swap append require ] each ;
: compile-remaining ( -- )
"Compiling remaining words..." print flush
vocabs [
words "compile" "compiler" lookup execute
] each ;
: count-words ( pred -- )
all-words swap subset length number>string write ;
: print-report ( time -- )
1000 /i
60 /mod swap
"Bootstrap completed in " write number>string write
" minutes and " write number>string write " seconds." print
[ compiled? ] count-words " compiled words" print
[ symbol? ] count-words " symbol words" print
[ ] count-words " words total" print
"Bootstrapping is complete." print
"Now, you can run Factor:" print
vm write " -i=" write "output-image" get print flush ;
! Wrap everything in a catch which starts a listener so ! Wrap everything in a catch which starts a listener so
! you can see what went wrong, instead of dealing with a ! you can see what went wrong, instead of dealing with a
! fep ! fep
[ [
vm file-name windows? [ "." split1 drop ] when ! We time bootstrap
".image" append "output-image" set-global millis >r
"math tools help compiler ui ui.tools io" "include" set-global default-image-name "output-image" set-global
"math help compiler tools ui ui.tools io" "include" set-global
"" "exclude" set-global "" "exclude" set-global
parse-command-line parse-command-line
"-no-crossref" cli-args member? [ "-no-crossref" cli-args member? [ do-crossref ] unless
"Cross-referencing..." print flush
H{ } clone crossref set-global
xref-words
xref-sources
] unless
! Set dll paths ! Set dll paths
wince? [ "windows.ce" require ] when wince? [ "windows.ce" require ] when
@ -39,19 +78,12 @@ IN: bootstrap.stage2
] if ] if
[ [
"exclude" "include" load-components
[ get-global " " split [ empty? not ] subset ] 2apply
seq-diff
[ "bootstrap." swap append require ] each
run-bootstrap-init run-bootstrap-init
"Compiling remaining words..." print flush
"bootstrap.compiler" vocab [ "bootstrap.compiler" vocab [
vocabs [ compile-remaining
words "compile" "compiler" lookup execute
] each
] when ] when
] with-compiler-errors ] with-compiler-errors
:errors :errors
@ -73,19 +105,13 @@ IN: bootstrap.stage2
] [ print-error 1 exit ] recover ] [ print-error 1 exit ] recover
] set-boot-quot ] set-boot-quot
: count-words ( pred -- ) millis r> - dup bootstrap-time set-global
all-words swap subset length number>string write ; print-report
[ compiled? ] count-words " compiled words" print
[ symbol? ] count-words " symbol words" print
[ ] count-words " words total" print
"Bootstrapping is complete." print
"Now, you can run Factor:" print
vm write " -i=" write "output-image" get print flush
"output-image" get resource-path save-image-and-exit "output-image" get resource-path save-image-and-exit
] if ] if
] [ ] [
print-error :c "listener" vocab-main execute print-error :c restarts.
"listener" vocab-main execute
1 exit
] recover ] recover

View File

@ -5,4 +5,4 @@ USING: tools.test byte-arrays ;
[ B{ 1 2 } ] [ 2 B{ 1 2 3 4 5 6 7 8 9 } resize-byte-array ] unit-test [ B{ 1 2 } ] [ 2 B{ 1 2 3 4 5 6 7 8 9 } resize-byte-array ] unit-test
[ -10 B{ } resize-byte-array ] unit-test-fails [ -10 B{ } resize-byte-array ] must-fail

View File

@ -91,7 +91,7 @@ M: union-1 generic-update-test drop "union-1" ;
[ f ] [ union-1 union-class? ] unit-test [ f ] [ union-1 union-class? ] unit-test
[ t ] [ union-1 predicate-class? ] unit-test [ t ] [ union-1 predicate-class? ] unit-test
[ "union-1" ] [ 8 generic-update-test ] unit-test [ "union-1" ] [ 8 generic-update-test ] unit-test
[ -7 generic-update-test ] unit-test-fails [ -7 generic-update-test ] must-fail
! Test mixins ! Test mixins
MIXIN: sequence-mixin MIXIN: sequence-mixin
@ -169,10 +169,14 @@ UNION: redefine-bug-2 redefine-bug-1 quotation ;
UNION: forget-class-bug-1 integer ; UNION: forget-class-bug-1 integer ;
UNION: forget-class-bug-2 forget-class-bug-1 dll ; UNION: forget-class-bug-2 forget-class-bug-1 dll ;
FORGET: forget-class-bug-1 [
FORGET: forget-class-bug-2 \ forget-class-bug-1 forget
\ forget-class-bug-2 forget
] with-compilation-unit
[ t ] [ integer dll class-or interned? ] unit-test [ f ] [ forget-class-bug-1 typemap get values [ memq? ] with contains? ] unit-test
[ f ] [ forget-class-bug-2 typemap get values [ memq? ] with contains? ] unit-test
DEFER: mixin-forget-test-g DEFER: mixin-forget-test-g
@ -191,7 +195,7 @@ DEFER: mixin-forget-test-g
] unit-test ] unit-test
[ { } ] [ { } mixin-forget-test-g ] unit-test [ { } ] [ { } mixin-forget-test-g ] unit-test
[ H{ } mixin-forget-test-g ] unit-test-fails [ H{ } mixin-forget-test-g ] must-fail
[ ] [ [ ] [
{ {
@ -205,7 +209,7 @@ DEFER: mixin-forget-test-g
parse-stream drop parse-stream drop
] unit-test ] unit-test
[ { } mixin-forget-test-g ] unit-test-fails [ { } mixin-forget-test-g ] must-fail
[ H{ } ] [ H{ } mixin-forget-test-g ] unit-test [ H{ } ] [ H{ } mixin-forget-test-g ] unit-test
! Method flattening interfered with mixin update ! Method flattening interfered with mixin update

View File

@ -1,4 +1,4 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: classes IN: classes
USING: arrays definitions assocs kernel USING: arrays definitions assocs kernel
@ -20,7 +20,9 @@ PREDICATE: class tuple-class
: classes ( -- seq ) class<map get keys ; : classes ( -- seq ) class<map get keys ;
: type>class ( n -- class ) builtins get nth ; : type>class ( n -- class ) builtins get-global nth ;
: bootstrap-type>class ( n -- class ) builtins get nth ;
: predicate-word ( word -- predicate ) : predicate-word ( word -- predicate )
[ word-name "?" append ] keep word-vocabulary create ; [ word-name "?" append ] keep word-vocabulary create ;

View File

@ -1,19 +1,34 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: words sequences kernel assocs combinators classes USING: words sequences kernel assocs combinators classes
generic.standard namespaces arrays ; generic.standard namespaces arrays math quotations ;
IN: classes.union IN: classes.union
PREDICATE: class union-class PREDICATE: class union-class
"metaclass" word-prop union-class eq? ; "metaclass" word-prop union-class eq? ;
! Union classes for dispatch on multiple classes. ! Union classes for dispatch on multiple classes.
: small-union-predicate-quot ( members -- quot )
dup empty? [
drop [ drop f ]
] [
unclip first "predicate" word-prop swap
[ >r "predicate" word-prop [ dup ] swap append r> ]
assoc-map alist>quot
] if ;
: big-union-predicate-quot ( members -- quot )
[ small-union-predicate-quot ] [ dup ]
class-hash-dispatch-quot ;
: union-predicate-quot ( members -- quot ) : union-predicate-quot ( members -- quot )
0 (dispatch#) [ [ [ drop t ] ] { } map>assoc
[ [ drop t ] ] { } map>assoc dup length 4 <= [
object bootstrap-word [ drop f ] 2array add* small-union-predicate-quot
single-combination ] [
] with-variable ; flatten-methods
big-union-predicate-quot
] if ;
: define-union-predicate ( class -- ) : define-union-predicate ( class -- )
dup predicate-word dup predicate-word

2
core/combinators/combinators-docs.factor Normal file → Executable file
View File

@ -1,6 +1,6 @@
USING: arrays help.markup help.syntax strings sbufs vectors USING: arrays help.markup help.syntax strings sbufs vectors
kernel quotations generic generic.standard classes kernel quotations generic generic.standard classes
math assocs sequences combinators.private ; math assocs sequences sequences.private ;
IN: combinators IN: combinators
ARTICLE: "combinators-quot" "Quotation construction utilities" ARTICLE: "combinators-quot" "Quotation construction utilities"

View File

@ -38,7 +38,7 @@ namespaces combinators words ;
! Interpreted ! Interpreted
[ "two" ] [ 2 \ case-test-1 word-def call ] unit-test [ "two" ] [ 2 \ case-test-1 word-def call ] unit-test
[ "x" case-test-1 ] unit-test-fails [ "x" case-test-1 ] must-fail
: case-test-2 : case-test-2
{ {

View File

@ -4,12 +4,6 @@ IN: combinators
USING: arrays sequences sequences.private math.private USING: arrays sequences sequences.private math.private
kernel kernel.private math assocs quotations vectors ; kernel kernel.private math assocs quotations vectors ;
<PRIVATE
: dispatch ( n array -- ) array-nth (call) ;
PRIVATE>
TUPLE: no-cond ; TUPLE: no-cond ;
: no-cond ( -- * ) \ no-cond construct-empty throw ; : no-cond ( -- * ) \ no-cond construct-empty throw ;

View File

@ -1,21 +0,0 @@
USING: io.files tools.test sequences namespaces kernel
compiler.units ;
{
"templates-early"
"simple"
"intrinsics"
"float"
"generic"
"ifte"
"templates"
"optimizer"
"redefine"
"stack-trace"
"alien"
"curry"
"tuples"
}
[ "resource:core/compiler/test/" swap ".factor" 3append ] map
[ run-test ] map
[ failures get push-all ] each

View File

@ -26,7 +26,7 @@ IN: compiler
>r dupd save-effect r> >r dupd save-effect r>
f pick compiler-error f pick compiler-error
over compiled-unxref over compiled-unxref
over word-vocabulary [ compiled-xref ] [ 2drop ] if ; over crossref? [ compiled-xref ] [ 2drop ] if ;
: compile-succeeded ( word -- effect dependencies ) : compile-succeeded ( word -- effect dependencies )
[ [

View File

@ -1,14 +1,15 @@
IN: compiler.errors IN: compiler.errors
USING: help.markup help.syntax vocabs.loader words io USING: help.markup help.syntax vocabs.loader words io
quotations ; quotations compiler.errors.private ;
ARTICLE: "compiler-errors" "Compiler warnings and errors" ARTICLE: "compiler-errors" "Compiler warnings and errors"
"The compiler saves compile warnings and errors in a global variable:" "The compiler saves various notifications in a global variable:"
{ $subsection compiler-errors } { $subsection compiler-errors }
"The warnings and errors can be viewed later:" "These notifications can be viewed later:"
{ $subsection :warnings }
{ $subsection :errors } { $subsection :errors }
"Normally, all warnings and errors are displayed at the end of a batch compilation, such as a call to " { $link require } " or " { $link refresh-all } ". This can be controlled with a combinator:" { $subsection :warnings }
{ $subsection :linkage }
"Words such as " { $link require } " and " { $link refresh-all } " use a combinator which counts errors and prints a report at the end:"
{ $link with-compiler-errors } ; { $link with-compiler-errors } ;
HELP: compiler-errors HELP: compiler-errors
@ -16,7 +17,7 @@ HELP: compiler-errors
HELP: compiler-error HELP: compiler-error
{ $values { "error" "an error" } { "word" word } } { $values { "error" "an error" } { "word" word } }
{ $description "If inside a " { $link with-compiler-errors } ", saves the error for future persual via " { $link :errors } " and " { $link :warnings } ", otherwise ignores the error." } ; { $description "If inside a " { $link with-compiler-errors } ", saves the error for future persual via " { $link :errors } ", " { $link :warnings } " and " { $link :linkage } ". If not inside a " { $link with-compiler-errors } ", ignores the error." } ;
HELP: compiler-error. HELP: compiler-error.
{ $values { "error" "an error" } { "word" word } } { $values { "error" "an error" } { "word" word } }
@ -25,24 +26,18 @@ HELP: compiler-error.
HELP: compiler-errors. HELP: compiler-errors.
{ $values { "errors" "an assoc mapping words to errors" } } { $values { "errors" "an assoc mapping words to errors" } }
{ $description "Prints a set of compiler errors to the " { $link stdio } " stream." } ; { $description "Prints a set of compiler errors to the " { $link stdio } " stream." } ;
HELP: (:errors)
{ $values { "seq" "an alist" } }
{ $description "Outputs all serious compiler errors from the most recent compile." } ;
HELP: :errors HELP: :errors
{ $description "Prints all serious compiler errors from the most recent compile to the " { $link stdio } " stream." } ; { $description "Prints all serious compiler errors from the most recent compile to the " { $link stdio } " stream." } ;
HELP: (:warnings)
{ $values { "seq" "an alist" } }
{ $description "Outputs all ignorable compiler warnings from the most recent compile." } ;
HELP: :warnings HELP: :warnings
{ $description "Prints all ignorable compiler warnings from the most recent compile to the " { $link stdio } " stream." } ; { $description "Prints all ignorable compiler warnings from the most recent compile to the " { $link stdio } " stream." } ;
{ :errors (:errors) :warnings (:warnings) } related-words HELP: :linkage
{ $description "Prints all C library interface linkage errors from the most recent compile to the " { $link stdio } " stream." } ;
{ :errors :warnings } related-words
HELP: with-compiler-errors HELP: with-compiler-errors
{ $values { "quot" quotation } } { $values { "quot" quotation } }
{ $description "Calls the quotation and collects any compiler warnings and errors. Compiler warnings and errors are summarized at the end and can be viewed with " { $link :warnings } " and " { $link :errors } "." } { $description "Calls the quotation and collects any compiler warnings and errors. Compiler warnings and errors are summarized at the end and can be viewed with " { $link :errors } ", " { $link :warnings } ", and " { $link :linkage } "." }
{ $notes "Nested calls to " { $link with-compiler-errors } " are ignored, and only the outermost call collects warnings and errors." } ; { $notes "Nested calls to " { $link with-compiler-errors } " are ignored, and only the outermost call collects warnings and errors." } ;

View File

@ -4,51 +4,66 @@ USING: kernel namespaces assocs prettyprint io sequences
sorting continuations debugger math math.parser ; sorting continuations debugger math math.parser ;
IN: compiler.errors IN: compiler.errors
SYMBOL: +error+
SYMBOL: +warning+
SYMBOL: +linkage+
GENERIC: compiler-error-type ( error -- ? )
M: object compiler-error-type drop +error+ ;
<PRIVATE
SYMBOL: compiler-errors SYMBOL: compiler-errors
SYMBOL: with-compiler-errors? SYMBOL: with-compiler-errors?
: compiler-error ( error word -- )
with-compiler-errors? get [
compiler-errors get pick
[ set-at ] [ delete-at drop ] if
] [ 2drop ] if ;
: compiler-error. ( error word -- ) : compiler-error. ( error word -- )
nl nl
"While compiling " write pprint ": " print "While compiling " write pprint ": " print
nl nl
print-error ; print-error ;
: compiler-errors. ( assoc -- ) : errors-of-type ( type -- assoc )
>alist sort-keys [ swap compiler-error. ] assoc-each ;
GENERIC: compiler-warning? ( error -- ? )
M: object compiler-warning? drop f ;
: (:errors) ( -- assoc )
compiler-errors get-global compiler-errors get-global
[ nip compiler-warning? not ] assoc-subset ; swap [ >r nip compiler-error-type r> eq? ] curry
assoc-subset ;
: :errors (:errors) compiler-errors. ; : compiler-errors. ( type -- )
errors-of-type >alist sort-keys
[ swap compiler-error. ] assoc-each ;
: (:warnings) ( -- seq ) : (compiler-report) ( what type word -- )
compiler-errors get-global over errors-of-type assoc-empty? [ 3drop ] [
[ nip compiler-warning? ] assoc-subset ;
: :warnings (:warnings) compiler-errors. ;
: (compiler-report) ( what assoc -- )
length dup zero? [ 2drop ] [
[ [
":" % over % " - print " % # " compiler " % % "." % ":" %
%
" - print " %
errors-of-type assoc-size #
" " %
%
"." %
] "" make print ] "" make print
] if ; ] if ;
: compiler-report ( -- ) : compiler-report ( -- )
"errors" (:errors) (compiler-report) "semantic errors" +error+ "errors" (compiler-report)
"warnings" (:warnings) (compiler-report) ; "semantic warnings" +warning+ "warnings" (compiler-report)
"linkage errors" +linkage+ "linkage" (compiler-report) ;
PRIVATE>
: compiler-error ( error word -- )
with-compiler-errors? get [
compiler-errors get pick
[ set-at ] [ delete-at drop ] if
] [ 2drop ] if ;
: :errors +error+ compiler-errors. ;
: :warnings +warning+ compiler-errors. ;
: :linkage +linkage+ compiler-errors. ;
: with-compiler-errors ( quot -- ) : with-compiler-errors ( quot -- )
with-compiler-errors? get "quiet" get or [ call ] [ with-compiler-errors? get "quiet" get or [ call ] [

View File

@ -1,30 +0,0 @@
IN: temporary
USING: compiler generic tools.test math kernel words arrays
sequences quotations ;
GENERIC: single-combination-test
M: object single-combination-test drop ;
M: f single-combination-test nip ;
M: array single-combination-test drop ;
M: integer single-combination-test drop ;
[ 2 3 ] [ 2 3 t single-combination-test ] unit-test
[ 2 3 ] [ 2 3 4 single-combination-test ] unit-test
[ 2 f ] [ 2 3 f single-combination-test ] unit-test
DEFER: single-combination-test-2
: single-combination-test-4
dup [ single-combination-test-2 ] when ;
: single-combination-test-3
drop 3 ;
GENERIC: single-combination-test-2
M: object single-combination-test-2 single-combination-test-3 ;
M: f single-combination-test-2 single-combination-test-4 ;
[ 3 ] [ t single-combination-test-2 ] unit-test
[ 3 ] [ 3 single-combination-test-2 ] unit-test
[ f ] [ f single-combination-test-2 ] unit-test

View File

@ -1,131 +0,0 @@
IN: temporary
USING: alien strings compiler tools.test math kernel words
math.private combinators ;
: dummy-if-1 t [ ] [ ] if ;
[ ] [ dummy-if-1 ] unit-test
: dummy-if-2 f [ ] [ ] if ;
[ ] [ dummy-if-2 ] unit-test
: dummy-if-3 t [ 1 ] [ 2 ] if ;
[ 1 ] [ dummy-if-3 ] unit-test
: dummy-if-4 f [ 1 ] [ 2 ] if ;
[ 2 ] [ dummy-if-4 ] unit-test
: dummy-if-5 0 dup 1 fixnum<= [ drop 1 ] [ ] if ;
[ 1 ] [ dummy-if-5 ] unit-test
: dummy-if-6
dup 1 fixnum<= [
drop 1
] [
1 fixnum- dup 1 fixnum- fixnum+
] if ;
[ 17 ] [ 10 dummy-if-6 ] unit-test
: dead-code-rec
t [
3.2
] [
dead-code-rec
] if ;
[ 3.2 ] [ dead-code-rec ] unit-test
: one-rec [ f one-rec ] [ "hi" ] if ;
[ "hi" ] [ t one-rec ] unit-test
: after-if-test
t [ ] [ ] if 5 ;
[ 5 ] [ after-if-test ] unit-test
DEFER: countdown-b
: countdown-a ( n -- ) dup 0 eq? [ drop ] [ 1 fixnum- countdown-b ] if ;
: countdown-b ( n -- ) dup 0 eq? [ drop ] [ 1 fixnum- countdown-a ] if ;
[ ] [ 10 countdown-b ] unit-test
: dummy-when-1 t [ ] when ;
[ ] [ dummy-when-1 ] unit-test
: dummy-when-2 f [ ] when ;
[ ] [ dummy-when-2 ] unit-test
: dummy-when-3 dup [ dup fixnum* ] when ;
[ 16 ] [ 4 dummy-when-3 ] unit-test
[ f ] [ f dummy-when-3 ] unit-test
: dummy-when-4 dup [ dup dup fixnum* fixnum* ] when swap ;
[ 64 f ] [ f 4 dummy-when-4 ] unit-test
[ f t ] [ t f dummy-when-4 ] unit-test
: dummy-when-5 f [ dup fixnum* ] when ;
[ f ] [ f dummy-when-5 ] unit-test
: dummy-unless-1 t [ ] unless ;
[ ] [ dummy-unless-1 ] unit-test
: dummy-unless-2 f [ ] unless ;
[ ] [ dummy-unless-2 ] unit-test
: dummy-unless-3 dup [ drop 3 ] unless ;
[ 3 ] [ f dummy-unless-3 ] unit-test
[ 4 ] [ 4 dummy-unless-3 ] unit-test
! Test cond expansion
[ "even" ] [
[
2 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] compile-call
] unit-test
[ "odd" ] [
[
3 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] compile-call
] unit-test
[ "neither" ] [
[
3 {
{ [ dup string? ] [ drop "string" ] }
{ [ dup float? ] [ drop "float" ] }
{ [ dup alien? ] [ drop "alien" ] }
{ [ t ] [ drop "neither" ] }
} cond
] compile-call
] unit-test
[ 3 ] [
[
3 {
{ [ dup fixnum? ] [ ] }
{ [ t ] [ drop t ] }
} cond
] compile-call
] unit-test

View File

@ -1,252 +0,0 @@
USING: compiler definitions generic assocs inference math
namespaces parser tools.test words kernel sequences arrays io
effects tools.test.inference compiler.units inference.state ;
IN: temporary
DEFER: x-1
DEFER: x-2
[ [ f ] { } map>assoc modify-code-heap ] recompile-hook [
"IN: temporary USE: math GENERIC: x-1 ( x -- y ) M: integer x-1 ;" eval
"IN: temporary : x-2 3 x-1 ;" eval
[ t ] [
{ x-2 } compile
\ x-2 word-xt
{ x-1 } compile
\ x-2 word-xt =
] unit-test
] with-variable
DEFER: b
DEFER: c
[ ] [ "IN: temporary : a 1 2 ; : b a a ;" eval ] unit-test
[ 1 2 1 2 ] [ "USE: temporary b" eval ] unit-test
{ 0 4 } [ b ] unit-test-effect
[ ] [ "IN: temporary : a 1 2 3 ;" eval ] unit-test
[ 1 2 3 1 2 3 ] [ "USE: temporary b" eval ] unit-test
{ 0 6 } [ b ] unit-test-effect
\ b word-xt "b-xt" set
[ ] [ "IN: temporary : c b ;" eval ] unit-test
[ t ] [ "b-xt" get \ b word-xt = ] unit-test
\ c word-xt "c-xt" set
[ ] [ "IN: temporary : a 1 2 4 ;" eval ] unit-test
[ t ] [ "c-xt" get \ c word-xt = ] unit-test
[ 1 2 4 1 2 4 ] [ "USE: temporary c" eval ] unit-test
[ ] [ "IN: temporary : a 1 2 ;" eval ] unit-test
{ 0 4 } [ c ] unit-test-effect
[ f ] [ "c-xt" get \ c word-xt = ] unit-test
[ 1 2 1 2 ] [ "USE: temporary c" eval ] unit-test
[ ] [ "IN: temporary : d 3 ; inline" eval ] unit-test
[ ] [ "IN: temporary : e d d ;" eval ] unit-test
[ 3 3 ] [ "USE: temporary e" eval ] unit-test
[ ] [ "IN: temporary : d 4 ; inline" eval ] unit-test
[ 4 4 ] [ "USE: temporary e" eval ] unit-test
DEFER: x-3
[ ] [ "IN: temporary : x-3 3 ;" eval ] unit-test
DEFER: x-4
[ ] [ "IN: temporary : x-4 x-3 ;" eval ] unit-test
[ t ] [ \ x-4 compiled? ] unit-test
[ ] [ "IN: temporary USE: sequences : x-3 { } [ ] each ;" eval ] unit-test
[ f ] [ \ x-3 compiled? ] unit-test
[ f ] [ \ x-4 compiled? ] unit-test
[ ] [ "IN: temporary USING: kernel sequences ; : x-3 { } [ drop ] each ;" eval ] unit-test
[ t ] [ \ x-3 compiled? ] unit-test
[ t ] [ \ x-4 compiled? ] unit-test
[ t ] [ \ x-3 "compiled-uses" word-prop >boolean ] unit-test
[ t ] [ \ x-3 "compiled-uses" word-prop [ drop interned? ] assoc-all? ] unit-test
DEFER: g-test-1
DEFER: g-test-3
[ ] [ "IN: temporary USE: math GENERIC: g-test-1 ( x -- y ) M: integer g-test-1 sq ;" eval ] unit-test
[ ] [ "IN: temporary : g-test-2 ( -- y ) 3 g-test-1 ;" eval ] unit-test
[ ] [ "IN: temporary : g-test-3 ( -- y ) g-test-2 ;" eval ] unit-test
[ 25 ] [ 5 g-test-1 ] unit-test
[ ] [ "IN: temporary USE: math GENERIC: g-test-1 ( x -- y ) M: integer g-test-1 ;" eval ] unit-test
[ 5 ] [ 5 g-test-1 ] unit-test
[ t ] [
\ g-test-3 word-xt
"IN: temporary USE: math GENERIC: g-test-1 ( x -- y ) M: integer g-test-1 3 + ;" eval
\ g-test-3 word-xt =
] unit-test
DEFER: g-test-5
[ ] [ "IN: temporary : g-test-4 ( -- y ) 3 g-test-1 ; inline" eval ] unit-test
[ ] [ "IN: temporary : g-test-5 ( -- y ) g-test-4 ;" eval ] unit-test
[ 6 ] [ g-test-5 ] unit-test
[ ] [ "IN: temporary USE: math GENERIC: g-test-1 ( x -- y ) M: integer g-test-1 10 + ;" eval ] unit-test
[ 13 ] [ g-test-5 ] unit-test
DEFER: g-test-6
[ ] [ "IN: temporary USING: arrays kernel ; GENERIC: g-test-6 ( x -- y ) M: array g-test-6 drop 123 g-test-1 ;" eval ] unit-test
DEFER: g-test-7
[ ] [ "IN: temporary : g-test-7 { } g-test-6 ;" eval ] unit-test
[ 133 ] [ g-test-7 ] unit-test
[ ] [ "IN: temporary USE: math GENERIC: g-test-1 ( x -- y ) M: integer g-test-1 15 + ;" eval ] unit-test
[ 138 ] [ g-test-7 ] unit-test
USE: macros
DEFER: macro-test-3
[ ] [ "IN: temporary USING: macros math ; : macro-test-1 sq ;" eval ] unit-test
[ ] [ "IN: temporary USING: macros arrays quotations ; MACRO: macro-test-2 ( n word -- quot ) <array> >quotation ;" eval ] unit-test
[ ] [ "IN: temporary : macro-test-3 2 \\ macro-test-1 macro-test-2 ;" eval ] unit-test
[ 625 ] [ 5 macro-test-3 ] unit-test
[ ] [ "IN: temporary USING: macros arrays quotations kernel math ; MACRO: macro-test-2 ( n word -- quot ) 2drop [ 3 + ] ;" eval ] unit-test
[ 8 ] [ 5 macro-test-3 ] unit-test
USE: hints
DEFER: hints-test-2
[ ] [ "IN: temporary USING: math hints ; : hints-test-1 3 + ; HINTS: hints-test-1 fixnum ;" eval ] unit-test
[ ] [ "IN: temporary : hints-test-2 5 hints-test-1 ;" eval ] unit-test
[ 8 ] [ hints-test-2 ] unit-test
[ ] [ "IN: temporary USE: math : hints-test-1 5 + ;" eval ] unit-test
[ 10 ] [ hints-test-2 ] unit-test
DEFER: inline-then-not-inline-test-1
DEFER: inline-then-not-inline-test-2
[ ] [ "IN: temporary : inline-then-not-inline-test-1 1 2 3 ; inline" eval ] unit-test
[ ] [ "IN: temporary : inline-then-not-inline-test-2 inline-then-not-inline-test-1 ;" eval ] unit-test
[ 1 2 3 ] [ inline-then-not-inline-test-2 ] unit-test
\ inline-then-not-inline-test-2 word-xt "a" set
[ ] [ "IN: temporary : inline-then-not-inline-test-1 6 6 9 ;" eval ] unit-test
[ f ] [ \ inline-then-not-inline-test-2 word-xt "a" get = ] unit-test
[ 6 6 9 ] [ inline-then-not-inline-test-2 ] unit-test
DEFER: generic-then-not-generic-test-1
DEFER: generic-then-not-generic-test-2
[ ] [ "IN: temporary GENERIC: generic-then-not-generic-test-1 ( a -- b )" eval ] unit-test
[ ] [ "IN: temporary USE: math M: integer generic-then-not-generic-test-1 sq ;" eval ] unit-test
[ ] [ "IN: temporary : generic-then-not-generic-test-2 3 generic-then-not-generic-test-1 ;" eval ] unit-test
[ 9 ] [ generic-then-not-generic-test-2 ] unit-test
[ ] [ "IN: temporary USE: math : generic-then-not-generic-test-1 1 + ;" eval ] unit-test
[ 4 ] [ generic-then-not-generic-test-2 ] unit-test
DEFER: foldable-test-1
DEFER: foldable-test-2
[ ] [ "IN: temporary : foldable-test-1 3 ; foldable" eval ] unit-test
[ ] [ "IN: temporary : foldable-test-2 foldable-test-1 ;" eval ] unit-test
[ +inlined+ ] [ \ foldable-test-2 \ foldable-test-1 compiled-usage at ] unit-test
[ 3 ] [ foldable-test-2 ] unit-test
[ ] [ "IN: temporary : foldable-test-1 4 ; foldable" eval ] unit-test
[ 4 ] [ foldable-test-2 ] unit-test
DEFER: flushable-test-2
[ ] [ "IN: temporary USE: kernel : flushable-test-1 drop 3 ; flushable" eval ] unit-test
[ ] [ "IN: temporary USE: kernel : flushable-test-2 V{ } dup flushable-test-1 drop ;" eval ] unit-test
[ V{ } ] [ flushable-test-2 ] unit-test
[ ] [ "IN: temporary USING: kernel sequences ; : flushable-test-1 3 over push ;" eval ] unit-test
[ V{ 3 } ] [ flushable-test-2 ] unit-test
: ax ;
: bx ax ;
[ \ bx forget ] with-compilation-unit
[ t ] [ \ ax compiled-usage [ drop interned? ] assoc-all? ] unit-test
DEFER: defer-redefine-test-2
[ ] [ "IN: temporary DEFER: defer-redefine-test-1" eval ] unit-test
[ ] [ "IN: temporary : defer-redefine-test-2 defer-redefine-test-1 1 ;" eval ] unit-test
[ defer-redefine-test-2 ] unit-test-fails
[ ] [ "IN: temporary : defer-redefine-test-1 2 ;" eval ] unit-test
[ 2 1 ] [ defer-redefine-test-2 ] unit-test

View File

@ -1,71 +0,0 @@
USING: compiler tools.test kernel kernel.private
combinators.private ;
IN: temporary
! Test empty word
[ ] [ [ ] compile-call ] unit-test
! Test literals
[ 1 ] [ [ 1 ] compile-call ] unit-test
[ 31 ] [ [ 31 ] compile-call ] unit-test
[ 255 ] [ [ 255 ] compile-call ] unit-test
[ -1 ] [ [ -1 ] compile-call ] unit-test
[ 65536 ] [ [ 65536 ] compile-call ] unit-test
[ -65536 ] [ [ -65536 ] compile-call ] unit-test
[ "hey" ] [ [ "hey" ] compile-call ] unit-test
! Calls
: no-op ;
[ ] [ [ no-op ] compile-call ] unit-test
[ 3 ] [ [ no-op 3 ] compile-call ] unit-test
[ 3 ] [ [ 3 no-op ] compile-call ] unit-test
: bar 4 ;
[ 4 ] [ [ bar no-op ] compile-call ] unit-test
[ 4 3 ] [ [ no-op bar 3 ] compile-call ] unit-test
[ 3 4 ] [ [ 3 no-op bar ] compile-call ] unit-test
[ ] [ no-op ] unit-test
! Conditionals
[ 1 ] [ t [ [ 1 ] [ 2 ] if ] compile-call ] unit-test
[ 2 ] [ f [ [ 1 ] [ 2 ] if ] compile-call ] unit-test
[ 1 3 ] [ t [ [ 1 ] [ 2 ] if 3 ] compile-call ] unit-test
[ 2 3 ] [ f [ [ 1 ] [ 2 ] if 3 ] compile-call ] unit-test
[ "hi" ] [ 0 [ { [ "hi" ] [ "bye" ] } dispatch ] compile-call ] unit-test
[ "bye" ] [ 1 [ { [ "hi" ] [ "bye" ] } dispatch ] compile-call ] unit-test
[ "hi" 3 ] [ 0 [ { [ "hi" ] [ "bye" ] } dispatch 3 ] compile-call ] unit-test
[ "bye" 3 ] [ 1 [ { [ "hi" ] [ "bye" ] } dispatch 3 ] compile-call ] unit-test
[ 4 1 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch ] compile-call ] unit-test
[ 3 1 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch ] compile-call ] unit-test
[ 4 1 3 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
[ 3 1 3 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
! Labels
: recursive ( ? -- ) [ f recursive ] when ; inline
[ ] [ t [ recursive ] compile-call ] unit-test
[ ] [ t recursive ] unit-test
! Make sure error reporting works
[ [ dup ] compile-call ] unit-test-fails
[ [ drop ] compile-call ] unit-test-fails
! Regression
[ ] [ [ callstack ] compile-call drop ] unit-test
! Regression
: empty ;
[ "b" ] [ 1 [ empty { [ "a" ] [ "b" ] } dispatch ] compile-call ] unit-test

View File

@ -4,7 +4,7 @@ math.private sequences strings tools.test words continuations
sequences.private hashtables.private byte-arrays strings.private sequences.private hashtables.private byte-arrays strings.private
system random layouts vectors.private sbufs.private system random layouts vectors.private sbufs.private
strings.private slots.private alien alien.accessors strings.private slots.private alien alien.accessors
alien.c-types alien.syntax namespaces libc combinators.private ; alien.c-types alien.syntax namespaces libc sequences.private ;
! Make sure that intrinsic ops compile to correct code. ! Make sure that intrinsic ops compile to correct code.
[ ] [ 1 [ drop ] compile-call ] unit-test [ ] [ 1 [ drop ] compile-call ] unit-test
@ -422,11 +422,11 @@ cell 8 = [
[ [
B{ 0 0 0 0 } [ { byte-array } declare <void*> ] compile-call B{ 0 0 0 0 } [ { byte-array } declare <void*> ] compile-call
] unit-test-fails ] must-fail
[ [
B{ 0 0 0 0 } [ { c-ptr } declare <void*> ] compile-call B{ 0 0 0 0 } [ { c-ptr } declare <void*> ] compile-call
] unit-test-fails ] must-fail
[ [
4 5 4 5

229
core/compiler/tests/simple.factor Executable file
View File

@ -0,0 +1,229 @@
USING: compiler tools.test kernel kernel.private
sequences.private math.private math combinators strings
alien arrays memory ;
IN: temporary
! Test empty word
[ ] [ [ ] compile-call ] unit-test
! Test literals
[ 1 ] [ [ 1 ] compile-call ] unit-test
[ 31 ] [ [ 31 ] compile-call ] unit-test
[ 255 ] [ [ 255 ] compile-call ] unit-test
[ -1 ] [ [ -1 ] compile-call ] unit-test
[ 65536 ] [ [ 65536 ] compile-call ] unit-test
[ -65536 ] [ [ -65536 ] compile-call ] unit-test
[ "hey" ] [ [ "hey" ] compile-call ] unit-test
! Calls
: no-op ;
[ ] [ [ no-op ] compile-call ] unit-test
[ 3 ] [ [ no-op 3 ] compile-call ] unit-test
[ 3 ] [ [ 3 no-op ] compile-call ] unit-test
: bar 4 ;
[ 4 ] [ [ bar no-op ] compile-call ] unit-test
[ 4 3 ] [ [ no-op bar 3 ] compile-call ] unit-test
[ 3 4 ] [ [ 3 no-op bar ] compile-call ] unit-test
[ ] [ no-op ] unit-test
! Conditionals
[ 1 ] [ t [ [ 1 ] [ 2 ] if ] compile-call ] unit-test
[ 2 ] [ f [ [ 1 ] [ 2 ] if ] compile-call ] unit-test
[ 1 3 ] [ t [ [ 1 ] [ 2 ] if 3 ] compile-call ] unit-test
[ 2 3 ] [ f [ [ 1 ] [ 2 ] if 3 ] compile-call ] unit-test
[ "hi" ] [ 0 [ { [ "hi" ] [ "bye" ] } dispatch ] compile-call ] unit-test
[ "bye" ] [ 1 [ { [ "hi" ] [ "bye" ] } dispatch ] compile-call ] unit-test
[ "hi" 3 ] [ 0 [ { [ "hi" ] [ "bye" ] } dispatch 3 ] compile-call ] unit-test
[ "bye" 3 ] [ 1 [ { [ "hi" ] [ "bye" ] } dispatch 3 ] compile-call ] unit-test
[ 4 1 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch ] compile-call ] unit-test
[ 3 1 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch ] compile-call ] unit-test
[ 4 1 3 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
[ 3 1 3 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
[ 2 3 ] [ 1 [ { [ code-gc 1 ] [ code-gc 2 ] } dispatch 3 ] compile-call ] unit-test
! Labels
: recursive ( ? -- ) [ f recursive ] when ; inline
[ ] [ t [ recursive ] compile-call ] unit-test
[ ] [ t recursive ] unit-test
! Make sure error reporting works
[ [ dup ] compile-call ] must-fail
[ [ drop ] compile-call ] must-fail
! Regression
[ ] [ [ callstack ] compile-call drop ] unit-test
! Regression
: empty ;
[ "b" ] [ 1 [ empty { [ "a" ] [ "b" ] } dispatch ] compile-call ] unit-test
: dummy-if-1 t [ ] [ ] if ;
[ ] [ dummy-if-1 ] unit-test
: dummy-if-2 f [ ] [ ] if ;
[ ] [ dummy-if-2 ] unit-test
: dummy-if-3 t [ 1 ] [ 2 ] if ;
[ 1 ] [ dummy-if-3 ] unit-test
: dummy-if-4 f [ 1 ] [ 2 ] if ;
[ 2 ] [ dummy-if-4 ] unit-test
: dummy-if-5 0 dup 1 fixnum<= [ drop 1 ] [ ] if ;
[ 1 ] [ dummy-if-5 ] unit-test
: dummy-if-6
dup 1 fixnum<= [
drop 1
] [
1 fixnum- dup 1 fixnum- fixnum+
] if ;
[ 17 ] [ 10 dummy-if-6 ] unit-test
: dead-code-rec
t [
3.2
] [
dead-code-rec
] if ;
[ 3.2 ] [ dead-code-rec ] unit-test
: one-rec [ f one-rec ] [ "hi" ] if ;
[ "hi" ] [ t one-rec ] unit-test
: after-if-test
t [ ] [ ] if 5 ;
[ 5 ] [ after-if-test ] unit-test
DEFER: countdown-b
: countdown-a ( n -- ) dup 0 eq? [ drop ] [ 1 fixnum- countdown-b ] if ;
: countdown-b ( n -- ) dup 0 eq? [ drop ] [ 1 fixnum- countdown-a ] if ;
[ ] [ 10 countdown-b ] unit-test
: dummy-when-1 t [ ] when ;
[ ] [ dummy-when-1 ] unit-test
: dummy-when-2 f [ ] when ;
[ ] [ dummy-when-2 ] unit-test
: dummy-when-3 dup [ dup fixnum* ] when ;
[ 16 ] [ 4 dummy-when-3 ] unit-test
[ f ] [ f dummy-when-3 ] unit-test
: dummy-when-4 dup [ dup dup fixnum* fixnum* ] when swap ;
[ 64 f ] [ f 4 dummy-when-4 ] unit-test
[ f t ] [ t f dummy-when-4 ] unit-test
: dummy-when-5 f [ dup fixnum* ] when ;
[ f ] [ f dummy-when-5 ] unit-test
: dummy-unless-1 t [ ] unless ;
[ ] [ dummy-unless-1 ] unit-test
: dummy-unless-2 f [ ] unless ;
[ ] [ dummy-unless-2 ] unit-test
: dummy-unless-3 dup [ drop 3 ] unless ;
[ 3 ] [ f dummy-unless-3 ] unit-test
[ 4 ] [ 4 dummy-unless-3 ] unit-test
! Test cond expansion
[ "even" ] [
[
2 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] compile-call
] unit-test
[ "odd" ] [
[
3 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] compile-call
] unit-test
[ "neither" ] [
[
3 {
{ [ dup string? ] [ drop "string" ] }
{ [ dup float? ] [ drop "float" ] }
{ [ dup alien? ] [ drop "alien" ] }
{ [ t ] [ drop "neither" ] }
} cond
] compile-call
] unit-test
[ 3 ] [
[
3 {
{ [ dup fixnum? ] [ ] }
{ [ t ] [ drop t ] }
} cond
] compile-call
] unit-test
GENERIC: single-combination-test
M: object single-combination-test drop ;
M: f single-combination-test nip ;
M: array single-combination-test drop ;
M: integer single-combination-test drop ;
[ 2 3 ] [ 2 3 t single-combination-test ] unit-test
[ 2 3 ] [ 2 3 4 single-combination-test ] unit-test
[ 2 f ] [ 2 3 f single-combination-test ] unit-test
DEFER: single-combination-test-2
: single-combination-test-4
dup [ single-combination-test-2 ] when ;
: single-combination-test-3
drop 3 ;
GENERIC: single-combination-test-2
M: object single-combination-test-2 single-combination-test-3 ;
M: f single-combination-test-2 single-combination-test-4 ;
[ 3 ] [ t single-combination-test-2 ] unit-test
[ 3 ] [ 3 single-combination-test-2 ] unit-test
[ f ] [ f single-combination-test-2 ] unit-test

View File

@ -10,7 +10,7 @@ words splitting ;
: foo 3 throw 7 ; : foo 3 throw 7 ;
: bar foo 4 ; : bar foo 4 ;
: baz bar 5 ; : baz bar 5 ;
[ 3 ] [ [ baz ] catch ] unit-test [ baz ] [ 3 = ] must-fail-with
[ t ] [ [ t ] [
symbolic-stack-trace symbolic-stack-trace
[ word? ] subset [ word? ] subset
@ -22,11 +22,11 @@ words splitting ;
: stack-trace-contains? symbolic-stack-trace memq? ; : stack-trace-contains? symbolic-stack-trace memq? ;
[ t ] [ [ t ] [
[ { 1 "hi" } bleh ] catch drop \ + stack-trace-contains? [ { 1 "hi" } bleh ] ignore-errors \ + stack-trace-contains?
] unit-test ] unit-test
[ t f ] [ [ t f ] [
[ { "hi" } bleh ] catch drop [ { "hi" } bleh ] ignore-errors
\ + stack-trace-contains? \ + stack-trace-contains?
\ > stack-trace-contains? \ > stack-trace-contains?
] unit-test ] unit-test
@ -34,6 +34,6 @@ words splitting ;
: quux [ t [ "hi" throw ] when ] times ; : quux [ t [ "hi" throw ] when ] times ;
[ t ] [ [ t ] [
[ 10 quux ] catch drop [ 10 quux ] ignore-errors
\ (each-integer) stack-trace-contains? \ (each-integer) stack-trace-contains?
] unit-test ] unit-test

View File

@ -2,7 +2,7 @@
USING: arrays compiler kernel kernel.private math USING: arrays compiler kernel kernel.private math
hashtables.private math.private namespaces sequences hashtables.private math.private namespaces sequences
sequences.private tools.test namespaces.private slots.private sequences.private tools.test namespaces.private slots.private
combinators.private byte-arrays alien alien.accessors layouts sequences.private byte-arrays alien alien.accessors layouts
words definitions compiler.units ; words definitions compiler.units ;
IN: temporary IN: temporary

9
core/compiler/units/units-docs.factor Normal file → Executable file
View File

@ -28,9 +28,7 @@ HELP: redefine-error
HELP: remember-definition HELP: remember-definition
{ $values { "definition" "a definition specifier" } { "loc" "a " { $snippet "{ path line# }" } " pair" } } { $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." { $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 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." } ; { $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." } ;
@ -38,11 +36,6 @@ HELP: old-definitions
HELP: new-definitions 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 } "." } ; { $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." } ;
HELP: with-compilation-unit HELP: with-compilation-unit
{ $values { "quot" quotation } } { $values { "quot" quotation } }
{ $description "Calls a quotation in a new compilation unit. The quotation can define new words and classes, as well as forget words. When the quotation returns, any changed words are recompiled, and changes are applied atomically." } { $description "Calls a quotation in a new compilation unit. The quotation can define new words and classes, as well as forget words. When the quotation returns, any changed words are recompiled, and changes are applied atomically." }

View File

@ -26,11 +26,6 @@ TUPLE: redefine-error def ;
over new-definitions get first key? [ dup redefine-error ] when over new-definitions get first key? [ dup redefine-error ] when
new-definitions get second (remember-definition) ; new-definitions get second (remember-definition) ;
TUPLE: forward-error word ;
: forward-error ( word -- )
\ forward-error construct-boa throw ;
: forward-reference? ( word -- ? ) : forward-reference? ( word -- ? )
dup old-definitions get assoc-stack dup old-definitions get assoc-stack
[ new-definitions get assoc-stack not ] [ new-definitions get assoc-stack not ]

View File

@ -23,10 +23,9 @@ $nl
"Two words raise an error in the innermost error handler for the current dynamic extent:" "Two words raise an error in the innermost error handler for the current dynamic extent:"
{ $subsection throw } { $subsection throw }
{ $subsection rethrow } { $subsection rethrow }
"A set of words establish an error handler:" "Two words for establishing an error handler:"
{ $subsection cleanup } { $subsection cleanup }
{ $subsection recover } { $subsection recover }
{ $subsection catch }
"Unhandled errors are reported in the listener and can be debugged using various tools. See " { $link "debugger" } "." "Unhandled errors are reported in the listener and can be debugged using various tools. See " { $link "debugger" } "."
{ $subsection "errors-restartable" } { $subsection "errors-restartable" }
{ $subsection "errors-post-mortem" } ; { $subsection "errors-post-mortem" } ;
@ -147,12 +146,7 @@ HELP: throw
{ $values { "error" object } } { $values { "error" object } }
{ $description "Saves the current continuation in the " { $link error-continuation } " global variable and throws an error. Execution does not continue at the point after the " { $link throw } " call. Rather, the innermost catch block is invoked, and execution continues at that point." } ; { $description "Saves the current continuation in the " { $link error-continuation } " global variable and throws an error. Execution does not continue at the point after the " { $link throw } " call. Rather, the innermost catch block is invoked, and execution continues at that point." } ;
HELP: catch { cleanup recover } related-words
{ $values { "try" quotation } { "error/f" object } }
{ $description "Calls the " { $snippet "try" } " quotation. If an error is thrown in the dynamic extent of the quotation, restores the data stack and pushes the error. If the quotation returns successfully, outputs " { $link f } " without restoring the data stack." }
{ $notes "This word cannot differentiate between the case of " { $link f } " being thrown, and no error being thrown. You should never throw " { $link f } ", and you should also use other error handling combinators where possible." } ;
{ catch cleanup recover } related-words
HELP: cleanup HELP: cleanup
{ $values { "try" quotation } { "cleanup-always" quotation } { "cleanup-error" quotation } } { $values { "try" quotation } { "cleanup-always" quotation } { "cleanup-error" quotation } }
@ -166,7 +160,7 @@ HELP: rethrow
{ $values { "error" object } } { $values { "error" object } }
{ $description "Throws an error without saving the current continuation in the " { $link error-continuation } " global variable. This is done so that inspecting the error stacks sheds light on the original cause of the exception, rather than the point where it was rethrown." } { $description "Throws an error without saving the current continuation in the " { $link error-continuation } " global variable. This is done so that inspecting the error stacks sheds light on the original cause of the exception, rather than the point where it was rethrown." }
{ $notes { $notes
"This word is intended to be used in conjunction with " { $link recover } " or " { $link catch } " to implement error handlers which perform an action and pass the error to the next outermost error handler." "This word is intended to be used in conjunction with " { $link recover } " to implement error handlers which perform an action and pass the error to the next outermost error handler."
} }
{ $examples { $examples
"The " { $link with-parser } " catches errors, annotates them with file name and line number information, and rethrows them:" "The " { $link with-parser } " catches errors, annotates them with file name and line number information, and rethrows them:"
@ -175,7 +169,7 @@ HELP: rethrow
HELP: throw-restarts HELP: throw-restarts
{ $values { "error" object } { "restarts" "a sequence of " { $snippet "{ string object }" } " pairs" } { "restart" object } } { $values { "error" object } { "restarts" "a sequence of " { $snippet "{ string object }" } " pairs" } { "restart" object } }
{ $description "Throws a restartable error using " { $link throw } ". The " { $snippet "restarts" } " parameter is a sequence of pairs where the first element in each pair is a human-readable description and the second is an arbitrary object. If the error reaches the top-level error handler, the user will be presented with the list of possible restarts, and upon invoking one, execution will continue after the call to " { $link condition } " with the object associated to the chosen restart on the stack." } { $description "Throws a restartable error using " { $link throw } ". The " { $snippet "restarts" } " parameter is a sequence of pairs where the first element in each pair is a human-readable description and the second is an arbitrary object. If the error reaches the top-level error handler, the user will be presented with the list of possible restarts, and upon invoking one, execution will continue after the call to " { $link throw-restarts } " with the object associated to the chosen restart on the stack." }
{ $examples { $examples
"Try invoking one of the two restarts which are offered after the below code throws an error:" "Try invoking one of the two restarts which are offered after the below code throws an error:"
{ $code { $code

View File

@ -25,13 +25,11 @@ IN: temporary
[ t ] [ 10 callcc1-test 10 reverse >vector = ] unit-test [ t ] [ 10 callcc1-test 10 reverse >vector = ] unit-test
[ t ] [ callcc-namespace-test ] unit-test [ t ] [ callcc-namespace-test ] unit-test
[ f ] [ [ ] catch ] unit-test [ 5 throw ] [ 5 = ] must-fail-with
[ 5 ] [ [ 5 throw ] catch ] unit-test
[ t ] [ [ t ] [
[ "Hello" throw ] catch drop [ "Hello" throw ] ignore-errors
global [ error get ] bind error get-global
"Hello" = "Hello" =
] unit-test ] unit-test
@ -41,13 +39,13 @@ IN: temporary
"!!! The following error is part of the test" print "!!! The following error is part of the test" print
[ [ "2 car" ] eval ] catch print-error [ ] [ [ [ "2 car" ] eval ] [ print-error ] recover ] unit-test
[ f throw ] unit-test-fails [ f throw ] must-fail
! Weird PowerPC bug. ! Weird PowerPC bug.
[ ] [ [ ] [
[ "4" throw ] catch drop [ "4" throw ] ignore-errors
data-gc data-gc
data-gc data-gc
] unit-test ] unit-test
@ -56,10 +54,10 @@ IN: temporary
[ f ] [ { "A" "B" } kernel-error? ] unit-test [ f ] [ { "A" "B" } kernel-error? ] unit-test
! ! See how well callstack overflow is handled ! ! See how well callstack overflow is handled
! [ clear drop ] unit-test-fails ! [ clear drop ] must-fail
! !
! : callstack-overflow callstack-overflow f ; ! : callstack-overflow callstack-overflow f ;
! [ callstack-overflow ] unit-test-fails ! [ callstack-overflow ] must-fail
: don't-compile-me { } [ ] each ; : don't-compile-me { } [ ] each ;
@ -84,24 +82,20 @@ SYMBOL: error-counter
[ 1 ] [ always-counter get ] unit-test [ 1 ] [ always-counter get ] unit-test
[ 0 ] [ error-counter get ] unit-test [ 0 ] [ error-counter get ] unit-test
[ "a" ] [ [
[ [ "a" throw ]
[ "a" throw ] [ always-counter inc ]
[ always-counter inc ] [ error-counter inc ] cleanup
[ error-counter inc ] cleanup ] [ "a" = ] must-fail-with
] catch
] unit-test
[ 2 ] [ always-counter get ] unit-test [ 2 ] [ always-counter get ] unit-test
[ 1 ] [ error-counter get ] unit-test [ 1 ] [ error-counter get ] unit-test
[ "a" ] [ [
[ [ ]
[ ] [ always-counter inc "a" throw ]
[ always-counter inc "a" throw ] [ error-counter inc ] cleanup
[ error-counter inc ] cleanup ] [ "a" = ] must-fail-with
] catch
] unit-test
[ 3 ] [ always-counter get ] unit-test [ 3 ] [ always-counter get ] unit-test
[ 1 ] [ error-counter get ] unit-test [ 1 ] [ error-counter get ] unit-test

View File

@ -1,4 +1,4 @@
! Copyright (C) 2003, 2007 Slava Pestov. ! Copyright (C) 2003, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays vectors kernel kernel.private sequences USING: arrays vectors kernel kernel.private sequences
namespaces math splitting sorting quotations assocs ; namespaces math splitting sorting quotations assocs ;
@ -17,9 +17,6 @@ SYMBOL: restarts
: c> ( -- continuation ) catchstack* pop ; : c> ( -- continuation ) catchstack* pop ;
: (catch) ( quot -- newquot )
[ swap >c call c> drop ] curry ; inline
: dummy ( -- obj ) : dummy ( -- obj )
#! Optimizing compiler assumes stack won't be messed with #! Optimizing compiler assumes stack won't be messed with
#! in-transit. To ensure that a value is actually reified #! in-transit. To ensure that a value is actually reified
@ -101,7 +98,7 @@ PRIVATE>
: continue-with ( obj continuation -- ) : continue-with ( obj continuation -- )
[ [
walker-hook [ >r 2array r> ] when* (continue-with) walker-hook [ >r 2array r> ] when* (continue-with)
] 2curry (throw) ; ] 2 (throw) ;
: continue ( continuation -- ) : continue ( continuation -- )
f swap continue-with ; f swap continue-with ;
@ -120,11 +117,8 @@ PRIVATE>
catchstack* empty? [ die ] when catchstack* empty? [ die ] when
dup save-error c> continue-with ; dup save-error c> continue-with ;
: catch ( try -- error/f )
(catch) [ f ] compose callcc1 ; inline
: recover ( try recovery -- ) : recover ( try recovery -- )
>r (catch) r> ifcc ; inline >r [ swap >c call c> drop ] curry r> ifcc ; inline
: cleanup ( try cleanup-always cleanup-error -- ) : cleanup ( try cleanup-always cleanup-error -- )
over >r compose [ dip rethrow ] curry over >r compose [ dip rethrow ] curry

View File

@ -60,9 +60,7 @@ HOOK: %jump-label compiler-backend ( label -- )
! Test if vreg is 'f' or not ! Test if vreg is 'f' or not
HOOK: %jump-t compiler-backend ( label -- ) HOOK: %jump-t compiler-backend ( label -- )
HOOK: %call-dispatch compiler-backend ( -- label ) HOOK: %dispatch compiler-backend ( -- )
HOOK: %jump-dispatch compiler-backend ( -- )
HOOK: %dispatch-label compiler-backend ( word -- ) HOOK: %dispatch-label compiler-backend ( word -- )

View File

@ -111,20 +111,15 @@ M: ppc-backend %jump-label ( label -- ) B ;
M: ppc-backend %jump-t ( label -- ) M: ppc-backend %jump-t ( label -- )
0 "flag" operand f v>operand CMPI BNE ; 0 "flag" operand f v>operand CMPI BNE ;
: (%dispatch) ( len -- ) M: ppc-backend %dispatch ( -- )
0 11 LOAD32 rc-absolute-ppc-2/2 rel-here [
"offset" operand "n" operand 1 SRAWI %epilogue-later
11 11 "offset" operand ADD 0 11 LOAD32 rc-absolute-ppc-2/2 rel-here
11 dup rot cells LWZ ; "offset" operand "n" operand 1 SRAWI
11 11 "offset" operand ADD
M: ppc-backend %call-dispatch ( word-table# -- ) 11 dup 6 cells LWZ
[ 7 (%dispatch) (%call) <label> dup B ] H{ (%jump)
{ +input+ { { f "n" } } } ] H{
{ +scratch+ { { f "offset" } } }
} with-template ;
M: ppc-backend %jump-dispatch ( -- )
[ %epilogue-later 6 (%dispatch) (%jump) ] H{
{ +input+ { { f "n" } } } { +input+ { { f "n" } } }
{ +scratch+ { { f "offset" } } } { +scratch+ { { f "offset" } } }
} with-template ; } with-template ;

View File

@ -13,3 +13,7 @@ namespaces alien.c-types kernel system combinators ;
} cond } cond
T{ ppc-backend } compiler-backend set-global T{ ppc-backend } compiler-backend set-global
macosx? [
4 "double" c-type set-c-type-align
] when

View File

@ -261,6 +261,10 @@ windows? [
cell "ulonglong" c-type set-c-type-align cell "ulonglong" c-type set-c-type-align
] unless ] unless
windows? [
4 "double" c-type set-c-type-align
] unless
T{ x86-backend f 4 } compiler-backend set-global T{ x86-backend f 4 } compiler-backend set-global
: sse2? "Intrinsic" throw ; : sse2? "Intrinsic" throw ;

View File

@ -4,7 +4,8 @@ USING: alien.c-types arrays cpu.x86.assembler
cpu.x86.architecture cpu.x86.intrinsics cpu.x86.sse2 cpu.x86.architecture cpu.x86.intrinsics cpu.x86.sse2
cpu.x86.allot cpu.architecture kernel kernel.private math cpu.x86.allot cpu.architecture kernel kernel.private math
namespaces sequences generator.registers generator.fixup system namespaces sequences generator.registers generator.fixup system
alien alien.compiler alien.structs slots splitting assocs ; alien alien.accessors alien.compiler alien.structs slots
splitting assocs ;
IN: cpu.x86.64 IN: cpu.x86.64
PREDICATE: x86-backend amd64-backend PREDICATE: x86-backend amd64-backend

View File

@ -77,26 +77,29 @@ M: x86-backend %jump-label ( label -- ) JMP ;
M: x86-backend %jump-t ( label -- ) M: x86-backend %jump-t ( label -- )
"flag" operand f v>operand CMP JNE ; "flag" operand f v>operand CMP JNE ;
: (%dispatch) ( n -- operand ) : code-alignment ( -- n )
! Load jump table base. We use a temporary register building get length dup cell align swap - ;
! since on AMD64 we have to load a 64-bit immediate. On
! x86, this is redundant.
! Untag and multiply to get a jump table offset
"n" operand fixnum>slot@
! Add jump table base
"offset" operand HEX: ffffffff MOV rc-absolute-cell rel-here
"n" operand "offset" operand ADD
"n" operand swap bootstrap-cell 8 = 14 9 ? + [+] ;
M: x86-backend %call-dispatch ( word-table# -- ) : align-code ( n -- )
[ 5 (%dispatch) CALL <label> dup JMP ] H{ 0 <repetition> % ;
{ +input+ { { f "n" } } }
{ +scratch+ { { f "offset" } } }
{ +clobber+ { "n" } }
} with-template ;
M: x86-backend %jump-dispatch ( -- ) M: x86-backend %dispatch ( -- )
[ %epilogue-later 0 (%dispatch) JMP ] H{ [
%epilogue-later
! Load jump table base. We use a temporary register
! since on AMD64 we have to load a 64-bit immediate. On
! x86, this is redundant.
! Untag and multiply to get a jump table offset
"n" operand fixnum>slot@
! Add jump table base
"offset" operand HEX: ffffffff MOV rc-absolute-cell rel-here
"n" operand "offset" operand ADD
"n" operand HEX: 7f [+] JMP
! Fix up the displacement above
code-alignment dup bootstrap-cell 8 = 15 9 ? +
building get dup pop* push
align-code
] H{
{ +input+ { { f "n" } } } { +input+ { { f "n" } } }
{ +scratch+ { { f "offset" } } } { +scratch+ { { f "offset" } } }
{ +clobber+ { "n" } } { +clobber+ { "n" } }

View File

@ -87,7 +87,32 @@ TUPLE: assert got expect ;
: depth ( -- n ) datastack length ; : depth ( -- n ) datastack length ;
: assert-depth ( quot -- ) depth slip depth swap assert= ; : trim-datastacks ( seq1 seq2 -- seq1' seq2' )
2dup [ length ] 2apply min tuck tail >r tail r> ;
TUPLE: relative-underflow stack ;
: relative-underflow ( before after -- * )
trim-datastacks nip \ relative-underflow construct-boa throw ;
M: relative-underflow summary
drop "Too many items removed from data stack" ;
TUPLE: relative-overflow stack ;
M: relative-overflow summary
drop "Superfluous items pushed to data stack" ;
: relative-overflow ( before after -- * )
trim-datastacks drop \ relative-overflow construct-boa throw ;
: assert-depth ( quot -- )
>r datastack r> swap slip >r datastack r>
2dup [ length ] compare sgn {
{ -1 [ relative-underflow ] }
{ 0 [ 2drop ] }
{ 1 [ relative-overflow ] }
} case ; inline
: expired-error. ( obj -- ) : expired-error. ( obj -- )
"Object did not survive image save/load: " write third . ; "Object did not survive image save/load: " write third . ;
@ -222,9 +247,6 @@ M: redefine-error error.
"Re-definition of " write "Re-definition of " write
redefine-error-def . ; redefine-error-def . ;
M: forward-error error.
"Forward reference to " write forward-error-word . ;
M: undefined summary M: undefined summary
drop "Calling a deferred word before it has been defined" ; drop "Calling a deferred word before it has been defined" ;

View File

@ -52,9 +52,7 @@ $nl
$nl $nl
"If the parser did not have special checks for this case, then the modified source file would still load, because when the definition of " { $snippet "hello-world" } " on line 4 is being parsed, the " { $snippet "world" } " word is already present in the dictionary from an earlier run. The developer would then not discover this mistake until attempting to load the source file into a fresh image." "If the parser did not have special checks for this case, then the modified source file would still load, because when the definition of " { $snippet "hello-world" } " on line 4 is being parsed, the " { $snippet "world" } " word is already present in the dictionary from an earlier run. The developer would then not discover this mistake until attempting to load the source file into a fresh image."
$nl $nl
"Since this is undesirable, the parser explicitly raises an error if a source file refers to a word which is in the dictionary, but defined after it is used." "Since this is undesirable, the parser explicitly raises a " { $link no-word } " error if a source file refers to a word which is in the dictionary, but defined after it is used."
{ $subsection forward-error }
"If a source file raises a " { $link forward-error } " when loaded into a development image, then it would have raised a " { $link no-word } " error when loaded into a fresh image."
$nl $nl
"The parser also catches duplicate definitions. If an artifact is defined twice in the same source file, the earlier definition will never be accessible, and this is almost always a mistake, perhaps due to a bad choice of word names, or a copy and paste error. The parser raises an error in this case." "The parser also catches duplicate definitions. If an artifact is defined twice in the same source file, the earlier definition will never be accessible, and this is almost always a mistake, perhaps due to a bad choice of word names, or a copy and paste error. The parser raises an error in this case."
{ $subsection redefine-error } ; { $subsection redefine-error } ;

View File

@ -6,12 +6,14 @@ TUPLE: combination-1 ;
M: combination-1 perform-combination 2drop { } [ ] each [ ] ; M: combination-1 perform-combination 2drop { } [ ] each [ ] ;
M: combination-1 make-default-method 2drop [ "No method" throw ] ;
SYMBOL: generic-1 SYMBOL: generic-1
[ [
generic-1 T{ combination-1 } define-generic generic-1 T{ combination-1 } define-generic
[ ] <method> object \ generic-1 define-method [ ] object \ generic-1 define-method
] with-compilation-unit ] with-compilation-unit
[ ] [ [ ] [
@ -20,7 +22,7 @@ SYMBOL: generic-1
] with-compilation-unit ] with-compilation-unit
] unit-test ] unit-test
GENERIC: some-generic GENERIC: some-generic ( a -- b )
USE: arrays USE: arrays

View File

@ -144,6 +144,11 @@ PRIVATE>
: dlist-delete ( obj dlist -- obj/f ) : dlist-delete ( obj dlist -- obj/f )
>r [ eq? ] curry r> delete-node-if ; >r [ eq? ] curry r> delete-node-if ;
: dlist-delete-all ( dlist -- )
f over set-dlist-front
f over set-dlist-back
0 swap set-dlist-length ;
: dlist-each ( dlist quot -- ) : dlist-each ( dlist quot -- )
[ dlist-node-obj ] swap compose dlist-each-node ; inline [ dlist-node-obj ] swap compose dlist-each-node ; inline

16
core/effects/effects.factor Normal file → Executable file
View File

@ -1,4 +1,4 @@
! Copyright (C) 2006, 2007 Slava Pestov. ! Copyright (C) 2006, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel math namespaces sequences strings words assocs USING: kernel math namespaces sequences strings words assocs
combinators ; combinators ;
@ -41,13 +41,13 @@ M: integer (stack-picture) drop "object" ;
")" % ")" %
] "" make ; ] "" make ;
: stack-effect ( word -- effect/f ) GENERIC: stack-effect ( word -- effect/f )
dup symbol? [
drop 0 1 <effect> M: symbol stack-effect drop 0 1 <effect> ;
] [
{ "declared-effect" "inferred-effect" } M: word stack-effect
swap word-props [ at ] curry map [ ] find nip { "declared-effect" "inferred-effect" }
] if ; swap word-props [ at ] curry map [ ] find nip ;
M: effect clone M: effect clone
[ effect-in clone ] keep effect-out clone <effect> ; [ effect-in clone ] keep effect-out clone <effect> ;

View File

@ -32,7 +32,7 @@ HELP: <float-array> ( n initial -- float-array )
HELP: >float-array HELP: >float-array
{ $values { "seq" "a sequence" } { "float-array" float-array } } { $values { "seq" "a sequence" } { "float-array" float-array } }
{ $description "Outputs a freshly-allocated float array whose elements have the same boolean values as a given sequence." } { $description "Outputs a freshly-allocated float array whose elements have the same floating-point values as a given sequence." }
{ $errors "Throws an error if the sequence contains elements other than real numbers." } ; { $errors "Throws an error if the sequence contains elements other than real numbers." } ;
HELP: 1float-array HELP: 1float-array

View File

@ -7,4 +7,4 @@ USING: float-arrays tools.test ;
[ F{ 1 2 } ] [ 2 F{ 1 2 3 4 5 6 7 8 9 } resize-float-array ] unit-test [ F{ 1 2 } ] [ 2 F{ 1 2 3 4 5 6 7 8 9 } resize-float-array ] unit-test
[ -10 F{ } resize-float-array ] unit-test-fails [ -10 F{ } resize-float-array ] must-fail

View File

@ -3,8 +3,9 @@
USING: arrays assocs classes combinators cpu.architecture USING: arrays assocs classes combinators cpu.architecture
effects generator.fixup generator.registers generic hashtables effects generator.fixup generator.registers generic hashtables
inference inference.backend inference.dataflow io kernel inference inference.backend inference.dataflow io kernel
kernel.private layouts math namespaces optimizer prettyprint kernel.private layouts math namespaces optimizer
quotations sequences system threads words vectors ; optimizer.specializers prettyprint quotations sequences system
threads words vectors ;
IN: generator IN: generator
SYMBOL: compile-queue SYMBOL: compile-queue
@ -55,13 +56,16 @@ GENERIC: generate-node ( node -- next )
: generate-nodes ( node -- ) : generate-nodes ( node -- )
[ node@ generate-node ] iterate-nodes end-basic-block ; [ node@ generate-node ] iterate-nodes end-basic-block ;
: init-generate-nodes ( -- )
init-templates
%save-word-xt
%prologue-later
current-label-start define-label
current-label-start resolve-label ;
: generate ( word label node -- ) : generate ( word label node -- )
[ [
init-templates init-generate-nodes
%save-word-xt
%prologue-later
current-label-start define-label
current-label-start resolve-label
[ generate-nodes ] with-node-iterator [ generate-nodes ] with-node-iterator
] generate-1 ; ] generate-1 ;
@ -154,22 +158,36 @@ M: #if generate-node
] generate-1 ] generate-1
] keep ; ] keep ;
: tail-dispatch? ( node -- ? )
#! Is the dispatch a jump to a tail call to a word?
dup #call? swap node-successor #return? and ;
: dispatch-branches ( node -- ) : dispatch-branches ( node -- )
node-children [ node-children [
compiling-word get dispatch-branch %dispatch-label dup tail-dispatch? [
node-param
] [
compiling-word get dispatch-branch
] if %dispatch-label
] each ; ] each ;
: generate-dispatch ( node -- )
%dispatch dispatch-branches init-templates ;
M: #dispatch generate-node M: #dispatch generate-node
#! The order here is important, dispatch-branches must #! The order here is important, dispatch-branches must
#! run after %dispatch, so that each branch gets the #! run after %dispatch, so that each branch gets the
#! correct register state #! correct register state
tail-call? [ tail-call? [
%jump-dispatch dispatch-branches generate-dispatch iterate-next
] [ ] [
0 frame-required compiling-word get gensym [
%call-dispatch >r dispatch-branches r> resolve-label rot [
] if init-generate-nodes
init-templates iterate-next ; generate-dispatch
] generate-1
] keep generate-call
] if ;
! #call ! #call
: define-intrinsics ( word intrinsics -- ) : define-intrinsics ( word intrinsics -- )

View File

@ -1,6 +1,6 @@
USING: help.markup help.syntax generic.math generic.standard USING: help.markup help.syntax generic.math generic.standard
words classes definitions kernel alien combinators sequences words classes definitions kernel alien combinators sequences
math ; math quotations ;
IN: generic IN: generic
ARTICLE: "method-order" "Method precedence" ARTICLE: "method-order" "Method precedence"
@ -107,10 +107,6 @@ HELP: make-generic
{ $description "Regenerates the definition of a generic word by applying the method combination to the set of defined methods." } { $description "Regenerates the definition of a generic word by applying the method combination to the set of defined methods." }
$low-level-note ; $low-level-note ;
HELP: init-methods
{ $values { "word" word } }
{ $description "Prepare to define a generic word." } ;
HELP: define-generic HELP: define-generic
{ $values { "word" word } { "combination" "a method combination" } } { $values { "word" word } { "combination" "a method combination" } }
{ $description "Defines a generic word. A method combination is an object which responds to the " { $link perform-combination } " generic word." } { $description "Defines a generic word. A method combination is an object which responds to the " { $link perform-combination } " generic word." }
@ -125,16 +121,12 @@ HELP: method
{ $description "Looks up a method definition." } { $description "Looks up a method definition." }
{ $class-description "Instances of this class are methods. A method consists of a quotation together with a source location where it was defined." } ; { $class-description "Instances of this class are methods. A method consists of a quotation together with a source location where it was defined." } ;
{ method method-def method-loc define-method POSTPONE: M: } related-words { method define-method POSTPONE: M: } related-words
HELP: <method> HELP: <method>
{ $values { "def" "a quotation" } { "method" "a new method definition" } } { $values { "def" "a quotation" } { "method" "a new method definition" } }
{ $description "Creates a new "{ $link method } " instance." } ; { $description "Creates a new "{ $link method } " instance." } ;
HELP: sort-methods
{ $values { "assoc" "an assoc mapping classes to methods" } { "newassoc" "an association list mapping classes to quotations" } }
{ $description "Outputs a sequence of pairs, where the first element of each pair is a class and the second element is the corresponding method quotation. The methods are sorted by class order; see " { $link sort-classes } "." } ;
HELP: methods HELP: methods
{ $values { "word" generic } { "assoc" "an association list mapping classes to quotations" } } { $values { "word" generic } { "assoc" "an association list mapping classes to quotations" } }
{ $description "Outputs a sequence of pairs, where the first element of each pair is a class and the second element is the corresponding method quotation. The methods are sorted by class order; see " { $link sort-classes } "." } ; { $description "Outputs a sequence of pairs, where the first element of each pair is a class and the second element is the corresponding method quotation. The methods are sorted by class order; see " { $link sort-classes } "." } ;
@ -154,7 +146,7 @@ HELP: with-methods
$low-level-note ; $low-level-note ;
HELP: define-method HELP: define-method
{ $values { "method" "an instance of " { $link method } } { "class" class } { "generic" generic } } { $values { "method" quotation } { "class" class } { "generic" generic } }
{ $description "Defines a method. This is the runtime equivalent of " { $link POSTPONE: M: } "." } ; { $description "Defines a method. This is the runtime equivalent of " { $link POSTPONE: M: } "." } ;
HELP: implementors HELP: implementors

View File

@ -16,7 +16,7 @@ M: word class-of drop "word" ;
[ "fixnum" ] [ 5 class-of ] unit-test [ "fixnum" ] [ 5 class-of ] unit-test
[ "word" ] [ \ class-of class-of ] unit-test [ "word" ] [ \ class-of class-of ] unit-test
[ 3.4 class-of ] unit-test-fails [ 3.4 class-of ] must-fail
[ "Hello world" ] [ 4 foobar foobar ] unit-test [ "Hello world" ] [ 4 foobar foobar ] unit-test
[ "Goodbye cruel world" ] [ 4 foobar ] unit-test [ "Goodbye cruel world" ] [ 4 foobar ] unit-test
@ -90,7 +90,7 @@ M: number union-containment drop 2 ;
"IN: temporary GENERIC: unhappy ( x -- x )" eval "IN: temporary GENERIC: unhappy ( x -- x )" eval
[ [
"IN: temporary M: dictionary unhappy ;" eval "IN: temporary M: dictionary unhappy ;" eval
] unit-test-fails ] must-fail
[ ] [ "IN: temporary GENERIC: unhappy ( x -- x )" eval ] unit-test [ ] [ "IN: temporary GENERIC: unhappy ( x -- x )" eval ] unit-test
GENERIC# complex-combination 1 ( a b -- c ) GENERIC# complex-combination 1 ( a b -- c )
@ -155,9 +155,7 @@ M: string my-hook "a string" ;
[ "an integer" ] [ 3 my-var set my-hook ] unit-test [ "an integer" ] [ 3 my-var set my-hook ] unit-test
[ "a string" ] [ my-hook my-var set my-hook ] unit-test [ "a string" ] [ my-hook my-var set my-hook ] unit-test
[ T{ no-method f 1.0 my-hook } ] [ [ 1.0 my-var set my-hook ] [ T{ no-method f 1.0 my-hook } = ] must-fail-with
1.0 my-var set [ my-hook ] catch
] unit-test
GENERIC: tag-and-f ( x -- x x ) GENERIC: tag-and-f ( x -- x x )
@ -176,6 +174,9 @@ M: f tag-and-f 4 ;
! define-class hashing issue ! define-class hashing issue
TUPLE: debug-combination ; TUPLE: debug-combination ;
M: debug-combination make-default-method
2drop [ "Oops" throw ] ;
M: debug-combination perform-combination M: debug-combination perform-combination
drop drop
order [ dup class-hashes ] { } map>assoc sort-keys order [ dup class-hashes ] { } map>assoc sort-keys
@ -200,3 +201,40 @@ TUPLE: redefinition-test-tuple ;
redefinition-test-generic , redefinition-test-generic ,
] { } make all-equal? ] { } make all-equal?
] unit-test ] unit-test
! Issues with forget
GENERIC: generic-forget-test-1
M: integer generic-forget-test-1 / ;
[ t ] [
\ / usage [ word? ] subset
[ word-name "generic-forget-test-1/integer" = ] contains?
] unit-test
[ ] [
[ \ generic-forget-test-1 forget ] with-compilation-unit
] unit-test
[ f ] [
\ / usage [ word? ] subset
[ word-name "generic-forget-test-1/integer" = ] contains?
] unit-test
GENERIC: generic-forget-test-2
M: sequence generic-forget-test-2 = ;
[ t ] [
\ = usage [ word? ] subset
[ word-name "generic-forget-test-2/sequence" = ] contains?
] unit-test
[ ] [
[ { sequence generic-forget-test-2 } forget ] with-compilation-unit
] unit-test
[ f ] [
\ = usage [ word? ] subset
[ word-name "generic-forget-test-2/sequence" = ] contains?
] unit-test

View File

@ -1,16 +1,11 @@
! Copyright (C) 2006, 2007 Slava Pestov. ! Copyright (C) 2006, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: words kernel sequences namespaces assocs hashtables USING: words kernel sequences namespaces assocs hashtables
definitions kernel.private classes classes.private definitions kernel.private classes classes.private
quotations arrays vocabs ; quotations arrays vocabs effects ;
IN: generic IN: generic
PREDICATE: word generic "combination" word-prop >boolean ; ! Method combination protocol
M: generic definer drop f f ;
M: generic definition drop f ;
GENERIC: perform-combination ( word combination -- quot ) GENERIC: perform-combination ( word combination -- quot )
M: object perform-combination M: object perform-combination
@ -22,27 +17,22 @@ M: object perform-combination
#! the method will throw an error. We don't want that. #! the method will throw an error. We don't want that.
nip [ "Invalid method combination" throw ] curry [ ] like ; nip [ "Invalid method combination" throw ] curry [ ] like ;
GENERIC: method-prologue ( class combination -- quot )
M: object method-prologue 2drop [ ] ;
GENERIC: make-default-method ( generic combination -- method )
PREDICATE: word generic "combination" word-prop >boolean ;
M: generic definer drop f f ;
M: generic definition drop f ;
: make-generic ( word -- ) : make-generic ( word -- )
dup dup "combination" word-prop perform-combination define ; dup dup "combination" word-prop perform-combination define ;
: init-methods ( word -- ) TUPLE: method word def specializer generic loc ;
dup "methods" word-prop
H{ } assoc-like
"methods" set-word-prop ;
: define-generic ( word combination -- )
dupd "combination" set-word-prop
dup init-methods make-generic ;
TUPLE: method loc def ;
: <method> ( def -- method )
{ set-method-def } \ method construct ;
M: f method-def ;
M: f method-loc ;
M: quotation method-def ;
M: quotation method-loc drop f ;
: method ( class generic -- method/f ) : method ( class generic -- method/f )
"methods" word-prop at ; "methods" word-prop at ;
@ -53,12 +43,10 @@ PREDICATE: pair method-spec
: order ( generic -- seq ) : order ( generic -- seq )
"methods" word-prop keys sort-classes ; "methods" word-prop keys sort-classes ;
: sort-methods ( assoc -- newassoc )
[ keys sort-classes ] keep
[ dupd at method-def 2array ] curry map ;
: methods ( word -- assoc ) : methods ( word -- assoc )
"methods" word-prop sort-methods ; "methods" word-prop
[ keys sort-classes ] keep
[ dupd at method-word ] curry { } map>assoc ;
TUPLE: check-method class generic ; TUPLE: check-method class generic ;
@ -71,22 +59,52 @@ TUPLE: check-method class generic ;
swap [ "methods" word-prop swap call ] keep make-generic ; swap [ "methods" word-prop swap call ] keep make-generic ;
inline inline
: define-method ( method class generic -- ) : method-word-name ( class word -- string )
>r bootstrap-word r> check-method word-name "/" rot word-name 3append ;
: make-method-def ( quot word combination -- quot )
"combination" word-prop method-prologue swap append ;
PREDICATE: word method-body "method" word-prop >boolean ;
M: method-body stack-effect
"method" word-prop method-generic stack-effect ;
: <method-word> ( quot class generic -- word )
[ make-method-def ] 2keep
method-word-name f <word>
dup rot define
dup xref ;
: <method> ( quot class generic -- method )
check-method
[ <method-word> ] 3keep f \ method construct-boa
dup method-word over "method" set-word-prop ;
: define-method ( quot class generic -- )
>r bootstrap-word r>
[ <method> ] 2keep
[ set-at ] with-methods ; [ set-at ] with-methods ;
: define-default-method ( generic combination -- )
dupd make-default-method object bootstrap-word pick <method>
"default-method" set-word-prop ;
! Definition protocol ! Definition protocol
M: method-spec where M: method-spec where
dup first2 method method-loc [ ] [ second where ] ?if ; dup first2 method [ method-loc ] [ second where ] ?if ;
M: method-spec set-where first2 method set-method-loc ; M: method-spec set-where first2 method set-method-loc ;
M: method-spec definer drop \ M: \ ; ; M: method-spec definer drop \ M: \ ; ;
M: method-spec definition first2 method method-def ; M: method-spec definition
first2 method dup [ method-def ] when ;
: forget-method ( class generic -- ) : forget-method ( class generic -- )
check-method [ delete-at ] with-methods ; check-method
[ delete-at* ] with-methods
[ method-word forget ] [ drop ] if ;
M: method-spec forget* first2 forget-method ; M: method-spec forget* first2 forget-method ;
@ -109,3 +127,28 @@ M: class forget* ( class -- )
M: assoc update-methods ( assoc -- ) M: assoc update-methods ( assoc -- )
implementors* [ make-generic ] each ; implementors* [ make-generic ] each ;
: define-generic ( word combination -- )
over "combination" word-prop over = [
2drop
] [
2dup "combination" set-word-prop
over H{ } clone "methods" set-word-prop
dupd define-default-method
make-generic
] if ;
GENERIC: subwords ( word -- seq )
M: word subwords drop f ;
M: generic subwords
dup "methods" word-prop values
swap "default-method" word-prop add
[ method-word ] map ;
M: generic forget-word
dup subwords [ forget-word ] each (forget-word) ;
: xref-generics ( -- )
all-words [ subwords [ xref ] each ] each ;

15
core/generic/math/math.factor Normal file → Executable file
View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays generic hashtables kernel kernel.private USING: arrays generic hashtables kernel kernel.private
math namespaces sequences words quotations layouts combinators math namespaces sequences words quotations layouts combinators
combinators.private classes definitions ; sequences.private classes definitions ;
IN: generic.math IN: generic.math
PREDICATE: class math-class ( object -- ? ) PREDICATE: class math-class ( object -- ? )
@ -38,9 +38,13 @@ TUPLE: no-math-method left right generic ;
: no-math-method ( left right generic -- * ) : no-math-method ( left right generic -- * )
\ no-math-method construct-boa throw ; \ no-math-method construct-boa throw ;
: default-math-method ( generic -- quot )
[ no-math-method ] curry [ ] like ;
: applicable-method ( generic class -- quot ) : applicable-method ( generic class -- quot )
over method method-def over method
[ ] [ [ no-math-method ] curry [ ] like ] ?if ; [ method-word word-def ]
[ default-math-method ] ?if ;
: object-method ( generic -- quot ) : object-method ( generic -- quot )
object bootstrap-word applicable-method ; object bootstrap-word applicable-method ;
@ -57,7 +61,7 @@ TUPLE: no-math-method left right generic ;
: math-vtable* ( picker max quot -- quot ) : math-vtable* ( picker max quot -- quot )
[ [
rot , \ tag , rot , \ tag ,
[ >r [ type>class ] map r> map % ] { } make , [ >r [ bootstrap-type>class ] map r> map % ] { } make ,
\ dispatch , \ dispatch ,
] [ ] make ; inline ] [ ] make ; inline
@ -66,6 +70,9 @@ TUPLE: no-math-method left right generic ;
TUPLE: math-combination ; TUPLE: math-combination ;
M: math-combination make-default-method
drop default-math-method ;
M: math-combination perform-combination M: math-combination perform-combination
drop drop
\ over [ \ over [

View File

@ -2,12 +2,16 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays assocs kernel kernel.private slots.private math USING: arrays assocs kernel kernel.private slots.private math
namespaces sequences vectors words quotations definitions namespaces sequences vectors words quotations definitions
hashtables layouts combinators combinators.private generic hashtables layouts combinators sequences.private generic
classes classes.private ; classes classes.private ;
IN: generic.standard IN: generic.standard
TUPLE: standard-combination # ; TUPLE: standard-combination # ;
M: standard-combination method-prologue
standard-combination-# object
<array> swap add* [ declare ] curry ;
C: <standard-combination> standard-combination C: <standard-combination> standard-combination
SYMBOL: (dispatch#) SYMBOL: (dispatch#)
@ -31,10 +35,10 @@ TUPLE: no-method object generic ;
: no-method ( object generic -- * ) : no-method ( object generic -- * )
\ no-method construct-boa throw ; \ no-method construct-boa throw ;
: error-method ( word -- method ) : error-method ( word -- quot )
picker swap [ no-method ] curry append ; picker swap [ no-method ] curry append ;
: empty-method ( word -- method ) : empty-method ( word -- quot )
[ [
picker % [ delegate dup ] % picker % [ delegate dup ] %
unpicker over add , unpicker over add ,
@ -65,13 +69,15 @@ TUPLE: no-method object generic ;
] if ; ] if ;
: default-method ( word -- pair ) : default-method ( word -- pair )
empty-method object bootstrap-word swap 2array ; "default-method" word-prop method-word
object bootstrap-word swap 2array ;
: method-alist>quot ( alist base-class -- quot ) : method-alist>quot ( alist base-class -- quot )
bootstrap-word swap simplify-alist bootstrap-word swap simplify-alist
class-predicates alist>quot ; class-predicates alist>quot ;
: small-generic ( methods -- def ) : small-generic ( methods -- def )
[ 1quotation ] assoc-map
object method-alist>quot ; object method-alist>quot ;
: hash-methods ( methods -- buckets ) : hash-methods ( methods -- buckets )
@ -83,12 +89,15 @@ TUPLE: no-method object generic ;
] if ] if
] distribute-buckets ; ] distribute-buckets ;
: class-hash-dispatch-quot ( methods quot picker -- quot )
>r >r hash-methods r> map
hash-dispatch-quot r> [ class-hash ] rot 3append ; inline
: big-generic ( methods -- quot ) : big-generic ( methods -- quot )
hash-methods [ small-generic ] map [ small-generic ] picker class-hash-dispatch-quot ;
hash-dispatch-quot picker [ class-hash ] rot 3append ;
: vtable-class ( n -- class ) : vtable-class ( n -- class )
type>class [ hi-tag bootstrap-word ] unless* ; bootstrap-type>class [ hi-tag bootstrap-word ] unless* ;
: group-methods ( assoc -- vtable ) : group-methods ( assoc -- vtable )
#! Input is a predicate -> method association. #! Input is a predicate -> method association.
@ -100,7 +109,8 @@ TUPLE: no-method object generic ;
: build-type-vtable ( alist-seq -- alist-seq ) : build-type-vtable ( alist-seq -- alist-seq )
dup length [ dup length [
vtable-class swap simplify-alist vtable-class
swap [ word-def ] assoc-map simplify-alist
class-predicates alist>quot class-predicates alist>quot
] 2map ; ] 2map ;
@ -137,30 +147,35 @@ TUPLE: no-method object generic ;
: standard-methods ( word -- alist ) : standard-methods ( word -- alist )
dup methods swap default-method add* ; dup methods swap default-method add* ;
M: standard-combination make-default-method
standard-combination-# (dispatch#)
[ empty-method ] with-variable ;
M: standard-combination perform-combination M: standard-combination perform-combination
standard-combination-# (dispatch#) [ standard-combination-# (dispatch#) [
[ standard-methods ] keep "inline" word-prop [ standard-methods ] keep "inline" word-prop
[ small-generic ] [ single-combination ] if [ small-generic ] [ single-combination ] if
] with-variable ; ] with-variable ;
: default-hook-method ( word -- pair )
error-method object bootstrap-word swap 2array ;
: hook-methods ( word -- methods )
dup methods [ [ drop ] swap append ] assoc-map
swap default-hook-method add* ;
TUPLE: hook-combination var ; TUPLE: hook-combination var ;
C: <hook-combination> hook-combination C: <hook-combination> hook-combination
M: hook-combination perform-combination M: hook-combination method-prologue
2drop [ drop ] ;
: with-hook ( combination quot -- quot' )
0 (dispatch#) [ 0 (dispatch#) [
[ swap slip
hook-combination-var [ get ] curry % hook-combination-var [ get ] curry
hook-methods single-combination % swap append
] [ ] make ] with-variable ; inline
] with-variable ;
M: hook-combination make-default-method
[ error-method ] with-hook ;
M: hook-combination perform-combination
[ standard-methods single-combination ] with-hook ;
: define-simple-generic ( word -- ) : define-simple-generic ( word -- )
T{ standard-combination f 0 } define-generic ; T{ standard-combination f 0 } define-generic ;

View File

@ -9,16 +9,16 @@ IN: temporary
! overflow bugs ! overflow bugs
[ "hi" most-positive-fixnum 2 * 2 + V{ } clone set-nth ] [ "hi" most-positive-fixnum 2 * 2 + V{ } clone set-nth ]
unit-test-fails must-fail
[ most-positive-fixnum 2 * 2 + { 1 } clone nth ] [ most-positive-fixnum 2 * 2 + { 1 } clone nth ]
unit-test-fails must-fail
[ most-positive-fixnum 2 * 2 + V{ } clone lengthen ] [ most-positive-fixnum 2 * 2 + V{ } clone lengthen ]
unit-test-fails must-fail
[ most-positive-fixnum 2 * 2 + V{ } clone set-length ] [ most-positive-fixnum 2 * 2 + V{ } clone set-length ]
unit-test-fails must-fail
[ ] [ [ ] [
10 V{ } [ set-length ] keep 10 V{ } [ set-length ] keep

View File

@ -127,9 +127,9 @@ H{ } "x" set
! Another crash discovered by erg ! Another crash discovered by erg
[ ] [ [ ] [
H{ } clone H{ } clone
[ 1 swap set-at ] catch drop [ 1 swap set-at ] ignore-errors
[ 2 swap set-at ] catch drop [ 2 swap set-at ] ignore-errors
[ 3 swap set-at ] catch drop [ 3 swap set-at ] ignore-errors
drop drop
] unit-test ] unit-test

View File

@ -5,8 +5,8 @@ USING: arrays kernel math namespaces tools.test
heaps heaps.private ; heaps heaps.private ;
IN: temporary IN: temporary
[ <min-heap> heap-pop ] unit-test-fails [ <min-heap> heap-pop ] must-fail
[ <max-heap> heap-pop ] unit-test-fails [ <max-heap> heap-pop ] must-fail
[ t ] [ <min-heap> heap-empty? ] unit-test [ t ] [ <min-heap> heap-empty? ] unit-test
[ f ] [ <min-heap> 1 t pick heap-push heap-empty? ] unit-test [ f ] [ <min-heap> 1 t pick heap-push heap-empty? ] unit-test

View File

@ -1,6 +1,6 @@
USING: help.syntax help.markup words effects inference.dataflow USING: help.syntax help.markup words effects inference.dataflow
inference.state inference.backend kernel sequences inference.state inference.backend kernel sequences
kernel.private combinators combinators.private ; kernel.private combinators sequences.private ;
HELP: literal-expected HELP: literal-expected
{ $error-description "Thrown when inference encounters a " { $link call } " or " { $link if } " being applied to a value which is not known to be a literal. Such a form can have an arbitrary stack effect, and does not compile." } { $error-description "Thrown when inference encounters a " { $link call } " or " { $link if } " being applied to a value which is not known to be a literal. Such a form can have an arbitrary stack effect, and does not compile." }

View File

@ -9,9 +9,13 @@ IN: inference.backend
: recursive-label ( word -- label/f ) : recursive-label ( word -- label/f )
recursive-state get at ; recursive-state get at ;
: inline? ( word -- ? )
dup "method" word-prop
[ method-generic inline? ] [ "inline" word-prop ] ?if ;
: local-recursive-state ( -- assoc ) : local-recursive-state ( -- assoc )
recursive-state get dup keys recursive-state get dup keys
[ dup word? [ "inline" word-prop ] when not ] find drop [ dup word? [ inline? ] when not ] find drop
[ head-slice ] when* ; [ head-slice ] when* ;
: inline-recursive-label ( word -- label/f ) : inline-recursive-label ( word -- label/f )
@ -20,24 +24,24 @@ IN: inference.backend
: recursive-quotation? ( quot -- ? ) : recursive-quotation? ( quot -- ? )
local-recursive-state [ first eq? ] with contains? ; local-recursive-state [ first eq? ] with contains? ;
TUPLE: inference-error rstate major? ; TUPLE: inference-error rstate type ;
M: inference-error compiler-warning? M: inference-error compiler-error-type
inference-error-major? not ; inference-error-type ;
: (inference-error) ( ... class important? -- * ) : (inference-error) ( ... class type -- * )
>r construct-boa r> >r construct-boa r>
recursive-state get { recursive-state get {
set-delegate set-delegate
set-inference-error-major? set-inference-error-type
set-inference-error-rstate set-inference-error-rstate
} \ inference-error construct throw ; inline } \ inference-error construct throw ; inline
: inference-error ( ... class -- * ) : inference-error ( ... class -- * )
t (inference-error) ; inline +error+ (inference-error) ; inline
: inference-warning ( ... class -- * ) : inference-warning ( ... class -- * )
f (inference-error) ; inline +warning+ (inference-error) ; inline
TUPLE: literal-expected ; TUPLE: literal-expected ;
@ -157,7 +161,7 @@ TUPLE: too-many-r> ;
meta-d get push-all ; meta-d get push-all ;
: if-inline ( word true false -- ) : if-inline ( word true false -- )
>r >r dup "inline" word-prop r> r> if ; inline >r >r dup inline? r> r> if ; inline
: consume/produce ( effect node -- ) : consume/produce ( effect node -- )
over effect-in over consume-values over effect-in over consume-values
@ -331,7 +335,7 @@ TUPLE: unbalanced-branches-error quots in out ;
#merge node, ; inline #merge node, ; inline
: make-call-node ( word effect -- ) : make-call-node ( word effect -- )
swap dup "inline" word-prop swap dup inline?
over dup recursive-label eq? not and [ over dup recursive-label eq? not and [
meta-d get clone -rot meta-d get clone -rot
recursive-label #call-label [ consume/produce ] keep recursive-label #call-label [ consume/produce ] keep
@ -366,6 +370,7 @@ TUPLE: effect-error word effect ;
init-inference init-inference
dependencies off dependencies off
dup word-def over dup infer-quot-recursive dup word-def over dup infer-quot-recursive
end-infer
finish-word finish-word
current-effect current-effect
] with-scope ] with-scope

View File

@ -263,3 +263,23 @@ cell-bits 32 = [
\ fixnum-shift inlined? \ fixnum-shift inlined?
] unit-test ] unit-test
] when ] when
[ t ] [
[ B{ 1 0 } *short 0 number= ]
\ number= inlined?
] unit-test
[ t ] [
[ B{ 1 0 } *short 0 { number number } declare number= ]
\ number= inlined?
] unit-test
[ t ] [
[ B{ 1 0 } *short 0 = ]
\ number= inlined?
] unit-test
[ t ] [
[ B{ 1 0 } *short dup number? [ 0 number= ] [ drop f ] if ]
\ number= inlined?
] unit-test

View File

@ -73,17 +73,27 @@ SYMBOL: value-intervals
! Current value --> class mapping ! Current value --> class mapping
SYMBOL: value-classes SYMBOL: value-classes
: value-interval* ( value -- interval/f )
value-intervals get at ;
: set-value-interval* ( interval value -- ) : set-value-interval* ( interval value -- )
value-intervals get set-at ; value-intervals get set-at ;
: intersect-value-interval ( interval value -- )
[ value-interval* interval-intersect ] keep
set-value-interval* ;
M: interval-constraint apply-constraint M: interval-constraint apply-constraint
dup interval-constraint-interval dup interval-constraint-interval
swap interval-constraint-value set-value-interval* ; swap interval-constraint-value intersect-value-interval ;
: set-class-interval ( class value -- ) : set-class-interval ( class value -- )
>r "interval" word-prop dup >r "interval" word-prop dup
[ r> set-value-interval* ] [ r> 2drop ] if ; [ r> set-value-interval* ] [ r> 2drop ] if ;
: value-class* ( value -- class )
value-classes get at object or ;
: set-value-class* ( class value -- ) : set-value-class* ( class value -- )
over [ over [
dup value-intervals get at [ dup value-intervals get at [
@ -93,9 +103,12 @@ M: interval-constraint apply-constraint
] when ] when
value-classes get set-at ; value-classes get set-at ;
: intersect-value-class ( class value -- )
[ value-class* class-and ] keep set-value-class* ;
M: class-constraint apply-constraint M: class-constraint apply-constraint
dup class-constraint-class dup class-constraint-class
swap class-constraint-value set-value-class* ; swap class-constraint-value intersect-value-class ;
: set-value-literal* ( literal value -- ) : set-value-literal* ( literal value -- )
over class over set-value-class* over class over set-value-class*
@ -127,16 +140,10 @@ M: literal-constraint constraint-satisfied?
dup literal-constraint-value value-literal* dup literal-constraint-value value-literal*
[ swap literal-constraint-literal eql? ] [ 2drop f ] if ; [ swap literal-constraint-literal eql? ] [ 2drop f ] if ;
: value-class* ( value -- class )
value-classes get at object or ;
M: class-constraint constraint-satisfied? M: class-constraint constraint-satisfied?
dup class-constraint-value value-class* dup class-constraint-value value-class*
swap class-constraint-class class< ; swap class-constraint-class class< ;
: value-interval* ( value -- interval/f )
value-intervals get at ;
M: pair apply-constraint M: pair apply-constraint
first2 2dup constraints get set-at first2 2dup constraints get set-at
constraint-satisfied? [ apply-constraint ] [ drop ] if ; constraint-satisfied? [ apply-constraint ] [ drop ] if ;
@ -159,13 +166,10 @@ M: pair constraint-satisfied?
2drop ; 2drop ;
: intersect-classes ( classes values -- ) : intersect-classes ( classes values -- )
[ [ value-class* class-and ] keep set-value-class* ] 2each ; [ intersect-value-class ] 2each ;
: intersect-intervals ( intervals values -- ) : intersect-intervals ( intervals values -- )
[ [ intersect-value-interval ] 2each ;
[ value-interval* interval-intersect ] keep
set-value-interval*
] 2each ;
: predicate-constraints ( class #call -- ) : predicate-constraints ( class #call -- )
[ [
@ -181,20 +185,14 @@ M: pair constraint-satisfied?
[ swap predicate-constraints ] [ 2drop ] if [ swap predicate-constraints ] [ 2drop ] if
] if* ; ] if* ;
: default-output-classes ( word -- classes )
"inferred-effect" word-prop {
{ [ dup not ] [ drop f ] }
{ [ dup effect-out [ class? ] all? not ] [ drop f ] }
{ [ t ] [ effect-out ] }
} cond ;
: compute-output-classes ( node word -- classes intervals ) : compute-output-classes ( node word -- classes intervals )
dup node-param "output-classes" word-prop dup dup node-param "output-classes" word-prop
[ call ] [ 2drop f f ] if ; dup [ call ] [ 2drop f f ] if ;
: output-classes ( node -- classes intervals ) : output-classes ( node -- classes intervals )
dup compute-output-classes dup compute-output-classes >r
>r [ ] [ node-param default-output-classes ] ?if r> ; [ ] [ node-param "default-output-classes" word-prop ] ?if
r> ;
M: #call infer-classes-before M: #call infer-classes-before
dup compute-constraints dup compute-constraints
@ -220,7 +218,8 @@ M: #dispatch child-constraints
] make-constraints ; ] make-constraints ;
M: #declare infer-classes-before M: #declare infer-classes-before
dup node-param swap node-in-d [ set-value-class* ] 2each ; dup node-param swap node-in-d
[ intersect-value-class ] 2each ;
DEFER: (infer-classes) DEFER: (infer-classes)

View File

@ -256,6 +256,28 @@ SYMBOL: node-stack
] iterate-nodes drop ] iterate-nodes drop
] with-node-iterator ; inline ] with-node-iterator ; inline
: change-children ( node quot -- )
over [
>r dup node-children dup r>
[ map swap set-node-children ] curry
[ 2drop ] if
] [
2drop
] if ; inline
: (transform-nodes) ( prev node quot -- )
dup >r call dup [
dup rot set-node-successor
dup node-successor r> (transform-nodes)
] [
r> drop f swap set-node-successor drop
] if ; inline
: transform-nodes ( node quot -- new-node )
over [
[ call dup dup node-successor ] keep (transform-nodes)
] [ drop ] if ; inline
: node-literal? ( node value -- ? ) : node-literal? ( node value -- ? )
dup value? >r swap node-literals key? r> or ; dup value? >r swap node-literals key? r> or ;

View File

@ -73,6 +73,12 @@ $nl
{ $subsection infer-quot-value } { $subsection infer-quot-value }
"The " { $vocab-link "macros" } " vocabulary defines some nice syntax sugar which makes compiler transforms easier to work with." ; "The " { $vocab-link "macros" } " vocabulary defines some nice syntax sugar which makes compiler transforms easier to work with." ;
ARTICLE: "dataflow-graphs" "Inspecting the dataflow graph"
"The dataflow graph used by " { $link "compiler" } " can be obtained:"
{ $subsection dataflow }
"The " { $vocab-link "optimizer.debugger" } " tool prints the dataflow graph in human readable form."
$nl ;
ARTICLE: "inference" "Stack effect inference" ARTICLE: "inference" "Stack effect inference"
"The stack effect inference tool is used to check correctness of code before it is run. It is also used by the compiler to build a dataflow graph on which optimizations can be performed. Only words for which a stack effect can be inferred will compile." "The stack effect inference tool is used to check correctness of code before it is run. It is also used by the compiler to build a dataflow graph on which optimizations can be performed. Only words for which a stack effect can be inferred will compile."
$nl $nl
@ -80,14 +86,15 @@ $nl
{ $subsection infer. } { $subsection infer. }
"Instead of printing the inferred information, it can be returned as objects on the stack:" "Instead of printing the inferred information, it can be returned as objects on the stack:"
{ $subsection infer } { $subsection infer }
"The dataflow graph used by " { $link "compiler" } " can be obtained:" "Static stack effect inference can be combined with unit tests; see " { $link "tools.test.write" } "."
{ $subsection dataflow } $nl
"The following articles describe the implementation of the stack effect inference algorithm:" "The following articles describe the implementation of the stack effect inference algorithm:"
{ $subsection "inference-simple" } { $subsection "inference-simple" }
{ $subsection "inference-combinators" } { $subsection "inference-combinators" }
{ $subsection "inference-branches" } { $subsection "inference-branches" }
{ $subsection "inference-recursive" } { $subsection "inference-recursive" }
{ $subsection "inference-limitations" } { $subsection "inference-limitations" }
{ $subsection "dataflow-graphs" }
{ $subsection "compiler-transforms" } ; { $subsection "compiler-transforms" } ;
ABOUT: "inference" ABOUT: "inference"

View File

@ -4,23 +4,23 @@ math.parser math.private namespaces namespaces.private parser
sequences strings vectors words quotations effects tools.test sequences strings vectors words quotations effects tools.test
continuations generic.standard sorting assocs definitions continuations generic.standard sorting assocs definitions
prettyprint io inspector tuples classes.union classes.predicate prettyprint io inspector tuples classes.union classes.predicate
debugger threads.private io.streams.string combinators.private debugger threads.private io.streams.string io.timeouts
tools.test.inference ; sequences.private ;
IN: temporary IN: temporary
{ 0 2 } [ 2 "Hello" ] unit-test-effect { 0 2 } [ 2 "Hello" ] must-infer-as
{ 1 2 } [ dup ] unit-test-effect { 1 2 } [ dup ] must-infer-as
{ 1 2 } [ [ dup ] call ] unit-test-effect { 1 2 } [ [ dup ] call ] must-infer-as
[ [ call ] infer ] unit-test-fails [ [ call ] infer ] must-fail
{ 2 4 } [ 2dup ] unit-test-effect { 2 4 } [ 2dup ] must-infer-as
{ 1 0 } [ [ ] [ ] if ] unit-test-effect { 1 0 } [ [ ] [ ] if ] must-infer-as
[ [ if ] infer ] unit-test-fails [ [ if ] infer ] must-fail
[ [ [ ] if ] infer ] unit-test-fails [ [ [ ] if ] infer ] must-fail
[ [ [ 2 ] [ ] if ] infer ] unit-test-fails [ [ [ 2 ] [ ] if ] infer ] must-fail
{ 4 3 } [ [ rot ] [ -rot ] if ] unit-test-effect { 4 3 } [ [ rot ] [ -rot ] if ] must-infer-as
{ 4 3 } [ { 4 3 } [
[ [
@ -28,21 +28,21 @@ IN: temporary
] [ ] [
-rot -rot
] if ] if
] unit-test-effect ] must-infer-as
{ 1 1 } [ dup [ ] when ] unit-test-effect { 1 1 } [ dup [ ] when ] must-infer-as
{ 1 1 } [ dup [ dup fixnum* ] when ] unit-test-effect { 1 1 } [ dup [ dup fixnum* ] when ] must-infer-as
{ 2 1 } [ [ dup fixnum* ] when ] unit-test-effect { 2 1 } [ [ dup fixnum* ] when ] must-infer-as
{ 1 0 } [ [ drop ] when* ] unit-test-effect { 1 0 } [ [ drop ] when* ] must-infer-as
{ 1 1 } [ [ { { [ ] } } ] unless* ] unit-test-effect { 1 1 } [ [ { { [ ] } } ] unless* ] must-infer-as
{ 0 1 } { 0 1 }
[ [ 2 2 fixnum+ ] dup [ ] when call ] unit-test-effect [ [ 2 2 fixnum+ ] dup [ ] when call ] must-infer-as
[ [
[ [ [ 2 2 fixnum+ ] ] [ [ 2 2 fixnum* ] ] if call ] infer [ [ [ 2 2 fixnum+ ] ] [ [ 2 2 fixnum* ] ] if call ] infer
] unit-test-fails ] must-fail
! Test inference of termination of control flow ! Test inference of termination of control flow
: termination-test-1 : termination-test-1
@ -50,37 +50,37 @@ IN: temporary
: termination-test-2 [ termination-test-1 ] [ 3 ] if ; : termination-test-2 [ termination-test-1 ] [ 3 ] if ;
{ 1 1 } [ termination-test-2 ] unit-test-effect { 1 1 } [ termination-test-2 ] must-infer-as
: infinite-loop infinite-loop ; : infinite-loop infinite-loop ;
[ [ infinite-loop ] infer ] unit-test-fails [ [ infinite-loop ] infer ] must-fail
: no-base-case-1 dup [ no-base-case-1 ] [ no-base-case-1 ] if ; : no-base-case-1 dup [ no-base-case-1 ] [ no-base-case-1 ] if ;
[ [ no-base-case-1 ] infer ] unit-test-fails [ [ no-base-case-1 ] infer ] must-fail
: simple-recursion-1 ( obj -- obj ) : simple-recursion-1 ( obj -- obj )
dup [ simple-recursion-1 ] [ ] if ; dup [ simple-recursion-1 ] [ ] if ;
{ 1 1 } [ simple-recursion-1 ] unit-test-effect { 1 1 } [ simple-recursion-1 ] must-infer-as
: simple-recursion-2 ( obj -- obj ) : simple-recursion-2 ( obj -- obj )
dup [ ] [ simple-recursion-2 ] if ; dup [ ] [ simple-recursion-2 ] if ;
{ 1 1 } [ simple-recursion-2 ] unit-test-effect { 1 1 } [ simple-recursion-2 ] must-infer-as
: bad-recursion-2 ( obj -- obj ) : bad-recursion-2 ( obj -- obj )
dup [ dup first swap second bad-recursion-2 ] [ ] if ; dup [ dup first swap second bad-recursion-2 ] [ ] if ;
[ [ bad-recursion-2 ] infer ] unit-test-fails [ [ bad-recursion-2 ] infer ] must-fail
: funny-recursion ( obj -- obj ) : funny-recursion ( obj -- obj )
dup [ funny-recursion 1 ] [ 2 ] if drop ; dup [ funny-recursion 1 ] [ 2 ] if drop ;
{ 1 1 } [ funny-recursion ] unit-test-effect { 1 1 } [ funny-recursion ] must-infer-as
! Simple combinators ! Simple combinators
{ 1 2 } [ [ first ] keep second ] unit-test-effect { 1 2 } [ [ first ] keep second ] must-infer-as
! Mutual recursion ! Mutual recursion
DEFER: foe DEFER: foe
@ -103,8 +103,8 @@ DEFER: foe
2drop f 2drop f
] if ; ] if ;
{ 2 1 } [ fie ] unit-test-effect { 2 1 } [ fie ] must-infer-as
{ 2 1 } [ foe ] unit-test-effect { 2 1 } [ foe ] must-infer-as
: nested-when ( -- ) : nested-when ( -- )
t [ t [
@ -113,7 +113,7 @@ DEFER: foe
] when ] when
] when ; ] when ;
{ 0 0 } [ nested-when ] unit-test-effect { 0 0 } [ nested-when ] must-infer-as
: nested-when* ( obj -- ) : nested-when* ( obj -- )
[ [
@ -122,11 +122,11 @@ DEFER: foe
] when* ] when*
] when* ; ] when* ;
{ 1 0 } [ nested-when* ] unit-test-effect { 1 0 } [ nested-when* ] must-infer-as
SYMBOL: sym-test SYMBOL: sym-test
{ 0 1 } [ sym-test ] unit-test-effect { 0 1 } [ sym-test ] must-infer-as
: terminator-branch : terminator-branch
dup [ dup [
@ -135,7 +135,7 @@ SYMBOL: sym-test
"foo" throw "foo" throw
] if ; ] if ;
{ 1 1 } [ terminator-branch ] unit-test-effect { 1 1 } [ terminator-branch ] must-infer-as
: recursive-terminator ( obj -- ) : recursive-terminator ( obj -- )
dup [ dup [
@ -144,7 +144,7 @@ SYMBOL: sym-test
"Hi" throw "Hi" throw
] if ; ] if ;
{ 1 0 } [ recursive-terminator ] unit-test-effect { 1 0 } [ recursive-terminator ] must-infer-as
GENERIC: potential-hang ( obj -- obj ) GENERIC: potential-hang ( obj -- obj )
M: fixnum potential-hang dup [ potential-hang ] when ; M: fixnum potential-hang dup [ potential-hang ] when ;
@ -157,24 +157,24 @@ M: funny-cons iterate funny-cons-cdr iterate ;
M: f iterate drop ; M: f iterate drop ;
M: real iterate drop ; M: real iterate drop ;
{ 1 0 } [ iterate ] unit-test-effect { 1 0 } [ iterate ] must-infer-as
! Regression ! Regression
: cat ( obj -- * ) dup [ throw ] [ throw ] if ; : cat ( obj -- * ) dup [ throw ] [ throw ] if ;
: dog ( a b c -- ) dup [ cat ] [ 3drop ] if ; : dog ( a b c -- ) dup [ cat ] [ 3drop ] if ;
{ 3 0 } [ dog ] unit-test-effect { 3 0 } [ dog ] must-infer-as
! Regression ! Regression
DEFER: monkey DEFER: monkey
: friend ( a b c -- ) dup [ friend ] [ monkey ] if ; : friend ( a b c -- ) dup [ friend ] [ monkey ] if ;
: monkey ( a b c -- ) dup [ 3drop ] [ friend ] if ; : monkey ( a b c -- ) dup [ 3drop ] [ friend ] if ;
{ 3 0 } [ friend ] unit-test-effect { 3 0 } [ friend ] must-infer-as
! Regression -- same as above but we infer the second word first ! Regression -- same as above but we infer the second word first
DEFER: blah2 DEFER: blah2
: blah ( a b c -- ) dup [ blah ] [ blah2 ] if ; : blah ( a b c -- ) dup [ blah ] [ blah2 ] if ;
: blah2 ( a b c -- ) dup [ blah ] [ 3drop ] if ; : blah2 ( a b c -- ) dup [ blah ] [ 3drop ] if ;
{ 3 0 } [ blah2 ] unit-test-effect { 3 0 } [ blah2 ] must-infer-as
! Regression ! Regression
DEFER: blah4 DEFER: blah4
@ -182,7 +182,7 @@ DEFER: blah4
dup [ blah3 ] [ dup [ blah4 ] [ blah3 ] if ] if ; dup [ blah3 ] [ dup [ blah4 ] [ blah3 ] if ] if ;
: blah4 ( a b c -- ) : blah4 ( a b c -- )
dup [ blah4 ] [ dup [ 3drop ] [ blah3 ] if ] if ; dup [ blah4 ] [ dup [ 3drop ] [ blah3 ] if ] if ;
{ 3 0 } [ blah4 ] unit-test-effect { 3 0 } [ blah4 ] must-infer-as
! Regression ! Regression
: bad-combinator ( obj quot -- ) : bad-combinator ( obj quot -- )
@ -192,14 +192,14 @@ DEFER: blah4
[ swap slip ] keep swap bad-combinator [ swap slip ] keep swap bad-combinator
] if ; inline ] if ; inline
[ [ [ 1 ] [ ] bad-combinator ] infer ] unit-test-fails [ [ [ 1 ] [ ] bad-combinator ] infer ] must-fail
! Regression ! Regression
: bad-input# : bad-input#
dup string? [ 2array throw ] unless dup string? [ 2array throw ] unless
over string? [ 2array throw ] unless ; over string? [ 2array throw ] unless ;
{ 2 2 } [ bad-input# ] unit-test-effect { 2 2 } [ bad-input# ] must-infer-as
! Regression ! Regression
@ -207,18 +207,18 @@ DEFER: blah4
DEFER: do-crap DEFER: do-crap
: more-crap ( obj -- ) dup [ drop ] [ dup do-crap call ] if ; : more-crap ( obj -- ) dup [ drop ] [ dup do-crap call ] if ;
: do-crap ( obj -- ) dup [ more-crap ] [ do-crap ] if ; : do-crap ( obj -- ) dup [ more-crap ] [ do-crap ] if ;
[ [ do-crap ] infer ] unit-test-fails [ [ do-crap ] infer ] must-fail
! This one does not ! This one does not
DEFER: do-crap* DEFER: do-crap*
: more-crap* ( obj -- ) dup [ drop ] [ dup do-crap* call ] if ; : more-crap* ( obj -- ) dup [ drop ] [ dup do-crap* call ] if ;
: do-crap* ( obj -- ) dup [ do-crap* ] [ more-crap* ] if ; : do-crap* ( obj -- ) dup [ do-crap* ] [ more-crap* ] if ;
[ [ do-crap* ] infer ] unit-test-fails [ [ do-crap* ] infer ] must-fail
! Regression ! Regression
: too-deep ( a b -- c ) : too-deep ( a b -- c )
dup [ drop ] [ 2dup too-deep too-deep * ] if ; inline dup [ drop ] [ 2dup too-deep too-deep * ] if ; inline
{ 2 1 } [ too-deep ] unit-test-effect { 2 1 } [ too-deep ] must-infer-as
! Error reporting is wrong ! Error reporting is wrong
MATH: xyz MATH: xyz
@ -226,7 +226,7 @@ M: fixnum xyz 2array ;
M: float xyz M: float xyz
[ 3 ] 2apply swapd >r 2array swap r> 2array swap ; [ 3 ] 2apply swapd >r 2array swap r> 2array swap ;
[ t ] [ [ [ xyz ] infer ] catch inference-error? ] unit-test [ [ xyz ] infer ] [ inference-error? ] must-fail-with
! Doug Coleman discovered this one while working on the ! Doug Coleman discovered this one while working on the
! calendar library ! calendar library
@ -258,17 +258,17 @@ DEFER: C
[ dup B C ] [ dup B C ]
} dispatch ; } dispatch ;
{ 1 0 } [ A ] unit-test-effect { 1 0 } [ A ] must-infer-as
{ 1 0 } [ B ] unit-test-effect { 1 0 } [ B ] must-infer-as
{ 1 0 } [ C ] unit-test-effect { 1 0 } [ C ] must-infer-as
! I found this bug by thinking hard about the previous one ! I found this bug by thinking hard about the previous one
DEFER: Y DEFER: Y
: X ( a b -- c d ) dup [ swap Y ] [ ] if ; : X ( a b -- c d ) dup [ swap Y ] [ ] if ;
: Y ( a b -- c d ) X ; : Y ( a b -- c d ) X ;
{ 2 2 } [ X ] unit-test-effect { 2 2 } [ X ] must-infer-as
{ 2 2 } [ Y ] unit-test-effect { 2 2 } [ Y ] must-infer-as
! This one comes from UI code ! This one comes from UI code
DEFER: #1 DEFER: #1
@ -277,78 +277,66 @@ DEFER: #1
: #4 ( a -- ) dup [ drop ] [ dup #4 dup #3 call ] if ; : #4 ( a -- ) dup [ drop ] [ dup #4 dup #3 call ] if ;
: #1 ( a -- ) dup [ dup #4 dup #3 ] [ ] if drop ; : #1 ( a -- ) dup [ dup #4 dup #3 ] [ ] if drop ;
[ \ #4 word-def infer ] unit-test-fails [ \ #4 word-def infer ] must-fail
[ [ #1 ] infer ] unit-test-fails [ [ #1 ] infer ] must-fail
! Similar ! Similar
DEFER: bar DEFER: bar
: foo ( a b -- c d ) dup [ 2drop f f bar ] [ ] if ; : foo ( a b -- c d ) dup [ 2drop f f bar ] [ ] if ;
: bar ( a b -- ) [ 2 2 + ] t foo drop call drop ; : bar ( a b -- ) [ 2 2 + ] t foo drop call drop ;
[ [ foo ] infer ] unit-test-fails [ [ foo ] infer ] must-fail
[ 1234 infer ] unit-test-fails [ 1234 infer ] must-fail
! This used to hang ! This used to hang
[ t ] [ [ [ [ dup call ] dup call ] infer ]
[ [ [ dup call ] dup call ] infer ] catch [ inference-error? ] must-fail-with
inference-error?
] unit-test
: m dup call ; inline : m dup call ; inline
[ t ] [ [ [ [ m ] m ] infer ] [ inference-error? ] must-fail-with
[ [ [ m ] m ] infer ] catch inference-error?
] unit-test
: m' dup curry call ; inline : m' dup curry call ; inline
[ t ] [ [ [ [ m' ] m' ] infer ] [ inference-error? ] must-fail-with
[ [ [ m' ] m' ] infer ] catch inference-error?
] unit-test
: m'' [ dup curry ] ; inline : m'' [ dup curry ] ; inline
: m''' m'' call call ; inline : m''' m'' call call ; inline
[ t ] [ [ [ [ m''' ] m''' ] infer ] [ inference-error? ] must-fail-with
[ [ [ m''' ] m''' ] infer ] catch inference-error?
] unit-test
: m-if t over if ; inline : m-if t over if ; inline
[ t ] [ [ [ [ m-if ] m-if ] infer ] [ inference-error? ] must-fail-with
[ [ [ m-if ] m-if ] infer ] catch inference-error?
] unit-test
! This doesn't hang but it's also an example of the ! This doesn't hang but it's also an example of the
! undedicable case ! undedicable case
[ t ] [ [ [ [ [ drop 3 ] swap call ] dup call ] infer ]
[ [ [ [ drop 3 ] swap call ] dup call ] infer ] catch [ inference-error? ] must-fail-with
inference-error?
] unit-test
! This form should not have a stack effect ! This form should not have a stack effect
: bad-recursion-1 ( a -- b ) : bad-recursion-1 ( a -- b )
dup [ drop bad-recursion-1 5 ] [ ] if ; dup [ drop bad-recursion-1 5 ] [ ] if ;
[ [ bad-recursion-1 ] infer ] unit-test-fails [ [ bad-recursion-1 ] infer ] must-fail
: bad-bin ( a b -- ) 5 [ 5 bad-bin bad-bin 5 ] [ 2drop ] if ; : bad-bin ( a b -- ) 5 [ 5 bad-bin bad-bin 5 ] [ 2drop ] if ;
[ [ bad-bin ] infer ] unit-test-fails [ [ bad-bin ] infer ] must-fail
[ t ] [ [ [ r> ] infer ] catch inference-error? ] unit-test [ [ r> ] infer ] [ inference-error? ] must-fail-with
! Regression ! Regression
[ t ] [ [ [ get-slots ] infer ] catch inference-error? ] unit-test [ [ get-slots ] infer ] [ inference-error? ] must-fail-with
! Test some curry stuff ! Test some curry stuff
{ 1 1 } [ 3 [ ] curry 4 [ ] curry if ] unit-test-effect { 1 1 } [ 3 [ ] curry 4 [ ] curry if ] must-infer-as
{ 2 1 } [ [ ] curry 4 [ ] curry if ] unit-test-effect { 2 1 } [ [ ] curry 4 [ ] curry if ] must-infer-as
[ [ 3 [ ] curry 1 2 [ ] 2curry if ] infer ] unit-test-fails [ [ 3 [ ] curry 1 2 [ ] 2curry if ] infer ] must-fail
! Test number protocol ! Test number protocol
\ bitor must-infer \ bitor must-infer
@ -393,7 +381,7 @@ DEFER: bar
\ assoc-like must-infer \ assoc-like must-infer
\ assoc-clone-like must-infer \ assoc-clone-like must-infer
\ >alist must-infer \ >alist must-infer
{ 1 3 } [ [ 2drop f ] assoc-find ] unit-test-effect { 1 3 } [ [ 2drop f ] assoc-find ] must-infer-as
! Test some random library words ! Test some random library words
\ 1quotation must-infer \ 1quotation must-infer
@ -416,10 +404,10 @@ DEFER: bar
\ define-predicate-class must-infer \ define-predicate-class must-infer
! Test words with continuations ! Test words with continuations
{ 0 0 } [ [ drop ] callcc0 ] unit-test-effect { 0 0 } [ [ drop ] callcc0 ] must-infer-as
{ 0 1 } [ [ 4 swap continue-with ] callcc1 ] unit-test-effect { 0 1 } [ [ 4 swap continue-with ] callcc1 ] must-infer-as
{ 2 1 } [ [ + ] [ ] [ ] cleanup ] unit-test-effect { 2 1 } [ [ + ] [ ] [ ] cleanup ] must-infer-as
{ 2 1 } [ [ + ] [ 3drop 0 ] recover ] unit-test-effect { 2 1 } [ [ + ] [ 3drop 0 ] recover ] must-infer-as
\ dispose must-infer \ dispose must-infer
@ -459,16 +447,16 @@ DEFER: bar
: fooxxx ( a b -- c ) over [ foo ] when ; inline : fooxxx ( a b -- c ) over [ foo ] when ; inline
: barxxx fooxxx ; : barxxx fooxxx ;
[ [ barxxx ] infer ] unit-test-fails [ [ barxxx ] infer ] must-fail
! A typo ! A typo
{ 1 0 } [ { [ ] } dispatch ] unit-test-effect { 1 0 } [ { [ ] } dispatch ] must-infer-as
DEFER: inline-recursive-2 DEFER: inline-recursive-2
: inline-recursive-1 ( -- ) inline-recursive-2 ; : inline-recursive-1 ( -- ) inline-recursive-2 ;
: inline-recursive-2 ( -- ) inline-recursive-1 ; : inline-recursive-2 ( -- ) inline-recursive-1 ;
{ 0 0 } [ inline-recursive-1 ] unit-test-effect { 0 0 } [ inline-recursive-1 ] must-infer-as
! Hooks ! Hooks
SYMBOL: my-var SYMBOL: my-var
@ -477,22 +465,22 @@ HOOK: my-hook my-var ( -- x )
M: integer my-hook "an integer" ; M: integer my-hook "an integer" ;
M: string my-hook "a string" ; M: string my-hook "a string" ;
{ 0 1 } [ my-hook ] unit-test-effect { 0 1 } [ my-hook ] must-infer-as
DEFER: deferred-word DEFER: deferred-word
: calls-deferred-word [ deferred-word ] [ 3 ] if ; : calls-deferred-word [ deferred-word ] [ 3 ] if ;
{ 1 1 } [ calls-deferred-word ] unit-test-effect { 1 1 } [ calls-deferred-word ] must-infer-as
USE: inference.dataflow USE: inference.dataflow
{ 1 0 } [ [ iterate-next ] iterate-nodes ] unit-test-effect { 1 0 } [ [ iterate-next ] iterate-nodes ] must-infer-as
{ 1 0 } { 1 0 }
[ [
[ [ iterate-next ] iterate-nodes ] with-node-iterator [ [ iterate-next ] iterate-nodes ] with-node-iterator
] unit-test-effect ] must-infer-as
: nilpotent ( quot -- ) : nilpotent ( quot -- )
t [ [ call ] keep nilpotent ] [ drop ] if ; inline t [ [ call ] keep nilpotent ] [ drop ] if ; inline
@ -502,11 +490,11 @@ USE: inference.dataflow
{ 0 1 } { 0 1 }
[ [ ] [ call ] keep [ [ call ] keep ] nilpotent ] [ [ ] [ call ] keep [ [ call ] keep ] nilpotent ]
unit-test-effect must-infer-as
{ 0 0 } [ [ ] semisimple ] unit-test-effect { 0 0 } [ [ ] semisimple ] must-infer-as
{ 1 0 } [ [ drop ] each-node ] unit-test-effect { 1 0 } [ [ drop ] each-node ] must-infer-as
DEFER: an-inline-word DEFER: an-inline-word
@ -522,9 +510,9 @@ DEFER: an-inline-word
: an-inline-word ( obj quot -- ) : an-inline-word ( obj quot -- )
>r normal-word r> call ; inline >r normal-word r> call ; inline
{ 1 1 } [ [ 3 * ] an-inline-word ] unit-test-effect { 1 1 } [ [ 3 * ] an-inline-word ] must-infer-as
{ 0 1 } [ [ 2 ] [ 2 ] [ + ] compose compose call ] unit-test-effect { 0 1 } [ [ 2 ] [ 2 ] [ + ] compose compose call ] must-infer-as
TUPLE: custom-error ; TUPLE: custom-error ;
@ -548,4 +536,9 @@ TUPLE: custom-error ;
! This was a false trigger of the undecidable quotation ! This was a false trigger of the undecidable quotation
! recursion bug ! recursion bug
{ 2 1 } [ find-last-sep ] unit-test-effect { 2 1 } [ find-last-sep ] must-infer-as
! Regression
: missing->r-check >r ;
[ [ missing->r-check ] infer ] must-fail

View File

@ -1,9 +1,9 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: inference.backend inference.state inference.dataflow USING: inference.backend inference.state inference.dataflow
inference.known-words inference.transforms inference.errors inference.known-words inference.transforms inference.errors
sequences prettyprint io effects kernel namespaces quotations kernel io effects namespaces sequences quotations vocabs
words vocabs ; generic words ;
IN: inference IN: inference
GENERIC: infer ( quot -- effect ) GENERIC: infer ( quot -- effect )
@ -28,4 +28,7 @@ M: callable dataflow-with
] with-infer nip ; ] with-infer nip ;
: forget-errors ( -- ) : forget-errors ( -- )
all-words [ f "no-effect" set-word-prop ] each ; all-words [
dup subwords [ f "no-effect" set-word-prop ] each
f "no-effect" set-word-prop
] each ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2004, 2008 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.accessors arrays bit-arrays byte-arrays USING: alien alien.accessors arrays bit-arrays byte-arrays
classes combinators.private continuations.private effects classes sequences.private continuations.private effects
float-arrays generic hashtables hashtables.private float-arrays generic hashtables hashtables.private
inference.state inference.backend inference.dataflow io inference.state inference.backend inference.dataflow io
io.backend io.files io.files.private io.streams.c kernel io.backend io.files io.files.private io.streams.c kernel
@ -126,15 +126,11 @@ M: object infer-call
pop-d pop-d swap <curried> push-d pop-d pop-d swap <curried> push-d
] "infer" set-word-prop ] "infer" set-word-prop
\ curry { object object } { curry } <effect> "inferred-effect" set-word-prop
\ compose [ \ compose [
2 ensure-values 2 ensure-values
pop-d pop-d swap <composed> push-d pop-d pop-d swap <composed> push-d
] "infer" set-word-prop ] "infer" set-word-prop
\ compose { object object } { curry } <effect> "inferred-effect" set-word-prop
! Variadic tuple constructor ! Variadic tuple constructor
\ <tuple-boa> [ \ <tuple-boa> [
\ <tuple-boa> \ <tuple-boa>
@ -142,440 +138,461 @@ M: object infer-call
make-call-node make-call-node
] "infer" set-word-prop ] "infer" set-word-prop
! We need this for default-output-classes
\ <tuple-boa> 2 { tuple } <effect> "inferred-effect" set-word-prop
! Non-standard control flow ! Non-standard control flow
\ (throw) { callable } { } <effect> \ (throw) [
t over set-effect-terminated? \ (throw)
"inferred-effect" set-word-prop peek-d value-literal 2 + { } <effect>
t over set-effect-terminated?
make-call-node
] "infer" set-word-prop
: set-primitive-effect ( word effect -- )
2dup effect-out "default-output-classes" set-word-prop
dupd [ make-call-node ] 2curry "infer" set-word-prop ;
! Stack effects for all primitives ! Stack effects for all primitives
\ fixnum< { fixnum fixnum } { object } <effect> "inferred-effect" set-word-prop \ fixnum< { fixnum fixnum } { object } <effect> set-primitive-effect
\ fixnum< make-foldable \ fixnum< make-foldable
\ fixnum<= { fixnum fixnum } { object } <effect> "inferred-effect" set-word-prop \ fixnum<= { fixnum fixnum } { object } <effect> set-primitive-effect
\ fixnum<= make-foldable \ fixnum<= make-foldable
\ fixnum> { fixnum fixnum } { object } <effect> "inferred-effect" set-word-prop \ fixnum> { fixnum fixnum } { object } <effect> set-primitive-effect
\ fixnum> make-foldable \ fixnum> make-foldable
\ fixnum>= { fixnum fixnum } { object } <effect> "inferred-effect" set-word-prop \ fixnum>= { fixnum fixnum } { object } <effect> set-primitive-effect
\ fixnum>= make-foldable \ fixnum>= make-foldable
\ eq? { object object } { object } <effect> "inferred-effect" set-word-prop \ eq? { object object } { object } <effect> set-primitive-effect
\ eq? make-foldable \ eq? make-foldable
\ rehash-string { string } { } <effect> "inferred-effect" set-word-prop \ rehash-string { string } { } <effect> set-primitive-effect
\ bignum>fixnum { bignum } { fixnum } <effect> "inferred-effect" set-word-prop \ bignum>fixnum { bignum } { fixnum } <effect> set-primitive-effect
\ bignum>fixnum make-foldable \ bignum>fixnum make-foldable
\ float>fixnum { float } { fixnum } <effect> "inferred-effect" set-word-prop \ float>fixnum { float } { fixnum } <effect> set-primitive-effect
\ bignum>fixnum make-foldable \ bignum>fixnum make-foldable
\ fixnum>bignum { fixnum } { bignum } <effect> "inferred-effect" set-word-prop \ fixnum>bignum { fixnum } { bignum } <effect> set-primitive-effect
\ fixnum>bignum make-foldable \ fixnum>bignum make-foldable
\ float>bignum { float } { bignum } <effect> "inferred-effect" set-word-prop \ float>bignum { float } { bignum } <effect> set-primitive-effect
\ float>bignum make-foldable \ float>bignum make-foldable
\ fixnum>float { fixnum } { float } <effect> "inferred-effect" set-word-prop \ fixnum>float { fixnum } { float } <effect> set-primitive-effect
\ fixnum>float make-foldable \ fixnum>float make-foldable
\ bignum>float { bignum } { float } <effect> "inferred-effect" set-word-prop \ bignum>float { bignum } { float } <effect> set-primitive-effect
\ bignum>float make-foldable \ bignum>float make-foldable
\ <ratio> { integer integer } { ratio } <effect> "inferred-effect" set-word-prop \ <ratio> { integer integer } { ratio } <effect> set-primitive-effect
\ <ratio> make-foldable \ <ratio> make-foldable
\ string>float { string } { float } <effect> "inferred-effect" set-word-prop \ string>float { string } { float } <effect> set-primitive-effect
\ string>float make-foldable \ string>float make-foldable
\ float>string { float } { string } <effect> "inferred-effect" set-word-prop \ float>string { float } { string } <effect> set-primitive-effect
\ float>string make-foldable \ float>string make-foldable
\ float>bits { real } { integer } <effect> "inferred-effect" set-word-prop \ float>bits { real } { integer } <effect> set-primitive-effect
\ float>bits make-foldable \ float>bits make-foldable
\ double>bits { real } { integer } <effect> "inferred-effect" set-word-prop \ double>bits { real } { integer } <effect> set-primitive-effect
\ double>bits make-foldable \ double>bits make-foldable
\ bits>float { integer } { float } <effect> "inferred-effect" set-word-prop \ bits>float { integer } { float } <effect> set-primitive-effect
\ bits>float make-foldable \ bits>float make-foldable
\ bits>double { integer } { float } <effect> "inferred-effect" set-word-prop \ bits>double { integer } { float } <effect> set-primitive-effect
\ bits>double make-foldable \ bits>double make-foldable
\ <complex> { real real } { complex } <effect> "inferred-effect" set-word-prop \ <complex> { real real } { complex } <effect> set-primitive-effect
\ <complex> make-foldable \ <complex> make-foldable
\ fixnum+ { fixnum fixnum } { integer } <effect> "inferred-effect" set-word-prop \ fixnum+ { fixnum fixnum } { integer } <effect> set-primitive-effect
\ fixnum+ make-foldable \ fixnum+ make-foldable
\ fixnum+fast { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum+fast { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum+fast make-foldable \ fixnum+fast make-foldable
\ fixnum- { fixnum fixnum } { integer } <effect> "inferred-effect" set-word-prop \ fixnum- { fixnum fixnum } { integer } <effect> set-primitive-effect
\ fixnum- make-foldable \ fixnum- make-foldable
\ fixnum-fast { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum-fast { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum-fast make-foldable \ fixnum-fast make-foldable
\ fixnum* { fixnum fixnum } { integer } <effect> "inferred-effect" set-word-prop \ fixnum* { fixnum fixnum } { integer } <effect> set-primitive-effect
\ fixnum* make-foldable \ fixnum* make-foldable
\ fixnum*fast { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum*fast { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum*fast make-foldable \ fixnum*fast make-foldable
\ fixnum/i { fixnum fixnum } { integer } <effect> "inferred-effect" set-word-prop \ fixnum/i { fixnum fixnum } { integer } <effect> set-primitive-effect
\ fixnum/i make-foldable \ fixnum/i make-foldable
\ fixnum-mod { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum-mod { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum-mod make-foldable \ fixnum-mod make-foldable
\ fixnum/mod { fixnum fixnum } { integer fixnum } <effect> "inferred-effect" set-word-prop \ fixnum/mod { fixnum fixnum } { integer fixnum } <effect> set-primitive-effect
\ fixnum/mod make-foldable \ fixnum/mod make-foldable
\ fixnum-bitand { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum-bitand { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum-bitand make-foldable \ fixnum-bitand make-foldable
\ fixnum-bitor { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum-bitor { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum-bitor make-foldable \ fixnum-bitor make-foldable
\ fixnum-bitxor { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum-bitxor { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum-bitxor make-foldable \ fixnum-bitxor make-foldable
\ fixnum-bitnot { fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum-bitnot { fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum-bitnot make-foldable \ fixnum-bitnot make-foldable
\ fixnum-shift { fixnum fixnum } { integer } <effect> "inferred-effect" set-word-prop \ fixnum-shift { fixnum fixnum } { integer } <effect> set-primitive-effect
\ fixnum-shift make-foldable \ fixnum-shift make-foldable
\ fixnum-shift-fast { fixnum fixnum } { fixnum } <effect> "inferred-effect" set-word-prop \ fixnum-shift-fast { fixnum fixnum } { fixnum } <effect> set-primitive-effect
\ fixnum-shift-fast make-foldable \ fixnum-shift-fast make-foldable
\ bignum= { bignum bignum } { object } <effect> "inferred-effect" set-word-prop \ bignum= { bignum bignum } { object } <effect> set-primitive-effect
\ bignum= make-foldable \ bignum= make-foldable
\ bignum+ { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum+ { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum+ make-foldable \ bignum+ make-foldable
\ bignum- { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum- { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum- make-foldable \ bignum- make-foldable
\ bignum* { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum* { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum* make-foldable \ bignum* make-foldable
\ bignum/i { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum/i { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum/i make-foldable \ bignum/i make-foldable
\ bignum-mod { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum-mod { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum-mod make-foldable \ bignum-mod make-foldable
\ bignum/mod { bignum bignum } { bignum bignum } <effect> "inferred-effect" set-word-prop \ bignum/mod { bignum bignum } { bignum bignum } <effect> set-primitive-effect
\ bignum/mod make-foldable \ bignum/mod make-foldable
\ bignum-bitand { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum-bitand { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum-bitand make-foldable \ bignum-bitand make-foldable
\ bignum-bitor { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum-bitor { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum-bitor make-foldable \ bignum-bitor make-foldable
\ bignum-bitxor { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum-bitxor { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum-bitxor make-foldable \ bignum-bitxor make-foldable
\ bignum-bitnot { bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum-bitnot { bignum } { bignum } <effect> set-primitive-effect
\ bignum-bitnot make-foldable \ bignum-bitnot make-foldable
\ bignum-shift { bignum bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum-shift { bignum bignum } { bignum } <effect> set-primitive-effect
\ bignum-shift make-foldable \ bignum-shift make-foldable
\ bignum< { bignum bignum } { object } <effect> "inferred-effect" set-word-prop \ bignum< { bignum bignum } { object } <effect> set-primitive-effect
\ bignum< make-foldable \ bignum< make-foldable
\ bignum<= { bignum bignum } { object } <effect> "inferred-effect" set-word-prop \ bignum<= { bignum bignum } { object } <effect> set-primitive-effect
\ bignum<= make-foldable \ bignum<= make-foldable
\ bignum> { bignum bignum } { object } <effect> "inferred-effect" set-word-prop \ bignum> { bignum bignum } { object } <effect> set-primitive-effect
\ bignum> make-foldable \ bignum> make-foldable
\ bignum>= { bignum bignum } { object } <effect> "inferred-effect" set-word-prop \ bignum>= { bignum bignum } { object } <effect> set-primitive-effect
\ bignum>= make-foldable \ bignum>= make-foldable
\ bignum-bit? { bignum integer } { object } <effect> "inferred-effect" set-word-prop \ bignum-bit? { bignum integer } { object } <effect> set-primitive-effect
\ bignum-bit? make-foldable \ bignum-bit? make-foldable
\ bignum-log2 { bignum } { bignum } <effect> "inferred-effect" set-word-prop \ bignum-log2 { bignum } { bignum } <effect> set-primitive-effect
\ bignum-log2 make-foldable \ bignum-log2 make-foldable
\ byte-array>bignum { byte-array } { bignum } <effect> "inferred-effect" set-word-prop \ byte-array>bignum { byte-array } { bignum } <effect> set-primitive-effect
\ byte-array>bignum make-foldable \ byte-array>bignum make-foldable
\ float= { float float } { object } <effect> "inferred-effect" set-word-prop \ float= { float float } { object } <effect> set-primitive-effect
\ float= make-foldable \ float= make-foldable
\ float+ { float float } { float } <effect> "inferred-effect" set-word-prop \ float+ { float float } { float } <effect> set-primitive-effect
\ float+ make-foldable \ float+ make-foldable
\ float- { float float } { float } <effect> "inferred-effect" set-word-prop \ float- { float float } { float } <effect> set-primitive-effect
\ float- make-foldable \ float- make-foldable
\ float* { float float } { float } <effect> "inferred-effect" set-word-prop \ float* { float float } { float } <effect> set-primitive-effect
\ float* make-foldable \ float* make-foldable
\ float/f { float float } { float } <effect> "inferred-effect" set-word-prop \ float/f { float float } { float } <effect> set-primitive-effect
\ float/f make-foldable \ float/f make-foldable
\ float< { float float } { object } <effect> "inferred-effect" set-word-prop \ float< { float float } { object } <effect> set-primitive-effect
\ float< make-foldable \ float< make-foldable
\ float-mod { float float } { float } <effect> "inferred-effect" set-word-prop \ float-mod { float float } { float } <effect> set-primitive-effect
\ float-mod make-foldable \ float-mod make-foldable
\ float<= { float float } { object } <effect> "inferred-effect" set-word-prop \ float<= { float float } { object } <effect> set-primitive-effect
\ float<= make-foldable \ float<= make-foldable
\ float> { float float } { object } <effect> "inferred-effect" set-word-prop \ float> { float float } { object } <effect> set-primitive-effect
\ float> make-foldable \ float> make-foldable
\ float>= { float float } { object } <effect> "inferred-effect" set-word-prop \ float>= { float float } { object } <effect> set-primitive-effect
\ float>= make-foldable \ float>= make-foldable
\ <word> { object object } { word } <effect> "inferred-effect" set-word-prop \ <word> { object object } { word } <effect> set-primitive-effect
\ <word> make-flushable \ <word> make-flushable
\ word-xt { word } { integer } <effect> "inferred-effect" set-word-prop \ word-xt { word } { integer } <effect> set-primitive-effect
\ word-xt make-flushable \ word-xt make-flushable
\ getenv { fixnum } { object } <effect> "inferred-effect" set-word-prop \ getenv { fixnum } { object } <effect> set-primitive-effect
\ getenv make-flushable \ getenv make-flushable
\ setenv { object fixnum } { } <effect> "inferred-effect" set-word-prop \ setenv { object fixnum } { } <effect> set-primitive-effect
\ (stat) { string } { object object object object } <effect> "inferred-effect" set-word-prop \ (stat) { string } { object object object object } <effect> set-primitive-effect
\ (directory) { string } { array } <effect> "inferred-effect" set-word-prop \ (directory) { string } { array } <effect> set-primitive-effect
\ data-gc { } { } <effect> "inferred-effect" set-word-prop \ data-gc { } { } <effect> set-primitive-effect
\ code-gc { } { } <effect> "inferred-effect" set-word-prop \ code-gc { } { } <effect> set-primitive-effect
\ gc-time { } { integer } <effect> "inferred-effect" set-word-prop \ gc-time { } { integer } <effect> set-primitive-effect
\ save-image { string } { } <effect> "inferred-effect" set-word-prop \ save-image { string } { } <effect> set-primitive-effect
\ save-image-and-exit { string } { } <effect> "inferred-effect" set-word-prop \ save-image-and-exit { string } { } <effect> set-primitive-effect
\ exit { integer } { } <effect> \ exit { integer } { } <effect>
t over set-effect-terminated? t over set-effect-terminated?
"inferred-effect" set-word-prop set-primitive-effect
\ data-room { } { integer array } <effect> "inferred-effect" set-word-prop \ data-room { } { integer array } <effect> set-primitive-effect
\ data-room make-flushable \ data-room make-flushable
\ code-room { } { integer integer } <effect> "inferred-effect" set-word-prop \ code-room { } { integer integer } <effect> set-primitive-effect
\ code-room make-flushable \ code-room make-flushable
\ os-env { string } { object } <effect> "inferred-effect" set-word-prop \ os-env { string } { object } <effect> set-primitive-effect
\ millis { } { integer } <effect> "inferred-effect" set-word-prop \ millis { } { integer } <effect> set-primitive-effect
\ millis make-flushable \ millis make-flushable
\ type { object } { fixnum } <effect> "inferred-effect" set-word-prop \ type { object } { fixnum } <effect> set-primitive-effect
\ type make-foldable \ type make-foldable
\ tag { object } { fixnum } <effect> "inferred-effect" set-word-prop \ tag { object } { fixnum } <effect> set-primitive-effect
\ tag make-foldable \ tag make-foldable
\ class-hash { object } { fixnum } <effect> "inferred-effect" set-word-prop \ class-hash { object } { fixnum } <effect> set-primitive-effect
\ class-hash make-foldable \ class-hash make-foldable
\ cwd { } { string } <effect> "inferred-effect" set-word-prop \ cwd { } { string } <effect> set-primitive-effect
\ cd { string } { } <effect> "inferred-effect" set-word-prop \ cd { string } { } <effect> set-primitive-effect
\ dlopen { string } { dll } <effect> "inferred-effect" set-word-prop \ dlopen { string } { dll } <effect> set-primitive-effect
\ dlsym { string object } { c-ptr } <effect> "inferred-effect" set-word-prop \ dlsym { string object } { c-ptr } <effect> set-primitive-effect
\ dlclose { dll } { } <effect> "inferred-effect" set-word-prop \ dlclose { dll } { } <effect> set-primitive-effect
\ <byte-array> { integer } { byte-array } <effect> "inferred-effect" set-word-prop \ <byte-array> { integer } { byte-array } <effect> set-primitive-effect
\ <byte-array> make-flushable \ <byte-array> make-flushable
\ <bit-array> { integer } { bit-array } <effect> "inferred-effect" set-word-prop \ <bit-array> { integer } { bit-array } <effect> set-primitive-effect
\ <bit-array> make-flushable \ <bit-array> make-flushable
\ <float-array> { integer float } { float-array } <effect> "inferred-effect" set-word-prop \ <float-array> { integer float } { float-array } <effect> set-primitive-effect
\ <float-array> make-flushable \ <float-array> make-flushable
\ <displaced-alien> { integer c-ptr } { c-ptr } <effect> "inferred-effect" set-word-prop \ <displaced-alien> { integer c-ptr } { c-ptr } <effect> set-primitive-effect
\ <displaced-alien> make-flushable \ <displaced-alien> make-flushable
\ alien-signed-cell { c-ptr integer } { integer } <effect> "inferred-effect" set-word-prop \ alien-signed-cell { c-ptr integer } { integer } <effect> set-primitive-effect
\ alien-signed-cell make-flushable
\ set-alien-signed-cell { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-signed-cell { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-unsigned-cell { c-ptr integer } { integer } <effect> "inferred-effect" set-word-prop \ alien-unsigned-cell { c-ptr integer } { integer } <effect> set-primitive-effect
\ alien-unsigned-cell make-flushable
\ set-alien-unsigned-cell { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-unsigned-cell { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-signed-8 { c-ptr integer } { integer } <effect> "inferred-effect" set-word-prop \ alien-signed-8 { c-ptr integer } { integer } <effect> set-primitive-effect
\ alien-signed-8 make-flushable
\ set-alien-signed-8 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-signed-8 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-unsigned-8 { c-ptr integer } { integer } <effect> "inferred-effect" set-word-prop \ alien-unsigned-8 { c-ptr integer } { integer } <effect> set-primitive-effect
\ alien-unsigned-8 make-flushable
\ set-alien-unsigned-8 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-unsigned-8 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-signed-4 { c-ptr integer } { integer } <effect> "inferred-effect" set-word-prop \ alien-signed-4 { c-ptr integer } { integer } <effect> set-primitive-effect
\ alien-signed-4 make-flushable
\ set-alien-signed-4 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-signed-4 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-unsigned-4 { c-ptr integer } { integer } <effect> "inferred-effect" set-word-prop \ alien-unsigned-4 { c-ptr integer } { integer } <effect> set-primitive-effect
\ alien-unsigned-4 make-flushable
\ set-alien-unsigned-4 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-unsigned-4 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-signed-2 { c-ptr integer } { fixnum } <effect> "inferred-effect" set-word-prop \ alien-signed-2 { c-ptr integer } { fixnum } <effect> set-primitive-effect
\ alien-signed-2 make-flushable
\ set-alien-signed-2 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-signed-2 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-unsigned-2 { c-ptr integer } { fixnum } <effect> "inferred-effect" set-word-prop \ alien-unsigned-2 { c-ptr integer } { fixnum } <effect> set-primitive-effect
\ alien-unsigned-2 make-flushable
\ set-alien-unsigned-2 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-unsigned-2 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-signed-1 { c-ptr integer } { fixnum } <effect> "inferred-effect" set-word-prop \ alien-signed-1 { c-ptr integer } { fixnum } <effect> set-primitive-effect
\ alien-signed-1 make-flushable
\ set-alien-signed-1 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-signed-1 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-unsigned-1 { c-ptr integer } { fixnum } <effect> "inferred-effect" set-word-prop \ alien-unsigned-1 { c-ptr integer } { fixnum } <effect> set-primitive-effect
\ alien-unsigned-1 make-flushable
\ set-alien-unsigned-1 { integer c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-unsigned-1 { integer c-ptr integer } { } <effect> set-primitive-effect
\ alien-float { c-ptr integer } { float } <effect> "inferred-effect" set-word-prop \ alien-float { c-ptr integer } { float } <effect> set-primitive-effect
\ alien-float make-flushable
\ set-alien-float { float c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-float { float c-ptr integer } { } <effect> set-primitive-effect
\ alien-double { c-ptr integer } { float } <effect> "inferred-effect" set-word-prop \ alien-double { c-ptr integer } { float } <effect> set-primitive-effect
\ alien-double make-flushable
\ set-alien-double { float c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-double { float c-ptr integer } { } <effect> set-primitive-effect
\ alien-cell { c-ptr integer } { simple-c-ptr } <effect> "inferred-effect" set-word-prop \ alien-cell { c-ptr integer } { simple-c-ptr } <effect> set-primitive-effect
\ alien-cell make-flushable
\ set-alien-cell { c-ptr c-ptr integer } { } <effect> "inferred-effect" set-word-prop \ set-alien-cell { c-ptr c-ptr integer } { } <effect> set-primitive-effect
\ alien>char-string { c-ptr } { string } <effect> "inferred-effect" set-word-prop \ alien>char-string { c-ptr } { string } <effect> set-primitive-effect
\ alien>char-string make-flushable
\ string>char-alien { string } { byte-array } <effect> "inferred-effect" set-word-prop \ string>char-alien { string } { byte-array } <effect> set-primitive-effect
\ string>char-alien make-flushable
\ alien>u16-string { c-ptr } { string } <effect> "inferred-effect" set-word-prop \ alien>u16-string { c-ptr } { string } <effect> set-primitive-effect
\ alien>u16-string make-flushable
\ string>u16-alien { string } { byte-array } <effect> "inferred-effect" set-word-prop \ string>u16-alien { string } { byte-array } <effect> set-primitive-effect
\ string>u16-alien make-flushable
\ alien-address { alien } { integer } <effect> "inferred-effect" set-word-prop \ alien-address { alien } { integer } <effect> set-primitive-effect
\ alien-address make-flushable \ alien-address make-flushable
\ slot { object fixnum } { object } <effect> "inferred-effect" set-word-prop \ slot { object fixnum } { object } <effect> set-primitive-effect
\ slot make-flushable \ slot make-flushable
\ set-slot { object object fixnum } { } <effect> "inferred-effect" set-word-prop \ set-slot { object object fixnum } { } <effect> set-primitive-effect
\ string-nth { fixnum string } { fixnum } <effect> "inferred-effect" set-word-prop \ string-nth { fixnum string } { fixnum } <effect> set-primitive-effect
\ string-nth make-flushable \ string-nth make-flushable
\ set-string-nth { fixnum fixnum string } { } <effect> "inferred-effect" set-word-prop \ set-string-nth { fixnum fixnum string } { } <effect> set-primitive-effect
\ resize-array { integer array } { array } <effect> "inferred-effect" set-word-prop \ resize-array { integer array } { array } <effect> set-primitive-effect
\ resize-array make-flushable \ resize-array make-flushable
\ resize-byte-array { integer byte-array } { byte-array } <effect> "inferred-effect" set-word-prop \ resize-byte-array { integer byte-array } { byte-array } <effect> set-primitive-effect
\ resize-byte-array make-flushable \ resize-byte-array make-flushable
\ resize-bit-array { integer bit-array } { bit-array } <effect> "inferred-effect" set-word-prop \ resize-bit-array { integer bit-array } { bit-array } <effect> set-primitive-effect
\ resize-bit-array make-flushable \ resize-bit-array make-flushable
\ resize-float-array { integer float-array } { float-array } <effect> "inferred-effect" set-word-prop \ resize-float-array { integer float-array } { float-array } <effect> set-primitive-effect
\ resize-float-array make-flushable \ resize-float-array make-flushable
\ resize-string { integer string } { string } <effect> "inferred-effect" set-word-prop \ resize-string { integer string } { string } <effect> set-primitive-effect
\ resize-string make-flushable \ resize-string make-flushable
\ <array> { integer object } { array } <effect> "inferred-effect" set-word-prop \ <array> { integer object } { array } <effect> set-primitive-effect
\ <array> make-flushable \ <array> make-flushable
\ begin-scan { } { } <effect> "inferred-effect" set-word-prop \ begin-scan { } { } <effect> set-primitive-effect
\ next-object { } { object } <effect> "inferred-effect" set-word-prop \ next-object { } { object } <effect> set-primitive-effect
\ end-scan { } { } <effect> "inferred-effect" set-word-prop \ end-scan { } { } <effect> set-primitive-effect
\ size { object } { fixnum } <effect> "inferred-effect" set-word-prop \ size { object } { fixnum } <effect> set-primitive-effect
\ size make-flushable \ size make-flushable
\ die { } { } <effect> "inferred-effect" set-word-prop \ die { } { } <effect> set-primitive-effect
\ fopen { string string } { alien } <effect> "inferred-effect" set-word-prop \ fopen { string string } { alien } <effect> set-primitive-effect
\ fgetc { alien } { object } <effect> "inferred-effect" set-word-prop \ fgetc { alien } { object } <effect> set-primitive-effect
\ fwrite { string alien } { } <effect> "inferred-effect" set-word-prop \ fwrite { string alien } { } <effect> set-primitive-effect
\ fread { integer string } { object } <effect> "inferred-effect" set-word-prop \ fread { integer string } { object } <effect> set-primitive-effect
\ fflush { alien } { } <effect> "inferred-effect" set-word-prop \ fflush { alien } { } <effect> set-primitive-effect
\ fclose { alien } { } <effect> "inferred-effect" set-word-prop \ fclose { alien } { } <effect> set-primitive-effect
\ expired? { object } { object } <effect> "inferred-effect" set-word-prop \ expired? { object } { object } <effect> set-primitive-effect
\ expired? make-flushable \ expired? make-flushable
\ <wrapper> { object } { wrapper } <effect> "inferred-effect" set-word-prop \ <wrapper> { object } { wrapper } <effect> set-primitive-effect
\ <wrapper> make-foldable \ <wrapper> make-foldable
\ (clone) { object } { object } <effect> "inferred-effect" set-word-prop \ (clone) { object } { object } <effect> set-primitive-effect
\ (clone) make-flushable \ (clone) make-flushable
\ <string> { integer integer } { string } <effect> "inferred-effect" set-word-prop \ <string> { integer integer } { string } <effect> set-primitive-effect
\ <string> make-flushable \ <string> make-flushable
\ array>quotation { array } { quotation } <effect> "inferred-effect" set-word-prop \ array>quotation { array } { quotation } <effect> set-primitive-effect
\ array>quotation make-flushable \ array>quotation make-flushable
\ quotation-xt { quotation } { integer } <effect> "inferred-effect" set-word-prop \ quotation-xt { quotation } { integer } <effect> set-primitive-effect
\ quotation-xt make-flushable \ quotation-xt make-flushable
\ <tuple> { word integer } { quotation } <effect> "inferred-effect" set-word-prop \ <tuple> { word integer } { quotation } <effect> set-primitive-effect
\ <tuple> make-flushable \ <tuple> make-flushable
\ (>tuple) { array } { tuple } <effect> "inferred-effect" set-word-prop \ (>tuple) { array } { tuple } <effect> set-primitive-effect
\ (>tuple) make-flushable \ (>tuple) make-flushable
\ tuple>array { tuple } { array } <effect> "inferred-effect" set-word-prop \ tuple>array { tuple } { array } <effect> set-primitive-effect
\ tuple>array make-flushable \ tuple>array make-flushable
\ datastack { } { array } <effect> "inferred-effect" set-word-prop \ datastack { } { array } <effect> set-primitive-effect
\ datastack make-flushable \ datastack make-flushable
\ retainstack { } { array } <effect> "inferred-effect" set-word-prop \ retainstack { } { array } <effect> set-primitive-effect
\ retainstack make-flushable \ retainstack make-flushable
\ callstack { } { callstack } <effect> "inferred-effect" set-word-prop \ callstack { } { callstack } <effect> set-primitive-effect
\ callstack make-flushable \ callstack make-flushable
\ callstack>array { callstack } { array } <effect> "inferred-effect" set-word-prop \ callstack>array { callstack } { array } <effect> set-primitive-effect
\ callstack>array make-flushable \ callstack>array make-flushable
\ (sleep) { integer } { } <effect> "inferred-effect" set-word-prop \ (sleep) { integer } { } <effect> set-primitive-effect
\ become { array array } { } <effect> "inferred-effect" set-word-prop \ become { array array } { } <effect> set-primitive-effect
\ innermost-frame-quot { callstack } { quotation } <effect> "inferred-effect" set-word-prop \ innermost-frame-quot { callstack } { quotation } <effect> set-primitive-effect
\ innermost-frame-scan { callstack } { fixnum } <effect> "inferred-effect" set-word-prop \ innermost-frame-scan { callstack } { fixnum } <effect> set-primitive-effect
\ set-innermost-frame-quot { quotation callstack } { } <effect> "inferred-effect" set-word-prop \ set-innermost-frame-quot { quotation callstack } { } <effect> set-primitive-effect
\ (os-envs) { } { array } <effect> "inferred-effect" set-word-prop \ (os-envs) { } { array } <effect> set-primitive-effect
\ do-primitive [ \ do-primitive no-effect ] "infer" set-word-prop \ do-primitive [ \ do-primitive no-effect ] "infer" set-word-prop

View File

@ -1,6 +1,6 @@
IN: temporary IN: temporary
USING: sequences inference.transforms tools.test math kernel USING: sequences inference.transforms tools.test math kernel
quotations tools.test.inference inference ; quotations inference ;
: compose-n-quot <repetition> >quotation ; : compose-n-quot <repetition> >quotation ;
: compose-n compose-n-quot call ; : compose-n compose-n-quot call ;
@ -31,4 +31,4 @@ TUPLE: a-tuple x y z ;
: set-slots-test-2 : set-slots-test-2
{ set-a-tuple-x set-a-tuple-x } set-slots ; { set-a-tuple-x set-a-tuple-x } set-slots ;
[ [ set-slots-test-2 ] infer ] unit-test-fails [ [ set-slots-test-2 ] infer ] must-fail

View File

@ -54,6 +54,10 @@ M: pair (bitfield-quot) ( spec -- quot )
\ bitfield [ bitfield-quot ] 1 define-transform \ bitfield [ bitfield-quot ] 1 define-transform
\ flags [
[ 0 , [ , \ bitor , ] each ] [ ] make
] 1 define-transform
! Tuple operations ! Tuple operations
: [get-slots] ( slots -- quot ) : [get-slots] ( slots -- quot )
[ [ 1quotation , \ keep , ] each \ drop , ] [ ] make ; [ [ 1quotation , \ keep , ] each \ drop , ] [ ] make ;
@ -89,5 +93,3 @@ M: duplicated-slots-error summary
\ construct-empty 1 1 <effect> make-call-node \ construct-empty 1 1 <effect> make-call-node
] if ] if
] "infer" set-word-prop ] "infer" set-word-prop
\ construct-empty 1 1 <effect> "inferred-effect" set-word-prop

View File

@ -2,16 +2,16 @@ USING: help.markup help.syntax math ;
IN: io.crc32 IN: io.crc32
HELP: crc32 HELP: crc32
{ $values { "seq" "a sequence" } { "n" integer } } { $values { "seq" "a sequence of bytes" } { "n" integer } }
{ $description "Computes the CRC32 checksum of a sequence of bytes." } ; { $description "Computes the CRC32 checksum of a sequence of bytes." } ;
HELP: file-crc32 HELP: lines-crc32
{ $values { "path" "a pathname string" } { "n" integer } } { $values { "lines" "a sequence of strings" } { "n" integer } }
{ $description "Computes the CRC32 checksum of a file's contents." } ; { $description "Computes the CRC32 checksum of a sequence of lines of bytes." } ;
ARTICLE: "io.crc32" "CRC32 checksum calculation" ARTICLE: "io.crc32" "CRC32 checksum calculation"
"The CRC32 checksum algorithm provides a quick but unreliable way to detect changes in data." "The CRC32 checksum algorithm provides a quick but unreliable way to detect changes in data."
{ $subsection crc32 } { $subsection crc32 }
{ $subsection file-crc32 } ; { $subsection lines-crc32 } ;
ABOUT: "io.crc32" ABOUT: "io.crc32"

View File

@ -23,8 +23,6 @@ IN: io.crc32
: crc32 ( seq -- n ) : crc32 ( seq -- n )
>r HEX: ffffffff dup r> [ (crc32) ] each bitxor ; >r HEX: ffffffff dup r> [ (crc32) ] each bitxor ;
: file-crc32 ( path -- n ) file-contents crc32 ;
: lines-crc32 ( seq -- n ) : lines-crc32 ( seq -- n )
HEX: ffffffff tuck [ HEX: ffffffff tuck [
[ (crc32) ] each CHAR: \n (crc32) [ (crc32) ] each CHAR: \n (crc32)

View File

@ -52,12 +52,27 @@ HELP: <file-appender>
{ $description "Outputs an output stream for writing to the specified pathname. The stream begins writing at the end of the file." } { $description "Outputs an output stream for writing to the specified pathname. The stream begins writing at the end of the file." }
{ $errors "Throws an error if the file cannot be opened for writing." } ; { $errors "Throws an error if the file cannot be opened for writing." } ;
HELP: cwd ( -- path ) HELP: with-file-in
{ $values { "path" "a pathname string" } { "quot" "a quotation" } }
{ $description "Opens a file for reading and calls the quotation using " { $link with-stream } "." }
{ $errors "Throws an error if the file is unreadable." } ;
HELP: with-file-out
{ $values { "path" "a pathname string" } { "quot" "a quotation" } }
{ $description "Opens a file for writing and calls the quotation using " { $link with-stream } "." }
{ $errors "Throws an error if the file cannot be opened for writing." } ;
HELP: with-file-appender
{ $values { "path" "a pathname string" } { "quot" "a quotation" } }
{ $description "Opens a file for appending and calls the quotation using " { $link with-stream } "." }
{ $errors "Throws an error if the file cannot be opened for writing." } ;
HELP: cwd
{ $values { "path" "a pathname string" } } { $values { "path" "a pathname string" } }
{ $description "Outputs the current working directory of the Factor process." } { $description "Outputs the current working directory of the Factor process." }
{ $errors "Windows CE has no concept of ``current directory'', so this word throws an error there." } ; { $errors "Windows CE has no concept of ``current directory'', so this word throws an error there." } ;
HELP: cd ( path -- ) HELP: cd
{ $values { "path" "a pathname string" } } { $values { "path" "a pathname string" } }
{ $description "Changes the current working directory of the Factor process." } { $description "Changes the current working directory of the Factor process." }
{ $errors "Windows CE has no concept of ``current directory'', so this word throws an error there." } ; { $errors "Windows CE has no concept of ``current directory'', so this word throws an error there." } ;

View File

@ -2,7 +2,8 @@ IN: temporary
USING: tools.test io.files io threads kernel continuations ; USING: tools.test io.files io threads kernel continuations ;
[ "passwd" ] [ "/etc/passwd" file-name ] unit-test [ "passwd" ] [ "/etc/passwd" file-name ] unit-test
[ "awk/" ] [ "/usr/libexec/awk/" file-name ] unit-test [ "awk" ] [ "/usr/libexec/awk/" file-name ] unit-test
[ "awk" ] [ "/usr/libexec/awk///" file-name ] unit-test
[ ] [ [ ] [
"test-foo.txt" resource-path <file-writer> [ "test-foo.txt" resource-path <file-writer> [

View File

@ -1,10 +1,14 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: io.files IN: io.files
USING: io.backend io.files.private io hashtables kernel math USING: io.backend io.files.private io hashtables kernel math
memory namespaces sequences strings assocs arrays definitions memory namespaces sequences strings assocs arrays definitions
system combinators splitting sbufs ; system combinators splitting sbufs ;
HOOK: cd io-backend ( path -- )
HOOK: cwd io-backend ( -- path )
HOOK: <file-reader> io-backend ( path -- stream ) HOOK: <file-reader> io-backend ( path -- stream )
HOOK: <file-writer> io-backend ( path -- stream ) HOOK: <file-writer> io-backend ( path -- stream )
@ -25,12 +29,15 @@ HOOK: root-directory? io-backend ( path -- ? )
M: object root-directory? ( path -- ? ) path-separator? ; M: object root-directory? ( path -- ? ) path-separator? ;
: trim-path-separators ( str -- newstr ) : right-trim-separators ( str -- newstr )
[ path-separator? ] right-trim ; [ path-separator? ] right-trim ;
: left-trim-separators ( str -- newstr )
[ path-separator? ] left-trim ;
: path+ ( str1 str2 -- str ) : path+ ( str1 str2 -- str )
>r trim-path-separators "/" r> >r right-trim-separators "/" r>
[ path-separator? ] left-trim 3append ; left-trim-separators 3append ;
: stat ( path -- directory? permissions length modified ) : stat ( path -- directory? permissions length modified )
normalize-pathname (stat) ; normalize-pathname (stat) ;
@ -57,7 +64,7 @@ M: object root-directory? ( path -- ? ) path-separator? ;
normalize-directory dup (directory) fixup-directory ; normalize-directory dup (directory) fixup-directory ;
: last-path-separator ( path -- n ? ) : last-path-separator ( path -- n ? )
[ length 2 [-] ] keep [ path-separator? ] find-last* ; [ length 1- ] keep [ path-separator? ] find-last* ;
TUPLE: no-parent-directory path ; TUPLE: no-parent-directory path ;
@ -65,7 +72,7 @@ TUPLE: no-parent-directory path ;
\ no-parent-directory construct-boa throw ; \ no-parent-directory construct-boa throw ;
: parent-directory ( path -- parent ) : parent-directory ( path -- parent )
trim-path-separators { right-trim-separators {
{ [ dup empty? ] [ drop "/" ] } { [ dup empty? ] [ drop "/" ] }
{ [ dup root-directory? ] [ ] } { [ dup root-directory? ] [ ] }
{ [ dup [ path-separator? ] contains? not ] [ drop "." ] } { [ dup [ path-separator? ] contains? not ] [ drop "." ] }
@ -76,7 +83,11 @@ TUPLE: no-parent-directory path ;
} cond ; } cond ;
: file-name ( path -- string ) : file-name ( path -- string )
dup last-path-separator [ 1+ tail ] [ drop ] if ; right-trim-separators {
{ [ dup empty? ] [ drop "/" ] }
{ [ dup last-path-separator ] [ 1+ tail ] }
{ [ t ] [ drop ] }
} cond ;
: resource-path ( path -- newpath ) : resource-path ( path -- newpath )
\ resource-path get [ image parent-directory ] unless* \ resource-path get [ image parent-directory ] unless*
@ -85,8 +96,11 @@ TUPLE: no-parent-directory path ;
: ?resource-path ( path -- newpath ) : ?resource-path ( path -- newpath )
"resource:" ?head [ resource-path ] when ; "resource:" ?head [ resource-path ] when ;
: resource-exists? ( path -- ? )
?resource-path exists? ;
: make-directories ( path -- ) : make-directories ( path -- )
normalize-pathname trim-path-separators { normalize-pathname right-trim-separators {
{ [ dup "." = ] [ ] } { [ dup "." = ] [ ] }
{ [ dup root-directory? ] [ ] } { [ dup root-directory? ] [ ] }
{ [ dup empty? ] [ ] } { [ dup empty? ] [ ] }
@ -162,3 +176,12 @@ PRIVATE>
: file-contents ( path -- str ) : file-contents ( path -- str )
dup <file-reader> swap file-length <sbuf> [ stream-copy ] keep >string ; dup <file-reader> swap file-length <sbuf> [ stream-copy ] keep >string ;
: with-file-in ( path quot -- )
>r <file-reader> r> with-stream ; inline
: with-file-out ( path quot -- )
>r <file-writer> r> with-stream ; inline
: with-file-appender ( path quot -- )
>r <file-appender> r> with-stream ; inline

View File

@ -22,8 +22,7 @@ $nl
{ $subsection make-block-stream } { $subsection make-block-stream }
{ $subsection make-cell-stream } { $subsection make-cell-stream }
{ $subsection stream-write-table } { $subsection stream-write-table }
"Optional word for network streams:" { $see-also "io.timeouts" } ;
{ $subsection set-timeout } ;
ARTICLE: "stdio" "The default stream" ARTICLE: "stdio" "The default stream"
"Various words take an implicit stream parameter from a variable to reduce stack shuffling." "Various words take an implicit stream parameter from a variable to reduce stack shuffling."
@ -73,11 +72,6 @@ ARTICLE: "streams" "Streams"
ABOUT: "streams" ABOUT: "streams"
HELP: set-timeout
{ $values { "n" "an integer" } { "stream" "a stream" } }
{ $contract "Sets a timeout, in milliseconds, for input and output operations on the stream. If a read or a write is initiated and no activity is seen before the timeout expires, an error will be thrown to the caller of the operation being performed." }
{ $notes "Whether or not the stream is closed when the error is thrown is implementation-specific, and user code should take care to close the stream on all error conditions in any case." } ;
HELP: stream-readln HELP: stream-readln
{ $values { "stream" "an input stream" } { "str" string } } { $values { "stream" "an input stream" } { "str" string } }
{ $contract "Reads a line of input from the stream. Outputs " { $link f } " on stream exhaustion." } { $contract "Reads a line of input from the stream. Outputs " { $link f } " on stream exhaustion." }

View File

@ -4,7 +4,6 @@ USING: hashtables generic kernel math namespaces sequences strings
continuations assocs io.styles sbufs ; continuations assocs io.styles sbufs ;
IN: io IN: io
GENERIC: set-timeout ( n stream -- )
GENERIC: stream-readln ( stream -- str ) GENERIC: stream-readln ( stream -- str )
GENERIC: stream-read1 ( stream -- ch/f ) GENERIC: stream-read1 ( stream -- ch/f )
GENERIC: stream-read ( n stream -- str/f ) GENERIC: stream-read ( n stream -- str/f )

View File

@ -74,3 +74,10 @@ M: object <file-writer>
M: object <file-appender> M: object <file-appender>
"ab" fopen <c-writer> <plain-writer> ; "ab" fopen <c-writer> <plain-writer> ;
: show ( msg -- )
#! A word which directly calls primitives. It is used to
#! print stuff from contexts where the I/O system would
#! otherwise not work (tools.deploy.shaker, the I/O
#! multiplexer thread).
"\r\n" append stdout-handle fwrite stdout-handle fflush ;

View File

@ -28,13 +28,13 @@ M: unclosable-stream dispose
[ t ] [ [ t ] [
<unclosable-stream> <closing-stream> [ <unclosable-stream> <closing-stream> [
<duplex-stream> <duplex-stream>
[ dup dispose ] catch 2drop [ dup dispose ] [ 2drop ] recover
] keep closing-stream-closed? ] keep closing-stream-closed?
] unit-test ] unit-test
[ t ] [ [ t ] [
<closing-stream> [ <unclosable-stream> <closing-stream> [ <unclosable-stream>
<duplex-stream> <duplex-stream>
[ dup dispose ] catch 2drop [ dup dispose ] [ 2drop ] recover
] keep closing-stream-closed? ] keep closing-stream-closed?
] unit-test ] unit-test

View File

@ -74,8 +74,3 @@ M: duplex-stream dispose
[ dup duplex-stream-out dispose ] [ dup duplex-stream-out dispose ]
[ dup duplex-stream-in dispose ] [ ] cleanup [ dup duplex-stream-in dispose ] [ ] cleanup
] unless drop ; ] unless drop ;
M: duplex-stream set-timeout
2dup
duplex-stream-in set-timeout
duplex-stream-out set-timeout ;

View File

@ -532,7 +532,7 @@ HELP: compose
"compose call" "compose call"
"append call" "append call"
} }
"However, " { $link compose } " runs in constant time, and the compiler is able to compile code which calls composed quotations." "However, " { $link compose } " runs in constant time, and the optimizing compiler is able to compile code which calls composed quotations."
} ; } ;
HELP: 3compose HELP: 3compose

View File

@ -7,25 +7,22 @@ IN: temporary
[ t ] [ [ \ = \ = ] all-equal? ] unit-test [ t ] [ [ \ = \ = ] all-equal? ] unit-test
! Don't leak extra roots if error is thrown ! Don't leak extra roots if error is thrown
[ ] [ 10000 [ [ 3 throw ] catch drop ] times ] unit-test [ ] [ 10000 [ [ 3 throw ] ignore-errors ] times ] unit-test
[ ] [ 10000 [ [ -1 f <array> ] catch drop ] times ] unit-test [ ] [ 10000 [ [ -1 f <array> ] ignore-errors ] times ] unit-test
! Make sure we report the correct error on stack underflow ! Make sure we report the correct error on stack underflow
[ { "kernel-error" 11 f f } ] [ clear drop ] [ { "kernel-error" 11 f f } = ] must-fail-with
[ [ clear drop ] catch ] unit-test
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
[ { "kernel-error" 13 f f } ] [ { } set-retainstack r> ] [ { "kernel-error" 13 f f } = ] must-fail-with
[ [ { } set-retainstack r> ] catch ] unit-test
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
: overflow-d 3 overflow-d ; : overflow-d 3 overflow-d ;
[ { "kernel-error" 12 f f } ] [ overflow-d ] [ { "kernel-error" 12 f f } = ] must-fail-with
[ [ overflow-d ] catch ] unit-test
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
@ -33,24 +30,17 @@ IN: temporary
: overflow-d-alt (overflow-d-alt) overflow-d-alt ; : overflow-d-alt (overflow-d-alt) overflow-d-alt ;
[ { "kernel-error" 12 f f } ] [ overflow-d-alt ] [ { "kernel-error" 12 f f } = ] must-fail-with
[ [ overflow-d-alt ] catch ] unit-test
[ ] [ [ :c ] string-out drop ] unit-test [ ] [ [ :c ] string-out drop ] unit-test
: overflow-r 3 >r overflow-r ; : overflow-r 3 >r overflow-r ;
[ { "kernel-error" 14 f f } ] [ overflow-r ] [ { "kernel-error" 14 f f } = ] must-fail-with
[ [ overflow-r ] catch ] unit-test
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
! : overflow-c overflow-c 3 ; [ -7 <byte-array> ] must-fail
!
! [ { "kernel-error" 16 f f } ]
! [ [ overflow-c ] catch ] unit-test
[ -7 <byte-array> ] unit-test-fails
[ 2 3 4 1 ] [ 1 2 3 4 roll ] unit-test [ 2 3 4 1 ] [ 1 2 3 4 roll ] unit-test
[ 1 2 3 4 ] [ 2 3 4 1 -roll ] unit-test [ 1 2 3 4 ] [ 2 3 4 1 -roll ] unit-test
@ -61,27 +51,27 @@ IN: temporary
[ 4 ] [ 4 6 or ] unit-test [ 4 ] [ 4 6 or ] unit-test
[ 6 ] [ f 6 or ] unit-test [ 6 ] [ f 6 or ] unit-test
[ slip ] unit-test-fails [ slip ] must-fail
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
[ 1 slip ] unit-test-fails [ 1 slip ] must-fail
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
[ 1 2 slip ] unit-test-fails [ 1 2 slip ] must-fail
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
[ 1 2 3 slip ] unit-test-fails [ 1 2 3 slip ] must-fail
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
[ 5 ] [ [ 2 2 + ] 1 slip + ] unit-test [ 5 ] [ [ 2 2 + ] 1 slip + ] unit-test
[ [ ] keep ] unit-test-fails [ [ ] keep ] must-fail
[ 6 ] [ 2 [ sq ] keep + ] unit-test [ 6 ] [ 2 [ sq ] keep + ] unit-test
[ [ ] 2keep ] unit-test-fails [ [ ] 2keep ] must-fail
[ 1 [ ] 2keep ] unit-test-fails [ 1 [ ] 2keep ] must-fail
[ 3 1 2 ] [ 1 2 [ 2drop 3 ] 2keep ] unit-test [ 3 1 2 ] [ 1 2 [ 2drop 3 ] 2keep ] unit-test
[ 0 ] [ f [ sq ] [ 0 ] if* ] unit-test [ 0 ] [ f [ sq ] [ 0 ] if* ] unit-test
@ -100,13 +90,13 @@ IN: temporary
[ ] [ callstack set-callstack ] unit-test [ ] [ callstack set-callstack ] unit-test
[ 3drop datastack ] unit-test-fails [ 3drop datastack ] must-fail
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
! Doesn't compile; important ! Doesn't compile; important
: foo 5 + 0 [ ] each ; : foo 5 + 0 [ ] each ;
[ drop foo ] unit-test-fails [ drop foo ] must-fail
[ ] [ :c ] unit-test [ ] [ :c ] unit-test
! Regression ! Regression
@ -117,4 +107,4 @@ IN: temporary
: loop ( obj obj -- ) : loop ( obj obj -- )
H{ } values swap >r dup length swap r> 0 -roll (loop) ; H{ } values swap >r dup length swap r> 0 -roll (loop) ;
[ loop ] unit-test-fails [ loop ] must-fail

View File

@ -17,7 +17,7 @@ IN: kernel
: clear ( -- ) { } set-datastack ; : clear ( -- ) { } set-datastack ;
! Combinators ! Combinators
: call ( callable -- ) uncurry (call) ; GENERIC: call ( callable -- )
DEFER: if DEFER: if
@ -70,6 +70,10 @@ DEFER: if
[ 2nip call ] if ; inline [ 2nip call ] if ; inline
! Quotation building ! Quotation building
USE: tuples.private
: curry ( obj quot -- curry )
\ curry 4 <tuple-boa> ;
: 2curry ( obj1 obj2 quot -- curry ) : 2curry ( obj1 obj2 quot -- curry )
curry curry ; inline curry curry ; inline
@ -81,12 +85,10 @@ DEFER: if
swapd [ swapd call ] 2curry ; inline swapd [ swapd call ] 2curry ; inline
: compose ( quot1 quot2 -- curry ) : compose ( quot1 quot2 -- curry )
! Not inline because this is treated as a primitive by \ compose 4 <tuple-boa> ;
! the compiler
[ slip call ] 2curry ;
: 3compose ( quot1 quot2 quot3 -- curry ) : 3compose ( quot1 quot2 quot3 -- curry )
[ 2slip slip call ] 3curry ; inline compose compose ; inline
! Object protocol ! Object protocol
@ -155,7 +157,7 @@ GENERIC: construct-boa ( ... class -- tuple )
! Error handling -- defined early so that other files can ! Error handling -- defined early so that other files can
! throw errors before continuations are loaded ! throw errors before continuations are loaded
: throw ( error -- * ) 5 getenv [ die ] or curry (throw) ; : throw ( error -- * ) 5 getenv [ die ] or 1 (throw) ;
<PRIVATE <PRIVATE

View File

@ -22,7 +22,7 @@ IN: temporary
[ [
"\\ + 1 2 3 4" parse-interactive "\\ + 1 2 3 4" parse-interactive
"cont" get continue-with "cont" get continue-with
] catch ] ignore-errors
"USE: debugger :1" eval "USE: debugger :1" eval
] callcc1 ] callcc1
] unit-test ] unit-test
@ -36,7 +36,7 @@ IN: temporary
[ [
"USE: vocabs.loader.test.c" parse-interactive "USE: vocabs.loader.test.c" parse-interactive
] unit-test-fails ] must-fail
[ ] [ [ ] [
[ [

11
core/math/bitfields/bitfields-tests.factor Normal file → Executable file
View File

@ -1,4 +1,4 @@
USING: math math.bitfields tools.test kernel ; USING: math math.bitfields tools.test kernel words ;
IN: temporary IN: temporary
[ 0 ] [ { } bitfield ] unit-test [ 0 ] [ { } bitfield ] unit-test
@ -6,3 +6,12 @@ IN: temporary
[ 268 ] [ 3 1 { 8 2 } bitfield ] unit-test [ 268 ] [ 3 1 { 8 2 } bitfield ] unit-test
[ 268 ] [ 1 { 8 { 3 2 } } bitfield ] unit-test [ 268 ] [ 1 { 8 { 3 2 } } bitfield ] unit-test
[ 512 ] [ 1 { { 1+ 8 } } bitfield ] unit-test [ 512 ] [ 1 { { 1+ 8 } } bitfield ] unit-test
: a 1 ; inline
: b 2 ; inline
: foo { a b } flags ;
[ 3 ] [ foo ] unit-test
[ 3 ] [ { a b } flags ] unit-test
[ t ] [ \ foo compiled? ] unit-test

View File

@ -1,4 +1,4 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2007, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays kernel math sequences words ; USING: arrays kernel math sequences words ;
IN: math.bitfields IN: math.bitfields
@ -13,3 +13,6 @@ M: pair (bitfield) ( value accum pair -- newaccum )
: bitfield ( values... bitspec -- n ) : bitfield ( values... bitspec -- n )
0 [ (bitfield) ] reduce ; 0 [ (bitfield) ] reduce ;
: flags ( values -- n )
0 [ dup word? [ execute ] when bitor ] reduce ;

View File

@ -121,8 +121,8 @@ unit-test
! We don't care if this fails or returns 0 (its CPU-specific) ! We don't care if this fails or returns 0 (its CPU-specific)
! as long as it doesn't crash ! as long as it doesn't crash
[ ] [ [ 0 0 /i ] catch clear ] unit-test [ ] [ [ 0 0 /i drop ] ignore-errors ] unit-test
[ ] [ [ 100000000000000000 0 /i ] catch clear ] unit-test [ ] [ [ 100000000000000000 0 /i drop ] ignore-errors ] unit-test
[ -2 ] [ 1 bitnot ] unit-test [ -2 ] [ 1 bitnot ] unit-test
[ -2 ] [ 1 >bignum bitnot ] unit-test [ -2 ] [ 1 >bignum bitnot ] unit-test

View File

@ -25,14 +25,10 @@ $nl
ABOUT: "number-strings" ABOUT: "number-strings"
HELP: digits>integer HELP: digits>integer
{ $values { "radix" "an integer between 2 and 36" } { "seq" "a sequence of integers" } { "n" integer } } { $values { "seq" "a sequence of integers" } { "radix" "an integer between 2 and 36" } { "n" integer } }
{ $description "Converts a sequence of digits (with most significant digit first) into an integer." } { $description "Converts a sequence of digits (with most significant digit first) into an integer." }
{ $notes "This is one of the factors of " { $link string>number } "." } ; { $notes "This is one of the factors of " { $link string>number } "." } ;
HELP: valid-digits?
{ $values { "radix" "an integer between 2 and 36" } { "seq" "a sequence of integers" } { "?" "a boolean" } }
{ $description "Tests if this sequence of integers represents a valid integer in the given radix." } ;
HELP: >digit HELP: >digit
{ $values { "n" "an integer between 0 and 35" } { "ch" "a character" } } { $values { "n" "an integer between 0 and 35" } { "ch" "a character" } }
{ $description "Outputs a character representation of a digit." } { $description "Outputs a character representation of a digit." }
@ -43,11 +39,6 @@ HELP: digit>
{ $description "Converts a character representation of a digit to an integer." } { $description "Converts a character representation of a digit to an integer." }
{ $notes "This is one of the factors of " { $link string>number } "." } ; { $notes "This is one of the factors of " { $link string>number } "." } ;
HELP: string>integer
{ $values { "str" string } { "radix" "an integer between 2 and 36" } { "n/f" "an integer or " { $link f } } }
{ $description "Creates an integer from a string representation." }
{ $notes "The " { $link base> } " word is more general." } ;
HELP: base> HELP: base>
{ $values { "str" string } { "radix" "an integer between 2 and 36" } { "n/f" "a real number or " { $link f } } } { $values { "str" string } { "radix" "an integer between 2 and 36" } { "n/f" "a real number or " { $link f } } }
{ $description "Creates a real number from a string representation with the given radix. The radix is ignored for floating point literals; they are always taken to be in base 10." { $description "Creates a real number from a string representation with the given radix. The radix is ignored for floating point literals; they are always taken to be in base 10."

View File

@ -95,16 +95,6 @@ unit-test
[ f ] [ "\0." string>number ] unit-test [ f ] [ "\0." string>number ] unit-test
! [ t ] [ [ 1 1 >base ] must-fail
! { "1.0/0.0" "-1.0/0.0" "0.0/0.0" } [ 1 0 >base ] must-fail
! [ dup string>number number>string = ] all? [ 1 -1 >base ] must-fail
! ] unit-test
!
! [ t ] [
! { 1.0/0.0 -1.0/0.0 0.0/0.0 }
! [ dup number>string string>number = ] all?
! ] unit-test
[ 1 1 >base ] unit-test-fails
[ 1 0 >base ] unit-test-fails
[ 1 -1 >base ] unit-test-fails

View File

@ -4,12 +4,6 @@ USING: kernel math.private namespaces sequences strings arrays
combinators splitting math assocs ; combinators splitting math assocs ;
IN: math.parser IN: math.parser
DEFER: base>
: string>ratio ( str radix -- a/b )
>r "/" split1 r> tuck base> >r base> r>
2dup and [ / ] [ 2drop f ] if ;
: digit> ( ch -- n ) : digit> ( ch -- n )
H{ H{
{ CHAR: 0 0 } { CHAR: 0 0 }
@ -36,30 +30,57 @@ DEFER: base>
{ CHAR: f 15 } { CHAR: f 15 }
} at ; } at ;
: digits>integer ( radix seq -- n )
0 rot [ swapd * + ] curry reduce ;
: valid-digits? ( radix seq -- ? )
{
{ [ dup empty? ] [ 2drop f ] }
{ [ f over memq? ] [ 2drop f ] }
{ [ t ] [ swap [ < ] curry all? ] }
} cond ;
: string>digits ( str -- digits ) : string>digits ( str -- digits )
[ digit> ] { } map-as ; [ digit> ] { } map-as ;
: string>integer ( str radix -- n/f ) : digits>integer ( seq radix -- n )
swap "-" ?head >r 0 swap [ swapd * + ] curry reduce ;
string>digits 2dup valid-digits?
[ digits>integer r> [ neg ] when ] [ r> 3drop f ] if ; DEFER: base>
<PRIVATE
SYMBOL: radix
SYMBOL: negative?
: sign negative? get "-" "+" ? ;
: with-radix ( radix quot -- )
radix swap with-variable ; inline
: (base>) ( str -- n ) radix get base> ;
: whole-part ( str -- m n )
sign split1 >r (base>) r>
dup [ (base>) ] [ drop 0 swap ] if ;
: string>ratio ( str -- a/b )
"/" split1 (base>) >r whole-part r>
3dup and and [ / + ] [ 3drop f ] if ;
: valid-digits? ( seq -- ? )
{
{ [ dup empty? ] [ drop f ] }
{ [ f over memq? ] [ drop f ] }
{ [ t ] [ radix get [ < ] curry all? ] }
} cond ;
: string>integer ( str -- n/f )
string>digits dup valid-digits?
[ radix get digits>integer ] [ drop f ] if ;
PRIVATE>
: base> ( str radix -- n/f ) : base> ( str radix -- n/f )
{ [
{ [ CHAR: / pick member? ] [ string>ratio ] } "-" ?head dup negative? set >r
{ [ CHAR: . pick member? ] [ drop string>float ] } {
{ [ t ] [ string>integer ] } { [ CHAR: / over member? ] [ string>ratio ] }
} cond ; { [ CHAR: . over member? ] [ string>float ] }
{ [ t ] [ string>integer ] }
} cond
r> [ dup [ neg ] when ] when
] with-radix ;
: string>number ( str -- n/f ) 10 base> ; : string>number ( str -- n/f ) 10 base> ;
: bin> ( str -- n/f ) 2 base> ; : bin> ( str -- n/f ) 2 base> ;
@ -74,8 +95,16 @@ DEFER: base>
dup >r /mod >digit , dup 0 > dup >r /mod >digit , dup 0 >
[ r> integer, ] [ r> 2drop ] if ; [ r> integer, ] [ r> 2drop ] if ;
PRIVATE>
GENERIC# >base 1 ( n radix -- str ) GENERIC# >base 1 ( n radix -- str )
<PRIVATE
: (>base) ( n -- str ) radix get >base ;
PRIVATE>
M: integer >base M: integer >base
[ [
over 0 < [ over 0 < [
@ -87,10 +116,15 @@ M: integer >base
M: ratio >base M: ratio >base
[ [
over numerator over >base % [
CHAR: / , dup 0 < dup negative? set [ "-" % neg ] when
swap denominator swap >base % 1 /mod
] "" make ; >r dup zero? [ drop ] [ (>base) % sign % ] if r>
dup numerator (>base) %
"/" %
denominator (>base) %
] "" make
] with-radix ;
: fix-float ( str -- newstr ) : fix-float ( str -- newstr )
{ {

View File

@ -4,7 +4,7 @@ IN: temporary
TUPLE: testing x y z ; TUPLE: testing x y z ;
[ save-image-and-exit ] unit-test-fails [ save-image-and-exit ] must-fail
[ ] [ [ ] [
num-types get [ num-types get [

98
core/optimizer/backend/backend.factor Normal file → Executable file
View File

@ -4,7 +4,7 @@ USING: arrays generic assocs inference inference.class
inference.dataflow inference.backend inference.state io kernel inference.dataflow inference.backend inference.state io kernel
math namespaces sequences vectors words quotations hashtables math namespaces sequences vectors words quotations hashtables
combinators classes generic.math continuations optimizer.def-use combinators classes generic.math continuations optimizer.def-use
optimizer.pattern-match generic.standard ; optimizer.pattern-match generic.standard optimizer.specializers ;
IN: optimizer.backend IN: optimizer.backend
SYMBOL: class-substitutions SYMBOL: class-substitutions
@ -52,13 +52,7 @@ GENERIC: optimize-node* ( node -- node/t changed? )
DEFER: optimize-nodes DEFER: optimize-nodes
: optimize-children ( node -- ) : optimize-children ( node -- )
[ [ optimize-nodes ] change-children ;
dup node-children dup [
[ optimize-nodes ] map swap set-node-children
] [
2drop
] if
] when* ;
: optimize-node ( node -- node ) : optimize-node ( node -- node )
dup [ dup [
@ -76,39 +70,17 @@ DEFER: optimize-nodes
M: f set-node-successor 2drop ; M: f set-node-successor 2drop ;
: (optimize-nodes) ( prev node -- )
optimize-node [
dup rot set-node-successor
dup node-successor (optimize-nodes)
] [
f swap set-node-successor
] if* ;
: optimize-nodes ( node -- newnode ) : optimize-nodes ( node -- newnode )
[ [
class-substitutions [ clone ] change class-substitutions [ clone ] change
literal-substitutions [ clone ] change literal-substitutions [ clone ] change
dup [ [ optimize-node ] transform-nodes
optimize-node optimizer-changed get
dup dup node-successor (optimize-nodes)
] when optimizer-changed get
] with-scope optimizer-changed set ; ] with-scope optimizer-changed set ;
: prune-if ( node quot -- successor/t )
over >r call [ r> node-successor t ] [ r> drop t f ] if ;
inline
! Generic nodes ! Generic nodes
M: node optimize-node* drop t f ; M: node optimize-node* drop t f ;
M: #shuffle optimize-node*
[
dup node-in-d empty? swap node-out-d empty? and
] prune-if ;
M: #push optimize-node*
[ node-out-d empty? ] prune-if ;
: cleanup-inlining ( node -- newnode changed? ) : cleanup-inlining ( node -- newnode changed? )
node-successor [ node-successor t ] [ t f ] if* ; node-successor [ node-successor t ] [ t f ] if* ;
@ -118,12 +90,6 @@ M: #return optimize-node* cleanup-inlining ;
! #values ! #values
M: #values optimize-node* cleanup-inlining ; M: #values optimize-node* cleanup-inlining ;
! #>r
M: #>r optimize-node* [ node-in-d empty? ] prune-if ;
! #r>
M: #r> optimize-node* [ node-in-r empty? ] prune-if ;
! Some utilities for splicing in dataflow IR subtrees ! Some utilities for splicing in dataflow IR subtrees
: follow ( key assoc -- value ) : follow ( key assoc -- value )
2dup at* [ swap follow nip ] [ 2drop ] if ; 2dup at* [ swap follow nip ] [ 2drop ] if ;
@ -194,10 +160,8 @@ M: node remember-method*
! Constant branch folding ! Constant branch folding
: fold-branch ( node branch# -- node ) : fold-branch ( node branch# -- node )
over drop-inputs >r
over node-children nth over node-children nth
swap node-successor over substitute-node swap node-successor over substitute-node ;
r> [ set-node-successor ] keep ;
! #if ! #if
: known-boolean-value? ( node value -- value ? ) : known-boolean-value? ( node value -- value ? )
@ -213,12 +177,18 @@ M: node remember-method*
] if ; ] if ;
M: #if optimize-node* M: #if optimize-node*
dup dup node-in-d first known-boolean-value? dup dup node-in-d first known-boolean-value? [
[ 0 1 ? fold-branch t ] [ 2drop t f ] if ; over drop-inputs >r
0 1 ? fold-branch
r> [ set-node-successor ] keep
t
] [ 2drop t f ] if ;
M: #dispatch optimize-node* M: #dispatch optimize-node*
dup dup node-in-d first 2dup node-literal? [ dup dup node-in-d first 2dup node-literal? [
node-literal fold-branch t "Optimizing #dispatch" print
node-literal
over drop-inputs >r fold-branch r> [ set-node-successor ] keep t
] [ ] [
3drop t f 3drop t f
] if ; ] if ;
@ -245,11 +215,33 @@ M: #dispatch optimize-node*
: dispatching-class ( node word -- class ) : dispatching-class ( node word -- class )
[ dispatch# node-class# ] keep specific-method ; [ dispatch# node-class# ] keep specific-method ;
! A heuristic to avoid excessive inlining
DEFER: (flat-length)
: word-flat-length ( word -- n )
dup get over inline? not or
[ drop 1 ] [ dup dup set word-def (flat-length) ] if ;
: (flat-length) ( seq -- n )
[
{
{ [ dup quotation? ] [ (flat-length) 1+ ] }
{ [ dup array? ] [ (flat-length) ] }
{ [ dup word? ] [ word-flat-length ] }
{ [ t ] [ drop 1 ] }
} cond
] map sum ;
: flat-length ( seq -- n )
[ word-def (flat-length) ] with-scope ;
: will-inline-method ( node word -- method-spec/t quot/t ) : will-inline-method ( node word -- method-spec/t quot/t )
#! t indicates failure #! t indicates failure
tuck dispatching-class dup [ tuck dispatching-class dup [
swap [ 2array ] 2keep swap [ 2array ] 2keep
method method-def method method-word
dup flat-length 10 >=
[ 1quotation ] [ word-def ] if
] [ ] [
2drop t t 2drop t t
] if ; ] if ;
@ -300,9 +292,19 @@ M: #dispatch optimize-node*
#! Make #shuffle -> #push -> #return -> successor #! Make #shuffle -> #push -> #return -> successor
dupd literal-quot splice-quot ; dupd literal-quot splice-quot ;
: optimize-predicate ( #call -- node ) : evaluate-predicate ( #call -- ? )
dup node-param "predicating" word-prop >r dup node-param "predicating" word-prop >r
dup node-class-first r> class< 1array inline-literals ; node-class-first r> class< ;
: optimize-predicate ( #call -- node )
dup evaluate-predicate swap
dup node-successor #if? [
dup drop-inputs >r
node-successor swap 0 1 ? fold-branch
r> [ set-node-successor ] keep
] [
swap 1array inline-literals
] if ;
: optimizer-hooks ( node -- conditions ) : optimizer-hooks ( node -- conditions )
node-param "optimizer-hooks" word-prop ; node-param "optimizer-hooks" word-prop ;
@ -355,7 +357,7 @@ M: #dispatch optimize-node*
: optimistic-inline? ( #call -- ? ) : optimistic-inline? ( #call -- ? )
dup node-param "specializer" word-prop dup [ dup node-param "specializer" word-prop dup [
>r node-input-classes r> length tail* >r node-input-classes r> specialized-length tail*
[ types length 1 = ] all? [ types length 1 = ] all?
] [ ] [
2drop f 2drop f

2
core/optimizer/def-use/def-use-tests.factor Normal file → Executable file
View File

@ -8,7 +8,7 @@ namespaces assocs kernel sequences math tools.test words ;
] unit-test ] unit-test
: kill-set ( quot -- seq ) : kill-set ( quot -- seq )
dataflow compute-def-use dead-literals keys dataflow compute-def-use compute-dead-literals keys
[ value-literal ] map ; [ value-literal ] map ;
: subset? [ member? ] curry all? ; : subset? [ member? ] curry all? ;

63
core/optimizer/def-use/def-use.factor Normal file → Executable file
View File

@ -70,19 +70,66 @@ M: #branch node-def-use
#! #values node. #! #values node.
dup branch-def-use (node-def-use) ; dup branch-def-use (node-def-use) ;
: dead-literals ( -- values ) ! : dead-literals ( -- values )
! def-use get [ >r value? r> empty? and ] assoc-subset ;
!
! : kill-node* ( node values -- )
! [ swap remove-all ] curry modify-values ;
!
! : kill-node ( node values -- )
! dup assoc-empty?
! [ 2drop ] [ [ kill-node* ] curry each-node ] if ;
!
! : kill-values ( node -- )
! #! Remove literals which are not actually used anywhere.
! dead-literals kill-node ;
: compute-dead-literals ( -- values )
def-use get [ >r value? r> empty? and ] assoc-subset ; def-use get [ >r value? r> empty? and ] assoc-subset ;
: kill-node* ( node values -- ) DEFER: kill-nodes
[ swap remove-all ] curry modify-values ; SYMBOL: dead-literals
: kill-node ( node values -- ) GENERIC: kill-node* ( node -- node/t )
dup assoc-empty?
[ 2drop ] [ [ kill-node* ] curry each-node ] if ;
: kill-values ( node -- ) M: node kill-node* drop t ;
: prune-if ( node quot -- successor/t )
over >r call [ r> node-successor ] [ r> drop t ] if ;
inline
M: #shuffle kill-node*
[
dup node-in-d empty? swap node-out-d empty? and
] prune-if ;
M: #push kill-node*
[ node-out-d empty? ] prune-if ;
M: #>r kill-node* [ node-in-d empty? ] prune-if ;
M: #r> kill-node* [ node-in-r empty? ] prune-if ;
: kill-node ( node -- node )
dup [
dup [ dead-literals get swap remove-all ] modify-values
dup kill-node* dup t eq? [
drop dup [ kill-nodes ] change-children
] [
nip kill-node
] if
] when ;
: kill-nodes ( node -- newnode )
[ kill-node ] transform-nodes ;
: kill-values ( node -- new-node )
#! Remove literals which are not actually used anywhere. #! Remove literals which are not actually used anywhere.
dead-literals kill-node ; compute-dead-literals dup assoc-empty? [ drop ] [
dead-literals [ kill-nodes ] with-variable
] if ;
!
: sole-consumer ( #call -- node/f ) : sole-consumer ( #call -- node/f )
node-out-d first used-by node-out-d first used-by

Some files were not shown because too many files have changed in this diff Show More