Merge branch 'master' of git://factorcode.org/git/factor

db4
John Benediktsson 2008-12-06 09:35:00 -08:00
commit c9c2be7500
60 changed files with 1875 additions and 167 deletions

View File

@ -60,7 +60,7 @@ nl
"." write flush
{
new-sequence nth push pop peek
new-sequence nth push pop peek flip
} compile-uncompiled
"." write flush

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel math namespaces assocs hashtables sequences
USING: kernel math namespaces assocs hashtables sequences arrays
accessors vectors combinators sets classes compiler.cfg
compiler.cfg.registers compiler.cfg.instructions
compiler.cfg.copy-prop ;
@ -194,6 +194,7 @@ M: ##slot insn-slot# slot>> constant ;
M: ##slot-imm insn-slot# slot>> ;
M: ##set-slot insn-slot# slot>> constant ;
M: ##set-slot-imm insn-slot# slot>> ;
M: ##alien-global insn-slot# [ library>> ] [ symbol>> ] bi 2array ;
M: ##peek insn-object loc>> class ;
M: ##replace insn-object loc>> class ;
@ -201,6 +202,7 @@ M: ##slot insn-object obj>> resolve ;
M: ##slot-imm insn-object obj>> resolve ;
M: ##set-slot insn-object obj>> resolve ;
M: ##set-slot-imm insn-object obj>> resolve ;
M: ##alien-global insn-object drop \ ##alien-global ;
: init-alias-analysis ( -- )
H{ } clone histories set
@ -224,6 +226,9 @@ M: ##load-immediate analyze-aliases*
M: ##load-indirect analyze-aliases*
dup dst>> set-heap-ac ;
M: ##alien-global analyze-aliases*
dup dst>> set-heap-ac ;
M: ##allot analyze-aliases*
#! A freshly allocated object is distinct from any other
#! object.

View File

@ -65,6 +65,7 @@ IN: compiler.cfg.hats
: ^^alien-cell ( src -- dst ) ^^i1 ##alien-cell ; inline
: ^^alien-float ( src -- dst ) ^^d1 ##alien-float ; inline
: ^^alien-double ( src -- dst ) ^^d1 ##alien-double ; inline
: ^^alien-global ( symbol library -- dst ) ^^i2 ##alien-global ; inline
: ^^compare ( src1 src2 cc -- dst ) ^^i3 i ##compare ; inline
: ^^compare-imm ( src1 src2 cc -- dst ) ^^i3 i ##compare-imm ; inline
: ^^compare-float ( src1 src2 cc -- dst ) ^^i3 i ##compare-float ; inline

View File

@ -161,6 +161,8 @@ INSN: ##set-alien-double < ##alien-setter ;
INSN: ##allot < ##flushable size class { temp vreg } ;
INSN: ##write-barrier < ##effect card# table ;
INSN: ##alien-global < ##read symbol library ;
! FFI
INSN: ##alien-invoke params ;
INSN: ##alien-indirect params ;

View File

@ -12,8 +12,7 @@ compiler.cfg.registers ;
IN: compiler.cfg.intrinsics.fixnum
: emit-both-fixnums? ( -- )
D 0 ^^peek
D 1 ^^peek
2inputs
^^or
tag-mask get ^^and-imm
0 cc= ^^compare-imm

View File

@ -9,6 +9,7 @@ compiler.cfg.intrinsics.allot
compiler.cfg.intrinsics.fixnum
compiler.cfg.intrinsics.float
compiler.cfg.intrinsics.slots
compiler.cfg.intrinsics.misc
compiler.cfg.iterator ;
QUALIFIED: kernel
QUALIFIED: arrays
@ -23,6 +24,7 @@ IN: compiler.cfg.intrinsics
{
kernel.private:tag
kernel.private:getenv
math.private:both-fixnums?
math.private:fixnum+
math.private:fixnum-
@ -94,6 +96,7 @@ IN: compiler.cfg.intrinsics
: emit-intrinsic ( node word -- node/f )
{
{ \ kernel.private:tag [ drop emit-tag iterate-next ] }
{ \ kernel.private:getenv [ emit-getenv iterate-next ] }
{ \ math.private:both-fixnums? [ drop emit-both-fixnums? iterate-next ] }
{ \ math.private:fixnum+ [ drop [ ##fixnum-add ] [ ##fixnum-add-tail ] emit-fixnum-overflow-op ] }
{ \ math.private:fixnum- [ drop [ ##fixnum-sub ] [ ##fixnum-sub-tail ] emit-fixnum-overflow-op ] }

View File

@ -0,0 +1,16 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces layouts sequences kernel
accessors compiler.tree.propagation.info
compiler.cfg.stacks compiler.cfg.hats
compiler.cfg.instructions compiler.cfg.utilities ;
IN: compiler.cfg.intrinsics.misc
: emit-tag ( -- )
ds-pop tag-mask get ^^and-imm ^^tag-fixnum ds-push ;
: emit-getenv ( node -- )
"userenv" f ^^alien-global
swap node-input-infos first literal>>
[ ds-drop 0 ^^slot-imm ] [ ds-pop ^^offset>slot 0 ^^slot ] if*
ds-push ;

View File

@ -6,9 +6,6 @@ compiler.cfg.stacks compiler.cfg.hats compiler.cfg.instructions
compiler.cfg.utilities ;
IN: compiler.cfg.intrinsics.slots
: emit-tag ( -- )
ds-pop tag-mask get ^^and-imm ^^tag-fixnum ds-push ;
: value-tag ( info -- n ) class>> class-tag ; inline
: (emit-slot) ( infos -- dst )

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays kernel sequences sequences.deep
USING: accessors arrays kernel sequences compiler.utilities
compiler.cfg.instructions cpu.architecture ;
IN: compiler.cfg.two-operand
@ -55,6 +55,6 @@ M: insn convert-two-operand* ;
: convert-two-operand ( mr -- mr' )
[
two-operand? [
[ convert-two-operand* ] map flatten
[ convert-two-operand* ] map-flat
] when
] change-instructions ;

View File

@ -236,6 +236,10 @@ M: _gc generate-insn drop %gc ;
M: ##loop-entry generate-insn drop %loop-entry ;
M: ##alien-global generate-insn
[ dst>> register ] [ symbol>> ] [ library>> ] tri
%alien-global ;
! ##alien-invoke
GENERIC: reg-size ( register-class -- n )
@ -451,7 +455,7 @@ M: ##alien-indirect generate-insn
TUPLE: callback-context ;
: current-callback 2 getenv ;
: current-callback ( -- id ) 2 getenv ;
: wait-to-return ( token -- )
dup current-callback eq? [

View File

@ -1,10 +1,11 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors sequences sequences.deep combinators fry
USING: kernel accessors sequences combinators fry
classes.algebra namespaces assocs words math math.private
math.partial-dispatch math.intervals classes classes.tuple
classes.tuple.private layouts definitions stack-checker.state
stack-checker.branches
compiler.utilities
compiler.tree
compiler.tree.combinators
compiler.tree.propagation.info
@ -33,7 +34,7 @@ GENERIC: cleanup* ( node -- node/nodes )
: cleanup ( nodes -- nodes' )
#! We don't recurse into children here, instead the methods
#! do it since the logic is a bit more involved
[ cleanup* ] map flatten ;
[ cleanup* ] map-flat ;
: cleanup-folding? ( #call -- ? )
node-output-infos

View File

@ -1,7 +1,8 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: assocs fry kernel accessors sequences sequences.deep arrays
stack-checker.inlining namespaces compiler.tree ;
USING: assocs fry kernel accessors sequences compiler.utilities
arrays stack-checker.inlining namespaces compiler.tree
math.order ;
IN: compiler.tree.combinators
: each-node ( nodes quot: ( node -- ) -- )
@ -27,7 +28,7 @@ IN: compiler.tree.combinators
[ _ map-nodes ] change-child
] when
] if
] map flatten ; inline recursive
] map-flat ; inline recursive
: contains-node? ( nodes quot: ( node -- ? ) -- ? )
dup dup '[
@ -48,12 +49,6 @@ IN: compiler.tree.combinators
: sift-children ( seq flags -- seq' )
zip [ nip ] assoc-filter keys ;
: (3each) [ 3array flip ] dip '[ first3 @ ] ; inline
: 3each ( seq1 seq2 seq3 quot -- seq ) (3each) each ; inline
: 3map ( seq1 seq2 seq3 quot -- seq ) (3each) map ; inline
: until-fixed-point ( #recursive quot: ( node -- ) -- )
over label>> t >>fixed-point drop
[ with-scope ] 2keep

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: fry accessors namespaces assocs deques search-deques
dlists kernel sequences sequences.deep words sets
dlists kernel sequences compiler.utilities words sets
stack-checker.branches compiler.tree compiler.tree.def-use
compiler.tree.combinators ;
IN: compiler.tree.dead-code.liveness
@ -49,4 +49,4 @@ GENERIC: remove-dead-code* ( node -- node' )
M: node remove-dead-code* ;
: (remove-dead-code) ( nodes -- nodes' )
[ remove-dead-code* ] map flatten ;
[ remove-dead-code* ] map-flat ;

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: sequences sequences.deep kernel
USING: sequences kernel fry vectors
compiler.tree compiler.tree.def-use ;
IN: compiler.tree.def-use.simplified
@ -9,8 +9,6 @@ IN: compiler.tree.def-use.simplified
! A 'real' usage is a usage of a value that is not a #renaming.
TUPLE: real-usage value node ;
GENERIC: actually-used-by* ( value node -- real-usages )
! Def
GENERIC: actually-defined-by* ( value node -- real-usage )
@ -25,16 +23,18 @@ M: #return-recursive actually-defined-by* real-usage boa ;
M: node actually-defined-by* real-usage boa ;
! Use
: (actually-used-by) ( value -- real-usages )
dup used-by [ actually-used-by* ] with map ;
GENERIC# actually-used-by* 1 ( value node accum -- )
: (actually-used-by) ( value accum -- )
[ [ used-by ] keep ] dip '[ _ swap _ actually-used-by* ] each ;
M: #renaming actually-used-by*
inputs/outputs [ indices ] dip nths
[ (actually-used-by) ] map ;
[ inputs/outputs [ indices ] dip nths ] dip
'[ _ (actually-used-by) ] each ;
M: #return-recursive actually-used-by* real-usage boa ;
M: #return-recursive actually-used-by* [ real-usage boa ] dip push ;
M: node actually-used-by* real-usage boa ;
M: node actually-used-by* [ real-usage boa ] dip push ;
: actually-used-by ( value -- real-usages )
(actually-used-by) flatten ;
10 <vector> [ (actually-used-by) ] keep ;

View File

@ -33,4 +33,4 @@ M: #branch escape-analysis*
2bi ;
M: #phi escape-analysis*
[ phi-in-d>> <flipped> ] [ out-d>> ] bi merge-allocations ;
[ phi-in-d>> flip ] [ out-d>> ] bi merge-allocations ;

View File

@ -0,0 +1,23 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: classes classes.tuple math math.private accessors
combinators kernel compiler.tree compiler.tree.combinators
compiler.tree.propagation.info ;
IN: compiler.tree.escape-analysis.check
GENERIC: run-escape-analysis* ( node -- ? )
M: #push run-escape-analysis*
literal>> [ class immutable-tuple-class? ] [ complex? ] bi or ;
M: #call run-escape-analysis*
{
{ [ dup word>> \ <complex> eq? ] [ t ] }
{ [ dup immutable-tuple-boa? ] [ t ] }
[ f ]
} cond nip ;
M: node run-escape-analysis* drop f ;
: run-escape-analysis? ( nodes -- ? )
[ run-escape-analysis* ] contains-node? ;

View File

@ -1,6 +1,7 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors sequences words memoize classes.builtin
USING: kernel accessors sequences words memoize combinators
classes classes.builtin classes.tuple math.partial-dispatch
fry assocs
compiler.tree
compiler.tree.combinators
@ -12,7 +13,7 @@ IN: compiler.tree.finalization
! See the comment in compiler.tree.late-optimizations.
! This pass runs after propagation, so that it can expand
! built-in type predicates; these cannot be expanded before
! type predicates; these cannot be expanded before
! propagation since we need to see 'fixnum?' instead of
! 'tag 0 eq?' and so on, for semantic reasoning.
@ -33,16 +34,24 @@ M: #shuffle finalize*
[ [ in-r>> ] [ out-r>> ] [ mapping>> ] tri '[ _ at ] map sequence= ]
bi and [ drop f ] when ;
: builtin-predicate? ( #call -- ? )
word>> "predicating" word-prop builtin-class? ;
MEMO: builtin-predicate-expansion ( word -- nodes )
MEMO: cached-expansion ( word -- nodes )
def>> splice-final ;
: expand-builtin-predicate ( #call -- nodes )
word>> builtin-predicate-expansion ;
GENERIC: finalize-word ( #call word -- nodes )
M: predicate finalize-word
"predicating" word-prop {
{ [ dup builtin-class? ] [ drop word>> cached-expansion ] }
{ [ dup tuple-class? ] [ drop word>> def>> splice-final ] }
[ drop ]
} cond ;
! M: math-partial finalize-word
! dup primitive? [ drop ] [ nip cached-expansion ] if ;
M: word finalize-word drop ;
M: #call finalize*
dup builtin-predicate? [ expand-builtin-predicate ] when ;
dup word>> finalize-word ;
M: node finalize* ;

View File

@ -1,10 +1,11 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: fry namespaces sequences math accessors kernel arrays
combinators sequences.deep assocs
combinators compiler.utilities assocs
stack-checker.backend
stack-checker.branches
stack-checker.inlining
compiler.utilities
compiler.tree
compiler.tree.combinators
compiler.tree.normalization.introductions
@ -46,7 +47,7 @@ M: #branch normalize*
[
[
[
[ normalize* ] map flatten
[ normalize* ] map-flat
introduction-stack get
2array
] with-scope
@ -70,7 +71,7 @@ M: #phi normalize*
: (normalize) ( nodes introductions -- nodes )
introduction-stack [
[ normalize* ] map flatten
[ normalize* ] map-flat
] with-variable ;
M: #recursive normalize*

View File

@ -6,6 +6,7 @@ compiler.tree.normalization
compiler.tree.propagation
compiler.tree.cleanup
compiler.tree.escape-analysis
compiler.tree.escape-analysis.check
compiler.tree.tuple-unboxing
compiler.tree.identities
compiler.tree.def-use
@ -22,8 +23,10 @@ SYMBOL: check-optimizer?
normalize
propagate
cleanup
escape-analysis
unbox-tuples
dup run-escape-analysis? [
escape-analysis
unbox-tuples
] when
apply-identities
compute-def-use
remove-dead-code

View File

@ -3,6 +3,7 @@
USING: fry kernel sequences assocs accessors namespaces
math.intervals arrays classes.algebra combinators columns
stack-checker.branches
compiler.utilities
compiler.tree
compiler.tree.combinators
compiler.tree.propagation.info
@ -78,7 +79,7 @@ SYMBOL: condition-value
M: #phi propagate-before ( #phi -- )
[ annotate-phi-inputs ]
[ [ phi-info-d>> <flipped> ] [ out-d>> ] bi merge-value-infos ]
[ [ phi-info-d>> flip ] [ out-d>> ] bi merge-value-infos ]
bi ;
: branch-phi-constraints ( output values booleans -- )
@ -137,8 +138,8 @@ M: #phi propagate-before ( #phi -- )
M: #phi propagate-after ( #phi -- )
condition-value get [
[ out-d>> ]
[ phi-in-d>> <flipped> ]
[ phi-info-d>> <flipped> ] tri
[ phi-in-d>> flip ]
[ phi-info-d>> flip ] tri
[
[ possible-boolean-values ] map
branch-phi-constraints

View File

@ -49,7 +49,7 @@ M: #renaming compute-copy-equiv* inputs/outputs are-copies-of ;
] 2each ;
M: #phi compute-copy-equiv*
[ phi-in-d>> <flipped> ] [ out-d>> ] bi compute-phi-equiv ;
[ phi-in-d>> flip ] [ out-d>> ] bi compute-phi-equiv ;
M: node compute-copy-equiv* drop ;

View File

@ -184,7 +184,7 @@ SYMBOL: history
over in-d>> second value-info literal>> dup class?
[ "predicate" word-prop '[ drop @ ] inline-word-def ] [ 3drop f ] if ;
: do-inlining ( #call word -- ? )
: (do-inlining) ( #call word -- ? )
#! If the generic was defined in an outer compilation unit,
#! then it doesn't have a definition yet; the definition
#! is built at the end of the compilation unit. We do not
@ -195,7 +195,6 @@ SYMBOL: history
#! discouraged, but it should still work.)
{
{ [ dup deferred? ] [ 2drop f ] }
{ [ dup custom-inlining? ] [ inline-custom ] }
{ [ dup \ instance? eq? ] [ inline-instance-check ] }
{ [ dup always-inline-word? ] [ inline-word ] }
{ [ dup standard-generic? ] [ inline-standard-method ] }
@ -203,3 +202,10 @@ SYMBOL: history
{ [ dup method-body? ] [ inline-method-body ] }
[ 2drop f ]
} cond ;
: do-inlining ( #call word -- ? )
#! Note the logic here: if there's a custom inlining hook,
#! it is permitted to return f, which means that we try the
#! normal inlining heuristic.
dup custom-inlining? [ 2dup inline-custom ] [ f ] if
[ 2drop t ] [ (do-inlining) ] if ;

View File

@ -5,7 +5,7 @@ math.partial-dispatch math.intervals math.parser math.order
layouts words sequences sequences.private arrays assocs classes
classes.algebra combinators generic.math splitting fry locals
classes.tuple alien.accessors classes.tuple.private slots.private
definitions
definitions strings.private vectors hashtables
stack-checker.state
compiler.tree.comparisons
compiler.tree.propagation.info
@ -194,6 +194,11 @@ generic-comparison-ops [
2bi and maybe-or-never
] "outputs" set-word-prop
\ both-fixnums? [
[ class>> fixnum classes-intersect? not ] either?
f <literal-info> object-info ?
] "outputs" set-word-prop
{
{ >fixnum fixnum }
{ bignum>fixnum fixnum }
@ -242,6 +247,10 @@ generic-comparison-ops [
] "custom-inlining" set-word-prop
] each
\ string-nth [
2drop fixnum 0 23 2^ [a,b] <class/interval-info>
] "outputs" set-word-prop
{
alien-signed-1
alien-unsigned-1
@ -283,6 +292,15 @@ generic-comparison-ops [
"outputs" set-word-prop
] each
! Generate more efficient code for common idiom
\ clone [
in-d>> first value-info literal>> {
{ V{ } [ [ drop { } 0 vector boa ] ] }
{ H{ } [ [ drop hashtable new ] ] }
[ drop f ]
} case
] "custom-inlining" set-word-prop
\ slot [
dup literal?>>
[ literal>> swap value-info-slot ] [ 2drop object-info ] if

View File

@ -8,7 +8,8 @@ math.functions math.private strings layouts
compiler.tree.propagation.info compiler.tree.def-use
compiler.tree.debugger compiler.tree.checker
slots.private words hashtables classes assocs locals
specialized-arrays.double system sorting math.libm ;
specialized-arrays.double system sorting math.libm
math.intervals ;
IN: compiler.tree.propagation.tests
\ propagate must-infer
@ -599,6 +600,10 @@ MIXIN: empty-mixin
[ V{ t } ] [ [ { fixnum } declare 10 mod >float -20 > ] final-literals ] unit-test
[ T{ interval f { 0 t } { 127 t } } ] [
[ { integer } declare 127 bitand ] final-info first interval>>
] unit-test
! [ V{ string } ] [
! [ dup string? t xor [ "A" throw ] [ ] if ] final-classes
! ] unit-test

View File

@ -1,9 +1,10 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces assocs accessors kernel combinators
classes.algebra sequences sequences.deep slots.private
classes.algebra sequences slots.private fry vectors
classes.tuple.private math math.private arrays
stack-checker.branches
compiler.utilities
compiler.tree
compiler.tree.combinators
compiler.tree.propagation.info
@ -21,7 +22,7 @@ GENERIC: unbox-tuples* ( node -- node/nodes )
: (expand-#push) ( object value -- nodes )
dup unboxed-allocation dup [
[ object-slots ] [ drop ] [ ] tri*
[ (expand-#push) ] 2map
[ (expand-#push) ] 2map-flat
] [
drop #push
] if ;
@ -38,11 +39,16 @@ M: #push unbox-tuples* ( #push -- nodes )
: unbox-<complex> ( #call -- nodes )
dup unbox-output? [ drop { } ] when ;
: (flatten-values) ( values -- values' )
[ dup unboxed-allocation [ (flatten-values) ] [ ] ?if ] map ;
: (flatten-values) ( values accum -- )
dup '[
dup unboxed-allocation
[ _ (flatten-values) ] [ _ push ] ?if
] each ;
: flatten-values ( values -- values' )
dup empty? [ (flatten-values) flatten ] unless ;
dup empty? [
10 <vector> [ (flatten-values) ] keep
] unless ;
: prepare-slot-access ( #call -- tuple-values outputs slot-values )
[ in-d>> flatten-values ]

View File

@ -0,0 +1,31 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences sequences.private arrays vectors fry
math.order ;
IN: compiler.utilities
: flattener ( seq quot -- seq vector quot' )
over length <vector> [
dup
'[
@ [
dup array?
[ _ push-all ] [ _ push ] if
] when*
]
] keep ; inline
: flattening ( seq quot combinator -- seq' )
[ flattener ] dip dip { } like ; inline
: map-flat ( seq quot -- seq' ) [ each ] flattening ; inline
: 2map-flat ( seq quot -- seq' ) [ 2each ] flattening ; inline
: (3each) ( seq1 seq2 seq3 quot -- n quot' )
[ [ [ length ] tri@ min min ] 3keep ] dip
'[ [ _ nth-unsafe ] [ _ nth-unsafe ] [ _ nth-unsafe ] tri @ ] ; inline
: 3each ( seq1 seq2 seq3 quot -- seq ) (3each) each ; inline
: 3map ( seq1 seq2 seq3 quot -- seq ) (3each) map ; inline

View File

@ -120,6 +120,8 @@ HOOK: %set-alien-cell cpu ( ptr value -- )
HOOK: %set-alien-float cpu ( ptr value -- )
HOOK: %set-alien-double cpu ( ptr value -- )
HOOK: %alien-global cpu ( dst symbol library -- )
HOOK: %allot cpu ( dst size class temp -- )
HOOK: %write-barrier cpu ( src card# table -- )
HOOK: %gc cpu ( -- )

View File

@ -139,9 +139,9 @@ M:: ppc %string-nth ( dst src index temp -- )
"end" define-label
temp src index ADD
dst temp string-offset LBZ
0 dst HEX: 80 CMPI
"end" get BLT
temp src string-aux-offset LWZ
0 temp \ f tag-number CMPI
"end" get BEQ
temp temp index ADD
temp temp index ADD
temp temp byte-array-offset LHZ
@ -150,6 +150,10 @@ M:: ppc %string-nth ( dst src index temp -- )
"end" resolve-label
] with-scope ;
M:: ppc %set-string-nth-fast ( ch obj index temp -- )
temp obj index ADD
ch temp string-offset STB ;
M: ppc %add ADD ;
M: ppc %add-imm ADDI ;
M: ppc %sub swap SUBF ;

View File

@ -44,8 +44,6 @@ M: x86.32 param-reg-2 EDX ;
M: x86.32 reserved-area-size 0 ;
M: x86.32 %alien-global 0 [] MOV rc-absolute-cell rel-dlsym ;
M: x86.32 %alien-invoke (CALL) rel-dlsym ;
M: x86.32 %alien-invoke-tail (JMP) rel-dlsym ;

View File

@ -158,9 +158,6 @@ M: x86.64 %prepare-box-struct ( -- )
M: x86.64 %prepare-var-args RAX RAX XOR ;
M: x86.64 %alien-global
[ 0 MOV rc-absolute-cell rel-dlsym ] [ dup [] MOV ] bi ;
M: x86.64 %alien-invoke
R11 0 MOV
rc-absolute-cell rel-dlsym

View File

@ -381,8 +381,8 @@ big-endian off
[
arg0 ds-reg [] MOV
arg0 ds-reg bootstrap-cell neg [+] OR
ds-reg bootstrap-cell ADD
ds-reg bootstrap-cell SUB
arg0 ds-reg [] OR
arg0 tag-mask get AND
arg0 \ f tag-number MOV
arg1 1 tag-fixnum MOV

View File

@ -391,7 +391,7 @@ M:: x86 %string-nth ( dst src index temp -- )
] with-small-register ;
M:: x86 %set-string-nth-fast ( ch str index temp -- )
ch { index str } [| new-ch |
ch { index str temp } [| new-ch |
new-ch ch ?MOV
temp str index [+] LEA
temp string-offset [+] new-ch 1 small-reg MOV
@ -458,19 +458,19 @@ M:: x86 %allot ( dst size class nursery-ptr -- )
dst class store-tagged
nursery-ptr size inc-allot-ptr ;
HOOK: %alien-global cpu ( symbol dll register -- )
M:: x86 %write-barrier ( src card# table -- )
#! Mark the card pointed to by vreg.
! Mark the card
card# src MOV
card# card-bits SHR
"cards_offset" f table %alien-global
table "cards_offset" f %alien-global
table table [] MOV
table card# [+] card-mark <byte> MOV
! Mark the card deck
card# deck-bits card-bits - SHR
"decks_offset" f table %alien-global
table "decks_offset" f %alien-global
table table [] MOV
table card# [+] card-mark <byte> MOV ;
M: x86 %gc ( -- )
@ -485,6 +485,9 @@ M: x86 %gc ( -- )
"minor_gc" f %alien-invoke
"end" resolve-label ;
M: x86 %alien-global
[ 0 MOV ] 2dip rc-absolute-cell rel-dlsym ;
HOOK: stack-reg cpu ( -- reg )
: decr-stack-reg ( n -- )
@ -595,7 +598,8 @@ M: x86 %prepare-alien-invoke
#! Save Factor stack pointers in case the C code calls a
#! callback which does a GC, which must reliably trace
#! all roots.
"stack_chain" f temp-reg-1 %alien-global
temp-reg-1 "stack_chain" f %alien-global
temp-reg-1 temp-reg-1 [] MOV
temp-reg-1 [] stack-reg MOV
temp-reg-1 [] cell SUB
temp-reg-1 2 cells [+] ds-reg MOV

View File

@ -1,9 +1,9 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel kernel.private math math.private words
sequences parser namespaces make assocs quotations arrays locals
sequences parser namespaces make assocs quotations arrays
generic generic.math hashtables effects compiler.units
classes.algebra ;
classes.algebra fry combinators ;
IN: math.partial-dispatch
PREDICATE: math-partial < word
@ -45,60 +45,62 @@ M: word integer-op-input-classes
{ bitnot fixnum-bitnot }
} at swap or ;
:: fixnum-integer-op ( a b fix-word big-word -- c )
b tag 0 eq? [
a b fix-word execute
] [
a fixnum>bignum b big-word execute
] if ; inline
:: integer-fixnum-op ( a b fix-word big-word -- c )
a tag 0 eq? [
a b fix-word execute
] [
a b fixnum>bignum big-word execute
] if ; inline
:: integer-integer-op ( a b fix-word big-word -- c )
b tag 0 eq? [
a b fix-word big-word integer-fixnum-op
] [
a dup tag 0 eq? [ fixnum>bignum ] when
b big-word execute
] if ; inline
: integer-op-combinator ( triple -- word )
: integer-fixnum-op-quot ( fix-word big-word -- quot )
[
[ second name>> % "-" % ]
[ third name>> % "-op" % ]
bi
] "" make "math.partial-dispatch" lookup ;
[ over fixnum? ] %
[ '[ _ execute ] , ]
[ '[ fixnum>bignum _ execute ] , ] bi*
\ if ,
] [ ] make ;
: fixnum-integer-op-quot ( fix-word big-word -- quot )
[
[ dup fixnum? ] %
[ '[ _ execute ] , ]
[ '[ [ fixnum>bignum ] dip _ execute ] , ] bi*
\ if ,
] [ ] make ;
: integer-integer-op-quot ( fix-word big-word -- quot )
[
[ dup fixnum? ] %
2dup integer-fixnum-op-quot ,
[
[ over fixnum? [ [ fixnum>bignum ] dip ] when ] %
nip ,
] [ ] make ,
\ if ,
] [ ] make ;
: integer-op-word ( triple -- word )
[ name>> ] map "-" join "math.partial-dispatch" create ;
: integer-op-quot ( triple fix-word big-word -- quot )
rot integer-op-combinator 1quotation 2curry ;
: integer-op-quot ( fix-word big-word triple -- quot )
[ second ] [ third ] bi 2array {
{ { fixnum integer } [ fixnum-integer-op-quot ] }
{ { integer fixnum } [ integer-fixnum-op-quot ] }
{ { integer integer } [ integer-integer-op-quot ] }
} case ;
: define-integer-op-word ( triple fix-word big-word -- )
: define-integer-op-word ( fix-word big-word triple -- )
[
[ 2drop integer-op-word ] [ integer-op-quot ] 3bi
[ 2nip integer-op-word ] [ integer-op-quot ] 3bi
(( x y -- z )) define-declared
] [
2drop
2nip
[ integer-op-word ] keep
"derived-from" set-word-prop
] 3bi ;
: define-integer-op-words ( triples fix-word big-word -- )
[ define-integer-op-word ] 2curry each ;
'[ [ _ _ ] dip define-integer-op-word ] each ;
: integer-op-triples ( word -- triples )
{
{ fixnum integer }
{ integer fixnum }
{ integer integer }
} swap [ prefix ] curry map ;
} swap '[ _ prefix ] map ;
: define-integer-ops ( word fix-word big-word -- )
[
@ -138,7 +140,7 @@ SYMBOL: fast-math-ops
[ drop math-class-max swap specific-method >boolean ] if ;
: (derived-ops) ( word assoc -- words )
swap [ rot first eq? nip ] curry assoc-filter ;
swap '[ swap first _ eq? nip ] assoc-filter ;
: derived-ops ( word -- words )
[ 1array ] [ math-ops get (derived-ops) values ] bi append ;

View File

@ -4,8 +4,7 @@ USING: kernel sequences strings fry namespaces make math assocs
debugger io vectors arrays math.parser math.order
vectors combinators classes sets unicode.categories
compiler.units parser words quotations effects memoize accessors
locals effects splitting combinators.short-circuit
combinators.short-circuit.smart generalizations ;
locals effects splitting combinators.short-circuit generalizations ;
IN: peg
USE: prettyprint
@ -278,7 +277,8 @@ GENERIC: (compile) ( peg -- quot )
: parser-body ( parser -- quot )
#! Return the body of the word that is the compiled version
#! of the parser.
gensym 2dup swap peg>> (compile) 0 1 <effect> define-declared swap dupd id>> "peg-id" set-word-prop
gensym 2dup swap peg>> (compile) (( -- result )) define-declared
swap dupd id>> "peg-id" set-word-prop
[ execute-parser ] curry ;
: preset-parser-word ( parser -- parser word )
@ -306,7 +306,7 @@ SYMBOL: delayed
#! Work through all delayed parsers and recompile their
#! words to have the correct bodies.
delayed get [
call compile-parser 1quotation 0 1 <effect> define-declared
call compile-parser 1quotation (( -- result )) define-declared
] assoc-each ;
: compile ( parser -- word )
@ -421,7 +421,7 @@ M: seq-parser (compile) ( peg -- quot )
[
parsers>> unclip compile-parser 1quotation [ parse-seq-element ] curry ,
[ compile-parser 1quotation [ merge-errors ] compose [ parse-seq-element ] curry , ] each
] { } make , \ && ,
] { } make , \ 1&& ,
] [ ] make ;
TUPLE: choice-parser parsers ;
@ -431,7 +431,7 @@ M: choice-parser (compile) ( peg -- quot )
[
parsers>> [ compile-parser ] map
unclip 1quotation , [ 1quotation [ merge-errors ] compose , ] each
] { } make , \ || ,
] { } make , \ 0|| ,
] [ ] make ;
TUPLE: repeat0-parser p1 ;

View File

@ -307,7 +307,7 @@ M: object infer-call*
\ <complex> { real real } { complex } define-primitive
\ <complex> make-foldable
\ both-fixnums? { object object } { object object object } define-primitive
\ both-fixnums? { object object } { object } define-primitive
\ fixnum+ { fixnum fixnum } { integer } define-primitive
\ fixnum+ make-foldable

View File

@ -4,9 +4,17 @@ IN: tools.annotations
ARTICLE: "tools.annotations" "Word annotations"
"The word annotation feature modifies word definitions to add debugging code. You can restore the old definition by calling " { $link reset } " on the word in question."
$nl
"Printing messages when a word is called or returns:"
{ $subsection watch }
{ $subsection watch-vars }
"Starting the walker when a word is called:"
{ $subsection breakpoint }
{ $subsection breakpoint-if }
"Timing words:"
{ $subsection reset-word-timing }
{ $subsection add-timing }
{ $subsection word-timing. }
"All of the above words are implemented using a single combinator which applies a quotation to a word definition to yield a new definition:"
{ $subsection annotate } ;
@ -63,3 +71,13 @@ HELP: word-inputs
{ "seq" sequence } }
{ $description "Makes a sequence of the inputs to a word by counting the number of inputs in the stack effect and saving that many items from the datastack." } ;
HELP: add-timing
{ $values { "word" word } }
{ $description "Adds timing code to a word, which records its total running time, including that of words it calls, on every invocation." }
{ $see-also "timing" "profiling" } ;
HELP: reset-word-timing
{ $description "Resets the word timing table." } ;
HELP: word-timing.
{ $description "Prints the word timing table." } ;

View File

@ -1,4 +1,4 @@
USING: tools.test tools.annotations math parser eval
USING: tools.test tools.annotations tools.time math parser eval
io.streams.string kernel ;
IN: tools.annotations.tests

View File

@ -1,9 +1,9 @@
! Copyright (C) 2005, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel words parser io summary quotations
sequences prettyprint continuations effects definitions
compiler.units namespaces assocs tools.walker generic
inspector fry ;
USING: accessors kernel math sorting words parser io summary
quotations sequences prettyprint continuations effects
definitions compiler.units namespaces assocs tools.walker
tools.time generic inspector fry ;
IN: tools.annotations
GENERIC: reset ( word -- )
@ -20,9 +20,11 @@ M: word reset
f "unannotated-def" set-word-prop
] [ drop ] if ;
ERROR: cannot-annotate-twice word ;
: annotate ( word quot -- )
over "unannotated-def" word-prop [
"Cannot annotate a word twice" throw
over cannot-annotate-twice
] when
[
over dup def>> "unannotated-def" set-word-prop
@ -82,3 +84,21 @@ M: word annotate-methods
: breakpoint-if ( word quot -- )
'[ [ _ [ [ break ] when ] ] dip 3append ] annotate-methods ;
SYMBOL: word-timing
word-timing global [ H{ } clone or ] change-at
: reset-word-timing ( -- )
word-timing get clear-assoc ;
: (add-timing) ( def word -- def' )
'[ _ benchmark _ word-timing get at+ ] ;
: add-timing ( word -- )
dup '[ _ (add-timing) ] annotate ;
: word-timing. ( -- )
word-timing get
>alist [ 1000000 /f ] assoc-map sort-values
simple-table. ;

View File

@ -1,13 +1,25 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: byte-arrays strings sequences sequences.private
fry kernel words parser lexer assocs math.order ;
fry kernel words parser lexer assocs math math.order summary ;
IN: tr
ERROR: bad-tr ;
M: bad-tr summary
drop "TR: can only be used with ASCII characters" ;
<PRIVATE
: ascii? ( ch -- ? ) 0 127 between? ; inline
: tr-nth ( n mapping -- ch ) nth-unsafe 127 bitand ; inline
: check-tr ( from to -- )
[ [ ascii? ] all? ] both? [ bad-tr ] unless ;
: compute-tr ( quot from to -- mapping )
zip [ 256 ] 2dip '[ [ @ _ at ] keep or ] B{ } map-as ; inline
zip [ 128 ] 2dip '[ [ @ _ at ] keep or ] B{ } map-as ; inline
: tr-hints ( word -- )
{ { byte-array } { string } } "specializer" set-word-prop ;
@ -16,13 +28,13 @@ IN: tr
create-in dup tr-hints ;
: tr-quot ( mapping -- quot )
'[ [ dup 0 255 between? [ _ nth-unsafe ] when ] map ] ;
'[ [ dup ascii? [ _ tr-nth ] when ] map ] ;
: define-tr ( word mapping -- )
tr-quot (( seq -- translated )) define-declared ;
: fast-tr-quot ( mapping -- quot )
'[ [ _ nth-unsafe ] change-each ] ;
'[ [ _ tr-nth ] change-each ] ;
: define-fast-tr ( word mapping -- )
fast-tr-quot (( seq -- )) define-declared ;
@ -32,6 +44,7 @@ PRIVATE>
: TR:
scan parse-definition
unclip-last [ unclip-last ] dip compute-tr
[ check-tr ]
[ [ create-tr ] dip define-tr ]
[ [ "-fast" append create-tr ] dip define-fast-tr ] 2bi ;
[ [ "-fast" append create-tr ] dip define-fast-tr ] 2tri ;
parsing

View File

@ -109,9 +109,6 @@ bootstrapping? on
} [ create-vocab drop ] each
! Builtin classes
: define-builtin-predicate ( class -- )
dup class>type [ builtin-instance? ] curry define-predicate ;
: lookup-type-number ( word -- n )
global [ target-word ] bind type-number ;
@ -192,6 +189,10 @@ define-union-class
] [ ] make
define-predicate-class
"array-capacity" "sequences.private" lookup
[ >fixnum ] bootstrap-max-array-capacity [ fixnum-bitand ] curry append
"coercer" set-word-prop
! Catch-all class for providing a default method.
"object" "kernel" create
[ f f { } intersection-class define-class ]

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license.
USING: accessors classes classes.algebra words kernel
kernel.private namespaces sequences math math.private
combinators assocs ;
combinators assocs quotations ;
IN: classes.builtin
SYMBOL: builtins
@ -10,10 +10,14 @@ SYMBOL: builtins
PREDICATE: builtin-class < class
"metaclass" word-prop builtin-class eq? ;
: type>class ( n -- class ) builtins get-global nth ;
: class>type ( class -- n ) "type" word-prop ; foldable
PREDICATE: lo-tag-class < builtin-class class>type 7 <= ;
PREDICATE: hi-tag-class < builtin-class class>type 7 > ;
: type>class ( n -- class ) builtins get-global nth ;
: bootstrap-type>class ( n -- class ) builtins get nth ;
M: hi-tag class hi-tag type>class ;
@ -22,16 +26,20 @@ M: object class tag type>class ;
M: builtin-class rank-class drop 0 ;
: builtin-instance? ( object n -- ? )
#! 7 == tag-mask get
#! 3 == hi-tag tag-number
dup 7 fixnum<= [ swap tag eq? ] [
swap dup tag 3 eq?
[ hi-tag eq? ] [ 2drop f ] if
] if ; inline
GENERIC: define-builtin-predicate ( class -- )
M: builtin-class instance?
class>type builtin-instance? ;
M: lo-tag-class define-builtin-predicate
dup class>type [ eq? ] curry [ tag ] prepend define-predicate ;
M: hi-tag-class define-builtin-predicate
dup class>type [ eq? ] curry [ hi-tag ] prepend 1quotation
[ dup tag 3 eq? ] [ [ drop f ] if ] surround
define-predicate ;
M: lo-tag-class instance? [ tag ] [ class>type ] bi* eq? ;
M: hi-tag-class instance?
over tag 3 eq? [ [ hi-tag ] [ class>type ] bi* eq? ] [ 2drop f ] if ;
M: builtin-class (flatten-class) dup set ;

View File

@ -90,10 +90,10 @@ ERROR: bad-superclass class ;
2drop f
] if ; inline
: tuple-instance-1? ( object class -- ? )
swap dup tuple? [
layout-of 7 slot eq?
] [ 2drop f ] if ; inline
: tuple-predicate-quot/1 ( class -- quot )
#! Fast path for tuples with no superclass
[ ] curry [ layout-of 7 slot ] [ eq? ] surround 1quotation
[ dup tuple? ] [ [ drop f ] if ] surround ;
: tuple-instance? ( object class offset -- ? )
rot dup tuple? [
@ -105,13 +105,16 @@ ERROR: bad-superclass class ;
: layout-class-offset ( echelon -- n )
2 * 5 + ;
: tuple-predicate-quot ( class echelon -- quot )
layout-class-offset [ tuple-instance? ] 2curry ;
: echelon-of ( class -- n )
tuple-layout third ;
: define-tuple-predicate ( class -- )
dup dup echelon-of {
{ 1 [ [ tuple-instance-1? ] curry ] }
[ layout-class-offset [ tuple-instance? ] 2curry ]
{ 1 [ tuple-predicate-quot/1 ] }
[ tuple-predicate-quot ]
} case define-predicate ;
: class-size ( class -- n )

View File

@ -83,7 +83,7 @@ M: math-combination perform-combination
drop
dup
[
\ both-fixnums? ,
[ 2dup both-fixnums? ] %
dup fixnum bootstrap-word dup math-method ,
\ over [
dup math-class? [

View File

@ -3,7 +3,7 @@
USING: classes.private generic.standard.engines namespaces make
arrays assocs sequences.private quotations kernel.private
math slots.private math.private kernel accessors words
layouts sorting sequences ;
layouts sorting sequences combinators ;
IN: generic.standard.engines.tag
TUPLE: lo-tag-dispatch-engine methods ;
@ -24,15 +24,21 @@ C: <lo-tag-dispatch-engine> lo-tag-dispatch-engine
: sort-tags ( assoc -- alist ) >alist sort-keys reverse ;
: tag-dispatch-test ( tag# -- quot )
picker [ tag ] append swap [ eq? ] curry append ;
: tag-dispatch-quot ( alist -- quot )
[ default get ] dip
[ [ tag-dispatch-test ] dip ] assoc-map
alist>quot ;
M: lo-tag-dispatch-engine engine>quot
methods>> engines>quots*
[ [ lo-tag-number ] dip ] assoc-map
[
picker % [ tag ] % [
sort-tags linear-dispatch-quot
] [
num-tags get direct-dispatch-quot
] if-small? %
[ sort-tags tag-dispatch-quot ]
[ picker % [ tag ] % num-tags get direct-dispatch-quot ]
if-small? %
] [ ] make ;
TUPLE: hi-tag-dispatch-engine methods ;

View File

@ -133,7 +133,7 @@ M: hashtable set-at ( value key hash -- )
: push-unsafe ( elt seq -- )
[ length ] keep
[ underlying>> set-array-nth ]
[ [ 1+ ] dip (>>length) ]
[ [ 1 fixnum+fast { array-capacity } declare ] dip (>>length) ]
2bi ; inline
PRIVATE>

View File

@ -154,8 +154,11 @@ TUPLE: identity-tuple ;
M: identity-tuple equal? 2drop f ;
USE: math.private
: = ( obj1 obj2 -- ? )
2dup eq? [ 2drop t ] [ equal? ] if ; inline
2dup eq? [ 2drop t ] [
2dup both-fixnums? [ 2drop f ] [ equal? ] if
] if ; inline
GENERIC: clone ( obj -- cloned )

View File

@ -835,12 +835,35 @@ PRIVATE>
: supremum ( seq -- n ) dup first [ max ] reduce ;
: flip ( matrix -- newmatrix )
dup empty? [
dup [ length ] map infimum
swap [ [ nth-unsafe ] with { } map-as ] curry { } map-as
] unless ;
: sigma ( seq quot -- n ) [ + ] compose 0 swap reduce ; inline
: count ( seq quot -- n ) [ 1 0 ? ] compose sigma ; inline
! We hand-optimize flip to such a degree because type hints
! cannot express that an array is an array of arrays yet, and
! this word happens to be performance-critical since the compiler
! itself uses it. Optimizing it like this reduced compile time.
<PRIVATE
: generic-flip ( matrix -- newmatrix )
[ dup first length [ length min ] reduce ] keep
[ [ nth-unsafe ] with { } map-as ] curry { } map-as ; inline
USE: arrays
: array-length ( array -- len )
{ array } declare length>> ;
: array-flip ( matrix -- newmatrix )
[ dup first array-length [ array-length min ] reduce ] keep
[ [ array-nth ] with { } map-as ] curry { } map-as ;
PRIVATE>
: flip ( matrix -- newmatrix )
dup empty? [
dup array? [
dup [ array? ] all?
[ array-flip ] [ generic-flip ] if
] [ generic-flip ] if
] unless ;

2
extra/fuel/authors.txt Normal file
View File

@ -0,0 +1,2 @@
Jose Antonio Ortega Ruiz
Eduardo Cavazos

View File

@ -0,0 +1,4 @@
! Copyright (C) 2008 Your name.
! See http://factorcode.org/license.txt for BSD license.
USING: tools.test fuel ;
IN: fuel.tests

121
extra/fuel/fuel.factor Normal file
View File

@ -0,0 +1,121 @@
! Copyright (C) 2008 Jose Antonio Ortega Ruiz.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays classes.tuple compiler.units continuations debugger
definitions eval io io.files io.streams.string kernel listener listener.private
make math namespaces parser prettyprint quotations sequences strings
vectors vocabs.loader ;
IN: fuel
! <PRIVATE
TUPLE: fuel-status in use ds? ;
SYMBOL: fuel-status-stack
V{ } clone fuel-status-stack set-global
: push-fuel-status ( -- )
in get use get clone display-stacks? get
fuel-status boa
fuel-status-stack get push ;
: pop-fuel-status ( -- )
fuel-status-stack get empty? [
fuel-status-stack get pop
[ in>> in set ]
[ use>> clone use set ]
[ ds?>> display-stacks? swap [ on ] [ off ] if ] tri
] unless ;
SYMBOL: fuel-eval-result
f clone fuel-eval-result set-global
SYMBOL: fuel-eval-output
f clone fuel-eval-result set-global
! PRIVATE>
GENERIC: fuel-pprint ( obj -- )
M: object fuel-pprint pprint ;
M: f fuel-pprint drop "nil" write ;
M: integer fuel-pprint pprint ;
M: string fuel-pprint pprint ;
M: sequence fuel-pprint
dup empty? [ drop f fuel-pprint ] [
"(" write
[ " " write ] [ fuel-pprint ] interleave
")" write
] if ;
M: tuple fuel-pprint tuple>array fuel-pprint ;
M: continuation fuel-pprint drop "~continuation~" write ;
: fuel-eval-set-result ( obj -- )
clone fuel-eval-result set-global ;
: fuel-retort ( -- )
error get
fuel-eval-result get-global
fuel-eval-output get-global
3array fuel-pprint ;
: fuel-forget-error ( -- )
f error set-global ;
: (fuel-begin-eval) ( -- )
push-fuel-status
display-stacks? off
fuel-forget-error
f fuel-eval-result set-global
f fuel-eval-output set-global ;
: (fuel-end-eval) ( quot -- )
with-string-writer fuel-eval-output set-global
fuel-retort
pop-fuel-status ;
: (fuel-eval) ( lines -- )
[ [ parse-lines ] with-compilation-unit call ] curry [ drop ] recover ;
: (fuel-eval-each) ( lines -- )
[ 1vector (fuel-eval) ] each ;
: (fuel-eval-usings) ( usings -- )
[ "USING: " prepend " ;" append ] map
(fuel-eval-each) fuel-forget-error ;
: (fuel-eval-in) ( in -- )
[ dup "IN: " prepend 1vector (fuel-eval) in set ] when* ;
: fuel-eval-in-context ( lines in usings -- )
(fuel-begin-eval) [
(fuel-eval-usings)
(fuel-eval-in)
(fuel-eval)
] (fuel-end-eval) ;
: fuel-begin-eval ( in -- )
(fuel-begin-eval)
(fuel-eval-in)
fuel-retort ;
: fuel-eval ( lines -- )
(fuel-begin-eval) [ (fuel-eval) ] (fuel-end-eval) ;
: fuel-end-eval ( -- )
[ ] (fuel-end-eval) ;
: fuel-get-edit-location ( defspec -- )
where [ first2 [ (normalize-path) ] dip 2array fuel-eval-set-result ] when* ;
: fuel-startup ( -- )
"listener" run ;
MAIN: fuel-startup

64
misc/fuel/README Normal file
View File

@ -0,0 +1,64 @@
FUEL, Factor's Ultimate Emacs Library
-------------------------------------
FUEL provides a complete environment for your Factor coding pleasure
inside Emacs, including source code edition and interaction with a
Factor listener instance running within Emacs.
FUEL was started by Jose A Ortega as an extension to Ed Cavazos'
original factor.el code.
Installation
------------
FUEL comes bundled with Factor's distribution. The folder misc/fuel
contains Elisp code, and there's a fuel vocabulary in extras/fuel.
To install FUEL, either add this line to your Emacs initialisation:
(load-file "<path/to/factor/installation>/misc/fuel/fu.el")
or
(add-to-list load-path "<path/to/factor/installation>/fuel")
(require 'fuel)
If all you want is a major mode for editing Factor code with pretty
font colors and indentation, without running the factor listener
inside Emacs, you can use instead:
(add-to-list load-path "<path/to/factor/installation>/fuel")
(setq factor-mode-use-fuel nil)
(require 'factor-mode)
Basic usage
-----------
If you're using the default factor binary and images locations inside
the Factor's source tree, that should be enough to start using FUEL.
Editing any file with the extension .factor will put you in
factor-mode; try C-hm for a summary of available commands.
To start the listener, try M-x run-factor.
Many aspects of the environment can be customized:
M-x customize-group fuel will show you how many.
Quick key reference
-------------------
- C-cz : switch to listener
- C-co : cycle between code, tests and docs factor files
- M-. : edit word at point in Emacs
- C-cr, C-cC-er : eval region
- C-M-r, C-cC-ee : eval region, extending it to definition boundaries
- C-M-x, C-cC-ex : eval definition around point
- C-cC-da : toggle autodoc mode
- C-cC-dd : help for word at point
- C-cC-ds : short help word at point
Chords ending in a single letter <x> accept also C-<x> (e.g. C-cC-z is
the same as C-cz).

239
misc/fuel/factor-mode.el Normal file
View File

@ -0,0 +1,239 @@
;;; factor-mode.el -- mode for editing Factor source
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages, fuel, factor
;; Start date: Tue Dec 02, 2008 21:32
;;; Comentary:
;; Definition of factor-mode, a major Emacs for editing Factor source
;; code.
;;; Code:
(require 'fuel-base)
(require 'fuel-syntax)
(require 'fuel-font-lock)
(require 'ring)
;;; Customization:
(defgroup factor-mode nil
"Major mode for Factor source code"
:group 'fuel)
(defcustom factor-mode-use-fuel t
"Whether to use the full FUEL facilities in factor mode.
Set this variable to nil if you just want to use Emacs as the
external editor of your Factor environment, e.g., by putting
these lines in your .emacs:
(add-to-list 'load-path \"/path/to/factor/misc/fuel\")
(setq factor-mode-use-fuel nil)
(require 'factor-mode)
"
:type 'boolean
:group 'factor-mode)
(defcustom factor-mode-default-indent-width 4
"Default indentation width for factor-mode.
This value will be used for the local variable
`factor-mode-indent-width' in new factor buffers. For existing
code, we first check if `factor-mode-indent-width' is set
explicitly in a local variable section or line (e.g.
'! -*- factor-mode-indent-witdth: 2 -*-'). If that's not the case,
`factor-mode' tries to infer its correct value from the existing
code in the buffer."
:type 'integer
:group 'fuel)
(defcustom factor-mode-hook nil
"Hook run when entering Factor mode."
:type 'hook
:group 'factor-mode)
;;; Syntax table:
(defun factor-mode--syntax-setup ()
(set-syntax-table fuel-syntax--syntax-table)
(set (make-local-variable 'beginning-of-defun-function)
'fuel-syntax--beginning-of-defun)
(set (make-local-variable 'end-of-defun-function) 'fuel-syntax--end-of-defun)
(set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil)
(fuel-syntax--enable-usings))
;;; Indentation:
(make-variable-buffer-local
(defvar factor-mode-indent-width factor-mode-default-indent-width
"Indentation width in factor buffers. A local variable."))
(defun factor-mode--guess-indent-width ()
"Chooses an indentation value from existing code."
(let ((word-cont "^ +[^ ]")
(iw))
(save-excursion
(beginning-of-buffer)
(while (not iw)
(if (not (re-search-forward fuel-syntax--definition-start-regex nil t))
(setq iw factor-mode-default-indent-width)
(forward-line)
(when (looking-at word-cont)
(setq iw (current-indentation))))))
iw))
(defun factor-mode--indent-in-brackets ()
(save-excursion
(beginning-of-line)
(when (> (fuel-syntax--brackets-depth) 0)
(let ((op (fuel-syntax--brackets-start))
(cl (fuel-syntax--brackets-end))
(ln (line-number-at-pos)))
(when (> ln (line-number-at-pos op))
(if (and (> cl 0) (= ln (line-number-at-pos cl)))
(fuel-syntax--indentation-at op)
(fuel-syntax--increased-indentation (fuel-syntax--indentation-at op))))))))
(defun factor-mode--indent-definition ()
(save-excursion
(beginning-of-line)
(when (fuel-syntax--at-begin-of-def) 0)))
(defun factor-mode--indent-setter-line ()
(when (fuel-syntax--at-setter-line)
(save-excursion
(let ((indent (and (fuel-syntax--at-constructor-line) (current-indentation))))
(while (not (or indent
(bobp)
(fuel-syntax--at-begin-of-def)
(fuel-syntax--at-end-of-def)))
(if (fuel-syntax--at-constructor-line)
(setq indent (fuel-syntax--increased-indentation))
(forward-line -1)))
indent))))
(defun factor-mode--indent-continuation ()
(save-excursion
(forward-line -1)
(while (and (not (bobp))
(fuel-syntax--looking-at-emptiness))
(forward-line -1))
(cond ((or (fuel-syntax--at-end-of-def)
(fuel-syntax--at-setter-line))
(fuel-syntax--decreased-indentation))
((and (fuel-syntax--at-begin-of-def)
(not (fuel-syntax--at-using)))
(fuel-syntax--increased-indentation))
(t (current-indentation)))))
(defun factor-mode--calculate-indentation ()
"Calculate Factor indentation for line at point."
(or (and (bobp) 0)
(factor-mode--indent-definition)
(factor-mode--indent-in-brackets)
(factor-mode--indent-setter-line)
(factor-mode--indent-continuation)
0))
(defun factor-mode--indent-line ()
"Indent current line as Factor code"
(let ((target (factor-mode--calculate-indentation))
(pos (- (point-max) (point))))
(if (= target (current-indentation))
(if (< (current-column) (current-indentation))
(back-to-indentation))
(beginning-of-line)
(delete-horizontal-space)
(indent-to target)
(if (> (- (point-max) pos) (point))
(goto-char (- (point-max) pos))))))
(defun factor-mode--indentation-setup ()
(set (make-local-variable 'indent-line-function) 'factor-mode--indent-line)
(setq factor-indent-width (factor-mode--guess-indent-width))
(setq indent-tabs-mode nil))
;;; Buffer cycling:
(defconst factor-mode--cycle-endings
'(".factor" "-tests.factor" "-docs.factor"))
(defconst factor-mode--regex-cycle-endings
(format "\\(.*?\\)\\(%s\\)$"
(regexp-opt factor-mode--cycle-endings)))
(defconst factor-mode--cycle-endings-ring
(let ((ring (make-ring (length factor-mode--cycle-endings))))
(dolist (e factor-mode--cycle-endings ring)
(ring-insert ring e))))
(defun factor-mode--cycle-next (file)
(let* ((match (string-match factor-mode--regex-cycle-endings file))
(base (and match (match-string-no-properties 1 file)))
(ending (and match (match-string-no-properties 2 file)))
(idx (and ending (ring-member factor-mode--cycle-endings-ring ending)))
(gfl (lambda (i) (concat base (ring-ref factor-mode--cycle-endings-ring i)))))
(if (not idx) file
(let ((l (length factor-mode--cycle-endings)) (i 1) next)
(while (and (not next) (< i l))
(when (file-exists-p (funcall gfl (+ idx i)))
(setq next (+ idx i)))
(setq i (1+ i)))
(funcall gfl (or next idx))))))
(defun factor-mode-visit-other-file (&optional file)
"Cycle between code, tests and docs factor files."
(interactive)
(find-file (factor-mode--cycle-next (or file (buffer-file-name)))))
;;; Keymap:
(defun factor-mode-insert-and-indent (n)
(interactive "p")
(self-insert-command n)
(indent-for-tab-command))
(defvar factor-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [?\]] 'factor-mode-insert-and-indent)
(define-key map [?}] 'factor-mode-insert-and-indent)
(define-key map "\C-m" 'newline-and-indent)
(define-key map "\C-co" 'factor-mode-visit-other-file)
(define-key map "\C-c\C-o" 'factor-mode-visit-other-file)
map))
(defun factor-mode--keymap-setup ()
(use-local-map factor-mode-map))
;;; Factor mode:
;;;###autoload
(defun factor-mode ()
"A mode for editing programs written in the Factor programming language.
\\{factor-mode-map}"
(interactive)
(kill-all-local-variables)
(setq major-mode 'factor-mode)
(setq mode-name "Factor")
(fuel-font-lock--font-lock-setup)
(factor-mode--keymap-setup)
(factor-mode--indentation-setup)
(factor-mode--syntax-setup)
(when factor-mode-use-fuel (require 'fuel-mode) (fuel-mode))
(run-hooks 'factor-mode-hook))
(provide 'factor-mode)
;;; factor-mode.el ends here

26
misc/fuel/fu.el Normal file
View File

@ -0,0 +1,26 @@
;;; fu.el --- Startup file for FUEL
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages
;;; Code:
(add-to-list 'load-path (file-name-directory load-file-name))
(add-to-list 'auto-mode-alist '("\\.factor\\'" . factor-mode))
(autoload 'factor-mode "factor-mode.el"
"Major mode for editing Factor source." t)
(autoload 'run-factor "fuel-listener.el"
"Start a Factor listener, or switch to a running one." t)
(autoload 'fuel-autodoc-mode "fuel-help.el"
"Minor mode showing in the minibuffer a synopsis of Factor word at point."
t)
;;; fu.el ends here

63
misc/fuel/fuel-base.el Normal file
View File

@ -0,0 +1,63 @@
;;; fuel-base.el --- Basic FUEL support code
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages
;;; Commentary:
;; Basic definitions likely to be used by all FUEL modules.
;;; Code:
(defconst fuel-version "1.0")
;;;###autoload
(defsubst fuel-version ()
"Echoes FUEL's version."
(interactive)
(message "FUEL %s" fuel-version))
;;; Customization:
;;;###autoload
(defgroup fuel nil
"Factor's Ultimate Emacs Library"
:group 'language)
;;; Emacs compatibility:
(eval-after-load "ring"
'(when (not (fboundp 'ring-member))
(defun ring-member (ring item)
(catch 'found
(dotimes (ind (ring-length ring) nil)
(when (equal item (ring-ref ring ind))
(throw 'found ind)))))))
;;; Utilities
(defun fuel--shorten-str (str len)
(let ((sl (length str)))
(if (<= sl len) str
(let* ((sep " ... ")
(sepl (length sep))
(segl (/ (- len sepl) 2)))
(format "%s%s%s"
(substring str 0 segl)
sep
(substring str (- sl segl)))))))
(defun fuel--shorten-region (begin end len)
(fuel--shorten-str (mapconcat 'identity
(split-string (buffer-substring begin end) nil t)
" ")
len))
(provide 'fuel-base)
;;; fuel-base.el ends here

112
misc/fuel/fuel-eval.el Normal file
View File

@ -0,0 +1,112 @@
;;; fuel-eval.el --- utilities for communication with fuel-listener
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages
;; Start date: Tue Dec 02, 2008
;;; Commentary:
;; Protocols for handling communications via a comint buffer running a
;; factor listener.
;;; Code:
(require 'fuel-base)
(require 'fuel-syntax)
;;; Syncronous string sending:
(defvar fuel-eval-log-max-length 16000)
(defvar fuel-eval--default-proc-function nil)
(defsubst fuel-eval--default-proc ()
(and fuel-eval--default-proc-function
(funcall fuel-eval--default-proc-function)))
(defvar fuel-eval--proc nil)
(defvar fuel-eval--log t)
(defun fuel-eval--send-string (str)
(let ((proc (or fuel-eval--proc (fuel-eval--default-proc))))
(when proc
(with-current-buffer (get-buffer-create "*factor messages*")
(goto-char (point-max))
(when (and (> fuel-eval-log-max-length 0)
(> (point) fuel-eval-log-max-length))
(erase-buffer))
(when fuel-eval--log (insert "\n>> " (fuel--shorten-str str 256) "\n"))
(let ((beg (point)))
(comint-redirect-send-command-to-process str (current-buffer) proc nil t)
(with-current-buffer (process-buffer proc)
(while (not comint-redirect-completed) (sleep-for 0 1)))
(goto-char beg)
(current-buffer))))))
;;; Evaluation protocol
(defsubst fuel-eval--retort-make (err result &optional output)
(list err result output))
(defsubst fuel-eval--retort-error (ret) (nth 0 ret))
(defsubst fuel-eval--retort-result (ret) (nth 1 ret))
(defsubst fuel-eval--retort-output (ret) (nth 2 ret))
(defsubst fuel-eval--retort-p (ret) (listp ret))
(defsubst fuel-eval--error-name (err) (car err))
(defsubst fuel-eval--make-parse-error-retort (str)
(fuel-eval--retort-make 'parse-retort-error nil str))
(defun fuel-eval--parse-retort (buffer)
(save-current-buffer
(set-buffer buffer)
(condition-case nil
(read (current-buffer))
(error (fuel-eval--make-parse-error-retort
(buffer-substring-no-properties (point) (point-max)))))))
(defsubst fuel-eval--send/retort (str)
(fuel-eval--parse-retort (fuel-eval--send-string str)))
(defsubst fuel-eval--eval-begin ()
(fuel-eval--send/retort "fuel-begin-eval"))
(defsubst fuel-eval--eval-end ()
(fuel-eval--send/retort "fuel-begin-eval"))
(defsubst fuel-eval--factor-array (strs)
(format "V{ %S }" (mapconcat 'identity strs " ")))
(defsubst fuel-eval--eval-strings (strs)
(let ((str (format "%s fuel-eval" (fuel-eval--factor-array strs))))
(fuel-eval--send/retort str)))
(defsubst fuel-eval--eval-string (str)
(fuel-eval--eval-strings (list str)))
(defun fuel-eval--eval-strings/context (strs)
(let ((usings (fuel-syntax--usings-update)))
(fuel-eval--send/retort
(format "%s %S %s fuel-eval-in-context"
(fuel-eval--factor-array strs)
(or fuel-syntax--current-vocab "f")
(if usings (fuel-eval--factor-array usings) "f")))))
(defsubst fuel-eval--eval-string/context (str)
(fuel-eval--eval-strings/context (list str)))
(defun fuel-eval--eval-region/context (begin end)
(let ((lines (split-string (buffer-substring-no-properties begin end)
"[\f\n\r\v]+" t)))
(when (> (length lines) 0)
(fuel-eval--eval-strings/context lines))))
(provide 'fuel-eval)
;;; fuel-eval.el ends here

View File

@ -0,0 +1,88 @@
;;; fuel-font-lock.el -- font lock for factor code
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages, fuel, factor
;; Start date: Wed Dec 03, 2008 21:40
;;; Comentary:
;; Font lock setup for highlighting Factor code.
;;; Code:
(require 'fuel-base)
(require 'fuel-syntax)
(require 'font-lock)
;;; Faces:
(defmacro fuel-font-lock--face (face def doc)
(let ((face (intern (format "factor-font-lock-%s" (symbol-name face))))
(def (intern (format "font-lock-%s-face" (symbol-name def)))))
`(defface ,face (face-default-spec ,def)
,(format "Face for %s." doc)
:group 'factor-mode
:group 'faces)))
(defmacro fuel-font-lock--faces-setup ()
(cons 'progn
(mapcar (lambda (f) (cons 'fuel-font-lock--face f))
'((comment comment "comments")
(constructor type "constructors (<foo>)")
(declaration keyword "declaration words")
(parsing-word keyword "parsing words")
(setter-word function-name "setter words (>>foo)")
(stack-effect comment "stack effect specifications")
(string string "strings")
(symbol variable-name "name of symbol being defined")
(type-name type "type names")
(vocabulary-name constant "vocabulary names")
(word function-name "word, generic or method being defined")))))
(fuel-font-lock--faces-setup)
;;; Font lock:
(defconst fuel-font-lock--parsing-lock-keywords
(cons '("\\(P\\|SBUF\\)\"" 1 'factor-font-lock-parsing-word)
(mapcar (lambda (w) `(,(format "\\(^\\| \\)\\(%s\\)\\($\\| \\)" w)
2 'factor-font-lock-parsing-word))
fuel-syntax--parsing-words)))
(defconst fuel-font-lock--font-lock-keywords
`(,@fuel-font-lock--parsing-lock-keywords
(,fuel-syntax--stack-effect-regex . 'factor-font-lock-stack-effect)
(,fuel-syntax--parsing-words-ext-regex . 'factor-font-lock-parsing-word)
(,fuel-syntax--declaration-words-regex 1 'factor-font-lock-declaration)
(,fuel-syntax--word-definition-regex 2 'factor-font-lock-word)
(,fuel-syntax--type-definition-regex 2 'factor-font-lock-type-name)
(,fuel-syntax--method-definition-regex (1 'factor-font-lock-type-name)
(2 'factor-font-lock-word))
(,fuel-syntax--parent-type-regex 1 'factor-font-lock-type)
(,fuel-syntax--constructor-regex . 'factor-font-lock-constructor)
(,fuel-syntax--setter-regex . 'factor-font-lock-setter-word)
(,fuel-syntax--symbol-definition-regex 2 'factor-font-lock-symbol)
(,fuel-syntax--use-line-regex 1 'factor-font-lock-vocabulary-name))
"Font lock keywords definition for Factor mode.")
(defun fuel-font-lock--font-lock-setup (&optional keywords no-syntax)
(set (make-local-variable 'comment-start) "! ")
(set (make-local-variable 'parse-sexp-lookup-properties) t)
(set (make-local-variable 'font-lock-comment-face) 'factor-font-lock-comment)
(set (make-local-variable 'font-lock-string-face) 'factor-font-lock-string)
(set (make-local-variable 'font-lock-defaults)
`(,(or keywords 'fuel-font-lock--font-lock-keywords)
nil nil nil nil
,@(if no-syntax nil
(list (cons 'font-lock-syntactic-keywords
fuel-syntax--syntactic-keywords))))))
(provide 'fuel-font-lock)
;;; fuel-font-lock.el ends here

208
misc/fuel/fuel-help.el Normal file
View File

@ -0,0 +1,208 @@
;;; fuel-help.el -- accessing Factor's help system
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages, fuel, factor
;; Start date: Wed Dec 03, 2008 21:41
;;; Comentary:
;; Modes and functions interfacing Factor's 'see' and 'help'
;; utilities, as well as an ElDoc-based autodoc mode.
;;; Code:
(require 'fuel-base)
(require 'fuel-font-lock)
(require 'fuel-eval)
;;; Customization:
(defgroup fuel-help nil
"Options controlling FUEL's help system"
:group 'fuel)
(defcustom fuel-help-minibuffer-font-lock t
"Whether to use font lock for info messages in the minibuffer."
:group 'fuel-help
:type 'boolean)
(defcustom fuel-help-always-ask t
"When enabled, always ask for confirmation in help prompts."
:type 'boolean
:group 'fuel-help)
(defcustom fuel-help-use-minibuffer t
"When enabled, use the minibuffer for short help messages."
:type 'boolean
:group 'fuel-help)
(defcustom fuel-help-mode-hook nil
"Hook run by `factor-help-mode'."
:type 'hook
:group 'fuel-help)
(defface fuel-help-font-lock-headlines '((t (:bold t :weight bold)))
"Face for headlines in help buffers."
:group 'fuel-help
:group 'faces)
;;; Autodoc mode:
(defvar fuel-help--font-lock-buffer
(let ((buffer (get-buffer-create " *fuel help minibuffer messages*")))
(set-buffer buffer)
(fuel-font-lock--font-lock-setup)
buffer))
(defun fuel-help--font-lock-str (str)
(set-buffer fuel-help--font-lock-buffer)
(erase-buffer)
(insert str)
(let ((font-lock-verbose nil)) (font-lock-fontify-buffer))
(buffer-string))
(defun fuel-help--word-synopsis (&optional word)
(let ((word (or word (fuel-syntax-symbol-at-point)))
(fuel-eval--log nil))
(when word
(let ((ret (fuel-eval--eval-string/context
(format "\\ %s synopsis fuel-eval-set-result" word))))
(when (not (fuel-eval--retort-error ret))
(if fuel-help-minibuffer-font-lock
(fuel-help--font-lock-str (fuel-eval--retort-result ret))
(fuel-eval--retort-result ret)))))))
(make-variable-buffer-local
(defvar fuel-autodoc-mode-string " A"
"Modeline indicator for fuel-autodoc-mode"))
(define-minor-mode fuel-autodoc-mode
"Toggle Fuel's Autodoc mode.
With no argument, this command toggles the mode.
Non-null prefix argument turns on the mode.
Null prefix argument turns off the mode.
When Autodoc mode is enabled, a synopsis of the word at point is
displayed in the minibuffer."
:init-value nil
:lighter fuel-autodoc-mode-string
:group 'fuel
(set (make-local-variable 'eldoc-documentation-function)
(when fuel-autodoc-mode 'fuel-help--word-synopsis))
(set (make-local-variable 'eldoc-minor-mode-string) nil)
(eldoc-mode fuel-autodoc-mode)
(message "Fuel Autodoc %s" (if fuel-autodoc-mode "enabled" "disabled")))
;;;; Factor help mode:
(defvar fuel-help-mode-map (make-sparse-keymap)
"Keymap for Factor help mode.")
(define-key fuel-help-mode-map [(return)] 'fuel-help)
(defconst fuel-help--headlines
(regexp-opt '("Class description"
"Definition"
"Examples"
"Generic word contract"
"Inputs and outputs"
"Methods"
"Notes"
"Parent topics:"
"See also"
"Syntax"
"Vocabulary"
"Warning"
"Word description")
t))
(defconst fuel-help--headlines-regexp (format "^%s" fuel-help--headlines))
(defconst fuel-help--font-lock-keywords
`(,@fuel-font-lock--font-lock-keywords
(,fuel-help--headlines-regexp . 'fuel-help-font-lock-headlines)))
(defun fuel-help-mode ()
"Major mode for displaying Factor documentation.
\\{fuel-help-mode-map}"
(interactive)
(kill-all-local-variables)
(use-local-map fuel-help-mode-map)
(setq mode-name "Factor Help")
(setq major-mode 'fuel-help-mode)
(fuel-font-lock--font-lock-setup fuel-help--font-lock-keywords t)
(set (make-local-variable 'view-no-disable-on-exit) t)
(view-mode)
(setq view-exit-action
(lambda (buffer)
;; Use `with-current-buffer' to make sure that `bury-buffer'
;; also removes BUFFER from the selected window.
(with-current-buffer buffer
(bury-buffer))))
(setq fuel-autodoc-mode-string "")
(fuel-autodoc-mode)
(run-mode-hooks 'fuel-help-mode-hook))
(defun fuel-help--help-buffer ()
(with-current-buffer (get-buffer-create "*fuel-help*")
(fuel-help-mode)
(current-buffer)))
(defvar fuel-help--history nil)
(defun fuel-help--show-help (&optional see)
(let* ((def (fuel-syntax-symbol-at-point))
(prompt (format "See%s help on%s: " (if see " short" "")
(if def (format " (%s)" def) "")))
(ask (or (not (memq major-mode '(factor-mode fuel-help-mode)))
(not def)
fuel-help-always-ask))
(def (if ask (read-string prompt nil 'fuel-help--history def) def))
(cmd (format "\\ %s %s" def (if see "see" "help")))
(fuel-eval--log nil)
(ret (fuel-eval--eval-string/context cmd))
(out (fuel-eval--retort-output ret)))
(if (or (fuel-eval--retort-error ret) (empty-string-p out))
(message "No help for '%s'" def)
(let ((hb (fuel-help--help-buffer))
(inhibit-read-only t)
(font-lock-verbose nil))
(set-buffer hb)
(erase-buffer)
(insert out)
(set-buffer-modified-p nil)
(pop-to-buffer hb)
(goto-char (point-min))))))
;;; Interface: see/help commands
(defun fuel-help-short (&optional arg)
"See a help summary of symbol at point.
By default, the information is shown in the minibuffer. When
called with a prefix argument, the information is displayed in a
separate help buffer."
(interactive "P")
(if (if fuel-help-use-minibuffer (not arg) arg)
(fuel-help--word-synopsis)
(fuel-help--show-help t)))
(defun fuel-help ()
"Show extended help about the symbol at point, using a help
buffer."
(interactive)
(fuel-help--show-help))
(provide 'fuel-help)
;;; fuel-help.el ends here

124
misc/fuel/fuel-listener.el Normal file
View File

@ -0,0 +1,124 @@
;;; fuel-listener.el --- starting the fuel listener
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages
;;; Commentary:
;; Utilities to maintain and switch to a factor listener comint
;; buffer, with an accompanying major fuel-listener-mode.
;;; Code:
(require 'fuel-eval)
(require 'fuel-base)
(require 'comint)
;;; Customization:
(defgroup fuel-listener nil
"Interacting with a Factor listener inside Emacs"
:group 'fuel)
(defcustom fuel-listener-factor-binary "~/factor/factor"
"Full path to the factor executable to use when starting a listener."
:type '(file :must-match t)
:group 'fuel-listener)
(defcustom fuel-listener-factor-image "~/factor/factor.image"
"Full path to the factor image to use when starting a listener."
:type '(file :must-match t)
:group 'fuel-listener)
(defcustom fuel-listener-use-other-window t
"Use a window other than the current buffer's when switching to
the factor-listener buffer."
:type 'boolean
:group 'fuel-listener)
(defcustom fuel-listener-window-allow-split t
"Allow window splitting when switching to the fuel listener
buffer."
:type 'boolean
:group 'fuel-listener)
;;; Fuel listener buffer/process:
(defvar fuel-listener-buffer nil
"The buffer in which the Factor listener is running.")
(defun fuel-listener--start-process ()
(let ((factor (expand-file-name fuel-listener-factor-binary))
(image (expand-file-name fuel-listener-factor-image)))
(unless (file-executable-p factor)
(error "Could not run factor: %s is not executable" factor))
(unless (file-readable-p image)
(error "Could not run factor: image file %s not readable" image))
(setq fuel-listener-buffer
(make-comint "fuel listener" factor nil "-run=fuel" (format "-i=%s" image)))
(with-current-buffer fuel-listener-buffer
(fuel-listener-mode))))
(defun fuel-listener--process (&optional start)
(or (and (buffer-live-p fuel-listener-buffer)
(get-buffer-process fuel-listener-buffer))
(if (not start)
(error "No running factor listener (try M-x run-factor)")
(fuel-listener--start-process)
(fuel-listener--process))))
(setq fuel-eval--default-proc-function 'fuel-listener--process)
;;; Interface: starting fuel listener
(defalias 'switch-to-factor 'run-factor)
(defalias 'switch-to-fuel-listener 'run-factor)
;;;###autoload
(defun run-factor (&optional arg)
"Show the fuel-listener buffer, starting the process if needed."
(interactive)
(let ((buf (process-buffer (fuel-listener--process t)))
(pop-up-windows fuel-listener-window-allow-split))
(if fuel-listener-use-other-window
(pop-to-buffer buf)
(switch-to-buffer buf))))
;;; Fuel listener mode:
(defconst fuel-listener--prompt-regex "( [^)]* ) ")
(defun fuel-listener--wait-for-prompt (&optional timeout)
(let ((proc (fuel-listener--process)))
(with-current-buffer fuel-listener-buffer
(goto-char comint-last-input-end)
(while (not (or (re-search-forward comint-prompt-regexp nil t)
(not (accept-process-output proc timeout))))
(goto-char comint-last-input-end))
(goto-char (point-max)))))
(defun fuel-listener--startup ()
(fuel-listener--wait-for-prompt)
(fuel-eval--send-string "USE: fuel")
(message "FUEL listener up and running!"))
(define-derived-mode fuel-listener-mode comint-mode "Fuel Listener"
"Major mode for interacting with an inferior Factor listener process.
\\{fuel-listener-mode-map}"
(set (make-local-variable 'comint-prompt-regexp)
fuel-listener--prompt-regex)
(set (make-local-variable 'comint-prompt-read-only) t)
(fuel-listener--startup))
;; (define-key fuel-listener-mode-map "\C-w" 'comint-kill-region)
;; (define-key fuel-listener-mode-map "\C-k" 'comint-kill-whole-line)
(provide 'fuel-listener)
;;; fuel-listener.el ends here

148
misc/fuel/fuel-mode.el Normal file
View File

@ -0,0 +1,148 @@
;;; fuel-mode.el -- Minor mode enabling FUEL niceties
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages, fuel, factor
;; Start date: Sat Dec 06, 2008 00:52
;;; Comentary:
;; Enhancements to vanilla factor-mode (notably, listener interaction)
;; enabled by means of a minor mode.
;;; Code:
(require 'factor-mode)
(require 'fuel-base)
(require 'fuel-syntax)
(require 'fuel-font-lock)
(require 'fuel-help)
(require 'fuel-eval)
(require 'fuel-listener)
;;; Customization:
(defgroup fuel-mode nil
"Mode enabling FUEL's ultimate abilities."
:group 'fuel)
(defcustom fuel-mode-autodoc-p t
"Whether `fuel-autodoc-mode' gets enable by default in fuel buffers."
:group 'fuel-mode
:type 'boolean)
;;; User commands
(defun fuel-eval-region (begin end &optional arg)
"Sends region to Fuel's listener for evaluation.
With prefix, switchs to the listener's buffer afterwards."
(interactive "r\nP")
(let* ((ret (fuel-eval--eval-region/context begin end))
(err (fuel-eval--retort-error ret)))
(message "%s" (or err (fuel--shorten-region begin end 70))))
(when arg (pop-to-buffer fuel-listener-buffer)))
(defun fuel-eval-extended-region (begin end &optional arg)
"Sends region extended outwards to nearest definitions,
to Fuel's listener for evaluation. With prefix, switchs to the
listener's buffer afterwards."
(interactive "r\nP")
(fuel-eval-region (save-excursion (goto-char begin) (mark-defun) (point))
(save-excursion (goto-char end) (mark-defun) (mark))))
(defun fuel-eval-definition (&optional arg)
"Sends definition around point to Fuel's listener for evaluation.
With prefix, switchs to the listener's buffer afterwards."
(interactive "P")
(save-excursion
(mark-defun)
(let* ((begin (point))
(end (mark)))
(unless (< begin end) (error "No evaluable definition around point"))
(fuel-eval-region begin end))))
(defun fuel-edit-word-at-point (&optional arg)
"Opens a new window visiting the definition of the word at point.
With prefix, asks for the word to edit."
(interactive "P")
(let* ((word (fuel-syntax-symbol-at-point))
(ask (or arg (not word)))
(word (if ask
(read-string nil
(format "Edit word%s: "
(if word (format " (%s)" word) ""))
word)
word)))
(let* ((ret (fuel-eval--eval-string/context
(format "\\ %s fuel-get-edit-location" word)))
(err (fuel-eval--retort-error ret))
(loc (fuel-eval--retort-result ret)))
(when (or err (not loc) (not (listp loc)) (not (stringp (car loc))))
(error "Couldn't find edit location for '%s'" word))
(unless (file-readable-p (car loc))
(error "Couldn't open '%s' for read" (car loc)))
(find-file-other-window (car loc))
(goto-line (if (numberp (cadr loc)) (cadr loc) 1)))))
;;; Minor mode definition:
(make-variable-buffer-local
(defvar fuel-mode-string " F"
"Modeline indicator for fuel-mode"))
(defvar fuel-mode-map (make-sparse-keymap)
"Key map for fuel-mode")
(define-minor-mode fuel-mode
"Toggle Fuel's mode.
With no argument, this command toggles the mode.
Non-null prefix argument turns on the mode.
Null prefix argument turns off the mode.
When Fuel mode is enabled, a host of nice utilities for
interacting with a factor listener is at your disposal.
\\{fuel-mode-map}"
:init-value nil
:lighter fuel-mode-string
:group 'fuel
:keymap fuel-mode-map
(setq fuel-autodoc-mode-string "/A")
(when fuel-mode-autodoc-p (fuel-autodoc-mode fuel-mode)))
;;; Keys:
(defun fuel-mode--key-1 (k c)
(define-key fuel-mode-map (vector '(control ?c) k) c)
(define-key fuel-mode-map (vector '(control ?c) `(control ,k)) c))
(defun fuel-mode--key (p k c)
(define-key fuel-mode-map (vector '(control ?c) `(control ,p) k) c)
(define-key fuel-mode-map (vector '(control ?c) `(control ,p) `(control ,k)) c))
(fuel-mode--key-1 ?z 'run-factor)
(define-key fuel-mode-map "\C-\M-x" 'fuel-eval-definition)
(fuel-mode--key ?e ?x 'fuel-eval-definition)
(fuel-mode--key-1 ?r 'fuel-eval-region)
(fuel-mode--key ?e ?r 'fuel-eval-region)
(define-key fuel-mode-map "\C-\M-r" 'fuel-eval-extended-region)
(fuel-mode--key ?e ?e 'fuel-eval-extended-region)
(define-key fuel-mode-map "\M-." 'fuel-edit-word-at-point)
(fuel-mode--key ?d ?a 'fuel-autodoc-mode)
(fuel-mode--key ?d ?d 'fuel-help)
(fuel-mode--key ?d ?s 'fuel-help-short)
(provide 'fuel-mode)
;;; fuel-mode.el ends here

281
misc/fuel/fuel-syntax.el Normal file
View File

@ -0,0 +1,281 @@
;;; fuel-syntax.el --- auxiliar definitions for factor code navigation.
;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
;; See http://factorcode.org/license.txt for BSD license.
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
;; Keywords: languages
;;; Commentary:
;; Auxiliar constants and functions to parse factor code.
;;; Code:
(require 'thingatpt)
;;; Thing-at-point support for factor symbols:
(defun fuel-syntax--beginning-of-symbol ()
"Move point to the beginning of the current symbol."
(while (eq (char-before) ?:) (backward-char))
(skip-syntax-backward "w_"))
(defun fuel-syntax--end-of-symbol ()
"Move point to the end of the current symbol."
(skip-syntax-forward "w_")
(while (looking-at ":") (forward-char)))
(put 'factor-symbol 'end-op 'fuel-syntax--end-of-symbol)
(put 'factor-symbol 'beginning-op 'fuel-syntax--beginning-of-symbol)
(defsubst fuel-syntax-symbol-at-point ()
(let ((s (substring-no-properties (thing-at-point 'factor-symbol))))
(and (> (length s) 0) s)))
;;; Regexps galore:
(defconst fuel-syntax--parsing-words
'("{" "}" "^:" "^::" ";" "<<" "<PRIVATE" ">>"
"BIN:" "BV{" "B{" "C:" "C-STRUCT:" "C-UNION:" "CHAR:" "CS{" "C{"
"DEFER:" "ERROR:" "EXCLUDE:" "FORGET:"
"GENERIC#" "GENERIC:" "HEX:" "HOOK:" "H{"
"IN:" "INSTANCE:" "INTERSECTION:"
"M:" "MACRO:" "MACRO::" "MAIN:" "MATH:" "METHOD:" "MIXIN:"
"OCT:" "POSTPONE:" "PREDICATE:" "PRIMITIVE:" "PRIVATE>" "PROVIDE:"
"REQUIRE:" "REQUIRES:" "SINGLETON:" "SLOT:" "SYMBOL:" "SYMBOLS:"
"TUPLE:" "T{" "t\\??" "TYPEDEF:"
"UNION:" "USE:" "USING:" "V{" "VARS:" "W{"))
(defconst fuel-syntax--parsing-words-ext-regex
(regexp-opt '("B" "call-next-method" "delimiter" "f" "initial:" "read-only")
'words))
(defconst fuel-syntax--declaration-words
'("flushable" "foldable" "inline" "parsing" "recursive"))
(defconst fuel-syntax--declaration-words-regex
(regexp-opt fuel-syntax--declaration-words 'words))
(defsubst fuel-syntax--second-word-regex (prefixes)
(format "^%s +\\([^ \r\n]+\\)" (regexp-opt prefixes t)))
(defconst fuel-syntax--method-definition-regex
"^M: +\\([^ ]+\\) +\\([^ ]+\\)")
(defconst fuel-syntax--word-definition-regex
(fuel-syntax--second-word-regex '(":" "::" "GENERIC:")))
(defconst fuel-syntax--type-definition-regex
(fuel-syntax--second-word-regex '("TUPLE:" "SINGLETON:")))
(defconst fuel-syntax--parent-type-regex "^TUPLE: +[^ ]+ +< +\\([^ ]+\\)")
(defconst fuel-syntax--constructor-regex "<[^ >]+>")
(defconst fuel-syntax--setter-regex "\\W>>[^ ]+\\b")
(defconst fuel-syntax--symbol-definition-regex
(fuel-syntax--second-word-regex '("SYMBOL:" "VAR:")))
(defconst fuel-syntax--stack-effect-regex " ( .* )")
(defconst fuel-syntax--using-lines-regex "^USING: +\\([^;]+\\);")
(defconst fuel-syntax--use-line-regex "^USE: +\\(.*\\)$")
(defconst fuel-syntax--current-vocab-regex "^IN: +\\([^ \r\n\f]+\\)")
(defconst fuel-syntax--sub-vocab-regex "^<\\([^ \n]+\\) *$")
(defconst fuel-syntax--definition-starters-regex
(regexp-opt '("VARS" "TUPLE" "MACRO" "MACRO:" "M" ":" "")))
(defconst fuel-syntax--definition-start-regex
(format "^\\(%s:\\) " fuel-syntax--definition-starters-regex))
(defconst fuel-syntax--definition-end-regex
(format "\\(\\(^\\| +\\);\\( +%s\\)*\\($\\| +\\)\\)"
fuel-syntax--declaration-words-regex))
(defconst fuel-syntax--single-liner-regex
(format "^%s" (regexp-opt '("DEFER:" "GENERIC:" "IN:"
"PRIVATE>" "<PRIVATE"
"SINGLETON:" "SYMBOL:" "USE:" "VAR:"))))
(defconst fuel-syntax--begin-of-def-regex
(format "^USING: \\|\\(%s\\)\\|\\(%s .*\\)"
fuel-syntax--definition-start-regex
fuel-syntax--single-liner-regex))
(defconst fuel-syntax--end-of-def-line-regex
(format "^.*%s" fuel-syntax--definition-end-regex))
(defconst fuel-syntax--end-of-def-regex
(format "\\(%s\\)\\|\\(%s .*\\)"
fuel-syntax--end-of-def-line-regex
fuel-syntax--single-liner-regex))
;;; Factor syntax table
(defvar fuel-syntax--syntax-table
(let ((i 0)
(table (make-syntax-table)))
;; Default is atom-constituent
(while (< i 256)
(modify-syntax-entry i "_ " table)
(setq i (1+ i)))
;; Word components.
(setq i ?0)
(while (<= i ?9)
(modify-syntax-entry i "w " table)
(setq i (1+ i)))
(setq i ?A)
(while (<= i ?Z)
(modify-syntax-entry i "w " table)
(setq i (1+ i)))
(setq i ?a)
(while (<= i ?z)
(modify-syntax-entry i "w " table)
(setq i (1+ i)))
;; Whitespace
(modify-syntax-entry ?\t " " table)
(modify-syntax-entry ?\f " " table)
(modify-syntax-entry ?\r " " table)
(modify-syntax-entry ? " " table)
;; (end of) Comments
(modify-syntax-entry ?\n ">" table)
;; Parenthesis
(modify-syntax-entry ?\[ "(] " table)
(modify-syntax-entry ?\] ")[ " table)
(modify-syntax-entry ?{ "(} " table)
(modify-syntax-entry ?} "){ " table)
(modify-syntax-entry ?\( "()" table)
(modify-syntax-entry ?\) ")(" table)
;; Strings
(modify-syntax-entry ?\" "\"" table)
(modify-syntax-entry ?\\ "/" table)
table)
"Syntax table used while in Factor mode.")
(defconst fuel-syntax--syntactic-keywords
`(("\\(#!\\)" (1 "<"))
(" \\(!\\)" (1 "<"))
("^\\(!\\)" (1 "<"))
("\\(!(\\) .* \\()\\)" (1 "<") (2 ">"))
("\\([[({]\\)\\([^ \"\n]\\)" (1 "_") (2 "_"))
("\\([^ \"\n]\\)\\([])}]\\)" (1 "_") (2 "_"))))
;;; Source code analysis:
(defsubst fuel-syntax--brackets-depth ()
(nth 0 (syntax-ppss)))
(defsubst fuel-syntax--brackets-start ()
(nth 1 (syntax-ppss)))
(defun fuel-syntax--brackets-end ()
(save-excursion
(goto-char (fuel-syntax--brackets-start))
(condition-case nil
(progn (forward-sexp)
(1- (point)))
(error -1))))
(defsubst fuel-syntax--indentation-at (pos)
(save-excursion (goto-char pos) (current-indentation)))
(defsubst fuel-syntax--increased-indentation (&optional i)
(+ (or i (current-indentation)) factor-indent-width))
(defsubst fuel-syntax--decreased-indentation (&optional i)
(- (or i (current-indentation)) factor-indent-width))
(defsubst fuel-syntax--at-begin-of-def ()
(looking-at fuel-syntax--begin-of-def-regex))
(defsubst fuel-syntax--at-end-of-def ()
(looking-at fuel-syntax--end-of-def-regex))
(defsubst fuel-syntax--looking-at-emptiness ()
(looking-at "^[ \t]*$"))
(defun fuel-syntax--at-setter-line ()
(save-excursion
(beginning-of-line)
(if (not (fuel-syntax--looking-at-emptiness))
(re-search-forward fuel-syntax--setter-regex (line-end-position) t)
(forward-line -1)
(or (fuel-syntax--at-constructor-line)
(fuel-syntax--at-setter-line)))))
(defun fuel-syntax--at-constructor-line ()
(save-excursion
(beginning-of-line)
(re-search-forward fuel-syntax--constructor-regex (line-end-position) t)))
(defsubst fuel-syntax--at-using ()
(looking-at fuel-syntax--using-lines-regex))
(defsubst fuel-syntax--beginning-of-defun (&optional times)
(re-search-backward fuel-syntax--begin-of-def-regex nil t times))
(defsubst fuel-syntax--end-of-defun ()
(re-search-forward fuel-syntax--end-of-def-regex nil t))
;;; USING/IN:
(make-variable-buffer-local
(defvar fuel-syntax--current-vocab nil))
(make-variable-buffer-local
(defvar fuel-syntax--usings nil))
(defun fuel-syntax--current-vocab ()
(let ((ip
(save-excursion
(when (re-search-backward fuel-syntax--current-vocab-regex nil t)
(setq fuel-syntax--current-vocab (match-string-no-properties 1))
(point)))))
(when ip
(let ((pp (save-excursion
(when (re-search-backward fuel-syntax--sub-vocab-regex ip t)
(point)))))
(when (and pp (> pp ip))
(let ((sub (match-string-no-properties 1)))
(unless (save-excursion (search-backward (format "%s>" sub) pp t))
(setq fuel-syntax--current-vocab
(format "%s.%s" fuel-syntax--current-vocab (downcase sub)))))))))
fuel-syntax--current-vocab)
(defun fuel-syntax--usings-update ()
(save-excursion
(setq fuel-syntax--usings (list (fuel-syntax--current-vocab)))
(while (re-search-backward fuel-syntax--using-lines-regex nil t)
(dolist (u (split-string (match-string-no-properties 1) nil t))
(push u fuel-syntax--usings)))
fuel-syntax--usings))
(defsubst fuel-syntax--usings-update-hook ()
(fuel-syntax--usings-update)
nil)
(defun fuel-syntax--enable-usings ()
(add-hook 'before-save-hook 'fuel-syntax--usings-update-hook nil t)
(fuel-syntax--usings-update))
(defsubst fuel-syntax--usings ()
(or fuel-syntax--usings (fuel-syntax--usings-update)))
(provide 'fuel-syntax)
;;; fuel-syntax.el ends here