working on the compiler
parent
7fa5d5f14a
commit
fdcf721857
|
@ -28,12 +28,14 @@ recrossref
|
||||||
t [
|
t [
|
||||||
"/library/inference/conditions.factor"
|
"/library/inference/conditions.factor"
|
||||||
"/library/inference/dataflow.factor"
|
"/library/inference/dataflow.factor"
|
||||||
|
"/library/inference/values.factor"
|
||||||
"/library/inference/inference.factor"
|
"/library/inference/inference.factor"
|
||||||
"/library/inference/ties.factor"
|
"/library/inference/ties.factor"
|
||||||
"/library/inference/branches.factor"
|
"/library/inference/branches.factor"
|
||||||
"/library/inference/words.factor"
|
"/library/inference/words.factor"
|
||||||
"/library/inference/stack.factor"
|
"/library/inference/stack.factor"
|
||||||
"/library/inference/types.factor"
|
"/library/inference/types.factor"
|
||||||
|
"/library/inference/partial-eval.factor"
|
||||||
|
|
||||||
"/library/compiler/assembler.factor"
|
"/library/compiler/assembler.factor"
|
||||||
"/library/compiler/relocate.factor"
|
"/library/compiler/relocate.factor"
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
! Copyright (C) 2004, 2005 Slava Pestov.
|
! Copyright (C) 2004, 2005 Slava Pestov.
|
||||||
! See http://factor.sf.net/license.txt for BSD license.
|
! See http://factor.sf.net/license.txt for BSD license.
|
||||||
USING: alien assembler command-line compiler io-internals kernel
|
USING: alien assembler command-line compiler compiler-backend
|
||||||
lists math namespaces parser sequences stdio unparser words ;
|
io-internals kernel lists math namespaces parser sequences stdio
|
||||||
|
unparser words ;
|
||||||
|
|
||||||
"Compiling base..." print
|
"Compiling base..." print
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ compile? [
|
||||||
\ = compile
|
\ = compile
|
||||||
\ unparse compile
|
\ unparse compile
|
||||||
\ scan compile
|
\ scan compile
|
||||||
|
\ (generate) compile
|
||||||
] when
|
] when
|
||||||
|
|
||||||
"Loading more library code..." print
|
"Loading more library code..." print
|
||||||
|
|
|
@ -182,7 +182,7 @@ C: range ( from to -- range )
|
||||||
[ set-range-from ] keep ;
|
[ set-range-from ] keep ;
|
||||||
|
|
||||||
M: range length ( range -- n )
|
M: range length ( range -- n )
|
||||||
dup range-to swap range-from - abs 1 + ;
|
dup range-to swap range-from - abs ;
|
||||||
|
|
||||||
M: range nth ( n range -- n )
|
M: range nth ( n range -- n )
|
||||||
[ range-step * ] keep range-from + ;
|
[ range-step * ] keep range-from + ;
|
||||||
|
@ -200,6 +200,9 @@ M: slice nth ( n slice -- obj )
|
||||||
M: slice set-nth ( obj n slice -- )
|
M: slice set-nth ( obj n slice -- )
|
||||||
[ delegate nth ] keep slice-seq set-nth ;
|
[ delegate nth ] keep slice-seq set-nth ;
|
||||||
|
|
||||||
|
: tail-slice ( n seq -- slice )
|
||||||
|
[ length [ swap - ] keep ] keep <slice> ;
|
||||||
|
|
||||||
IN: kernel
|
IN: kernel
|
||||||
|
|
||||||
: depth ( -- n )
|
: depth ( -- n )
|
||||||
|
|
|
@ -11,18 +11,20 @@ sequences words ;
|
||||||
#! by GC, and is indexed through a table.
|
#! by GC, and is indexed through a table.
|
||||||
dup fixnum? swap f eq? or ;
|
dup fixnum? swap f eq? or ;
|
||||||
|
|
||||||
|
: push-1 ( obj -- )
|
||||||
|
0 swap literal-value dup
|
||||||
|
immediate? [ %immediate ] [ %indirect ] ifte , ;
|
||||||
|
|
||||||
#push [
|
#push [
|
||||||
1 %inc-d ,
|
[ node-produce-d get ] bind
|
||||||
[ node-param get ] bind dup immediate? [
|
dup length dup %inc-d ,
|
||||||
%immediate-d ,
|
1 - swap [
|
||||||
] [
|
push-1 0 over %replace-d ,
|
||||||
0 swap %indirect , out-1
|
] each drop
|
||||||
] ifte
|
|
||||||
] "linearizer" set-word-prop
|
] "linearizer" set-word-prop
|
||||||
|
|
||||||
\ drop [
|
#drop [
|
||||||
drop
|
[ node-consume-d get length ] bind %dec-d ,
|
||||||
1 %dec-d ,
|
|
||||||
] "linearizer" set-word-prop
|
] "linearizer" set-word-prop
|
||||||
|
|
||||||
\ dup [
|
\ dup [
|
||||||
|
@ -171,9 +173,12 @@ sequences words ;
|
||||||
1 <vreg> 0 <vreg> rot execute ,
|
1 <vreg> 0 <vreg> rot execute ,
|
||||||
r> 0 %replace-d , ;
|
r> 0 %replace-d , ;
|
||||||
|
|
||||||
|
: literal-fixnum? ( value -- ? )
|
||||||
|
dup literal? [ literal-value fixnum? ] [ drop f ] ifte ;
|
||||||
|
|
||||||
: binary-op ( node op out -- )
|
: binary-op ( node op out -- )
|
||||||
#! out is a vreg where the vop stores the result.
|
#! out is a vreg where the vop stores the result.
|
||||||
>r >r node-peek dup literal? [
|
>r >r node-peek dup literal-fixnum? [
|
||||||
1 %dec-d ,
|
1 %dec-d ,
|
||||||
in-1
|
in-1
|
||||||
literal-value 0 <vreg> r> execute ,
|
literal-value 0 <vreg> r> execute ,
|
||||||
|
@ -206,7 +211,7 @@ sequences words ;
|
||||||
|
|
||||||
\ fixnum* [
|
\ fixnum* [
|
||||||
! Turn multiplication by a power of two into a left shift.
|
! Turn multiplication by a power of two into a left shift.
|
||||||
node-peek dup literal? [
|
node-peek dup literal-fixnum? [
|
||||||
literal-value dup power-of-2? [
|
literal-value dup power-of-2? [
|
||||||
1 %dec-d ,
|
1 %dec-d ,
|
||||||
in-1
|
in-1
|
||||||
|
|
|
@ -21,16 +21,6 @@ math namespaces words strings errors prettyprint sequences ;
|
||||||
#! rest is arguments.
|
#! rest is arguments.
|
||||||
[ %prologue , (linearize) ] make-list ;
|
[ %prologue , (linearize) ] make-list ;
|
||||||
|
|
||||||
: linearize-simple-label ( node -- )
|
|
||||||
#! Some labels become simple labels after the optimization
|
|
||||||
#! stage.
|
|
||||||
dup [ node-label get ] bind %label ,
|
|
||||||
[ node-param get ] bind (linearize) ;
|
|
||||||
|
|
||||||
#simple-label [
|
|
||||||
linearize-simple-label
|
|
||||||
] "linearizer" set-word-prop
|
|
||||||
|
|
||||||
: linearize-label ( node -- )
|
: linearize-label ( node -- )
|
||||||
#! Labels are tricky, because they might contain non-tail
|
#! Labels are tricky, because they might contain non-tail
|
||||||
#! calls. So we push the address of the location right after
|
#! calls. So we push the address of the location right after
|
||||||
|
@ -39,7 +29,8 @@ math namespaces words strings errors prettyprint sequences ;
|
||||||
#! this in the common case where the labelled block does
|
#! this in the common case where the labelled block does
|
||||||
#! not contain non-tail recursive calls to itself.
|
#! not contain non-tail recursive calls to itself.
|
||||||
<label> dup %return-to , >r
|
<label> dup %return-to , >r
|
||||||
linearize-simple-label
|
dup [ node-label get ] bind %label ,
|
||||||
|
[ node-param get ] bind (linearize)
|
||||||
f %return ,
|
f %return ,
|
||||||
r> %label , ;
|
r> %label , ;
|
||||||
|
|
||||||
|
|
|
@ -100,9 +100,26 @@ SYMBOL: branch-returns
|
||||||
node-param [ [ dupd kill-nodes ] map nip ] change
|
node-param [ [ dupd kill-nodes ] map nip ] change
|
||||||
] extend , ;
|
] extend , ;
|
||||||
|
|
||||||
#push [ [ node-param get ] bind , ] "scan-literal" set-word-prop
|
: kill-literal ( literals values -- values )
|
||||||
#push [ consumes-literal? not ] "can-kill" set-word-prop
|
[
|
||||||
#push [ kill-node ] "kill-node" set-word-prop
|
swap [ swap value= ] some-with? not
|
||||||
|
] subset-with ;
|
||||||
|
|
||||||
|
#push [
|
||||||
|
[ node-produce-d get ] bind [ literal-value ] map %
|
||||||
|
] "scan-literal" set-word-prop
|
||||||
|
|
||||||
|
#push [ 2drop t ] "can-kill" set-word-prop
|
||||||
|
|
||||||
|
#push [
|
||||||
|
[ node-produce-d [ kill-literal ] change ] extend ,
|
||||||
|
] "kill-node" set-word-prop
|
||||||
|
|
||||||
|
#drop [ 2drop t ] "can-kill" set-word-prop
|
||||||
|
|
||||||
|
#drop [
|
||||||
|
[ node-consume-d [ kill-literal ] change ] extend ,
|
||||||
|
] "kill-node" set-word-prop
|
||||||
|
|
||||||
#label [
|
#label [
|
||||||
[ node-param get ] bind (scan-literals)
|
[ node-param get ] bind (scan-literals)
|
||||||
|
@ -123,10 +140,6 @@ SYMBOL: branch-returns
|
||||||
[ node-param get ] bind calls-label?
|
[ node-param get ] bind calls-label?
|
||||||
] "calls-label" set-word-prop
|
] "calls-label" set-word-prop
|
||||||
|
|
||||||
#simple-label [
|
|
||||||
[ node-param get ] bind calls-label?
|
|
||||||
] "calls-label" set-word-prop
|
|
||||||
|
|
||||||
: branches-call-label? ( label list -- ? )
|
: branches-call-label? ( label list -- ? )
|
||||||
[ calls-label? ] some-with? ;
|
[ calls-label? ] some-with? ;
|
||||||
|
|
||||||
|
@ -138,16 +151,8 @@ SYMBOL: branch-returns
|
||||||
[ node-param get ] bind branches-call-label?
|
[ node-param get ] bind branches-call-label?
|
||||||
] "calls-label" set-word-prop
|
] "calls-label" set-word-prop
|
||||||
|
|
||||||
: optimize-label ( -- op )
|
|
||||||
#! Does the label node contain calls to itself?
|
|
||||||
node-label get node-param get calls-label?
|
|
||||||
#label #simple-label ? ;
|
|
||||||
|
|
||||||
#label [ ( literals node -- )
|
#label [ ( literals node -- )
|
||||||
[
|
[ node-param [ kill-nodes ] change ] extend ,
|
||||||
optimize-label node-op set
|
|
||||||
node-param [ kill-nodes ] change
|
|
||||||
] extend ,
|
|
||||||
] "kill-node" set-word-prop
|
] "kill-node" set-word-prop
|
||||||
|
|
||||||
#values [
|
#values [
|
||||||
|
|
|
@ -51,14 +51,15 @@ M: %label simplify-node ( linear vop -- linear ? )
|
||||||
|
|
||||||
M: %inc-d simplify-node ( linear vop -- linear ? )
|
M: %inc-d simplify-node ( linear vop -- linear ? )
|
||||||
#! %inc-d cancels a following %inc-d.
|
#! %inc-d cancels a following %inc-d.
|
||||||
>r dup \ %inc-d next-physical? [
|
dup vop-literal 0 = [
|
||||||
vop-literal r> vop-literal + dup 0 = [
|
drop cdr t
|
||||||
drop cdr cdr f
|
|
||||||
] [
|
|
||||||
%inc-d >r cdr cdr r> swons t
|
|
||||||
] ifte
|
|
||||||
] [
|
] [
|
||||||
r> 2drop f
|
>r dup \ %inc-d next-physical? [
|
||||||
|
vop-literal r> vop-literal +
|
||||||
|
%inc-d >r cdr cdr r> swons t
|
||||||
|
] [
|
||||||
|
r> 2drop f
|
||||||
|
] ifte
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: dead-load? ( linear vop -- ? )
|
: dead-load? ( linear vop -- ? )
|
||||||
|
@ -91,8 +92,8 @@ M: %replace-d simplify-node ( linear vop -- linear ? )
|
||||||
] ifte
|
] ifte
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
M: %immediate-d simplify-node ( linear vop -- linear ? )
|
! M: %immediate-d simplify-node ( linear vop -- linear ? )
|
||||||
over 0 dead-store? [ drop cdr t ] [ drop f ] ifte ;
|
! over 0 dead-store? [ drop cdr t ] [ drop f ] ifte ;
|
||||||
|
|
||||||
: pop? ( vop -- ? ) dup %inc-d? swap vop-literal -1 = and ;
|
: pop? ( vop -- ? ) dup %inc-d? swap vop-literal -1 = and ;
|
||||||
|
|
||||||
|
|
|
@ -93,8 +93,8 @@ VOP: %inc-d
|
||||||
: %inc-d ( n -- ) literal-vop <%inc-d> ;
|
: %inc-d ( n -- ) literal-vop <%inc-d> ;
|
||||||
: %dec-d ( n -- ) neg %inc-d ;
|
: %dec-d ( n -- ) neg %inc-d ;
|
||||||
VOP: %immediate
|
VOP: %immediate
|
||||||
VOP: %immediate-d
|
: %immediate ( vreg obj -- )
|
||||||
: %immediate-d ( obj -- ) literal-vop <%immediate-d> ;
|
>r <vreg> r> dest/literal-vop <%immediate> ;
|
||||||
VOP: %peek-r
|
VOP: %peek-r
|
||||||
: %peek-r ( vreg n -- ) >r >r f r> <vreg> r> f <%peek-r> ;
|
: %peek-r ( vreg n -- ) >r >r f r> <vreg> r> f <%peek-r> ;
|
||||||
VOP: %replace-r
|
VOP: %replace-r
|
||||||
|
|
|
@ -36,7 +36,7 @@ memory namespaces words ;
|
||||||
! An untagged pointer to the bignum is now in EAX; tag it
|
! An untagged pointer to the bignum is now in EAX; tag it
|
||||||
EAX bignum-tag OR
|
EAX bignum-tag OR
|
||||||
ESP 4 ADD
|
ESP 4 ADD
|
||||||
"end" get save-xt ;
|
"end" get save-xt ; inline
|
||||||
|
|
||||||
M: %fixnum+ generate-node ( vop -- )
|
M: %fixnum+ generate-node ( vop -- )
|
||||||
dest/src 2dup ADD \ SUB \ ADD simple-overflow ;
|
dest/src 2dup ADD \ SUB \ ADD simple-overflow ;
|
||||||
|
|
|
@ -30,9 +30,6 @@ M: %inc-d generate-node ( vop -- )
|
||||||
M: %immediate generate-node ( vop -- )
|
M: %immediate generate-node ( vop -- )
|
||||||
dup vop-dest v>operand swap vop-literal address MOV ;
|
dup vop-dest v>operand swap vop-literal address MOV ;
|
||||||
|
|
||||||
M: %immediate-d generate-node ( vop -- )
|
|
||||||
vop-literal [ ESI ] swap address MOV ;
|
|
||||||
|
|
||||||
: load-indirect ( dest literal -- )
|
: load-indirect ( dest literal -- )
|
||||||
intern-literal unit MOV 0 0 rel-address ;
|
intern-literal unit MOV 0 0 rel-address ;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ builtin [ 2drop t ] "class<" set-word-prop
|
||||||
dup intern-symbol
|
dup intern-symbol
|
||||||
dup r> "builtin-type" set-word-prop
|
dup r> "builtin-type" set-word-prop
|
||||||
dup builtin define-class
|
dup builtin define-class
|
||||||
dup r> unit "predicate" set-word-prop
|
dup r> set-predicate
|
||||||
dup builtin-predicate
|
dup builtin-predicate
|
||||||
dup r> define-slots
|
dup r> define-slots
|
||||||
register-builtin ;
|
register-builtin ;
|
||||||
|
|
|
@ -174,4 +174,8 @@ SYMBOL: object
|
||||||
dup builtin-supertypes [ > ] sort
|
dup builtin-supertypes [ > ] sort
|
||||||
typemap get set-hash ;
|
typemap get set-hash ;
|
||||||
|
|
||||||
|
: set-predicate ( class word -- )
|
||||||
|
dup t "inline" set-word-prop
|
||||||
|
unit "predicate" set-word-prop ;
|
||||||
|
|
||||||
typemap get [ <namespace> typemap set ] unless
|
typemap get [ <namespace> typemap set ] unless
|
||||||
|
|
|
@ -69,8 +69,7 @@ UNION: arrayed array tuple ;
|
||||||
: tuple-predicate ( word -- )
|
: tuple-predicate ( word -- )
|
||||||
#! Make a foo? word for testing the tuple class at the top
|
#! Make a foo? word for testing the tuple class at the top
|
||||||
#! of the stack.
|
#! of the stack.
|
||||||
dup predicate-word
|
dup predicate-word 2dup set-predicate
|
||||||
2dup unit "predicate" set-word-prop
|
|
||||||
swap [
|
swap [
|
||||||
[ dup tuple? ] %
|
[ dup tuple? ] %
|
||||||
[ \ class-tuple , literal, \ eq? , ] make-list ,
|
[ \ class-tuple , literal, \ eq? , ] make-list ,
|
||||||
|
@ -78,12 +77,15 @@ UNION: arrayed array tuple ;
|
||||||
\ ifte ,
|
\ ifte ,
|
||||||
] make-list define-compound ;
|
] make-list define-compound ;
|
||||||
|
|
||||||
|
: forget-tuple ( class -- )
|
||||||
|
dup forget "predicate" word-prop car forget ;
|
||||||
|
|
||||||
: check-shape ( word slots -- )
|
: check-shape ( word slots -- )
|
||||||
#! If the new list of slots is different from the previous,
|
#! If the new list of slots is different from the previous,
|
||||||
#! forget the old definition.
|
#! forget the old definition.
|
||||||
>r "use" get search dup [
|
>r "use" get search dup [
|
||||||
dup "tuple-size" word-prop r> length 2 + =
|
dup "tuple-size" word-prop r> length 2 + =
|
||||||
[ drop ] [ forget ] ifte
|
[ drop ] [ forget-tuple ] ifte
|
||||||
] [
|
] [
|
||||||
r> 2drop
|
r> 2drop
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
|
@ -4,7 +4,7 @@ IN: inference
|
||||||
USING: errors generic interpreter kernel lists math namespaces
|
USING: errors generic interpreter kernel lists math namespaces
|
||||||
sequences strings vectors words hashtables prettyprint ;
|
sequences strings vectors words hashtables prettyprint ;
|
||||||
|
|
||||||
: longest-vector ( list -- length )
|
: longest ( list -- length )
|
||||||
0 swap [ length max ] each ;
|
0 swap [ length max ] each ;
|
||||||
|
|
||||||
: computed-value-vector ( n -- vector )
|
: computed-value-vector ( n -- vector )
|
||||||
|
@ -17,7 +17,7 @@ sequences strings vectors words hashtables prettyprint ;
|
||||||
: unify-lengths ( list -- list )
|
: unify-lengths ( list -- list )
|
||||||
#! Pad all vectors to the same length. If one vector is
|
#! Pad all vectors to the same length. If one vector is
|
||||||
#! shorter, pad it with unknown results at the bottom.
|
#! shorter, pad it with unknown results at the bottom.
|
||||||
dup longest-vector swap [ add-inputs ] map-with ;
|
dup longest swap [ add-inputs ] map-with ;
|
||||||
|
|
||||||
: unify-results ( list -- value )
|
: unify-results ( list -- value )
|
||||||
#! If all values in list are equal, return the value.
|
#! If all values in list are equal, return the value.
|
||||||
|
@ -137,49 +137,20 @@ SYMBOL: cloned
|
||||||
#! base case to this stack effect and try again.
|
#! base case to this stack effect and try again.
|
||||||
(infer-branches) dup unify-effects unify-dataflow ;
|
(infer-branches) dup unify-effects unify-dataflow ;
|
||||||
|
|
||||||
: (with-block) ( [[ label quot ]] quot -- node )
|
: infer-ifte ( true false -- )
|
||||||
#! Call a quotation in a new namespace, and transfer
|
|
||||||
#! inference state from the outer scope.
|
|
||||||
swap car >r [
|
|
||||||
dataflow-graph off
|
|
||||||
call
|
|
||||||
d-in get meta-d get meta-r get get-dataflow
|
|
||||||
] with-scope
|
|
||||||
r> swap #label dataflow, [ node-label set ] extend >r
|
|
||||||
meta-r set meta-d set d-in set r> ;
|
|
||||||
|
|
||||||
: with-block ( word [[ label quot ]] quot -- node )
|
|
||||||
#! Execute a quotation with the word on the stack, and add
|
|
||||||
#! its dataflow contribution to a new block node in the IR.
|
|
||||||
over [
|
|
||||||
>r
|
|
||||||
dupd cons
|
|
||||||
recursive-state [ cons ] change
|
|
||||||
r> call
|
|
||||||
] (with-block) ;
|
|
||||||
|
|
||||||
: dynamic-ifte ( true false -- )
|
|
||||||
#! If branch taken is computed, infer along both paths and
|
#! If branch taken is computed, infer along both paths and
|
||||||
#! unify.
|
#! unify.
|
||||||
2list >r peek-d \ ifte r>
|
2list >r pop-d \ ifte r>
|
||||||
pop-d [
|
pick [ general-t POSTPONE: f ] [ <class-tie> ] map-with
|
||||||
dup \ general-t <class-tie> ,
|
zip ( condition )
|
||||||
\ f <class-tie> ,
|
|
||||||
] make-list zip ( condition )
|
|
||||||
infer-branches ;
|
infer-branches ;
|
||||||
|
|
||||||
: infer-ifte ( -- )
|
\ ifte [
|
||||||
#! Infer effects for both branches, unify.
|
2 dataflow-drop, pop-d pop-d swap infer-ifte
|
||||||
[ object general-list general-list ] ensure-d
|
] "infer" set-word-prop
|
||||||
dataflow-drop, pop-d
|
|
||||||
dataflow-drop, pop-d swap
|
|
||||||
dynamic-ifte ;
|
|
||||||
|
|
||||||
\ ifte [ infer-ifte ] "infer" set-word-prop
|
: vtable>list ( rstate vtable -- list )
|
||||||
|
[ swap <literal> ] map-with >list ;
|
||||||
: vtable>list ( value -- list )
|
|
||||||
dup value-recursion swap literal-value >list
|
|
||||||
[ over <literal> ] map nip ;
|
|
||||||
|
|
||||||
: <dispatch-index> ( value -- value )
|
: <dispatch-index> ( value -- value )
|
||||||
value-literal-ties
|
value-literal-ties
|
||||||
|
@ -188,17 +159,12 @@ SYMBOL: cloned
|
||||||
|
|
||||||
USE: kernel-internals
|
USE: kernel-internals
|
||||||
|
|
||||||
: dynamic-dispatch ( vtable -- )
|
: infer-dispatch ( rstate vtable -- )
|
||||||
>r peek-d \ dispatch r>
|
>r >r peek-d \ dispatch r> r>
|
||||||
vtable>list
|
vtable>list
|
||||||
pop-d <dispatch-index>
|
pop-d <dispatch-index>
|
||||||
over length [ <literal-tie> ] project-with
|
over length [ <literal-tie> ] project-with
|
||||||
zip infer-branches ;
|
zip infer-branches ;
|
||||||
|
|
||||||
: infer-dispatch ( -- )
|
\ dispatch [ pop-literal infer-dispatch ] "infer" set-word-prop
|
||||||
#! Infer effects for all branches, unify.
|
|
||||||
[ object vector ] ensure-d
|
|
||||||
dataflow-drop, pop-d dynamic-dispatch ;
|
|
||||||
|
|
||||||
\ dispatch [ infer-dispatch ] "infer" set-word-prop
|
|
||||||
\ dispatch [ [ fixnum vector ] [ ] ] "infer-effect" set-word-prop
|
\ dispatch [ [ fixnum vector ] [ ] ] "infer-effect" set-word-prop
|
||||||
|
|
|
@ -1,39 +1,11 @@
|
||||||
! :folding=indent:collapseFolds=1:
|
! Copyright (C) 2004, 2005 Slava Pestov.
|
||||||
|
! See http://factor.sf.net/license.txt for BSD license.
|
||||||
! $Id$
|
|
||||||
!
|
|
||||||
! Copyright (C) 2004 Slava Pestov.
|
|
||||||
!
|
|
||||||
! Redistribution and use in source and binary forms, with or without
|
|
||||||
! modification, are permitted provided that the following conditions are met:
|
|
||||||
!
|
|
||||||
! 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
! this list of conditions and the following disclaimer.
|
|
||||||
!
|
|
||||||
! 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
! this list of conditions and the following disclaimer in the documentation
|
|
||||||
! and/or other materials provided with the distribution.
|
|
||||||
!
|
|
||||||
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
||||||
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
IN: inference
|
IN: inference
|
||||||
USE: interpreter
|
USING: interpreter kernel lists namespaces sequences vectors
|
||||||
USE: kernel
|
words ;
|
||||||
USE: lists
|
|
||||||
USE: math
|
! Recursive state. An alist, mapping words to labels.
|
||||||
USE: namespaces
|
SYMBOL: recursive-state
|
||||||
USE: words
|
|
||||||
USE: vectors
|
|
||||||
USE: sequences
|
|
||||||
|
|
||||||
! We build a dataflow graph for the compiler.
|
! We build a dataflow graph for the compiler.
|
||||||
SYMBOL: dataflow-graph
|
SYMBOL: dataflow-graph
|
||||||
|
@ -41,14 +13,10 @@ SYMBOL: dataflow-graph
|
||||||
! Label nodes have the node-label variable set.
|
! Label nodes have the node-label variable set.
|
||||||
SYMBOL: #label
|
SYMBOL: #label
|
||||||
|
|
||||||
! A label that is not called recursively at all, or only tail
|
|
||||||
! recursively. The optimizer changes some #labels to
|
|
||||||
! #simple-labels.
|
|
||||||
SYMBOL: #simple-label
|
|
||||||
|
|
||||||
SYMBOL: #call ( non-tail call )
|
SYMBOL: #call ( non-tail call )
|
||||||
SYMBOL: #call-label
|
SYMBOL: #call-label
|
||||||
SYMBOL: #push ( literal )
|
SYMBOL: #push ( literal )
|
||||||
|
SYMBOL: #drop
|
||||||
|
|
||||||
! This is purely a marker for values we retain after a
|
! This is purely a marker for values we retain after a
|
||||||
! conditional. It does not generate code, but merely alerts the
|
! conditional. It does not generate code, but merely alerts the
|
||||||
|
@ -101,10 +69,11 @@ SYMBOL: node-param
|
||||||
#! Add a node to the dataflow IR.
|
#! Add a node to the dataflow IR.
|
||||||
<dataflow-node> dup dataflow-graph [ cons ] change ;
|
<dataflow-node> dup dataflow-graph [ cons ] change ;
|
||||||
|
|
||||||
: dataflow-drop, ( -- )
|
: dataflow-drop, ( n -- )
|
||||||
#! Remove the top stack element and add a dataflow node
|
f #drop dataflow, [ 0 node-inputs ] bind ;
|
||||||
#! noting this.
|
|
||||||
f \ drop dataflow, [ 1 0 node-inputs ] bind ;
|
: dataflow-push, ( n -- )
|
||||||
|
f #push dataflow, [ 0 node-outputs ] bind ;
|
||||||
|
|
||||||
: apply-dataflow ( dataflow name default -- )
|
: apply-dataflow ( dataflow name default -- )
|
||||||
#! For the dataflow node, look up named word property,
|
#! For the dataflow node, look up named word property,
|
||||||
|
|
|
@ -17,68 +17,9 @@ SYMBOL: inferring-base-case
|
||||||
! inputs.
|
! inputs.
|
||||||
SYMBOL: d-in
|
SYMBOL: d-in
|
||||||
|
|
||||||
! Recursive state. An alist, mapping words to labels.
|
|
||||||
SYMBOL: recursive-state
|
|
||||||
|
|
||||||
GENERIC: value= ( literal value -- ? )
|
|
||||||
GENERIC: value-class-and ( class value -- )
|
|
||||||
|
|
||||||
TUPLE: value class recursion class-ties literal-ties ;
|
|
||||||
|
|
||||||
C: value ( recursion -- value )
|
|
||||||
[ set-value-recursion ] keep ;
|
|
||||||
|
|
||||||
TUPLE: computed ;
|
|
||||||
|
|
||||||
C: computed ( class -- value )
|
|
||||||
swap recursive-state get <value> [ set-value-class ] keep
|
|
||||||
over set-delegate ;
|
|
||||||
|
|
||||||
M: computed value= ( literal value -- ? )
|
|
||||||
2drop f ;
|
|
||||||
|
|
||||||
: failing-class-and ( class class -- class )
|
|
||||||
2dup class-and dup null = [
|
|
||||||
-rot [
|
|
||||||
word-name , " and " , word-name ,
|
|
||||||
" do not intersect" ,
|
|
||||||
] make-string inference-warning
|
|
||||||
] [
|
|
||||||
2nip
|
|
||||||
] ifte ;
|
|
||||||
|
|
||||||
M: computed value-class-and ( class value -- )
|
|
||||||
[
|
|
||||||
value-class failing-class-and
|
|
||||||
] keep set-value-class ;
|
|
||||||
|
|
||||||
TUPLE: literal value ;
|
|
||||||
|
|
||||||
C: literal ( obj rstate -- value )
|
|
||||||
[
|
|
||||||
>r <value> [ >r dup class r> set-value-class ] keep
|
|
||||||
r> set-delegate
|
|
||||||
] keep
|
|
||||||
[ set-literal-value ] keep ;
|
|
||||||
|
|
||||||
M: literal value= ( literal value -- ? )
|
|
||||||
literal-value = ;
|
|
||||||
|
|
||||||
M: literal value-class-and ( class value -- )
|
|
||||||
value-class class-and drop ;
|
|
||||||
|
|
||||||
M: literal set-value-class ( class value -- )
|
|
||||||
2drop ;
|
|
||||||
|
|
||||||
M: computed literal-value ( value -- )
|
|
||||||
"A literal value was expected where a computed value was"
|
|
||||||
" found: " rot unparse cat3 inference-error ;
|
|
||||||
|
|
||||||
: value-types ( value -- list )
|
|
||||||
value-class builtin-supertypes ;
|
|
||||||
|
|
||||||
: pop-literal ( -- rstate obj )
|
: pop-literal ( -- rstate obj )
|
||||||
dataflow-drop, pop-d dup value-recursion swap literal-value ;
|
1 dataflow-drop, pop-d
|
||||||
|
dup value-recursion swap literal-value ;
|
||||||
|
|
||||||
: (ensure-types) ( typelist n stack -- )
|
: (ensure-types) ( typelist n stack -- )
|
||||||
pick [
|
pick [
|
||||||
|
@ -131,8 +72,7 @@ GENERIC: apply-object
|
||||||
: apply-literal ( obj -- )
|
: apply-literal ( obj -- )
|
||||||
#! Literals are annotated with the current recursive
|
#! Literals are annotated with the current recursive
|
||||||
#! state.
|
#! state.
|
||||||
dup recursive-state get <literal> push-d
|
recursive-state get <literal> push-d 1 dataflow-push, ;
|
||||||
#push dataflow, [ 1 0 node-outputs ] bind ;
|
|
||||||
|
|
||||||
M: object apply-object apply-literal ;
|
M: object apply-object apply-literal ;
|
||||||
|
|
||||||
|
@ -140,11 +80,6 @@ M: object apply-object apply-literal ;
|
||||||
#! Is this branch not terminated?
|
#! Is this branch not terminated?
|
||||||
d-in get meta-d get and ;
|
d-in get meta-d get and ;
|
||||||
|
|
||||||
: check-active ( -- )
|
|
||||||
active? [
|
|
||||||
"Provable runtime error" inference-error
|
|
||||||
] unless ;
|
|
||||||
|
|
||||||
: effect ( -- [[ d-in meta-d ]] )
|
: effect ( -- [[ d-in meta-d ]] )
|
||||||
d-in get meta-d get cons ;
|
d-in get meta-d get cons ;
|
||||||
|
|
||||||
|
@ -170,9 +105,12 @@ M: object apply-object apply-literal ;
|
||||||
drop
|
drop
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
|
: check-active ( -- )
|
||||||
|
active? [ "Provable runtime error" inference-error ] unless ;
|
||||||
|
|
||||||
: check-return ( -- )
|
: check-return ( -- )
|
||||||
#! Raise an error if word leaves values on return stack.
|
#! Raise an error if word leaves values on return stack.
|
||||||
meta-r get length 0 = [
|
meta-r get empty? [
|
||||||
"Word leaves elements on return stack" inference-error
|
"Word leaves elements on return stack" inference-error
|
||||||
] unless ;
|
] unless ;
|
||||||
|
|
||||||
|
@ -182,16 +120,18 @@ M: object apply-object apply-literal ;
|
||||||
meta-d get >list node-consume-d set
|
meta-d get >list node-consume-d set
|
||||||
] bind ;
|
] bind ;
|
||||||
|
|
||||||
: (infer) ( quot -- )
|
: with-infer ( quot -- )
|
||||||
f init-inference
|
[
|
||||||
infer-quot
|
f init-inference
|
||||||
check-active
|
call
|
||||||
#return values-node check-return ;
|
check-active
|
||||||
|
check-return
|
||||||
|
] with-scope ;
|
||||||
|
|
||||||
: infer ( quot -- [[ in out ]] )
|
: infer ( quot -- [[ in out ]] )
|
||||||
#! Stack effect of a quotation.
|
#! Stack effect of a quotation.
|
||||||
[ (infer) effect present-effect ] with-scope ;
|
[ infer-quot effect present-effect ] with-infer ;
|
||||||
|
|
||||||
: dataflow ( quot -- dataflow )
|
: dataflow ( quot -- dataflow )
|
||||||
#! Data flow of a quotation.
|
#! Data flow of a quotation.
|
||||||
[ (infer) get-dataflow ] with-scope ;
|
[ infer-quot #return values-node get-dataflow ] with-infer ;
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
! Copyright (C) 2005 Slava Pestov.
|
||||||
|
! See http://factor.sf.net/license.txt for BSD license.
|
||||||
|
IN: inference
|
||||||
|
USING: generic interpreter kernel lists math namespaces
|
||||||
|
sequences words ;
|
||||||
|
|
||||||
|
: literal-inputs? ( in stack -- )
|
||||||
|
tail-slice dup >list [ literal-safe? ] all? [
|
||||||
|
length dataflow-drop, t
|
||||||
|
] [
|
||||||
|
drop f
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: literal-inputs ( out stack -- )
|
||||||
|
tail-slice [ literal-value ] nmap ;
|
||||||
|
|
||||||
|
: literal-outputs ( out stack -- )
|
||||||
|
tail-slice dup [ recursive-state get <literal> ] nmap
|
||||||
|
length dataflow-push, ;
|
||||||
|
|
||||||
|
: partial-eval? ( word -- ? )
|
||||||
|
"infer-effect" word-prop car length
|
||||||
|
meta-d get literal-inputs? ;
|
||||||
|
|
||||||
|
: infer-eval ( word -- )
|
||||||
|
dup partial-eval? [
|
||||||
|
dup "infer-effect" word-prop 2unlist
|
||||||
|
>r length meta-d get
|
||||||
|
literal-inputs
|
||||||
|
host-word
|
||||||
|
r> length meta-d get literal-outputs
|
||||||
|
] [
|
||||||
|
dup "infer-effect" word-prop consume/produce
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: stateless ( word -- )
|
||||||
|
#! A stateless word can be evaluated at compile-time.
|
||||||
|
dup unit [ car infer-eval ] cons "infer" set-word-prop ;
|
||||||
|
|
||||||
|
! Could probably add more words here
|
||||||
|
[
|
||||||
|
car
|
||||||
|
cdr
|
||||||
|
cons
|
||||||
|
<
|
||||||
|
<=
|
||||||
|
>
|
||||||
|
>=
|
||||||
|
number=
|
||||||
|
+
|
||||||
|
-
|
||||||
|
*
|
||||||
|
/
|
||||||
|
/i
|
||||||
|
/f
|
||||||
|
mod
|
||||||
|
/mod
|
||||||
|
bitand
|
||||||
|
bitor
|
||||||
|
bitxor
|
||||||
|
shift
|
||||||
|
bitnot
|
||||||
|
>fixnum
|
||||||
|
>bignum
|
||||||
|
>float
|
||||||
|
real
|
||||||
|
imaginary
|
||||||
|
] [
|
||||||
|
stateless
|
||||||
|
] each
|
||||||
|
|
||||||
|
! Partially-evaluated words need their stack effects to be
|
||||||
|
! entered by hand.
|
||||||
|
\ car [ [ general-list ] [ object ] ] "infer-effect" set-word-prop
|
||||||
|
\ cdr [ [ general-list ] [ object ] ] "infer-effect" set-word-prop
|
||||||
|
\ < [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
|
||||||
|
\ <= [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
|
||||||
|
\ > [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
|
||||||
|
\ >= [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
|
||||||
|
\ number= [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
|
||||||
|
\ + [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
||||||
|
\ - [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
||||||
|
\ * [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
||||||
|
\ / [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
||||||
|
\ /i [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
||||||
|
\ /f [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
||||||
|
\ mod [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ /mod [ [ integer integer ] [ integer integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ bitand [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ bitor [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ bitxor [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ shift [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ bitnot [ [ integer ] [ integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ gcd [ [ integer integer ] [ integer integer ] ] "infer-effect" set-word-prop
|
||||||
|
\ real [ [ number ] [ real ] ] "infer-effect" set-word-prop
|
||||||
|
\ imaginary [ [ number ] [ real ] ] "infer-effect" set-word-prop
|
|
@ -15,12 +15,13 @@ USING: interpreter kernel namespaces words ;
|
||||||
[ 1 0 node-outputs ] bind
|
[ 1 0 node-outputs ] bind
|
||||||
] "infer" set-word-prop
|
] "infer" set-word-prop
|
||||||
|
|
||||||
: infer-shuffle ( word -- )
|
: partial-eval ( word quot -- | quot: word -- )
|
||||||
f over dup
|
>r f over dup "infer-effect" word-prop r> with-dataflow ;
|
||||||
"infer-effect" word-prop
|
|
||||||
[ host-word ] with-dataflow ;
|
|
||||||
|
|
||||||
\ drop [ \ drop infer-shuffle ] "infer" set-word-prop
|
: infer-shuffle ( word -- )
|
||||||
|
[ host-word ] partial-eval ;
|
||||||
|
|
||||||
|
\ drop [ 1 dataflow-drop, pop-d drop ] "infer" set-word-prop
|
||||||
\ dup [ \ dup infer-shuffle ] "infer" set-word-prop
|
\ dup [ \ dup infer-shuffle ] "infer" set-word-prop
|
||||||
\ swap [ \ swap infer-shuffle ] "infer" set-word-prop
|
\ swap [ \ swap infer-shuffle ] "infer" set-word-prop
|
||||||
\ over [ \ over infer-shuffle ] "infer" set-word-prop
|
\ over [ \ over infer-shuffle ] "infer" set-word-prop
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
! Copyright (C) 2004, 2005 Slava Pestov.
|
||||||
|
! See http://factor.sf.net/license.txt for BSD license.
|
||||||
|
IN: inference
|
||||||
|
USING: generic kernel namespaces sequences unparser words ;
|
||||||
|
|
||||||
|
GENERIC: value= ( literal value -- ? )
|
||||||
|
GENERIC: value-class-and ( class value -- )
|
||||||
|
|
||||||
|
TUPLE: value class recursion class-ties literal-ties ;
|
||||||
|
|
||||||
|
C: value ( recursion -- value )
|
||||||
|
[ set-value-recursion ] keep ;
|
||||||
|
|
||||||
|
TUPLE: computed ;
|
||||||
|
|
||||||
|
C: computed ( class -- value )
|
||||||
|
swap recursive-state get <value> [ set-value-class ] keep
|
||||||
|
over set-delegate ;
|
||||||
|
|
||||||
|
M: computed value= ( literal value -- ? )
|
||||||
|
2drop f ;
|
||||||
|
|
||||||
|
: failing-class-and ( class class -- class )
|
||||||
|
2dup class-and dup null = [
|
||||||
|
-rot [
|
||||||
|
word-name , " and " , word-name ,
|
||||||
|
" do not intersect" ,
|
||||||
|
] make-string inference-warning
|
||||||
|
] [
|
||||||
|
2nip
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
M: computed value-class-and ( class value -- )
|
||||||
|
[
|
||||||
|
value-class failing-class-and
|
||||||
|
] keep set-value-class ;
|
||||||
|
|
||||||
|
TUPLE: literal value safe? ;
|
||||||
|
|
||||||
|
C: literal ( obj rstate -- value )
|
||||||
|
[ t swap set-literal-safe? ] keep
|
||||||
|
[
|
||||||
|
>r <value> [ >r dup class r> set-value-class ] keep
|
||||||
|
r> set-delegate
|
||||||
|
] keep
|
||||||
|
[ set-literal-value ] keep ;
|
||||||
|
|
||||||
|
M: literal value= ( literal value -- ? )
|
||||||
|
literal-value = ;
|
||||||
|
|
||||||
|
M: literal value-class-and ( class value -- )
|
||||||
|
value-class class-and drop ;
|
||||||
|
|
||||||
|
M: literal set-value-class ( class value -- )
|
||||||
|
2drop ;
|
||||||
|
|
||||||
|
M: computed literal-safe? drop f ;
|
||||||
|
|
||||||
|
M: computed set-literal-safe? 2drop ;
|
||||||
|
|
||||||
|
M: computed literal-value ( value -- )
|
||||||
|
"A literal value was expected where a computed value was"
|
||||||
|
" found: " rot unparse append3 inference-error ;
|
||||||
|
|
||||||
|
: value-types ( value -- list )
|
||||||
|
value-class builtin-supertypes ;
|
|
@ -33,13 +33,48 @@ hashtables parser prettyprint ;
|
||||||
: no-effect ( word -- )
|
: no-effect ( word -- )
|
||||||
"Unknown stack effect: " swap word-name cat2 inference-error ;
|
"Unknown stack effect: " swap word-name cat2 inference-error ;
|
||||||
|
|
||||||
: inline-compound ( word -- effect node )
|
: inhibit-parital ( -- )
|
||||||
|
meta-d get [ f swap set-literal-safe? ] each ;
|
||||||
|
|
||||||
|
: recursive? ( word -- ? )
|
||||||
|
f swap dup word-def [ = or ] tree-each-with ;
|
||||||
|
|
||||||
|
: (with-block) ( [[ label quot ]] quot -- node )
|
||||||
|
#! Call a quotation in a new namespace, and transfer
|
||||||
|
#! inference state from the outer scope.
|
||||||
|
swap car >r [
|
||||||
|
dataflow-graph off
|
||||||
|
call
|
||||||
|
d-in get meta-d get meta-r get get-dataflow
|
||||||
|
] with-scope
|
||||||
|
r> swap #label dataflow, [ node-label set ] extend >r
|
||||||
|
meta-r set meta-d set d-in set r> ;
|
||||||
|
|
||||||
|
: with-block ( word [[ label quot ]] quot -- node )
|
||||||
|
#! Execute a quotation with the word on the stack, and add
|
||||||
|
#! its dataflow contribution to a new block node in the IR.
|
||||||
|
over [
|
||||||
|
>r
|
||||||
|
dupd cons
|
||||||
|
recursive-state [ cons ] change
|
||||||
|
r> call
|
||||||
|
] (with-block) ;
|
||||||
|
|
||||||
|
: inline-block ( word -- effect node )
|
||||||
|
gensym over word-def cons [
|
||||||
|
inhibit-parital
|
||||||
|
word-def infer-quot effect
|
||||||
|
] with-block ;
|
||||||
|
|
||||||
|
: inline-compound ( word -- )
|
||||||
#! Infer the stack effect of a compound word in the current
|
#! Infer the stack effect of a compound word in the current
|
||||||
#! inferencer instance. If the word in question is recursive
|
#! inferencer instance. If the word in question is recursive
|
||||||
#! we infer its stack effect inside a new block.
|
#! we infer its stack effect inside a new block.
|
||||||
gensym over word-def cons [
|
dup recursive? [
|
||||||
word-def infer-quot effect
|
inline-block 2drop
|
||||||
] with-block ;
|
] [
|
||||||
|
word-def infer-quot
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
: infer-compound ( word -- )
|
: infer-compound ( word -- )
|
||||||
#! Infer a word's stack effect in a separate inferencer
|
#! Infer a word's stack effect in a separate inferencer
|
||||||
|
@ -47,7 +82,7 @@ hashtables parser prettyprint ;
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
recursive-state get init-inference
|
recursive-state get init-inference
|
||||||
dup dup inline-compound drop present-effect
|
dup dup inline-block drop present-effect
|
||||||
[ "infer-effect" set-word-prop ] keep
|
[ "infer-effect" set-word-prop ] keep
|
||||||
] with-scope consume/produce
|
] with-scope consume/produce
|
||||||
] [
|
] [
|
||||||
|
@ -66,6 +101,9 @@ M: object (apply-word) ( word -- )
|
||||||
#! A primitive with an unknown stack effect.
|
#! A primitive with an unknown stack effect.
|
||||||
no-effect ;
|
no-effect ;
|
||||||
|
|
||||||
|
M: primitive (apply-word) ( word -- )
|
||||||
|
dup "infer-effect" word-prop consume/produce ;
|
||||||
|
|
||||||
M: compound (apply-word) ( word -- )
|
M: compound (apply-word) ( word -- )
|
||||||
#! Infer a compound word's stack effect.
|
#! Infer a compound word's stack effect.
|
||||||
dup "no-effect" word-prop [
|
dup "no-effect" word-prop [
|
||||||
|
@ -95,7 +133,7 @@ M: word apply-word ( word -- )
|
||||||
|
|
||||||
M: compound apply-word ( word -- )
|
M: compound apply-word ( word -- )
|
||||||
dup "inline" word-prop [
|
dup "inline" word-prop [
|
||||||
inline-compound 2drop
|
inline-compound
|
||||||
] [
|
] [
|
||||||
apply-default
|
apply-default
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
@ -111,7 +149,7 @@ M: compound apply-word ( word -- )
|
||||||
|
|
||||||
: base-case ( word [ label quot ] -- )
|
: base-case ( word [ label quot ] -- )
|
||||||
[
|
[
|
||||||
car over inline-compound [
|
car over inline-block [
|
||||||
drop
|
drop
|
||||||
[ #call-label ] [ #call ] ?ifte
|
[ #call-label ] [ #call ] ?ifte
|
||||||
node-op set
|
node-op set
|
||||||
|
@ -126,11 +164,15 @@ M: compound apply-word ( word -- )
|
||||||
#! Handle a recursive call, by either applying a previously
|
#! Handle a recursive call, by either applying a previously
|
||||||
#! inferred base case, or raising an error. If the recursive
|
#! inferred base case, or raising an error. If the recursive
|
||||||
#! call is to a local block, emit a label call node.
|
#! call is to a local block, emit a label call node.
|
||||||
inferring-base-case get [
|
over "infer-effect" word-prop [
|
||||||
drop no-base-case
|
nip consume/produce
|
||||||
] [
|
] [
|
||||||
base-case
|
inferring-base-case get [
|
||||||
] ifte ;
|
drop no-base-case
|
||||||
|
] [
|
||||||
|
base-case
|
||||||
|
] ifte
|
||||||
|
] ifte* ;
|
||||||
|
|
||||||
M: word apply-object ( word -- )
|
M: word apply-object ( word -- )
|
||||||
#! Apply the word's stack effect to the inferencer state.
|
#! Apply the word's stack effect to the inferencer state.
|
||||||
|
@ -141,41 +183,28 @@ M: word apply-object ( word -- )
|
||||||
] ifte* ;
|
] ifte* ;
|
||||||
|
|
||||||
: infer-quot-value ( rstate quot -- )
|
: infer-quot-value ( rstate quot -- )
|
||||||
gensym dup pick cons [
|
recursive-state get >r
|
||||||
drop
|
swap recursive-state set
|
||||||
swap recursive-state set
|
dup infer-quot handle-terminator
|
||||||
dup infer-quot
|
r> recursive-state set ;
|
||||||
] with-block drop handle-terminator ;
|
|
||||||
|
|
||||||
\ call [
|
\ call [
|
||||||
[ general-list ] ensure-d pop-literal infer-quot-value
|
pop-literal infer-quot-value
|
||||||
] "infer" set-word-prop
|
] "infer" set-word-prop
|
||||||
|
|
||||||
\ execute [
|
\ execute [
|
||||||
[ word ] ensure-d pop-literal unit infer-quot-value
|
pop-literal unit infer-quot-value
|
||||||
] "infer" set-word-prop
|
] "infer" set-word-prop
|
||||||
|
|
||||||
! These hacks will go away soon
|
! These hacks will go away soon
|
||||||
\ * [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
\ delegate [ [ object ] [ object ] ] "infer-effect" set-word-prop
|
||||||
\ - [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
\ no-method t "terminator" set-word-prop
|
||||||
\ + [ [ number number ] [ number ] ] "infer-effect" set-word-prop
|
\ no-method [ [ object word ] [ ] ] "infer-effect" set-word-prop
|
||||||
\ integer/ [ [ integer integer ] [ rational ] ] "infer-effect" set-word-prop
|
|
||||||
\ gcd [ [ integer integer ] [ integer integer ] ] "infer-effect" set-word-prop
|
|
||||||
\ = [ [ object object ] [ boolean ] ] "infer-effect" set-word-prop
|
|
||||||
\ <= [ [ number number ] [ boolean ] ] "infer-effect" set-word-prop
|
|
||||||
\ < [ [ number number ] [ boolean ] ] "infer-effect" set-word-prop
|
|
||||||
\ >= [ [ number number ] [ boolean ] ] "infer-effect" set-word-prop
|
|
||||||
\ > [ [ number number ] [ boolean ] ] "infer-effect" set-word-prop
|
|
||||||
\ <no-method> [ [ object object ] [ tuple ] ] "infer-effect" set-word-prop
|
\ <no-method> [ [ object object ] [ tuple ] ] "infer-effect" set-word-prop
|
||||||
\ set-no-method-generic [ [ object tuple ] [ ] ] "infer-effect" set-word-prop
|
\ set-no-method-generic [ [ object tuple ] [ ] ] "infer-effect" set-word-prop
|
||||||
\ set-no-method-object [ [ object tuple ] [ ] ] "infer-effect" set-word-prop
|
\ set-no-method-object [ [ object tuple ] [ ] ] "infer-effect" set-word-prop
|
||||||
\ car [ [ general-list ] [ object ] ] "infer-effect" set-word-prop
|
|
||||||
\ real [ [ number ] [ real ] ] "infer-effect" set-word-prop
|
|
||||||
\ imaginary [ [ number ] [ real ] ] "infer-effect" set-word-prop
|
|
||||||
\ delegate [ [ object ] [ object ] ] "infer-effect" set-word-prop
|
|
||||||
|
|
||||||
\ no-method t "terminator" set-word-prop
|
|
||||||
\ no-method [ [ object word ] [ ] ] "infer-effect" set-word-prop
|
|
||||||
\ <no-method> [ [ object word ] [ tuple ] ] "infer-effect" set-word-prop
|
|
||||||
\ not-a-number t "terminator" set-word-prop
|
\ not-a-number t "terminator" set-word-prop
|
||||||
\ throw t "terminator" set-word-prop
|
\ throw t "terminator" set-word-prop
|
||||||
|
\ = [ [ object object ] [ boolean ] ] "infer-effect" set-word-prop
|
||||||
|
\ integer/ [ [ integer integer ] [ rational ] ] "infer-effect" set-word-prop
|
||||||
|
\ gcd [ [ integer integer ] [ integer integer ] ] "infer-effect" set-word-prop
|
||||||
|
|
|
@ -33,19 +33,18 @@ GENERIC: truncate ( n -- n )
|
||||||
GENERIC: floor ( n -- n )
|
GENERIC: floor ( n -- n )
|
||||||
GENERIC: ceiling ( n -- n )
|
GENERIC: ceiling ( n -- n )
|
||||||
|
|
||||||
: max ( x y -- z ) [ > ] 2keep ? ;
|
: max ( x y -- z ) [ > ] 2keep ? ; inline
|
||||||
|
: min ( x y -- z ) [ < ] 2keep ? ; inline
|
||||||
: min ( x y -- z ) [ < ] 2keep ? ;
|
|
||||||
|
|
||||||
: between? ( x min max -- ? )
|
: between? ( x min max -- ? )
|
||||||
#! Push if min <= x <= max. Handles case where min > max
|
#! Push if min <= x <= max. Handles case where min > max
|
||||||
#! by swapping them.
|
#! by swapping them.
|
||||||
2dup > [ swap ] when >r dupd max r> min = ;
|
2dup > [ swap ] when >r dupd max r> min = ;
|
||||||
|
|
||||||
: sq dup * ;
|
: sq dup * ; inline
|
||||||
|
|
||||||
: neg 0 swap - ;
|
: neg 0 swap - ; inline
|
||||||
: recip 1 swap / ;
|
: recip 1 swap / ; inline
|
||||||
|
|
||||||
: rem ( x y -- x%y )
|
: rem ( x y -- x%y )
|
||||||
#! Like modulus, but always gives a positive result.
|
#! Like modulus, but always gives a positive result.
|
||||||
|
|
|
@ -4,6 +4,7 @@ USE: prettyprint
|
||||||
USE: test
|
USE: test
|
||||||
USE: words
|
USE: words
|
||||||
USE: kernel
|
USE: kernel
|
||||||
|
USE: sequences
|
||||||
|
|
||||||
[ ] [ gensym dup [ ] define-compound . ] unit-test
|
[ ] [ gensym dup [ ] define-compound . ] unit-test
|
||||||
[ ] [ vocabs [ words [ see ] each ] each ] unit-test
|
[ ] [ vocabs [ words [ see ] each ] each ] unit-test
|
|
@ -1,5 +1,6 @@
|
||||||
IN: temporary
|
IN: temporary
|
||||||
USE: test
|
USE: test
|
||||||
|
USE: assembler
|
||||||
USE: compiler
|
USE: compiler
|
||||||
USE: compiler-frontend
|
USE: compiler-frontend
|
||||||
USE: inference
|
USE: inference
|
||||||
|
@ -13,8 +14,6 @@ USE: sequences
|
||||||
|
|
||||||
[ [ ] ] [ \ foo word-def dataflow kill-set ] unit-test
|
[ [ ] ] [ \ foo word-def dataflow kill-set ] unit-test
|
||||||
|
|
||||||
[ [ [ + ] [ - ] ] ] [ [ 3 4 1 2 > [ + ] [ - ] ifte ] dataflow kill-set ] unit-test
|
|
||||||
|
|
||||||
[ [ [ 1 ] [ 2 ] ] ] [ [ [ 1 ] [ 2 ] ifte ] dataflow kill-set ] unit-test
|
[ [ [ 1 ] [ 2 ] ] ] [ [ [ 1 ] [ 2 ] ifte ] dataflow kill-set ] unit-test
|
||||||
|
|
||||||
[ [ [ 1 ] [ 2 ] ] ] [ [ [ 1 ] [ 2 ] ifte ] dataflow kill-set ] unit-test
|
[ [ [ 1 ] [ 2 ] ] ] [ [ [ 1 ] [ 2 ] ifte ] dataflow kill-set ] unit-test
|
||||||
|
@ -22,3 +21,15 @@ USE: sequences
|
||||||
[ [ t t f ] ] [ [ 1 2 ] [ 1 2 3 ] [ f <literal> ] map kill-mask ] unit-test
|
[ [ t t f ] ] [ [ 1 2 ] [ 1 2 3 ] [ f <literal> ] map kill-mask ] unit-test
|
||||||
|
|
||||||
[ t ] [ 3 [ 3 over [ ] [ ] ifte drop ] dataflow kill-set contains? ] unit-test
|
[ t ] [ 3 [ 3 over [ ] [ ] ifte drop ] dataflow kill-set contains? ] unit-test
|
||||||
|
|
||||||
|
: literal-kill-test-1 4 compiled-offset cell 2 * - ; compiled
|
||||||
|
|
||||||
|
[ 4 ] [ literal-kill-test-1 drop ] unit-test
|
||||||
|
|
||||||
|
: literal-kill-test-2 3 compiled-offset cell 2 * - ; compiled
|
||||||
|
|
||||||
|
[ 3 ] [ literal-kill-test-2 drop ] unit-test
|
||||||
|
|
||||||
|
: literal-kill-test-3 10 3 /mod drop ; compiled
|
||||||
|
|
||||||
|
[ 3 ] [ literal-kill-test-3 ] unit-test
|
||||||
|
|
|
@ -19,7 +19,7 @@ sequences test words ;
|
||||||
] some-with? ;
|
] some-with? ;
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
\ + [ 2 2 + ] dataflow dataflow-contains-param? >boolean
|
\ + [ 2 + ] dataflow dataflow-contains-param? >boolean
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
: inline-test
|
: inline-test
|
||||||
|
@ -79,10 +79,3 @@ SYMBOL: #test
|
||||||
[[ node-param 5 ]]
|
[[ node-param 5 ]]
|
||||||
}} "foobar" [ [ node-param get ] bind 1 + ] apply-dataflow
|
}} "foobar" [ [ node-param get ] bind 1 + ] apply-dataflow
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
! Somebody (cough) got the order of ifte nodes wrong.
|
|
||||||
|
|
||||||
[ t ] [
|
|
||||||
\ ifte [ [ 1 ] [ 2 ] ifte ] dataflow dataflow-contains-op? car
|
|
||||||
[ node-param get ] bind car car [ node-param get ] bind 1 =
|
|
||||||
] unit-test
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
IN: temporary
|
IN: temporary
|
||||||
USING: gadgets kernel lists math namespaces test ;
|
USING: gadgets kernel lists math namespaces test sequences ;
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
[
|
[
|
||||||
|
|
|
@ -3,6 +3,7 @@ USE: kernel
|
||||||
USE: math
|
USE: math
|
||||||
USE: test
|
USE: test
|
||||||
USE: lists
|
USE: lists
|
||||||
|
USE: sequences
|
||||||
|
|
||||||
[ -2 ] [ 1 bitnot ] unit-test
|
[ -2 ] [ 1 bitnot ] unit-test
|
||||||
[ -2 ] [ 1 >bignum bitnot ] unit-test
|
[ -2 ] [ 1 >bignum bitnot ] unit-test
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
IN: temporary
|
IN: temporary
|
||||||
USING: generic kernel lists math memory words prettyprint test ;
|
USING: generic kernel lists math memory words prettyprint
|
||||||
|
sequences test ;
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
num-types [
|
num-types [
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
IN: temporary
|
IN: temporary
|
||||||
USING: lists test sequences ;
|
USING: lists sequences test vectors ;
|
||||||
|
|
||||||
[ [ 1 2 3 4 ] ] [ 1 4 <range> >list ] unit-test
|
[ [ 1 2 3 4 ] ] [ 1 5 <range> >list ] unit-test
|
||||||
[ 4 ] [ 1 4 <range> length ] unit-test
|
[ 3 ] [ 1 4 <range> length ] unit-test
|
||||||
[ [ 4 3 2 1 ] ] [ 4 1 <range> >list ] unit-test
|
[ [ 4 3 2 1 ] ] [ 4 0 <range> >list ] unit-test
|
||||||
[ 2 ] [ 1 2 { 1 2 3 4 } <slice> length ] unit-test
|
[ 2 ] [ 1 3 { 1 2 3 4 } <slice> length ] unit-test
|
||||||
[ [ 2 3 ] ] [ 1 2 { 1 2 3 4 } <slice> >list ] unit-test
|
[ [ 2 3 ] ] [ 1 3 { 1 2 3 4 } <slice> >list ] unit-test
|
||||||
|
[ { 4 5 } ] [ 2 { 1 2 3 4 5 } tail-slice >vector ] unit-test
|
||||||
|
|
|
@ -69,7 +69,7 @@ SYMBOL: failures
|
||||||
"lists/namespaces" "lists/combinators" "combinators"
|
"lists/namespaces" "lists/combinators" "combinators"
|
||||||
"continuations" "errors" "hashtables" "strings"
|
"continuations" "errors" "hashtables" "strings"
|
||||||
"namespaces" "generic" "tuple" "files" "parser"
|
"namespaces" "generic" "tuple" "files" "parser"
|
||||||
"parse-number" "prettyprint" "image" "init" "io/io"
|
"parse-number" "image" "init" "io/io"
|
||||||
"listener" "vectors" "words" "unparser" "random"
|
"listener" "vectors" "words" "unparser" "random"
|
||||||
"stream" "math/bitops"
|
"stream" "math/bitops"
|
||||||
"math/math-combinators" "math/rational" "math/float"
|
"math/math-combinators" "math/rational" "math/float"
|
||||||
|
@ -102,7 +102,7 @@ SYMBOL: failures
|
||||||
"benchmark/fib" "benchmark/sort"
|
"benchmark/fib" "benchmark/sort"
|
||||||
"benchmark/continuations" "benchmark/ack"
|
"benchmark/continuations" "benchmark/ack"
|
||||||
"benchmark/hashtables" "benchmark/strings"
|
"benchmark/hashtables" "benchmark/strings"
|
||||||
"benchmark/vectors"
|
"benchmark/vectors" "benchmark/prettyprint"
|
||||||
] %
|
] %
|
||||||
] make-list ;
|
] make-list ;
|
||||||
|
|
||||||
|
|
|
@ -41,13 +41,16 @@ C: quuux-tuple-2
|
||||||
[
|
[
|
||||||
100
|
100
|
||||||
] [
|
] [
|
||||||
|
FORGET: point
|
||||||
|
FORGET: point?
|
||||||
|
FORGET: point-x
|
||||||
TUPLE: point x y ;
|
TUPLE: point x y ;
|
||||||
C: point [ set-point-y ] keep [ set-point-x ] keep ;
|
C: point [ set-point-y ] keep [ set-point-x ] keep ;
|
||||||
|
|
||||||
100 200 <point>
|
100 200 <point>
|
||||||
|
|
||||||
! Use eval to sequence parsing explicitly
|
! Use eval to sequence parsing explicitly
|
||||||
"TUPLE: point x y z ;" eval
|
"IN: temporary TUPLE: point x y z ;" eval
|
||||||
|
|
||||||
point-x
|
point-x
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
IN: temporary
|
IN: temporary
|
||||||
USING: generic kernel lists math namespaces test words ;
|
USING: generic kernel lists math namespaces test words sequences ;
|
||||||
|
|
||||||
[ 4 ] [
|
[ 4 ] [
|
||||||
"poo" "scratchpad" create [ 2 2 + ] define-compound
|
"poo" "scratchpad" create [ 2 2 + ] define-compound
|
||||||
|
|
|
@ -109,7 +109,7 @@ M: object (each-slot) ( quot obj -- )
|
||||||
: orphan? ( word -- ? )
|
: orphan? ( word -- ? )
|
||||||
#! Test if the word is not a member of its vocabulary.
|
#! Test if the word is not a member of its vocabulary.
|
||||||
dup dup word-name swap word-vocabulary dup [
|
dup dup word-name swap word-vocabulary dup [
|
||||||
vocab hash eq? not
|
vocab dup [ hash eq? not ] [ 3drop t ] ifte
|
||||||
] [
|
] [
|
||||||
3drop t
|
3drop t
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
|
@ -37,7 +37,7 @@ SYMBOL: vocabularies
|
||||||
|
|
||||||
: recrossref ( -- )
|
: recrossref ( -- )
|
||||||
#! Update word cross referencing information.
|
#! Update word cross referencing information.
|
||||||
[ f "usages" set-word-prop ] each-word
|
global [ <namespace> crossref set ] bind
|
||||||
[ add-crossref ] each-word ;
|
[ add-crossref ] each-word ;
|
||||||
|
|
||||||
: (search) ( name vocab -- word )
|
: (search) ( name vocab -- word )
|
||||||
|
|
Loading…
Reference in New Issue