factor/basis/generator/generator.factor

275 lines
6.8 KiB
Factor
Raw Normal View History

2008-06-11 03:58:38 -04:00
! Copyright (C) 2004, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs classes combinators cpu.architecture
2007-09-20 18:09:08 -04:00
effects generator.fixup generator.registers generic hashtables
2007-09-29 19:43:03 -04:00
inference inference.backend inference.dataflow io kernel
2008-02-05 21:11:35 -05:00
kernel.private layouts math namespaces optimizer
optimizer.specializers prettyprint quotations sequences system
2008-06-11 03:58:38 -04:00
threads words vectors sets dequeues ;
2007-09-20 18:09:08 -04:00
IN: generator
SYMBOL: compile-queue
SYMBOL: compiled
2007-09-20 18:09:08 -04:00
: queue-compile ( word -- )
{
2008-07-05 21:37:28 -04:00
{ [ dup "forgotten" word-prop ] [ ] }
{ [ dup compiled get key? ] [ ] }
{ [ dup inlined-block? ] [ ] }
{ [ dup primitive? ] [ ] }
[ dup compile-queue get push-front ]
} cond drop ;
: maybe-compile ( word -- )
dup compiled>> [ drop ] [ queue-compile ] if ;
2007-09-20 18:09:08 -04:00
SYMBOL: compiling-word
SYMBOL: compiling-label
2008-02-15 19:07:56 -05:00
SYMBOL: compiling-loops
2008-02-13 00:27:05 -05:00
2007-09-20 18:09:08 -04:00
! Label of current word, after prologue, makes recursion faster
SYMBOL: current-label-start
: compiled-stack-traces? ( -- ? ) 59 getenv ;
2007-09-20 18:09:08 -04:00
2008-02-13 00:27:05 -05:00
: begin-compiling ( word label -- )
2008-02-15 19:07:56 -05:00
H{ } clone compiling-loops set
2008-02-13 00:27:05 -05:00
compiling-label set
compiling-word set
2008-01-16 15:45:04 -05:00
compiled-stack-traces?
2008-02-13 00:27:05 -05:00
compiling-word get f ?
1vector literal-table set
f compiling-label get compiled get set-at ;
2008-02-13 00:27:05 -05:00
: save-machine-code ( literals relocation labels code -- )
2008-02-13 00:27:05 -05:00
4array compiling-label get compiled get set-at ;
: with-generator ( node word label quot -- )
[
>r begin-compiling r>
{ } make fixup
save-machine-code
2008-02-13 00:27:05 -05:00
] with-scope ; inline
2007-09-20 18:09:08 -04:00
GENERIC: generate-node ( node -- next )
: generate-nodes ( node -- )
[ node@ generate-node ] iterate-nodes end-basic-block ;
2008-02-09 22:12:00 -05:00
: init-generate-nodes ( -- )
init-templates
%save-word-xt
%prologue-later
current-label-start define-label
current-label-start resolve-label ;
2008-02-12 21:35:25 -05:00
2008-02-13 00:27:05 -05:00
: generate ( node word label -- )
2007-09-20 18:09:08 -04:00
[
2008-02-09 22:12:00 -05:00
init-generate-nodes
2007-09-20 18:09:08 -04:00
[ generate-nodes ] with-node-iterator
2008-02-13 00:27:05 -05:00
] with-generator ;
2007-09-20 18:09:08 -04:00
: word-dataflow ( word -- effect dataflow )
2007-09-20 18:09:08 -04:00
[
2008-06-11 18:40:33 -04:00
[
dup "cannot-infer" word-prop [ cannot-infer-effect ] when
dup "no-compile" word-prop [ cannot-infer-effect ] when
dup specialized-def over dup 2array 1array infer-quot
finish-word
] maybe-cannot-infer
] with-infer ;
2007-09-20 18:09:08 -04:00
: intrinsics ( #call -- quot )
node-param "intrinsics" word-prop ;
: if-intrinsics ( #call -- quot )
node-param "if-intrinsics" word-prop ;
! node
M: node generate-node drop iterate-next ;
: %jump ( word -- )
2008-01-18 17:09:30 -05:00
dup compiling-label get eq?
[ drop current-label-start get ] [ %epilogue-later ] if
%jump-label ;
2007-09-20 18:09:08 -04:00
: generate-call ( label -- next )
dup maybe-compile
2007-09-20 18:09:08 -04:00
end-basic-block
2008-02-15 19:07:56 -05:00
dup compiling-loops get at [
%jump-label f
2007-09-20 18:09:08 -04:00
] [
2008-02-13 00:27:05 -05:00
tail-call? [
%jump f
] [
0 frame-required
%call
iterate-next
] if
2008-02-15 19:07:56 -05:00
] ?if ;
2007-09-20 18:09:08 -04:00
! #label
M: #label generate-node
dup node-param generate-call >r
2008-02-13 01:31:00 -05:00
dup node-child over #label-word rot node-param generate
2007-09-20 18:09:08 -04:00
r> ;
2008-02-12 21:35:25 -05:00
! #loop
2008-02-15 19:07:56 -05:00
: compiling-loop ( word -- )
<label> dup resolve-label swap compiling-loops get set-at ;
2008-02-12 21:35:25 -05:00
M: #loop generate-node
end-basic-block
2008-02-15 19:07:56 -05:00
dup node-param compiling-loop
node-child generate-nodes
2008-02-13 00:27:05 -05:00
iterate-next ;
2008-02-12 21:35:25 -05:00
2007-09-20 18:09:08 -04:00
! #if
: end-false-branch ( label -- )
tail-call? [ %return drop ] [ %jump-label ] if ;
: generate-branch ( node -- )
[ copy-templates generate-nodes ] with-scope ;
: generate-if ( node label -- next )
<label> [
2008-04-17 04:06:55 -04:00
>r >r node-children first2 swap generate-branch
2007-09-20 18:09:08 -04:00
r> r> end-false-branch resolve-label
generate-branch
init-templates
] keep resolve-label iterate-next ;
M: #if generate-node
2008-04-17 04:06:55 -04:00
[ <label> dup %jump-f ]
2007-09-20 18:09:08 -04:00
H{ { +input+ { { f "flag" } } } }
with-template
generate-if ;
! #dispatch
: dispatch-branch ( node word -- label )
gensym [
2008-02-13 00:27:05 -05:00
[
2007-09-20 18:09:08 -04:00
copy-templates
2007-11-04 23:18:05 -05:00
%save-dispatch-xt
%prologue-later
2007-09-20 18:09:08 -04:00
[ generate-nodes ] with-node-iterator
2008-02-13 00:27:05 -05:00
] with-generator
2007-09-20 18:09:08 -04:00
] keep ;
: dispatch-branches ( node -- )
node-children [
compiling-word get dispatch-branch
%dispatch-label
] each ;
2007-09-20 18:09:08 -04:00
2008-02-09 22:12:00 -05:00
: generate-dispatch ( node -- )
%dispatch dispatch-branches init-templates ;
M: #dispatch generate-node
#! The order here is important, dispatch-branches must
#! run after %dispatch, so that each branch gets the
#! correct register state
2007-09-20 18:09:08 -04:00
tail-call? [
2008-02-09 22:12:00 -05:00
generate-dispatch iterate-next
2007-09-20 18:09:08 -04:00
] [
2008-02-09 22:12:00 -05:00
compiling-word get gensym [
2008-02-13 00:27:05 -05:00
[
2008-02-09 22:12:00 -05:00
init-generate-nodes
generate-dispatch
2008-02-13 00:27:05 -05:00
] with-generator
2008-02-09 22:12:00 -05:00
] keep generate-call
] if ;
2007-09-20 18:09:08 -04:00
! #call
: define-intrinsics ( word intrinsics -- )
"intrinsics" set-word-prop ;
: define-intrinsic ( word quot assoc -- )
2array 1array define-intrinsics ;
: define-if>branch-intrinsics ( word intrinsics -- )
"if-intrinsics" set-word-prop ;
: if>boolean-intrinsic ( quot -- )
2008-04-17 04:06:55 -04:00
"false" define-label
2007-09-20 18:09:08 -04:00
"end" define-label
2008-04-17 04:06:55 -04:00
"false" get swap call
2007-09-20 18:09:08 -04:00
t "if-scratch" get load-literal
2008-04-17 04:06:55 -04:00
"end" get %jump-label
"false" resolve-label
f "if-scratch" get load-literal
2007-09-20 18:09:08 -04:00
"end" resolve-label
2007-09-27 17:30:34 -04:00
"if-scratch" get phantom-push ; inline
2007-09-20 18:09:08 -04:00
: define-if>boolean-intrinsics ( word intrinsics -- )
[
>r [ if>boolean-intrinsic ] curry r>
{ { f "if-scratch" } } +scratch+ associate assoc-union
2007-10-29 01:12:27 -04:00
] assoc-map "intrinsics" set-word-prop ;
2007-09-20 18:09:08 -04:00
: define-if-intrinsics ( word intrinsics -- )
[ +input+ associate ] assoc-map
2dup define-if>branch-intrinsics
define-if>boolean-intrinsics ;
: define-if-intrinsic ( word quot inputs -- )
2array 1array define-if-intrinsics ;
2008-02-12 18:32:17 -05:00
: do-if-intrinsic ( pair -- next )
<label> [
swap do-template
node> node-successor dup >node
] keep generate-if ;
2007-09-20 18:09:08 -04:00
: find-intrinsic ( #call -- pair/f )
intrinsics find-template ;
: find-if-intrinsic ( #call -- pair/f )
dup node-successor #if? [
if-intrinsics find-template
] [
drop f
] if ;
M: #call generate-node
2007-09-29 19:43:03 -04:00
dup node-input-classes set-operand-classes
2007-09-20 18:09:08 -04:00
dup find-if-intrinsic [
do-if-intrinsic
] [
dup find-intrinsic [
2007-09-29 19:43:03 -04:00
do-template iterate-next
2007-09-20 18:09:08 -04:00
] [
node-param generate-call
] ?if
2008-02-12 18:32:17 -05:00
] ?if ;
2007-09-20 18:09:08 -04:00
! #call-label
M: #call-label generate-node node-param generate-call ;
! #push
M: #push generate-node
2007-09-29 19:43:03 -04:00
node-out-d [ value-literal <constant> phantom-push ] each
iterate-next ;
2007-09-20 18:09:08 -04:00
! #shuffle
M: #shuffle generate-node
node-shuffle phantom-shuffle iterate-next ;
M: #>r generate-node
node-in-d length
2007-09-27 17:30:34 -04:00
phantom->r
2007-09-20 18:09:08 -04:00
iterate-next ;
M: #r> generate-node
node-out-d length
2007-09-27 17:30:34 -04:00
phantom-r>
2007-09-20 18:09:08 -04:00
iterate-next ;
! #return
2008-02-12 21:35:25 -05:00
M: #return generate-node
2008-02-15 19:07:56 -05:00
end-basic-block
node-param compiling-loops get key?
[ %return ] unless f ;