TUPLE: ast-number value ;
TUPLE: ast-local name ;
TUPLE: ast-array name index ;
-TUPLE: ast-slice name from to ;
+TUPLE: ast-slice name from to step ;
TUPLE: ast-function name arguments ;
TUPLE: ast-op left right op ;
TUPLE: ast-negation term ;
[ "foo" ] [ [let "foobar" :> s [infix s[0:3] infix] ] ] unit-test
[ "foo" ] [ [let "foobar" :> s [infix s[:3] infix] ] ] unit-test
[ "bar" ] [ [let "foobar" :> s [infix s[-3:] infix] ] ] unit-test
+[ "rab" ] [ [let "foobar" :> s [infix s[-3::-1] infix] ] ] unit-test
[ "foobar" ] [ [let "foobar" :> s [infix s[:] infix] ] ] unit-test
+[ "foa" ] [ [let "foobar" :> s [infix s[::2] infix] ] ] unit-test
[ "bar" ] [ [let "foobar" :> s [infix s[-3:100] infix] ] ] unit-test
[ "foobar" ] [ [let "foobar" :> s [infix s[-100:100] infix] ] ] unit-test
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs combinators combinators.short-circuit
effects fry infix.parser infix.ast kernel locals locals.parser
-locals.types math math.order multiline namespaces parser
-quotations sequences summary words vocabs.parser ;
+locals.types math math.order math.ranges multiline namespaces
+parser quotations sequences summary words vocabs.parser ;
IN: infix
[ index>> infix-codegen prepare-operand ]
[ name>> >local-word ] bi '[ @ _ infix-nth ] ;
-:: infix-subseq ( from to seq -- subseq )
+: infix-subseq-step ( subseq step -- subseq' )
+ dup 0 < [ [ reverse! ] dip ] when
+ abs dup 1 = [ drop ] [
+ [ dup length 1 - 0 swap ] dip
+ <range> swap nths
+ ] if ;
+
+:: infix-subseq ( from to step seq -- subseq )
seq length :> len
from 0 or dup 0 < [ len + ] when
to [ dup 0 < [ len + ] when ] [ len ] if*
- [ 0 len clamp ] bi@ dupd max seq subseq ;
+ [ 0 len clamp ] bi@ dupd max seq subseq
+ step [ infix-subseq-step ] when* ;
M: ast-slice infix-codegen
- [ from>> [ infix-codegen prepare-operand ] [ [ f ] ] if* ]
- [ to>> [ infix-codegen prepare-operand ] [ [ f ] ] if* ]
- [ name>> >local-word ] tri '[ @ @ _ infix-subseq ] ;
+ {
+ [ from>> [ infix-codegen prepare-operand ] [ [ f ] ] if* ]
+ [ to>> [ infix-codegen prepare-operand ] [ [ f ] ] if* ]
+ [ step>> [ infix-codegen prepare-operand ] [ [ f ] ] if* ]
+ [ name>> >local-word ]
+ } cleave '[ @ @ @ _ infix-subseq ] ;
M: ast-op infix-codegen
[ left>> infix-codegen ] [ right>> infix-codegen ]
: [infix-parse ( end -- result/quot )
parse-multiline-string build-infix-ast
infix-codegen prepare-operand ;
+
PRIVATE>
SYNTAX: [infix
Number = . ?[ ast-number? ]?
Identifier = . ?[ string? ]?
Array = Identifier:i "[" Sum:s "]" => [[ i s ast-array boa ]]
-Slice = Identifier:i "[" Sum?:s ":" Sum?:t "]" => [[ i s t ast-slice boa ]]
+Slice1 = Identifier:i "[" Sum?:from ":" Sum?:to "]" => [[ i from to f ast-slice boa ]]
+Slice2 = Identifier:i "[" Sum?:from ":" Sum?:to ":" Sum?:step "]" => [[ i from to step ast-slice boa ]]
+Slice = Slice1 | Slice2
Function = Identifier:i "(" FunArgs?:a ")" => [[ i a [ V{ } ] unless* ast-function boa ]]
FunArgs = FunArgs:a "," Sum:s => [[ s a push a ]]