]> gitweb.factorcode.org Git - factor.git/commitdiff
arm.64.factor: extra semicolon removed clean-linux-x86-32 clean-linux-x86-64 clean-macosx-x86-64 clean-windows-x86-32 clean-windows-x86-64 main master
authorLimnanthes Serafini <78130750+magpyed@users.noreply.github.com>
Fri, 3 May 2024 01:24:24 +0000 (18:24 -0700)
committerJohn Benediktsson <mrjbq7@gmail.com>
Fri, 3 May 2024 01:37:23 +0000 (18:37 -0700)
34 files changed:
basis/bootstrap/assembler/arm.64.factor
basis/bootstrap/assembler/arm.unix.factor
basis/calendar/format/format-tests.factor
basis/calendar/format/format.factor
basis/compiler/constants/constants-docs.factor
basis/compiler/constants/constants.factor
basis/cpu/arm/64/assembler/assembler.factor
basis/cpu/arm/64/assembler/opcodes/opcodes.factor
basis/inverse/inverse-docs.factor
basis/inverse/inverse-tests.factor
basis/inverse/inverse.factor
core/io/pathnames/pathnames-tests.factor
core/io/pathnames/pathnames.factor
extra/imap/imap.factor
extra/io/streams/tee/authors.txt [new file with mode: 0644]
extra/io/streams/tee/tee-tests.factor [new file with mode: 0644]
extra/io/streams/tee/tee.factor [new file with mode: 0644]
extra/mason/authors.txt
extra/mason/build/build.factor
extra/mason/notify/notify.factor
extra/mason/report/report.factor
extra/scryfall/scryfall.factor
extra/webapps/mason/authors.txt
extra/webapps/mason/backend/backend.factor
extra/webapps/mason/benchmarks/authors.txt [new file with mode: 0644]
extra/webapps/mason/benchmarks/benchmarks.factor [new file with mode: 0644]
extra/webapps/mason/mason.factor
extra/webapps/mason/status-update/status-update.factor
extra/webapps/mason/utils/utils.factor
vm/cpu-arm.hpp
vm/instruction_operands.cpp
vm/instruction_operands.hpp
vm/os-linux-arm.64.hpp
vm/os-linux-arm.cpp

index ccc1408d60120b16db57e1042b0355d3211923f7..bd6e9b4adf319cb918ddfe79bdb00f6908ec6ede 100644 (file)
@@ -12,6 +12,13 @@ IN: bootstrap.assembler.arm
 
 big-endian off
 
+: context-callstack-top-offset ( -- n ) 0 bootstrap-cells ; inline
+: context-callstack-bottom-offset ( -- n ) 2 bootstrap-cells ; inline
+: context-datastack-offset ( -- n ) 3 bootstrap-cells ; inline
+: context-retainstack-offset ( -- n ) 4 bootstrap-cells ; inline
+: context-callstack-save-offset ( -- n ) 5 bootstrap-cells ; inline
+: context-callstack-seg-offset ( -- n ) 8 bootstrap-cells ; inline
+
 ! X0-X17  volatile     scratch registers
 ! X0-X8                parameter registers
 ! X0                   result register
@@ -77,14 +84,23 @@ big-endian off
 : store1 ( -- ) 0 ds-reg temp1 STRuoff ;
 : store0/1 ( -- ) -8 ds-reg temp1 temp0 STPsoff ;
 : store0/2 ( -- ) -8 ds-reg temp2 temp0 STPsoff ;
+: store2/0 ( -- ) -8 ds-reg temp0 temp2 STPsoff ;
 : store1/0 ( -- ) -8 ds-reg temp0 temp1 STPsoff ;
 : store1/2 ( -- ) -16 ds-reg temp2 temp1 STPsoff ;
 
+! add tag bits to integers
 :: tag ( reg -- ) tag-bits get reg reg LSLi ;
+! remove tag bits
 :: untag ( reg -- ) tag-bits get reg reg ASRi ;
+
 : tagged>offset0 ( -- ) 1 temp0 temp0 ASRi ;
 
+! pops an item from the data stack and pushes it 
+! onto the retain stack (used for dip-like operations)
 : >r ( -- ) pop0 pushr ;
+
+! pops an item from the retain stack and pushes it 
+! onto the data stack (used for dip-like operations)
 : r> ( -- ) popr push0 ;
 
 : absolute-jump ( -- word class )
@@ -100,32 +116,25 @@ big-endian off
     3 words Br
     NOP NOP f rc-absolute-cell ; inline
 
+! This is used when a word is called at the end of a quotation.
+! JIT-WORD-CALL is used for other word calls.
 [
-    ! ! pic-tail-reg 5 [RIP+] LEA
     ! why do we store the address after JMP in EBX, where is it
     ! picked up?
     4 pic-tail-reg ADR
-    ! ! 0 JMP f rc-relative rel-word-pic-tail
-    ! 0 Br f rc-relative-arm64-branch rel-word-pic-tail
     absolute-jump rel-word-pic-tail
 ] JIT-WORD-JUMP jit-define
 
+! This is used when a word is called. 
+! JIT-WORD-JUMP is used if the word is the last piece of code in a quotation.
 [
-    ! ! 0 CALL f rc-relative rel-word-pic
-    ! push-link-reg
-    ! 0 BL f rc-relative-arm64-branch rel-word-pic
-    ! pop-link-reg
     absolute-call rel-word-pic
 ] JIT-WORD-CALL jit-define
 
 : jit-call ( name -- )
-    ! RAX 0 MOV f rc-absolute-cell rel-dlsym
-    ! RAX CALL ;
     absolute-call rel-dlsym ;
 
 :: jit-call-1arg ( arg1s name -- )
-    ! arg1 arg1s MOVr
-    ! name jit-call ;
     arg1s arg1 MOVr
     name jit-call ;
 
@@ -137,31 +146,31 @@ big-endian off
     arg2s arg2 MOVr
     name jit-call ;
 
+! loads the address of the vm struct. 
+! A no-op on ARM (vm-reg always contains this address).
 : jit-load-vm ( -- ) ;
 
+! Loads the address of the ctx struct into ctx-reg.
 : jit-load-context ( -- )
-    ! ctx-reg vm-reg vm-context-offset [+] MOV ;
     vm-context-offset vm-reg ctx-reg LDRuoff ;
 
+! Saves the addresses of the callstack, datastack, and retainstack tops 
+! into the corresponding fields in the ctx struct.
 : jit-save-context ( -- )
     jit-load-context
     ! The reason for -8 I think is because we are anticipating a CALL
     ! instruction. After the call instruction, the contexts frame_top
     ! will point to the origin jump address.
-    ! R11 RSP -8 [+] LEA
-    ! ctx-reg context-callstack-top-offset [+] R11 MOV
     stack-reg temp0 MOVsp
     16 temp0 temp0 SUBi
     context-callstack-top-offset ctx-reg temp0 STRuoff
-    ! ctx-reg context-datastack-offset [+] ds-reg MOV
-    ! ctx-reg context-retainstack-offset [+] rs-reg MOV ;
     context-datastack-offset ctx-reg ds-reg STRuoff
     context-retainstack-offset ctx-reg rs-reg STRuoff ;
 
-! ctx-reg must already have been loaded
+! Retrieves the addresses of the datastack and retainstack tops 
+! from the corresponding fields in the ctx struct.
+! ctx-reg must already have been loaded.
 : jit-restore-context ( -- )
-    ! ds-reg ctx-reg context-datastack-offset [+] MOV
-    ! rs-reg ctx-reg context-retainstack-offset [+] MOV ;
     context-datastack-offset ctx-reg ds-reg LDRuoff
     context-retainstack-offset ctx-reg rs-reg LDRuoff ;
 
@@ -178,18 +187,35 @@ big-endian off
     jit-restore-context
 ] JIT-PRIMITIVE jit-define
 
+! Used to a call a quotation if the quotation is the last piece of code
 : jit-jump-quot ( -- )
-    ! arg1 quot-entry-point-offset [+] JMP ;
     quot-entry-point-offset arg1 temp0 LDUR
     temp0 BR ;
 
+! Used to call a quotation if the quotation is not the last piece of code
 : jit-call-quot ( -- )
-    ! arg1 quot-entry-point-offset [+] CALL ;
     push-link-reg
     quot-entry-point-offset arg1 temp0 LDUR
     temp0 BLR
     pop-link-reg ;
 
+! calls a quotation
+[
+    pop-arg1
+]
+[ jit-call-quot ]
+[ jit-jump-quot ]
+\ (call) define-combinator-primitive
+
+[
+    jit-save-context
+    vm-reg arg2 MOVr
+    "lazy_jit_compile" jit-call
+]
+[ jit-call-quot ]
+[ jit-jump-quot ]
+\ lazy-jit-compile define-combinator-primitive
+
 [
     ! temp2 0 MOV f rc-absolute-cell rel-literal
     ! temp1 temp2 CMP
@@ -199,6 +225,7 @@ big-endian off
     NOP NOP f rc-absolute-cell rel-literal
 ] PIC-CHECK-TUPLE jit-define
 
+
 ! Inline cache miss entry points
 : jit-load-return-address ( -- )
     ! RBX RSP stack-frame-size bootstrap-cell - [+] MOV ;
@@ -261,32 +288,22 @@ big-endian off
     ctx-reg jit-update-tib ;
 
 : jit-pop-context-and-param ( -- )
-    ! arg1 ds-reg [] MOV
-    ! arg1 arg1 alien-offset [+] MOV
-    ! arg2 ds-reg -8 [+] MOV
-    ! ds-reg 16 SUB ;
     pop-arg1
     alien-offset arg1 arg1 ADDi
     0 arg1 arg1 LDRuoff
     pop-arg2 ;
 
 : jit-push-param ( -- )
-    ! ds-reg 8 ADD
-    ! ds-reg [] arg2 MOV ;
     push-arg2 ;
 
 : jit-set-context ( -- )
     jit-pop-context-and-param
     jit-save-context
     arg1 jit-switch-context
-    ! RSP 8 ADD
     16 stack-reg stack-reg ADDi
     jit-push-param ;
 
 : jit-pop-quot-and-param ( -- )
-    ! arg1 ds-reg [] MOV
-    ! arg2 ds-reg -8 [+] MOV
-    ! ds-reg 16 SUB ;
     pop-arg1 pop-arg2 ;
 
 : jit-start-context ( -- )
@@ -327,16 +344,16 @@ big-endian off
     jit-jump-quot ;
 
 [
-    ! 0 [RIP+] EAX MOV rc-relative rel-safepoint
     3 words temp0 LDRl
     0 temp0 W0 STRuoff
     3 words Br
     NOP NOP rc-absolute-cell rel-safepoint
 ] JIT-SAFEPOINT jit-define
 
-! C to Factor entry point
+! The main C to Factor entry point. 
+! Sets up and executes the boot quote, 
+! then performs a teardown and returns into C++. 
 [
-    0xabcd BRK
     ! ! Optimizing compiler's side of callback accesses
     ! ! arguments that are on the stack via the frame pointer.
     ! ! On x86-32 fastcall, and x86-64, some arguments are passed
@@ -345,8 +362,7 @@ big-endian off
     ! frame-reg PUSH
     ! frame-reg stack-reg MOV
 
-    ! ! Save all non-volatile registers
-    ! nv-regs [ PUSH ] each
+    ! Save all non-volatile registers
     -16 SP X19 X18 STPpre
     -16 SP X21 X20 STPpre
     -16 SP X23 X22 STPpre
@@ -358,74 +374,52 @@ big-endian off
 
     jit-save-tib
 
-    ! ! Load VM into vm-reg
-    ! vm-reg 0 MOV 0 rc-absolute-cell rel-vm
+    ! Load VM into vm-reg
     2 words vm-reg LDRl
     3 words Br
     NOP NOP 0 rc-absolute-cell rel-vm
 
-    ! ! Save old context
-    ! nv-reg vm-reg vm-context-offset [+] MOV
-    ! nv-reg PUSH
+    ! Save old context
     vm-context-offset vm-reg ctx-reg LDRuoff
     8 SP ctx-reg STRuoff
 
-    ! ! Switch over to the spare context
-    ! nv-reg vm-reg vm-spare-context-offset [+] MOV
-    ! vm-reg vm-context-offset [+] nv-reg MOV
+    ! Switch over to the spare context
     vm-spare-context-offset vm-reg ctx-reg LDRuoff
     vm-context-offset vm-reg ctx-reg STRuoff
 
-    ! ! Save C callstack pointer
-    ! nv-reg context-callstack-save-offset [+] stack-reg MOV
-
+    ! Save C callstack pointer
     stack-reg temp0 MOVsp
     context-callstack-save-offset ctx-reg temp0 STRuoff
-    ! stack-reg X24 MOVsp
-    ! NOP
 
-    ! ! Load Factor stack pointers
-    ! stack-reg nv-reg context-callstack-bottom-offset [+] MOV
+    ! Load Factor stack pointers
     context-callstack-bottom-offset ctx-reg temp0 LDRuoff
     temp0 stack-reg MOVsp
 
     ctx-reg jit-update-tib
     jit-install-seh
 
-    ! rs-reg nv-reg context-retainstack-offset [+] MOV
-    ! ds-reg nv-reg context-datastack-offset [+] MOV
     context-retainstack-offset ctx-reg rs-reg LDRuoff
     context-datastack-offset ctx-reg ds-reg LDRuoff
 
-    ! ! Call into Factor code
-    ! link-reg 0 MOV f rc-absolute-cell rel-word
-    ! link-reg CALL
+    ! Call into Factor code
     3 words temp0 LDRl
     temp0 BLR
     3 words Br
     NOP NOP f rc-absolute-cell rel-word
 
-    ! ! Load C callstack pointer
-    ! nv-reg vm-reg vm-context-offset [+] MOV
-    ! stack-reg nv-reg context-callstack-save-offset [+] MOV
+    ! Load C callstack pointer
     vm-context-offset vm-reg ctx-reg LDRuoff
 
     context-callstack-save-offset ctx-reg temp0 LDRuoff
     temp0 stack-reg MOVsp
-    ! X24 stack-reg MOVsp
-    ! NOP
 
-    ! ! Load old context
-    ! nv-reg POP
-    ! vm-reg vm-context-offset [+] nv-reg MOV
+    ! Load old context
     8 SP ctx-reg LDRuoff
     vm-context-offset vm-reg ctx-reg STRuoff
 
     jit-restore-tib
 
-    ! ! Restore non-volatile registers
-    ! nv-regs <reversed> [ POP ] each
-    ! frame-reg POP
+    ! Restore non-volatile registers
     16 SP X30 LDRpost
     16 SP X29 X28 LDPpost
     16 SP X27 X26 LDPpost
@@ -434,28 +428,19 @@ big-endian off
     16 SP X21 X20 LDPpost
     16 SP X19 X18 LDPpost
 
-    ! Callbacks which return structs, or use stdcall/fastcall/thiscall,
-    ! need a parameter here.
+    ! Callbacks which return structs, or use stdcall/fastcall/thiscall,
+    ! need a parameter here.
 
-    ! ! See the comment for M\ x86.32 stack-cleanup in cpu.x86.32
-    ! 0xffff RET f rc-absolute-2 rel-untagged
-    4 words temp0 ADR
-    2 temp0 temp0 LDRHuoff
-    temp0 stack-reg stack-reg ADDr
     f RET
-    NOP f rc-absolute-2 rel-untagged
 ] CALLBACK-STUB jit-define
 
+! pushes a literal value to the stack
 [
-    ! ! load literal
-    ! temp0 0 MOV f rc-absolute-cell rel-literal
+    ! load literal
     2 words temp0 LDRl
     3 words Br
     NOP NOP f rc-absolute-cell rel-literal
-    ! ! increment datastack pointer
-    ! ds-reg bootstrap-cell ADD
-    ! ! store literal on datastack
-    ! ds-reg [] temp0 MOV
+    ! store literal on datastack
     push0
 ] JIT-PUSH-LITERAL jit-define
 
@@ -522,56 +507,42 @@ big-endian off
     16 SP X3 X2 LDPpost
     16 SP X1 X0 LDPpost ;
 
+! if-statement control flow
 [
-    ! ! load boolean
-    ! temp0 ds-reg [] MOV
-    ! ! pop boolean
-    ! ds-reg bootstrap-cell SUB
+    ! pop boolean
     pop0
-    ! ! compare boolean with f
-    ! temp0 \ f type-number CMP
+    ! compare boolean with f
     \ f type-number temp0 CMPi
-    ! ! jump to true branch if not equal
-    ! ! 0 JNE f rc-relative rel-word
-    ! 0 NE B.cond f rc-relative-arm64-bcond rel-word
+    ! skip over true branch if equal
     5 words EQ B.cond
+    ! jump to true branch
     absolute-jump rel-word
-    ! ! jump to false branch if equal
-    ! ! 0 JMP f rc-relative rel-word
-    ! 0 Br f rc-relative-arm64-branch rel-word
+    ! jump to false branch
     absolute-jump rel-word
 ] JIT-IF jit-define
 
+! calls the second item on the stack
 [
     >r
-    ! ! 0 CALL f rc-relative rel-word
-    ! push-link-reg
-    ! 0 Br f rc-relative-arm64-branch rel-word
-    ! pop-link-reg
     absolute-call rel-word
     r>
 ] JIT-DIP jit-define
 
+! calls the third item on the stack
 [
     >r >r
-    ! ! 0 CALL f rc-relative rel-word
-    ! push-link-reg
-    ! 0 Br f rc-relative-arm64-branch rel-word
-    ! pop-link-reg
     absolute-call rel-word
     r> r>
 ] JIT-2DIP jit-define
 
+! calls the fourth item on the stack
 [
     >r >r >r
-    ! ! 0 CALL f rc-relative rel-word
-    ! push-link-reg
-    ! 0 Br f rc-relative-arm64-branch rel-word
-    ! pop-link-reg
     absolute-call rel-word
     r> r> r>
 ] JIT-3DIP jit-define
 
+! executes a word pushed onto the stack with \
 [
     ! ! load from stack
     ! temp0 ds-reg [] MOV
@@ -598,19 +569,20 @@ big-endian off
 ] JIT-EXECUTE jit-define
 
 ! https://elixir.bootlin.com/linux/latest/source/arch/arm64/kernel/stacktrace.c#L22
+! Performs setup for a quotation
 [
     ! ! make room for LR plus magic number of callback, 16byte align
-    ! x64 ! stack-reg stack-frame-size bootstrap-cell - SUB
     stack-frame-size stack-reg stack-reg SUBi
     push-link-reg
 ] JIT-PROLOG jit-define
 
+! Performs teardown for a quotation
 [
-    ! x64 ! stack-reg stack-frame-size bootstrap-cell - ADD
     pop-link-reg
     stack-frame-size stack-reg stack-reg ADDi
 ] JIT-EPILOG jit-define
 
+! returns to the outer stack frame
 [ f RET ] JIT-RETURN jit-define
 
 ! ! ! Polymorphic inline caches
@@ -627,6 +599,13 @@ big-endian off
     NOP f rc-absolute-1 rel-untagged
 ] PIC-LOAD jit-define
 
+! ! Factor 2024 Clinic Code:
+! ! this arm relocation could actually work
+! ! due to the small bitwidth required  
+! 0 0 temp2 MOVZ f rc-absolute-arm64-movz rel-untagged
+! temp2 temp2 UXTB
+! temp2 ds-reg temp1 LDRr
+
 [
     ! temp1/32 tag-mask get AND
     tag-mask get temp1 temp1 ANDi
@@ -655,6 +634,14 @@ big-endian off
     NOP f rc-absolute-1 rel-untagged
 ] PIC-CHECK-TAG jit-define
 
+! ! Factor 2024 Clinic Code:
+! ! this arm relocation could actually work
+! ! due to the small bitwidth required  
+! 0 0 temp2 MOVZ f rc-absolute-arm64-movz rel-untagged
+! temp2 temp2 UXTB
+! temp2 temp1 CMPr
+
+
 [
     ! ! 0 JE f rc-relative rel-word
     ! 0 EQ B.cond f rc-relative-arm64-bcond rel-word
@@ -720,70 +707,51 @@ big-endian off
     ] jit-conditional
 ] MEGA-LOOKUP jit-define
 
-! Comparisons
+! helper for comparison operations which return a boolean value
 : jit-compare ( cond -- )
-    ! ! load t
-    ! temp3 0 MOV t rc-absolute-cell rel-literal
+    ! load t
     2 words temp3 LDRl
     3 words Br
     NOP NOP t rc-absolute-cell rel-literal
-    ! ! load f
-    ! temp1 \ f type-number MOV
+    ! load f
     \ f type-number temp2 MOVwi
-    ! ! load first value
-    ! temp0 ds-reg [] MOV
-    ! ! adjust stack pointer
-    ! ds-reg bootstrap-cell SUB
+    ! load values
     load1/0
-    ! ! compare with second value
-    ! ds-reg [] temp0 CMP
+    ! compare
     temp1 temp0 CMPr
-    ! ! move t if true
-    ! [ temp1 temp3 ] dip execute( dst src -- )
+    ! move t if true (f otherwise)
     [ temp2 temp3 temp0 ] dip CSEL
-    ! ! store
-    ! ds-reg [] temp1 MOV
+    ! store
     1 push-down0 ;
 
 ! Math
 
-! Overflowing fixnum arithmetic
+! Overflowing fixnum (integer) arithmetic
 : jit-overflow ( insn func -- )
-    ! ds-reg 8 SUB
     jit-save-context
-    ! arg1 ds-reg [] MOV
-    ! arg2 ds-reg 8 [+] MOV
     load-arg1/2
-    ! arg3 arg1 MOV
-    ! [ [ arg3 arg2 ] dip call ] dip
     [ [ arg2 arg1 arg3 ] dip call ] dip
-    ! ds-reg [] arg3 MOV
     push-down-arg3
-    ! [ JNO ]
-    [ VC B.cond ] [
-        ! arg3 vm-reg MOV
+    [ 8 fixnum+fast VC B.cond ] [
         vm-reg arg3 MOVr
         jit-call
     ] jit-conditional ; inline
 
+! non-overflowing fixnum (integer) arithmetic
 : jit-math ( insn -- )
-    ! ! load second input
-    ! temp0 ds-reg [] MOV
-    ! ! pop stack
-    ! ds-reg bootstrap-cell SUB
+    ! load inputs
     load1/0
-    ! ! compute result
-    ! [ ds-reg [] temp0 ] dip execute( dst src -- )
+    ! compute result
     [ temp0 temp1 temp0 ] dip execute( arg2 arg1 dst -- )
+    ! store result
     1 push-down0 ;
 
+! fixnum (integer) division and modulo operations. 
+! Does not tag or push results.
 : jit-fixnum-/mod ( -- )
-    ! ! load second parameter
-    ! temp1 ds-reg [] MOV
-    ! ! load first parameter
-    ! div-arg ds-reg bootstrap-cell neg [+] MOV
+    ! load parameters
     load1/0
-    ! divide
+    ! divide
     temp0 temp1 temp2 SDIV
     temp1 temp0 temp2 temp0 MSUB ;
 
@@ -799,6 +767,9 @@ big-endian off
     { (start-context-and-delete) [ jit-start-context-and-delete ] }
 
     ! ## Entry points
+    ! called by callback-stub. 
+    ! this contains some C++ setup/teardown, 
+    ! as well as the actual call into the boot quote.
     { c-to-factor [
             arg1 arg2 MOVr
             vm-reg "begin_callback" jit-call-1arg
@@ -830,35 +801,15 @@ big-endian off
     ] }
 
     ! ## Math
-    { fixnum+ [ [ ADDr ] "overflow_fixnum_add" jit-overflow ] }
-    { fixnum- [ [ SUBr ] "overflow_fixnum_subtract" jit-overflow ] }
+    ! Overflowing fixnum (integer) addition
+    { fixnum+ [ 
+        [ ADDr ] "overflow_fixnum_add" jit-overflow ] }
+    ! Overflowing fixnum (integer) subtraction
+    { fixnum- [ 
+        [ SUBr ] "overflow_fixnum_subtract" jit-overflow ] }
+    ! Overflowing fixnum (integer) multiplication
     { fixnum* [
-        ! ds-reg 8 SUB
-        jit-save-context
-        ! RCX ds-reg [] MOV
-        ! RBX ds-reg 8 [+] MOV
-        load1/0
-        ! RBX tag-bits get SAR
-        temp0 untag
-        ! RAX RCX MOV
-        ! RBX IMUL
-        ! RAX * RBX = RDX:RAX
-        temp1 temp0 temp0 MUL
-        ! ds-reg [] RAX MOV
-        1 push-down0
-        ! [ JNO ]
-        [ VC B.cond ] [
-            ! arg1 RCX MOV
-            temp1 arg1 MOVr
-            ! arg1 tag-bits get SAR
-            temp1 untag
-            ! arg2 RBX MOV
-            temp0 arg2 MOVr
-            ! arg3 vm-reg MOV
-            vm-reg arg3 MOVr
-            "overflow_fixnum_multiply" jit-call
-        ] jit-conditional
-    ] }
+        [ MUL ] "overflow_fixnum_multiply" jit-overflow ] }
 
     ! ## Misc
     { fpu-state [
@@ -870,6 +821,11 @@ big-endian off
         FPSR XZR MSRr
         FPCR arg1 MRS
     ] }
+
+! ! Factor 2024 Clinic Code:
+! FPCR arg1 MRS
+! FPSR XZR MSRr
+
     { set-fpu-state [
         ! RSP 2 SUB
         ! RSP [] arg1 16-bit-version-of MOV
@@ -914,246 +870,230 @@ big-endian off
         f RET
     ] }
 
-    ! ## Fixnums
+    ! ! Factor 2024 Clinic Code:
+    ! ! we think the below two lines
+    ! ! 2 temp0 temp0 SUBi ! callstack-length-offset
+    ! ! 0 temp0 arg3 LDRuoff
+    ! ! may need to be replaced with:
+    ! callstack-length-offset arg4 arg3 LDRuoff
+
 
-    ! ### Add
+    ! ## Fixnums
+    ! Non-overflowing fixnum (integer) addition
     { fixnum+fast [ \ ADDr jit-math ] }
 
     ! ### Bit manipulation
+    ! fixnum (integer) bitwise AND
     { fixnum-bitand [ \ ANDr jit-math ] }
+    
+    ! fixnum (integer) bitwise NOT
     { fixnum-bitnot [
-        ! ! complement
-        ! ds-reg [] NOT
         load0
+        ! complement
         temp0 temp0 MVN
-        ! ! clear tag bits
-        ! ds-reg [] tag-mask get XOR
+        ! clear tag bits
         tag-mask get temp0 temp0 EORi
         store0
     ] }
+    
+    ! fixnum (integer) bitwise OR
     { fixnum-bitor [ \ ORRr jit-math ] }
+    
+    ! fixnum (integer) bitwise XOR
     { fixnum-bitxor [ \ EORr jit-math ] }
+    
+    ! fixnum (integer) bitwise shift (positive = left, negative = right)
     { fixnum-shift-fast [
-        ! ! load shift count
-        ! shift-arg ds-reg [] MOV
-        ! ! adjust stack pointer
-        ! ds-reg bootstrap-cell SUB
-        ! ! load value
-        ! temp3 ds-reg [] MOV
+        ! load shift count and value
         load1/0
-        ! ! untag shift count
-        ! shift-arg tag-bits get SAR
+        ! untag shift count
         temp0 untag
-        ! ! make a copy
-        ! temp2 temp3 MOV
+        ! make a copy
         temp1 temp2 MOVr
-        ! ! compute positive shift value in temp2
-        ! temp2 CL SHL
+        ! compute positive shift value in temp1
         temp0 temp1 temp1 LSLr
-        ! ! compute negative shift value in temp3
-        ! shift-arg NEG
+        ! compute negative shift value in temp2
         temp0 temp0 NEG
-        ! temp3 CL SAR
         temp0 temp2 temp2 ASRr
-        ! temp3 tag-mask get bitnot AND
         tag-mask get bitnot temp2 temp2 ANDi
-        ! ! if shift count was negative, move temp3 to temp2
-        ! shift-arg 0 CMP
-        ! temp2 temp3 CMOVGE
-        temp2 temp1 temp0 PL CSEL
-        ! ! push to stack
-        ! ds-reg [] temp2 MOV
+        ! if shift count was negative
+        ! choose temp2 (else temp1)
+        0 temp0 CMPi
+        temp2 temp1 temp0 MI CSEL
+        ! push to stack
         1 push-down0
     ] }
 
     ! ### Comparisons
+    ! returns true if both arguments are fixnums, and false otherwise
     { both-fixnums? [
-        ! temp0 ds-reg [] MOV
-        ! ds-reg bootstrap-cell SUB
         load1/0
-        ! temp0 ds-reg [] OR
         temp1 temp0 temp0 ORRr
-        ! temp0 tag-mask get TEST
         tag-mask get temp0 TSTi
-        ! temp0 \ f type-number MOV
         \ f type-number temp0 MOVwi
-        ! temp1 1 tag-fixnum MOV
         1 tag-fixnum temp1 MOVwi
-        ! temp0 temp1 CMOVE
         temp0 temp1 temp0 EQ CSEL
-        ! ds-reg [] temp0 MOV
         1 push-down0
     ] }
+
+    ! fixnum (integer) equality comparison
     { eq? [ EQ jit-compare ] }
+    ! fixnum (integer) greater-than comparison
     { fixnum> [ GT jit-compare ] }
+    ! fixnum (integer) greater-than-or-equal comparison
     { fixnum>= [ GE jit-compare ] }
+    ! fixnum (integer) less-than comparison
     { fixnum< [ LT jit-compare ] }
+    ! fixnum (integer) less-than-or-equal comparison
     { fixnum<= [ LE jit-compare ] }
 
     ! ### Div/mod
+    ! fixnum (integer) modulo
     { fixnum-mod [
         jit-fixnum-/mod
-        ! ! adjust stack pointer
-        ! ds-reg bootstrap-cell SUB
-        ! ! push to stack
-        ! ds-reg [] mod-arg MOV
+        ! push to stack
         1 push-down0
     ] }
+    ! fixnum (integer) division
     { fixnum/i-fast [
         jit-fixnum-/mod
-        ! ! adjust stack pointer
-        ! ds-reg bootstrap-cell SUB
-        ! ! tag it
-        ! div-arg tag-bits get SHL
+        ! tag it
         tag-bits get temp2 temp0 LSLi
-        ! ! push to stack
-        ! ds-reg [] div-arg MOV
+        ! push to stack
         1 push-down0
     ] }
+    ! fixnum (integer) division and modulo
     { fixnum/mod-fast [
         jit-fixnum-/mod
-        ! ! tag it
-        ! div-arg tag-bits get SHL
+        ! tag it
         temp2 tag
-        ! ! push to stack
-        ! ds-reg [] mod-arg MOV
-        ! ds-reg bootstrap-cell neg [+] div-arg MOV
-        store0/2
+        ! push to stack
+        store2/0
     ] }
 
     ! ### Mul
+    ! Non-overflowing fixnum (integer) multiplication
     { fixnum*fast [
-        ! ! load second input
-        ! temp0 ds-reg [] MOV
-        ! ! pop stack
-        ! ds-reg bootstrap-cell SUB
-        ! ! load first input
-        ! temp1 ds-reg [] MOV
+        ! load both inputs
         load1/0
-        ! ! untag second input
-        ! temp0 tag-bits get SAR
+        ! untag second input
         temp0 untag
-        ! ! multiply
-        ! temp0 temp1 IMUL2
+        ! multiply
         temp1 temp0 temp0 MUL
-        ! ! push result
-        ! ds-reg [] temp0 MOV
+        ! push result
         1 push-down0
     ] }
 
     ! ### Sub
+    ! Non-overflowing fixnum (integer) subtraction
     { fixnum-fast [ \ SUBr jit-math ] }
 
     ! ## Locals
+    ! Drops all current locals stored on the retainstack.
     { drop-locals [
-        ! ! load local count
-        ! temp0 ds-reg [] MOV
-        ! ! adjust stack pointer
-        ! ds-reg bootstrap-cell SUB
+        ! load local count
         pop0
-        ! turn local number into offset
+        ! turn local number into offset
         tagged>offset0
-        ! ! decrement retain stack pointer
-        ! rs-reg temp0 SUB
+        ! decrement retain stack pointer
         temp0 rs-reg rs-reg SUBr
     ] }
+
+    ! Gets the nth local stored on the retainstack.
     { get-local [
-        ! ! load local number
-        ! temp0 ds-reg [] MOV
+        ! load local number
         load0
-        ! turn local number into offset
+        ! turn local number into offset
         tagged>offset0
-        ! ! load local value
-        ! temp0 rs-reg temp0 [+] MOV
+        ! load local value
         temp0 rs-reg temp0 LDRr
-        ! ! push to stack
-        ! ds-reg [] temp0 MOV
+        ! push to stack
         store0
     ] }
+
+    ! Turns the top item on the datastack 
+    ! into a local stored on the retainstack.
     { load-local [ >r ] }
 
     ! ## Objects
+    ! Reads the nth slot of a given object. (non-bounds-checking)
     { slot [
-        ! ! load slot number
-        ! temp0 ds-reg [] MOV
-        ! ! adjust stack pointer
-        ! ds-reg bootstrap-cell SUB
-        ! ! load object
-        ! temp1 ds-reg [] MOV
+        ! load object and slot number
         load1/0
-        ! turn slot number into offset
+        ! turn slot number into offset
         tagged>offset0
-        ! ! mask off tag
-        ! temp1 tag-bits get SHR
-        ! temp1 tag-bits get SHL
+        ! mask off tag
         tag-mask get bitnot temp1 temp1 ANDi
-        ! ! load slot value
-        ! temp0 temp1 temp0 [+] MOV
+        ! load slot value
         temp1 temp0 temp0 LDRr
-        ! ! push to stack
-        ! ds-reg [] temp0 MOV
+        ! push to stack
         1 push-down0
     ] }
+
+    ! nth string element selector (non-bounds-checking)
     { string-nth-fast [
-        ! ! load string index from stack
-        ! temp0 ds-reg bootstrap-cell neg [+] MOV
-        ! temp0 tag-bits get SHR
-        ! ! load string from stack
-        ! temp1 ds-reg [] MOV
+        ! load string index and string from stack
         load1/0
-        ! ! load character
-        ! temp0 8-bit-version-of temp0 temp1 string-offset [++] MOV
-        ! temp0 temp0 8-bit-version-of MOVZX
-        ! temp0 tag-bits get SHL
+        temp1 untag
+        ! load character
+        string-offset temp0 temp0 ADDi
         temp1 temp0 temp0 LDRBr
         temp0 tag
-        ! ! store character to stack
-        ! ds-reg bootstrap-cell SUB
-        ! ds-reg [] temp0 MOV
+        ! store character to stack
         1 push-down0
     ] }
+
+    ! add tag bits to integers
+    ! (the local word tag just shifts left)
     { tag [
-        ! ! load from stack
-        ! temp0 ds-reg [] MOV
+        ! load from stack
         load0
-        ! ! compute tag
-        ! temp0/32 tag-mask get AND
+        ! compute tag
         tag-mask get temp0 temp0 ANDi
-        ! ! tag the tag
-        ! temp0/32 tag-bits get SHL
+        ! tag the tag
         temp0 tag
-        ! ! push to stack
-        ! ds-reg [] temp0 MOV
+        ! push to stack
         store0
     ] }
 
-    ! ## Shufflers
+    ! ## Shufflers
 
-    ! ! ### Drops
+    ! ### Drops
+    ! drops the top n stack items
     { drop [ 1 ndrop ] }
     { 2drop [ 2 ndrop ] }
     { 3drop [ 3 ndrop ] }
     { 4drop [ 4 ndrop ] }
 
-    ! ! ### Dups
+    ! ### Dups
+    ! duplicates the top n stack items in order
     { dup [ load0 push0 ] }
     { 2dup [ load1/0 push1 push0 ] }
     { 3dup [ load2 load1/0 push2 push1 push0 ] }
     { 4dup [ load3/2 load1/0 push3 push2 push1 push0 ] }
+    ! duplicates the second stack item and puts it below the top stack item
     { dupd [ load1/0 store1 push0 ] }
 
-    ! ! ### Misc shufflers
+    ! ### Misc shufflers
+    ! Duplicates the second stack item and puts it above the top stack item
     { over [ load1 push1 ] }
+    ! Duplicates the the third stack item and puts it above the top stack item
     { pick [ load2 push2 ] }
 
-    ! ! ### Nips
+    ! ### Nips
+    ! Drops the second stack item
     { nip [ load0 1 push-down0 ] }
+    ! Drops the second and third stack items
     { 2nip [ load0 2 push-down0 ] }
 
-    ! ! ### Swaps
+    ! ### Swaps
+    ! Rotates the top three elements of the stack (1st -> 3rd)
     { -rot [ pop0 load2/1* store0/2 push1 ] }
+    ! Rotates the top three elements of the stack (1st -> 2nd)
     { rot [ pop0 load2/1* store1/0 push2 ] }
+    ! Swaps the top two elements of the stack
     { swap [ load1/0 store0/1 ] }
+    ! Swaps the second and third elements of the stack
     { swapd [ load2/1 store1/2 ] }
 
     ! ## Signal handling
index 1aa49684386c6a1d4867eb93ff6146c85f403b3b..1035a30e551ff4479018e6e7b08f09455d79c82f 100644 (file)
@@ -5,6 +5,8 @@ IN: bootstrap.assembler.arm
 
 DEFER: stack-reg
 
+! these are all windows-only functions.
+! NO-OPs appear to be correct on UNIX. 
 : jit-save-tib ( -- ) ;
 : jit-restore-tib ( -- ) ;
 : jit-update-tib ( ctx-reg -- ) drop ;
index f502f98568bd156908572684dccdc1a6c16915f5..cde4e5e037981c42947ae489772e5afd241a8eb2 100644 (file)
@@ -90,3 +90,10 @@ Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
 { "about a minute ago" } [ 60 relative-time ] unit-test
 { "about a minute ago" } [ 90 relative-time ] unit-test
 { "4 minutes ago" } [ 270 relative-time ] unit-test
+
+{ "1 minute" } [ 60 seconds duration>human-readable ] unit-test
+{ "1 hour" } [ 1 hours duration>human-readable ] unit-test
+{ "3 hours" } [ 3 hours duration>human-readable ] unit-test
+{ "2 minutes and 3 seconds" } [ 123 seconds duration>human-readable ] unit-test
+{ "20 minutes and 34 seconds" } [ 1234 seconds duration>human-readable ] unit-test
+{ "3 hours, 25 minutes and 45 seconds" } [ 12345 seconds duration>human-readable ] unit-test
index e3da029bcc9faf1f93b28c43cbafde0bf4831c4f..a85f24af7207974120dbd25b883d2c1fc7460041 100644 (file)
@@ -205,20 +205,43 @@ M: timestamp present timestamp>string ;
 
 : duration>human-readable ( duration -- string )
     [
-        [
-            duration>years >integer
-            [
-                [ number>string write ]
-                [ 1 > " years, " " year, " ? write ] bi
-            ] unless-zero
-        ] [
-            duration>days >integer 365 mod
+        {
             [
-                [ number>string write ]
-                [ 1 > " days, " " day, " ? write ] bi
-            ] unless-zero
-        ] [ duration>hms write ] tri
-    ] with-string-writer ;
+                duration>years >integer
+                [
+                    [ number>string ]
+                    [ 1 > " years" " year" ? append , ] bi
+                ] unless-zero
+            ] [
+                duration>days >integer 365 mod
+                [
+                    [ number>string ]
+                    [ 1 > " days" " day" ? append , ] bi
+                ] unless-zero
+            ] [
+                duration>hours >integer 24 mod
+                [
+                    [ number>string ]
+                    [ 1 > " hours" " hour" ? append , ] bi
+                ] unless-zero
+            ] [
+                duration>minutes >integer 60 mod
+                [
+                    [ number>string ]
+                    [ 1 > " minutes" " minute" ? append , ] bi
+                ] unless-zero
+            ] [
+                duration>seconds >integer 60 mod
+                [
+                    number>string " seconds" append ,
+                ] unless-zero
+            ]
+        } cleave
+    ] { } make [ "0 seconds" ] [
+        unclip-last-slice over empty? [ nip ] [
+            [ ", " join ] [ " and " glue ] bi*
+        ] if
+    ] if-empty ;
 
 GENERIC: elapsed-time ( seconds -- string )
 
index 1552d37e4c332ceaaabdd02f161bc06c707d3efc..a097f05565bcc9fbfdfc79655174381125ad3f83 100644 (file)
@@ -11,6 +11,19 @@ HELP: rc-absolute
 HELP: rc-absolute-cell
 { $description "Indicates that the relocation is a cell-sized absolute address to an object in the VM." } ;
 
+HELP: rc-relative-arm64-branch
+{ $description "Relative address stored, divided by four, in bits 25:0 of an ARM64 instruction." } ;
+
+HELP: rc-relative-arm64-bcond
+{ $description "Relative address stored, divided by four, in bits 23:5 of an ARM64 instruction." } ;
+
+HELP: rc-absolute-arm64-movz
+{ $description "Absolute address stored in bits 20:5 of an ARM64 instruction." } ;
+
+HELP: rc-relative-cell
+{ $description "Indicates that the relocation is a cell-sized relative address to an object in the VM." } ;
+
+
 HELP: rt-cards-offset
 { $description "Relocation offset type for the cards table." }
 { $see-also rel-cards-offset } ;
@@ -86,6 +99,10 @@ $nl
     rc-absolute-2
     rc-absolute-1
     rc-absolute-ppc-2/2/2/2
+    rc-relative-arm64-branch
+    rc-relative-arm64-bcond
+    rc-absolute-arm64-movz
+    rc-relative-cell
 }
 "Relocation types:"
 { $subsections
index 9c9c2acfe905fa3566d11dffee84cd1354e09d6e..3e881dbc4ae3b906d76a6dd1da965d956ee06a7b 100644 (file)
@@ -55,6 +55,8 @@ CONSTANT: rc-absolute-1 11
 CONSTANT: rc-absolute-ppc-2/2/2/2 12
 CONSTANT: rc-relative-arm64-branch 13
 CONSTANT: rc-relative-arm64-bcond 14
+CONSTANT: rc-absolute-arm64-movz 15
+CONSTANT: rc-relative-cell 16
 
 CONSTANT: rt-dlsym 0
 CONSTANT: rt-entry-point 1
index b0c2787f36e920a3eda494c5704bdfafc2cd272d..ead52d3c6c2883c7fe87a97a9a3f791044d6cf78 100644 (file)
@@ -291,7 +291,8 @@ PRIVATE>
 
 : LDUR ( simm9 Rn Rt -- ) 2bw [ swap 9 ?sbits ] 2dip LDUR-encode ;
 
-: LSLi ( uimm6 Rn Rd -- ) 2bw [ tuck [ dup ] 2dip 6 ?ubits ] 2dip LSLi-encode ;
+: LSLi ( uimm6 Rn Rd -- ) 2bw 2bw [ spin 6 ?ubits [ 64 swap - ] [ 63 swap - ] bi ] 
+                                   2dip LSLi-encode ;
 : LSLr ( Rm Rn Rd -- ) 3bw LSLr-encode ;
 
 : LSRi ( uimm6 Rn Rd -- ) 2bw [ tuck [ dup ] 2dip 6 ?ubits ] 2dip LSRi-encode ;
@@ -342,3 +343,5 @@ PRIVATE>
 : SVC ( uimm16 -- ) 16 ?ubits SVC-encode ;
 
 : TSTi ( imm64 Rn -- ) 1bw [ swap encode-bitmask ] dip TSTi-encode ;
+
+: UXTB ( Rn Rd -- ) UXTB-encode ;
index 767dc5b949764c359645d687b4949242af9faf5e..93d70a8c13992502ab08f4a0739b365b9425f567 100644 (file)
@@ -208,21 +208,22 @@ M: integer-literal value value>> ;
 M: object value ;
 
 : arm-bitfield ( seq -- assoc )
-    [ current-vocab name>> ?lookup-word ] map
-    [ dup width ] map>alist
-    dup values [ f = ] any? [ throw ] when ;
+    [ current-vocab name>> ?lookup-word ] map ! looks up the fields associated with the effect labels
+    [ dup width ] map>alist ! creates a list of { field bitwidth } pairs 
+    dup values [ f = ] any? [ throw ] when ; ! if any have no assigned bitwidth, throw.
 
 ERROR: bad-instruction values ;
 
 SYNTAX: ARM-INSTRUCTION:
-    scan-new-word
-    scan-effect
+    scan-new-word ! scans in the name given
+    scan-effect ! scans in the effect given (effect objects hold input and output sequences)
     [
-      in>> arm-bitfield
-      [ keys [ value ] map ]
-      [ values 32 [ - ] accumulate* ] bi zip
-      dup last second 0 = [ bad-instruction ] unless
-      '[ _ bitfield* 4 >le % ]
+      in>> arm-bitfield ! generates a list of { field bitwidth } pairs from the input
+      [ keys [ value ] map ] ! gets the fields back
+      ! for each field, how many bits are left in the instr after it?
+      [ values 32 [ - ] accumulate* ] bi zip ! then combines into another assoc
+      dup last second 0 = [ bad-instruction ] unless ! and there better be 0 bits left after the last field
+      '[ _ bitfield* 4 >le % ] ! this quot is the actual word effect
     ] [ in>> [ string>number ] reject { } <effect> ] bi define-declared ;
 >>
 
@@ -273,7 +274,7 @@ ARM-INSTRUCTION: ANDSi-encode ( bw 11 100100 (N)immrimms Rn Rd -- )
 ARM-INSTRUCTION: ANDSsr-encode ( bw 11 01010 shift2 0 Rm imm6 Rn Rd -- )
 
 ! ASR (immediate): Arithmetic Shift Right (immediate): an alias of SBFM.
-ARM-INSTRUCTION: ASRi-encode ( bw 00 100110 0 immr 011111 Rn Rd -- )
+ARM-INSTRUCTION: ASRi-encode ( bw 00 100110 1 immr 111111 Rn Rd -- )
 
 ! ASR (register): Arithmetic Shift Right (register): an alias of ASRV.
 ARM-INSTRUCTION: ASRr-encode ( bw 0 0 11010110 Rm 0010 10 Rn Rd -- )
@@ -701,7 +702,7 @@ ARM-INSTRUCTION: LDRpre-encode  ( 1 bw 111 0 00 01 0 imm9 11 Rn Rt -- )
 ARM-INSTRUCTION: LDRuoff-encode ( 1 bw 111 0 01 01 imm12 Rn Rt -- )
 
 ! LDR (literal): Load Register (literal).
-ARM-INSTRUCTION: LDRl-encode ( 1 bw 011 0 00 imm19 Rt -- )
+ARM-INSTRUCTION: LDRl-encode ( 0 bw 011 0 00 imm19 Rt -- )
 
 ! LDR (register): Load Register (register).
 ARM-INSTRUCTION: LDRr-encode ( 1 bw 111 0 00 01 1 Rm option3 S 1 0 Rn Rt -- )
@@ -906,7 +907,7 @@ ARM-INSTRUCTION: LDXRB-encode ( 00 001000 0 1 0 11111 0 11111 Rn Rt -- )
 ARM-INSTRUCTION: LDXRH-encode ( 01 001000 0 1 0 11111 0 11111 Rn Rt -- )
 
 ! LSL (immediate): Logical Shift Left (immediate): an alias of UBFM.
-ARM-INSTRUCTION: LSLi-encode ( bw 10 100110 bw immr bw 00000 Rn Rd -- )
+ARM-INSTRUCTION: LSLi-encode ( bw 10 100110 bw immr imms Rn Rd -- )
 
 ! LSL (register): Logical Shift Left (register): an alias of LSLV.
 ARM-INSTRUCTION: LSLr-encode ( bw 0 0 11010110 Rm 0010 00 Rn Rd -- )
index adda3838cc03234966968c9b1cc791c5ad46824e..af0a6452f72e75455a3e53d3740285acea9a1443 100644 (file)
@@ -48,6 +48,18 @@ HELP: switch
 "    } switch ;" }
 { $see-also undo } ;
 
+HELP: under
+{ $values { "invertible-quot" quotation } { "quot" quotation } }
+{ $description "Applies " { $snippet "invertible-quot" } ", then " { $snippet "quot" } " and finally the inverse of " { $snippet "invertible-quot" } "." }
+{ $examples
+    "Round a decimal number to two decimals:"
+    { $example
+        "USING: inverse math math.functions prettyprint ;"
+        "123.456 [ 100 * ] [ round ] under ."
+        "123.46"
+    }
+} ;
+
 ARTICLE: { "inverse" "intro" } "Invertible quotations"
 "The inverse vocab defines a way to 'undo' quotations, and builds a pattern matching framework on that basis. A quotation can be inverted by reversing it and inverting each word. To define the inverse for particular word, use"
 { $subsections
index 04db91310840b134ae5052d09dc6bfc32c639974..c619156b8a0c950e4afffb29edb7bfa9270f82df 100644 (file)
@@ -97,3 +97,5 @@ TUPLE: funny-tuple ;
 
 { 0 } [ { 1 2 } [ [ 1 + 2 ] { } output>sequence ] undo ] unit-test
 { { 0 1 } } [ 1 2 [ [ [ 1 + ] bi@ ] input<sequence ] undo ] unit-test
+
+{ 123.46 } [ 123.456 [ 100 * ] [ round ] under ] unit-test
index 3a442db48e512bae153aae5e4fc00e64df7fc870..04ee00c361b76c8dd6d387e0e029fec0edc0b761 100644 (file)
@@ -291,3 +291,6 @@ MACRO: switch ( quot-alist -- quot ) [switch] ;
 SYNTAX: INVERSE: scan-word parse-definition define-inverse ;
 
 SYNTAX: DUAL: scan-word scan-word define-dual ;
+
+MACRO: under ( invertible-quot quot -- quot )
+    over [undo] '[ @ @ @ ] ;
index ac2ac7c5d92bb86f2873acb04e9bbb46820c4f0f..6dcdcb104157aeb0bcabdf1b23bea005b314b273 100644 (file)
@@ -97,7 +97,8 @@ os windows? [
 
     { "c:/Users" } [ "c:/Users" canonicalize-path ] unit-test
     { "c:/Users" } [ "c:/Users/." canonicalize-path ] unit-test
-    { "c:/Users\\foo\\bar" } [ "c:/Users/foo/bar" canonicalize-path ] unit-test
+    { "c:/Users/foo/bar" } [ "c:/Users/foo/bar" canonicalize-path ] unit-test
+    { "C:/foo/bar" } [ "C:\\foo\\bar" canonicalize-path ] unit-test
 ] [
     { "/" } [ "/" canonicalize-path ] unit-test
     { "/" } [ "/." canonicalize-path ] unit-test
@@ -148,6 +149,7 @@ os windows? [
     { "c:\\" } [ "\\\\?\\c:\\\\\\//Users//\\//merlen//" root-path ] unit-test
     { "d:\\" } [ "\\\\?\\d:\\././././././/../../../" root-path ] unit-test
     { "d:\\" } [ "\\\\?\\d:\\merlen\\dog" root-path ] unit-test
+    { "D:\\" } [ "\\\\?\\D:\\merlen\\dog" root-path ] unit-test
 ] [
     { "/" } [ "/" root-path ] unit-test
     { "/" } [ "//" root-path ] unit-test
index f67e38dcbd109166b5ee202e835757d50967c0fd..b588e55095c0fab7d2aa6b3fca1af0d8d13558d5 100644 (file)
@@ -6,6 +6,8 @@ IN: io.pathnames
 
 SYMBOL: current-directory
 
+CONSTANT: cross-platform-path-separator "/"
+
 : path-separator? ( ch -- ? ) os windows? "/\\" "/" ? member? ;
 
 : path-separator ( -- string ) os windows? "\\" "/" ? ;
@@ -217,10 +219,10 @@ M: object relative-path relative-path* ;
     ] keep dup absolute-path? [
         [
             [ ".." = ] trim-head
-            path-separator join
+            cross-platform-path-separator join
         ] dip root-path prepend-path
     ] [
-        drop path-separator join [ "." ] when-empty
+        drop cross-platform-path-separator join [ "." ] when-empty
     ] if ;
 
 HOOK: canonicalize-path io-backend ( path -- path' )
index ef3fc63f346367e21a21dab56f92c1c582218657..86b0093d2e33b79039c54ff2affd81b057703ee8 100644 (file)
@@ -1,9 +1,10 @@
-USING: accessors arrays assocs calendar calendar.english
-calendar.format calendar.parser formatting grouping io io.crlf
-io.encodings.ascii io.encodings.binary io.encodings.string
-io.encodings.utf7 io.encodings.utf8 io.sockets io.sockets.secure
-io.streams.duplex io.streams.string kernel math math.parser
-multiline sequences sequences.extras splitting strings ;
+USING: accessors arrays ascii assocs base64 calendar
+calendar.english calendar.format calendar.parser combinators
+formatting grouping io io.crlf io.encodings.ascii
+io.encodings.binary io.encodings.string io.encodings.utf7
+io.encodings.utf8 io.sockets io.sockets.secure io.streams.duplex
+io.streams.string kernel math math.parser multiline sequences
+sequences.extras splitting splitting.monotonic strings ;
 QUALIFIED: pcre
 IN: imap
 
@@ -155,6 +156,9 @@ PRIVATE>
     [ "UID SEARCH CHARSET UTF-8 %s" sprintf ] dip utf8 encode
     command-response parse-items [ string>number ] map ;
 
+: search-imap-by-subject ( string -- uids ) [ "SUBJECT" ] dip search-mails ;
+: search-imap-by-body ( string -- uids ) [ "BODY" ] dip search-mails ;
+
 : fetch-mails ( uids data-spec -- texts )
     [ comma-list ] dip "UID FETCH %s %s" sprintf "" command-response but-last ;
 
@@ -175,8 +179,61 @@ PRIVATE>
     "" command-response
     parse-store-mail ;
 
+TUPLE: parsed-email
+date to from subject cc
+return-path
+content-type
+content-transfer-encoding
+headers
+decoded-body ;
+
+: <parsed-email> ( -- obj )
+    parsed-email new
+        V{ } clone >>headers ; inline
+
+: decode-email-body ( parsed-email body -- parsed-email )
+    over content-transfer-encoding>> {
+        { "base64" [ base64> utf8 decode >>decoded-body ] }
+        [
+            ! "unsupported content-transfer-encoding" print
+            drop
+            >>decoded-body
+        ]
+    } case ;
+
+: parse-email-header ( parsed-email strings -- parsed-email )
+    [ nip ?first "\t\s" member? ] monotonic-split
+    [
+        [ [ blank? ] trim ] map " " join
+        ": " split1 swap >lower
+    ] { } map>assoc
+    [
+        [ pick headers>> push-at ]
+        [
+            {
+                { "date" [ >>date ] }
+                { "to" [ >>to ] }
+                { "from" [ >>from ] }
+                { "subject" [ >>subject ] }
+                { "return-path" [ >>return-path ] }
+                { "cc" [ >>to ] }
+                { "content-transfer-encoding" [ >>content-transfer-encoding ] }
+                { "content-type" [ >>content-type ] }
+                [ 2drop ]
+            } case
+        ] 2bi
+    ] assoc-each ;
+
+: parse-email ( string -- parsed-email )
+    [ <parsed-email> ] dip
+    "\r\n\r\n" split1
+    [ string-lines parse-email-header ] dip decode-email-body ;
+
 ! High level API
 
+: fetch-rfc822-mails ( uids -- parsed-email )
+    "(RFC822)" fetch-mails [ parse-email ] map ;
+
 : with-imap ( host email password quot -- )
     [ <imap4ssl> ] 3dip '[ _ _ login drop @ ] with-stream ; inline
 
diff --git a/extra/io/streams/tee/authors.txt b/extra/io/streams/tee/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/io/streams/tee/tee-tests.factor b/extra/io/streams/tee/tee-tests.factor
new file mode 100644 (file)
index 0000000..6111d65
--- /dev/null
@@ -0,0 +1,30 @@
+USING: combinators.smart io io.encodings.utf8 io.files
+io.streams.tee kernel tools.test ;
+
+{ t } [
+    "resource:LICENSE.txt" utf8 [
+        [
+            utf8 [
+                tee-to-file-writer
+                [
+                    readln
+                    42 read
+                    " " read-until
+                    read1
+                    read-contents
+                ] output>array
+            ]
+            [
+                [
+                    [
+                        readln
+                        42 read
+                        " " read-until
+                        read1
+                        read-contents
+                    ] output>array
+                ] with-file-reader
+            ] 2bi =
+        ] with-test-file
+    ] with-file-reader
+] unit-test
diff --git a/extra/io/streams/tee/tee.factor b/extra/io/streams/tee/tee.factor
new file mode 100644 (file)
index 0000000..12429f6
--- /dev/null
@@ -0,0 +1,76 @@
+! Copyright (C) 2024 John Benediktsson
+! See https://factorcode.org/license.txt for BSD license
+
+USING: accessors destructors io io.files kernel math namespaces
+sequences ;
+
+IN: io.streams.tee
+
+TUPLE: tee-stream in out ;
+
+C: <tee-stream> tee-stream
+
+INSTANCE: tee-stream input-stream
+
+<PRIVATE
+
+: >tee-stream< ( tee-stream -- in out )
+    [ in>> ] [ out>> ] bi ; inline
+
+MACRO: tee1 ( read-quot write-quot -- quot )
+    '[ >tee-stream< _ [ [ over _ dip ] [ stream-flush ] bi ] bi* ] ;
+
+MACRO: tee2 ( read-quot write-quot -- quot )
+    '[ >tee-stream< _ [ [ 2over _ 2dip ] [ stream-flush ] bi ] bi* ] ;
+
+PRIVATE>
+
+M: tee-stream stream-element-type in>> stream-element-type ;
+
+M: tee-stream stream-read1
+    [ stream-read1 ] [ stream-write1 ] tee1 ;
+
+M:: tee-stream stream-read-unsafe ( n buf stream -- count )
+    n buf stream
+    [ stream-read-unsafe ]
+    [ '[ buf swap head _ stream-write ] unless-zero ] tee1 ;
+
+M:: tee-stream stream-read-partial-unsafe ( n buf stream -- count )
+    n buf stream
+    [ stream-read-partial-unsafe ]
+    [ '[ buf swap head _ stream-write ] unless-zero ] tee1 ;
+
+M: tee-stream stream-readln
+    [ stream-readln ]
+    [ '[ _ [ stream-write ] [ stream-nl ] bi ] when* ] tee1 ;
+
+M: tee-stream stream-read-until
+    >tee-stream<
+    [ stream-read-until ]
+    [
+        dup '[
+            [ [ _ stream-write ] when* ]
+            [ [ _ stream-write1 ] when* ] bi*
+        ] 2over [ call ] 2dip
+    ] bi* ;
+
+M: tee-stream stream-contents*
+    [ stream-contents* ] [ stream-write ] tee1 ;
+
+M: tee-stream dispose
+    >tee-stream< [ dispose ] bi@ ;
+
+: with-tee-stream ( input output quot -- )
+    [ <tee-stream> ] dip with-input-stream ; inline
+
+: tee-to-file-writer ( path encoding -- )
+    [ input-stream ] 2dip '[ _ _ <file-writer> <tee-stream> ] change ;
+
+: tee-to-file-appender ( path encoding -- )
+    [ input-stream ] 2dip '[ _ _ <file-appender> <tee-stream> ] change ;
+
+: tee-to-stdout ( -- )
+    input-stream [ output-stream get-global <tee-stream> ] change ;
+
+: tee-to-stderr ( -- )
+    input-stream [ error-stream get-global <tee-stream> ] change ;
index db8d84451d6f439c128a9d0422df725583b3da8c..4eba32299c507b27a4da423bddad3a49f58cfb16 100644 (file)
@@ -1,2 +1,3 @@
 Eduardo Cavazos
 Slava Pestov
+nomennescio
index c67369103295e9ff6cdc96bd84bc0d0b1b4f6f72..698c419033d0a5c4cd604ea0a3d507e4f3372b32 100644 (file)
@@ -45,7 +45,7 @@ IN: mason.build
         build-child
         [ notify-report ] [
             status-clean eq?
-            [ notify-upload upload-docs release ] when
+            [ notify-benchmarks notify-upload upload-docs release ] when
         ] bi
         notify-finish
         finish-build
index a2e350f2deb92dbac359e16531a3947d5e0ce246..7e0f59d5007258253671f4d488ce85808cb26ffb 100644 (file)
@@ -63,6 +63,9 @@ IN: mason.notify
         [ name>> "report" status-notify ] [ email-report ] 2bi
     ] bi ;
 
+: notify-benchmarks ( -- )
+    "benchmark-results" utf8 file-contents f "benchmarks" status-notify ;
+
 : notify-upload ( -- )
     f f "upload" status-notify ;
 
index 1a05114bac99a414e4bf23aa109b38b83f99f424..d6781d16a857b2e2e4fb80cb0ddb5e1bb1325616 100644 (file)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2008, 2010 Eduardo Cavazos, Slava Pestov.
 ! See https://factorcode.org/license.txt for BSD license.
-USING: assocs combinators.smart debugger formatting
+USING: arrays assocs combinators.smart debugger formatting
 io.encodings.utf8 io.files io.streams.string kernel literals
-mason.common mason.config mason.disk math namespaces sequences
-splitting xml.syntax xml.writer ;
+mason.common mason.config mason.disk math namespaces prettyprint
+sequences sets splitting xml.syntax xml.writer ;
 IN: mason.report
 
 : git-link ( id -- link )
@@ -132,6 +132,23 @@ IN: mason.report
         ] output>array sift
     ] with-report ;
 
+: benchmark-results ( -- assoc )
+    ${
+        boot-time-file
+        load-time-file
+        test-time-file
+        help-lint-time-file
+        benchmark-time-file
+        html-help-time-file
+    } [
+        dup eval-file 2array
+    ] map
+    benchmarks-file eval-file
+    union ;
+
+: successful-benchmarks ( -- )
+    "benchmark-results" utf8 [ benchmark-results ... ] with-file-writer ;
+
 : build-clean? ( -- ? )
     ${
         load-all-vocabs-file
@@ -142,4 +159,4 @@ IN: mason.report
     } [ eval-file empty? ] all? ;
 
 : success ( -- status )
-    successful-report build-clean? status-clean status-dirty ? ;
+    successful-report build-clean? [ successful-benchmarks status-clean ] [ status-dirty ] if ;
index e3f2d35bfcd91fec0a992e263d5afdc035667f59..860d46c21f5eb047c626f3494cdcfdc5f71f687e 100644 (file)
@@ -2,12 +2,13 @@
 ! See https://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs assocs.extras calendar
 calendar.parser combinators combinators.short-circuit
-combinators.smart grouping http.download images.loader
-images.viewer io io.directories json json.http kernel math
-math.combinatorics math.order math.parser math.statistics
-namespaces sequences sequences.deep sequences.extras sets
-sorting sorting.specification splitting strings ui.gadgets.panes
-unicode urls ;
+combinators.smart formatting grouping http.download
+images.loader images.viewer io io.directories json json.http
+kernel math math.combinatorics math.order math.parser
+math.statistics namespaces random sequences sequences.deep
+sequences.extras sequences.generalizations sets sorting
+sorting.specification splitting splitting.extras strings
+ui.gadgets.panes unicode urls ;
 IN: scryfall
 
 CONSTANT: scryfall-oracle-json-path "resource:scryfall-oracle-json"
@@ -28,7 +29,7 @@ CONSTANT: scryfall-images-path "resource:scryfall-images/"
 
 : load-scryfall-json ( type path -- uri )
     [ find-scryfall-json "download_uri" of ] dip
-    10 days download-outdated-as path>json ;
+    30 days download-outdated-as path>json ;
 
 MEMO: mtg-oracle-cards ( -- json )
     "oracle_cards" scryfall-oracle-json-path load-scryfall-json ;
@@ -253,6 +254,9 @@ MEMO: scryfall-rulings-json ( -- json )
 
 : type-line-of ( assoc -- string ) "type_line" of parse-type-line ;
 
+: types-of ( assoc -- seq ) type-line-of [ first ] map concat ;
+: subtypes-of ( assoc -- seq ) type-line-of [ second ] map concat ;
+
 ! cards can have several type lines (one for each face)
 : any-type? ( json name -- ? )
     [ type-line-of ] dip >lower '[ first [ >lower ] map _ member-of? ] any? ;
@@ -293,6 +297,18 @@ MEMO: scryfall-rulings-json ( -- json )
 : filter-artifact ( seq -- seq' ) [ "Artifact" any-type? ] filter ;
 : filter-artifact-subtype ( seq text -- seq' ) [ filter-artifact ] dip filter-subtype ;
 
+: reject-basic ( seq -- seq' ) [ "Basic" any-type? ] reject ;
+: reject-land ( seq -- seq' ) [ "Land" any-type? ] reject ;
+: reject-creature ( seq -- seq' ) [ "Creature" any-type? ] reject ;
+: reject-emblem ( seq -- seq' ) [ "Emblem" any-type? ] reject ;
+: reject-enchantment ( seq -- seq' ) [ "Enchantment" any-type? ] reject ;
+: reject-instant ( seq -- seq' ) [ "Instant" any-type? ] reject ;
+: reject-sorcery ( seq -- seq' ) [ "Sorcery" any-type? ] reject ;
+: reject-planeswalker ( seq -- seq' ) [ "Planeswalker" any-type? ] reject ;
+: reject-legendary ( seq -- seq' ) [ "Legendary" any-type? ] reject ;
+: reject-battle ( seq -- seq' ) [ "Battle" any-type? ] reject ;
+: reject-artifact ( seq -- seq' ) [ "Artifact" any-type? ] reject ;
+
 : filter-mounts ( seq -- seq' ) "mount" filter-subtype ;
 : filter-vehicles ( seq -- seq' ) "vehicle" filter-subtype ;
 : filter-adventure ( seq -- seq' ) "adventure" filter-subtype ;
@@ -326,26 +342,44 @@ MEMO: scryfall-rulings-json ( -- json )
     [ "type_line" of ] map-card-faces
     concat members sort ;
 
-: filter-card-faces ( json quot -- seq )
+: card>faces ( assoc -- seq )
+    [ "card_faces" of ] [ ] [ 1array ] ?if ;
+
+: filter-card-faces-sub-card ( seq quot -- seq )
+    [ [ card>faces ] map concat ] dip filter ; inline
+
+: filter-card-faces-sub-card-prop ( seq string prop -- seq' )
+    swap '[ _ of _ subseq-of? ] filter-card-faces-sub-card ;
+
+: filter-card-faces-sub-card-iprop ( seq string prop -- seq' )
+    swap >lower '[ _ of >lower _ subseq-of? ] filter-card-faces-sub-card ;
+
+: filter-card-faces-main-card ( seq quot -- seq )
     dup '[ [ "card_faces" of ] [ _ any? ] _ ?if ] filter ; inline
 
-: filter-card-faces-prop ( seq string prop -- seq' )
-    swap '[ _ of _ subseq-of? ] filter-card-faces ;
+: filter-card-faces-main-card-prop ( seq string prop -- seq' )
+    swap '[ _ of _ subseq-of? ] filter-card-faces-main-card ;
+
+: filter-card-faces-main-card-iprop ( seq string prop -- seq' )
+    swap >lower '[ _ of >lower _ subseq-of? ] filter-card-faces-main-card ;
 
-: filter-card-faces-iprop ( seq string prop -- seq' )
-    swap >lower '[ _ of >lower _ subseq-of? ] filter-card-faces ;
+: filter-card-faces-main-card-iprop-member ( seq string prop -- seq' )
+    swap >lower '[ _ of [ >lower ] map _ member-of? ] filter-card-faces-main-card ;
 
 : filter-by-flavor-text ( seq string -- seq' )
-    "flavor_text" filter-card-faces-prop ;
+    "flavor_text" filter-card-faces-main-card-prop ;
 
 : filter-by-flavor-itext ( seq string -- seq' )
-    "flavor_text" filter-card-faces-iprop ;
+    "flavor_text" filter-card-faces-main-card-iprop ;
 
 : filter-by-oracle-text ( seq string -- seq' )
-    "oracle_text" filter-card-faces-prop ;
+    "oracle_text" filter-card-faces-main-card-prop ;
 
 : filter-by-oracle-itext ( seq string -- seq' )
-    "oracle_text" filter-card-faces-iprop ;
+    "oracle_text" filter-card-faces-main-card-iprop ;
+
+: filter-by-keyword ( seq string -- seq' )
+    "keywords" filter-card-faces-main-card-iprop-member ;
 
 : filter-by-name-text ( seq string -- seq' ) "name" filter-by-text-prop ;
 : filter-by-name-itext ( seq string -- seq' ) "name" filter-by-itext-prop ;
@@ -357,63 +391,277 @@ MEMO: scryfall-rulings-json ( -- json )
 : filter-create-map-token ( seq -- seq' ) "create a map token" filter-by-oracle-itext ;
 : filter-map-token ( seq -- seq' ) "map token" filter-by-oracle-itext ;
 
-: filter-affinity ( seq -- seq' ) "affinity" filter-by-oracle-itext ;
-: filter-backup ( seq -- seq' ) "backup" filter-by-oracle-itext ;
-: filter-blitz ( seq -- seq' ) "blitz" filter-by-oracle-itext ;
-: filter-compleated ( seq -- seq' ) "compleated" filter-by-oracle-itext ;
-: filter-corrupted ( seq -- seq' ) "corrupted" filter-by-oracle-itext ;
-: filter-counter ( seq -- seq' ) "counter" filter-by-oracle-itext ;
-: filter-crew ( seq -- seq' ) "crew" filter-by-oracle-itext ;
-: filter-cycling ( seq -- seq' ) "cycling" filter-by-oracle-itext ;
-: filter-deathtouch ( seq -- seq' ) "deathtouch" filter-by-oracle-itext ;
-: filter-defender ( seq -- seq' ) "defender" filter-by-oracle-itext ;
-: filter-descend ( seq -- seq' ) "descend" filter-by-oracle-itext ;
-: filter-destroy-target ( seq -- seq' ) "destroy target" filter-by-oracle-itext ;
-: filter-discover ( seq -- seq' ) "discover" filter-by-oracle-itext ;
-: filter-disguise ( seq -- seq' ) "disguise" filter-by-oracle-itext ;
-: filter-domain ( seq -- seq' ) "domain" filter-by-oracle-itext ;
-: filter-double-strike ( seq -- seq' ) "double strike" filter-by-oracle-itext ;
-: filter-equip ( seq -- seq' ) "equip" filter-by-oracle-itext ;
-: filter-equip-n ( seq -- seq' ) "equip {" filter-by-oracle-itext ;
-: filter-exile ( seq -- seq' ) "exile" filter-by-oracle-itext ;
-: filter-fights ( seq -- seq' ) "fights" filter-by-oracle-itext ;
-: filter-first-strike ( seq -- seq' ) "first strike" filter-by-oracle-itext ;
-: filter-flash ( seq -- seq' ) "flash" filter-by-oracle-itext ;
-: filter-flying ( seq -- seq' ) "flying" filter-by-oracle-itext ;
-: filter-for-mirrodin ( seq -- seq' ) "for mirrodin!" filter-by-oracle-itext ;
-: filter-graveyard ( seq -- seq' ) "graveyard" filter-by-oracle-itext ;
-: filter-haste ( seq -- seq' ) "haste" filter-by-oracle-itext ;
-: filter-hideaway ( seq -- seq' ) "hideaway" filter-by-oracle-itext ;
-: filter-hexproof ( seq -- seq' ) "hexproof" filter-by-oracle-itext ;
-: filter-indestructible ( seq -- seq' ) "indestructible" filter-by-oracle-itext ;
-: filter-investigate ( seq -- seq' ) "investigate" filter-by-oracle-itext ;
-: filter-lifelink ( seq -- seq' ) "lifelink" filter-by-oracle-itext ;
-: filter-madness ( seq -- seq' ) "madness" filter-by-oracle-itext ;
-: filter-menace ( seq -- seq' ) "menace" filter-by-oracle-itext ;
-: filter-mill ( seq -- seq' ) "mill" filter-by-oracle-itext ;
-: filter-ninjutsu ( seq -- seq' ) "ninjutsu" filter-by-oracle-itext ;
-: filter-proliferate ( seq -- seq' ) "proliferate" filter-by-oracle-itext ;
-: filter-protection ( seq -- seq' ) "protection" filter-by-oracle-itext ;
-: filter-prowess ( seq -- seq' ) "prowess" filter-by-oracle-itext ;
-: filter-reach ( seq -- seq' ) "reach" filter-by-oracle-itext ;
-: filter-read-ahead ( seq -- seq' ) "read ahead" filter-by-oracle-itext ;
-: filter-reconfigure ( seq -- seq' ) "reconfigure" filter-by-oracle-itext ;
-: filter-role ( seq -- seq' ) "role" filter-by-oracle-itext ;
-: filter-sacrifice ( seq -- seq' ) "sacrifice" filter-by-oracle-itext ;
-: filter-scry ( seq -- seq' ) "scry" filter-by-oracle-itext ;
-: filter-shroud ( seq -- seq' ) "shroud" filter-by-oracle-itext ;
-: filter-token ( seq -- seq' ) "token" filter-by-oracle-itext ;
-: filter-toxic ( seq -- seq' ) "toxic" filter-by-oracle-itext ;
-: filter-trample ( seq -- seq' ) "trample" filter-by-oracle-itext ;
-: filter-vehicle ( seq -- seq' ) "vehicle" filter-by-oracle-itext ;
-: filter-vigilance ( seq -- seq' ) "vigilance" filter-by-oracle-itext ;
-: filter-ward ( seq -- seq' ) "ward" filter-by-oracle-itext ;
+: filter-adamant-text ( seq -- seq' ) "adamant" filter-by-oracle-itext ;
+: filter-adapt-text ( seq -- seq' ) "adapt" filter-by-oracle-itext ;
+: filter-addendum-text ( seq -- seq' ) "addendum" filter-by-oracle-itext ;
+: filter-affinity-text ( seq -- seq' ) "affinity" filter-by-oracle-itext ;
+: filter-afflict-text ( seq -- seq' ) "afflict" filter-by-oracle-itext ;
+: filter-afterlife-text ( seq -- seq' ) "afterlife" filter-by-oracle-itext ;
+: filter-aftermath-text ( seq -- seq' ) "aftermath" filter-by-oracle-itext ;
+: filter-alliance-text ( seq -- seq' ) "alliance" filter-by-oracle-itext ;
+: filter-amass-text ( seq -- seq' ) "amass" filter-by-oracle-itext ;
+: filter-amplify-text ( seq -- seq' ) "amplify" filter-by-oracle-itext ;
+: filter-annihilator-text ( seq -- seq' ) "annihilator" filter-by-oracle-itext ;
+: filter-ascend-text ( seq -- seq' ) "ascend" filter-by-oracle-itext ;
+: filter-assemble-text ( seq -- seq' ) "assemble" filter-by-oracle-itext ;
+: filter-assist-text ( seq -- seq' ) "assist" filter-by-oracle-itext ;
+: filter-augment-text ( seq -- seq' ) "augment" filter-by-oracle-itext ;
+: filter-awaken-text ( seq -- seq' ) "awaken" filter-by-oracle-itext ;
+: filter-backup-text ( seq -- seq' ) "backup" filter-by-oracle-itext ;
+: filter-banding-text ( seq -- seq' ) "banding" filter-by-oracle-itext ;
+: filter-bargain-text ( seq -- seq' ) "bargain" filter-by-oracle-itext ;
+: filter-basic-landcycling-text ( seq -- seq' ) "basic landcycling" filter-by-oracle-itext ;
+: filter-battalion-text ( seq -- seq' ) "battalion" filter-by-oracle-itext ;
+: filter-battle-cry-text ( seq -- seq' ) "battle cry" filter-by-oracle-itext ;
+: filter-bestow-text ( seq -- seq' ) "bestow" filter-by-oracle-itext ;
+: filter-blitz-text ( seq -- seq' ) "blitz" filter-by-oracle-itext ;
+: filter-bloodrush-text ( seq -- seq' ) "bloodrush" filter-by-oracle-itext ;
+: filter-bloodthirst-text ( seq -- seq' ) "bloodthirst" filter-by-oracle-itext ;
+: filter-boast-text ( seq -- seq' ) "boast" filter-by-oracle-itext ;
+: filter-bolster-text ( seq -- seq' ) "bolster" filter-by-oracle-itext ;
+: filter-bushido-text ( seq -- seq' ) "bushido" filter-by-oracle-itext ;
+: filter-buyback-text ( seq -- seq' ) "buyback" filter-by-oracle-itext ;
+: filter-cascade-text ( seq -- seq' ) "cascade" filter-by-oracle-itext ;
+: filter-casualty-text ( seq -- seq' ) "casualty" filter-by-oracle-itext ;
+: filter-celebration-text ( seq -- seq' ) "celebration" filter-by-oracle-itext ;
+: filter-champion-text ( seq -- seq' ) "champion" filter-by-oracle-itext ;
+: filter-changeling-text ( seq -- seq' ) "changeling" filter-by-oracle-itext ;
+: filter-channel-text ( seq -- seq' ) "channel" filter-by-oracle-itext ;
+: filter-choose-a-background-text ( seq -- seq' ) "choose a background" filter-by-oracle-itext ;
+: filter-chroma-text ( seq -- seq' ) "chroma" filter-by-oracle-itext ;
+: filter-cipher-text ( seq -- seq' ) "cipher" filter-by-oracle-itext ;
+: filter-clash-text ( seq -- seq' ) "clash" filter-by-oracle-itext ;
+: filter-cleave-text ( seq -- seq' ) "cleave" filter-by-oracle-itext ;
+: filter-cloak-text ( seq -- seq' ) "cloak" filter-by-oracle-itext ;
+: filter-cohort-text ( seq -- seq' ) "cohort" filter-by-oracle-itext ;
+: filter-collect-evidence-text ( seq -- seq' ) "collect evidence" filter-by-oracle-itext ;
+: filter-companion-text ( seq -- seq' ) "companion" filter-by-oracle-itext ;
+: filter-compleated-text ( seq -- seq' ) "compleated" filter-by-oracle-itext ;
+: filter-conjure-text ( seq -- seq' ) "conjure" filter-by-oracle-itext ;
+: filter-connive-text ( seq -- seq' ) "connive" filter-by-oracle-itext ;
+: filter-conspire-text ( seq -- seq' ) "conspire" filter-by-oracle-itext ;
+: filter-constellation-text ( seq -- seq' ) "constellation" filter-by-oracle-itext ;
+: filter-converge-text ( seq -- seq' ) "converge" filter-by-oracle-itext ;
+: filter-convert-text ( seq -- seq' ) "convert" filter-by-oracle-itext ;
+: filter-convoke-text ( seq -- seq' ) "convoke" filter-by-oracle-itext ;
+: filter-corrupted-text ( seq -- seq' ) "corrupted" filter-by-oracle-itext ;
+: filter-council's-dilemma-text ( seq -- seq' ) "council's dilemma" filter-by-oracle-itext ;
+: filter-coven-text ( seq -- seq' ) "coven" filter-by-oracle-itext ;
+: filter-craft-text ( seq -- seq' ) "craft" filter-by-oracle-itext ;
+: filter-crew-text ( seq -- seq' ) "crew" filter-by-oracle-itext ;
+: filter-cumulative-upkeep-text ( seq -- seq' ) "cumulative upkeep" filter-by-oracle-itext ;
+: filter-cycling-text ( seq -- seq' ) "cycling" filter-by-oracle-itext ;
+: filter-dash-text ( seq -- seq' ) "dash" filter-by-oracle-itext ;
+: filter-daybound-text ( seq -- seq' ) "daybound" filter-by-oracle-itext ;
+: filter-deathtouch-text ( seq -- seq' ) "deathtouch" filter-by-oracle-itext ;
+: filter-defender-text ( seq -- seq' ) "defender" filter-by-oracle-itext ;
+: filter-delirium-text ( seq -- seq' ) "delirium" filter-by-oracle-itext ;
+: filter-delve-text ( seq -- seq' ) "delve" filter-by-oracle-itext ;
+: filter-descend-text ( seq -- seq' ) "descend" filter-by-oracle-itext ;
+: filter-detain-text ( seq -- seq' ) "detain" filter-by-oracle-itext ;
+: filter-dethrone-text ( seq -- seq' ) "dethrone" filter-by-oracle-itext ;
+: filter-devoid-text ( seq -- seq' ) "devoid" filter-by-oracle-itext ;
+: filter-devour-text ( seq -- seq' ) "devour" filter-by-oracle-itext ;
+: filter-discover-text ( seq -- seq' ) "discover" filter-by-oracle-itext ;
+: filter-disguise-text ( seq -- seq' ) "disguise" filter-by-oracle-itext ;
+: filter-disturb-text ( seq -- seq' ) "disturb" filter-by-oracle-itext ;
+: filter-doctor's-companion-text ( seq -- seq' ) "doctor's companion" filter-by-oracle-itext ;
+: filter-domain-text ( seq -- seq' ) "domain" filter-by-oracle-itext ;
+: filter-double-strike-text ( seq -- seq' ) "double strike" filter-by-oracle-itext ;
+: filter-dredge-text ( seq -- seq' ) "dredge" filter-by-oracle-itext ;
+: filter-echo-text ( seq -- seq' ) "echo" filter-by-oracle-itext ;
+: filter-embalm-text ( seq -- seq' ) "embalm" filter-by-oracle-itext ;
+: filter-emerge-text ( seq -- seq' ) "emerge" filter-by-oracle-itext ;
+: filter-eminence-text ( seq -- seq' ) "eminence" filter-by-oracle-itext ;
+: filter-enchant-text ( seq -- seq' ) "enchant" filter-by-oracle-itext ;
+: filter-encore-text ( seq -- seq' ) "encore" filter-by-oracle-itext ;
+: filter-enlist-text ( seq -- seq' ) "enlist" filter-by-oracle-itext ;
+: filter-enrage-text ( seq -- seq' ) "enrage" filter-by-oracle-itext ;
+: filter-entwine-text ( seq -- seq' ) "entwine" filter-by-oracle-itext ;
+: filter-equip-text ( seq -- seq' ) "equip" filter-by-oracle-itext ;
+: filter-escalate-text ( seq -- seq' ) "escalate" filter-by-oracle-itext ;
+: filter-escape-text ( seq -- seq' ) "escape" filter-by-oracle-itext ;
+: filter-eternalize-text ( seq -- seq' ) "eternalize" filter-by-oracle-itext ;
+: filter-evoke-text ( seq -- seq' ) "evoke" filter-by-oracle-itext ;
+: filter-evolve-text ( seq -- seq' ) "evolve" filter-by-oracle-itext ;
+: filter-exalted-text ( seq -- seq' ) "exalted" filter-by-oracle-itext ;
+: filter-exert-text ( seq -- seq' ) "exert" filter-by-oracle-itext ;
+: filter-exploit-text ( seq -- seq' ) "exploit" filter-by-oracle-itext ;
+: filter-explore-text ( seq -- seq' ) "explore" filter-by-oracle-itext ;
+: filter-extort-text ( seq -- seq' ) "extort" filter-by-oracle-itext ;
+: filter-fabricate-text ( seq -- seq' ) "fabricate" filter-by-oracle-itext ;
+: filter-fading-text ( seq -- seq' ) "fading" filter-by-oracle-itext ;
+: filter-fateful-hour-text ( seq -- seq' ) "fateful hour" filter-by-oracle-itext ;
+: filter-fathomless-descent-text ( seq -- seq' ) "fathomless descent" filter-by-oracle-itext ;
+: filter-fear-text ( seq -- seq' ) "fear" filter-by-oracle-itext ;
+: filter-ferocious-text ( seq -- seq' ) "ferocious" filter-by-oracle-itext ;
+: filter-fight-text ( seq -- seq' ) "fight" filter-by-oracle-itext ;
+: filter-first-strike-text ( seq -- seq' ) "first strike" filter-by-oracle-itext ;
+: filter-flanking-text ( seq -- seq' ) "flanking" filter-by-oracle-itext ;
+: filter-flash-text ( seq -- seq' ) "flash" filter-by-oracle-itext ;
+: filter-flashback-text ( seq -- seq' ) "flashback" filter-by-oracle-itext ;
+: filter-flying-text ( seq -- seq' ) "flying" filter-by-oracle-itext ;
+: filter-food-text ( seq -- seq' ) "food" filter-by-oracle-itext ;
+: filter-for-mirrodin!-text ( seq -- seq' ) "for mirrodin!" filter-by-oracle-itext ;
+: filter-forecast-text ( seq -- seq' ) "forecast" filter-by-oracle-itext ;
+: filter-forestcycling-text ( seq -- seq' ) "forestcycling" filter-by-oracle-itext ;
+: filter-forestwalk-text ( seq -- seq' ) "forestwalk" filter-by-oracle-itext ;
+: filter-foretell-text ( seq -- seq' ) "foretell" filter-by-oracle-itext ;
+: filter-formidable-text ( seq -- seq' ) "formidable" filter-by-oracle-itext ;
+: filter-friends-forever-text ( seq -- seq' ) "friends forever" filter-by-oracle-itext ;
+: filter-fuse-text ( seq -- seq' ) "fuse" filter-by-oracle-itext ;
+: filter-goad-text ( seq -- seq' ) "goad" filter-by-oracle-itext ;
+: filter-graft-text ( seq -- seq' ) "graft" filter-by-oracle-itext ;
+: filter-haste-text ( seq -- seq' ) "haste" filter-by-oracle-itext ;
+: filter-haunt-text ( seq -- seq' ) "haunt" filter-by-oracle-itext ;
+: filter-hellbent-text ( seq -- seq' ) "hellbent" filter-by-oracle-itext ;
+: filter-hero's-reward-text ( seq -- seq' ) "hero's reward" filter-by-oracle-itext ;
+: filter-heroic-text ( seq -- seq' ) "heroic" filter-by-oracle-itext ;
+: filter-hexproof-text ( seq -- seq' ) "hexproof" filter-by-oracle-itext ;
+: filter-hexproof-from-text ( seq -- seq' ) "hexproof from" filter-by-oracle-itext ;
+: filter-hidden-agenda-text ( seq -- seq' ) "hidden agenda" filter-by-oracle-itext ;
+: filter-hideaway-text ( seq -- seq' ) "hideaway" filter-by-oracle-itext ;
+: filter-horsemanship-text ( seq -- seq' ) "horsemanship" filter-by-oracle-itext ;
+: filter-imprint-text ( seq -- seq' ) "imprint" filter-by-oracle-itext ;
+: filter-improvise-text ( seq -- seq' ) "improvise" filter-by-oracle-itext ;
+: filter-incubate-text ( seq -- seq' ) "incubate" filter-by-oracle-itext ;
+: filter-indestructible-text ( seq -- seq' ) "indestructible" filter-by-oracle-itext ;
+: filter-infect-text ( seq -- seq' ) "infect" filter-by-oracle-itext ;
+: filter-ingest-text ( seq -- seq' ) "ingest" filter-by-oracle-itext ;
+: filter-inspired-text ( seq -- seq' ) "inspired" filter-by-oracle-itext ;
+: filter-intensity-text ( seq -- seq' ) "intensity" filter-by-oracle-itext ;
+: filter-intimidate-text ( seq -- seq' ) "intimidate" filter-by-oracle-itext ;
+: filter-investigate-text ( seq -- seq' ) "investigate" filter-by-oracle-itext ;
+: filter-islandcycling-text ( seq -- seq' ) "islandcycling" filter-by-oracle-itext ;
+: filter-islandwalk-text ( seq -- seq' ) "islandwalk" filter-by-oracle-itext ;
+: filter-jump-start-text ( seq -- seq' ) "jump-start" filter-by-oracle-itext ;
+: filter-kicker-text ( seq -- seq' ) "kicker" filter-by-oracle-itext ;
+: filter-kinship-text ( seq -- seq' ) "kinship" filter-by-oracle-itext ;
+: filter-landcycling-text ( seq -- seq' ) "landcycling" filter-by-oracle-itext ;
+: filter-landfall-text ( seq -- seq' ) "landfall" filter-by-oracle-itext ;
+: filter-landwalk-text ( seq -- seq' ) "landwalk" filter-by-oracle-itext ;
+: filter-learn-text ( seq -- seq' ) "learn" filter-by-oracle-itext ;
+: filter-level-up-text ( seq -- seq' ) "level up" filter-by-oracle-itext ;
+: filter-lieutenant-text ( seq -- seq' ) "lieutenant" filter-by-oracle-itext ;
+: filter-lifelink-text ( seq -- seq' ) "lifelink" filter-by-oracle-itext ;
+: filter-living-metal-text ( seq -- seq' ) "living metal" filter-by-oracle-itext ;
+: filter-living-weapon-text ( seq -- seq' ) "living weapon" filter-by-oracle-itext ;
+: filter-madness-text ( seq -- seq' ) "madness" filter-by-oracle-itext ;
+: filter-magecraft-text ( seq -- seq' ) "magecraft" filter-by-oracle-itext ;
+: filter-manifest-text ( seq -- seq' ) "manifest" filter-by-oracle-itext ;
+: filter-megamorph-text ( seq -- seq' ) "megamorph" filter-by-oracle-itext ;
+: filter-meld-text ( seq -- seq' ) "meld" filter-by-oracle-itext ;
+: filter-melee-text ( seq -- seq' ) "melee" filter-by-oracle-itext ;
+: filter-menace-text ( seq -- seq' ) "menace" filter-by-oracle-itext ;
+: filter-mentor-text ( seq -- seq' ) "mentor" filter-by-oracle-itext ;
+: filter-metalcraft-text ( seq -- seq' ) "metalcraft" filter-by-oracle-itext ;
+: filter-mill-text ( seq -- seq' ) "mill" filter-by-oracle-itext ;
+: filter-miracle-text ( seq -- seq' ) "miracle" filter-by-oracle-itext ;
+: filter-modular-text ( seq -- seq' ) "modular" filter-by-oracle-itext ;
+: filter-monstrosity-text ( seq -- seq' ) "monstrosity" filter-by-oracle-itext ;
+: filter-morbid-text ( seq -- seq' ) "morbid" filter-by-oracle-itext ;
+: filter-more-than-meets-the-eye-text ( seq -- seq' ) "more than meets the eye" filter-by-oracle-itext ;
+: filter-morph-text ( seq -- seq' ) "morph" filter-by-oracle-itext ;
+: filter-mountaincycling-text ( seq -- seq' ) "mountaincycling" filter-by-oracle-itext ;
+: filter-mountainwalk-text ( seq -- seq' ) "mountainwalk" filter-by-oracle-itext ;
+: filter-multikicker-text ( seq -- seq' ) "multikicker" filter-by-oracle-itext ;
+: filter-mutate-text ( seq -- seq' ) "mutate" filter-by-oracle-itext ;
+: filter-myriad-text ( seq -- seq' ) "myriad" filter-by-oracle-itext ;
+: filter-nightbound-text ( seq -- seq' ) "nightbound" filter-by-oracle-itext ;
+: filter-ninjutsu-text ( seq -- seq' ) "ninjutsu" filter-by-oracle-itext ;
+: filter-offering-text ( seq -- seq' ) "offering" filter-by-oracle-itext ;
+: filter-open-an-attraction-text ( seq -- seq' ) "open an attraction" filter-by-oracle-itext ;
+: filter-outlast-text ( seq -- seq' ) "outlast" filter-by-oracle-itext ;
+: filter-overload-text ( seq -- seq' ) "overload" filter-by-oracle-itext ;
+: filter-pack-tactics-text ( seq -- seq' ) "pack tactics" filter-by-oracle-itext ;
+: filter-paradox-text ( seq -- seq' ) "paradox" filter-by-oracle-itext ;
+: filter-parley-text ( seq -- seq' ) "parley" filter-by-oracle-itext ;
+: filter-partner-text ( seq -- seq' ) "partner" filter-by-oracle-itext ;
+: filter-partner-with-text ( seq -- seq' ) "partner with" filter-by-oracle-itext ;
+: filter-persist-text ( seq -- seq' ) "persist" filter-by-oracle-itext ;
+: filter-phasing-text ( seq -- seq' ) "phasing" filter-by-oracle-itext ;
+: filter-plainscycling-text ( seq -- seq' ) "plainscycling" filter-by-oracle-itext ;
+: filter-plot-text ( seq -- seq' ) "plot" filter-by-oracle-itext ;
+: filter-populate-text ( seq -- seq' ) "populate" filter-by-oracle-itext ;
+: filter-proliferate-text ( seq -- seq' ) "proliferate" filter-by-oracle-itext ;
+: filter-protection-text ( seq -- seq' ) "protection" filter-by-oracle-itext ;
+: filter-prototype-text ( seq -- seq' ) "prototype" filter-by-oracle-itext ;
+: filter-provoke-text ( seq -- seq' ) "provoke" filter-by-oracle-itext ;
+: filter-prowess-text ( seq -- seq' ) "prowess" filter-by-oracle-itext ;
+: filter-prowl-text ( seq -- seq' ) "prowl" filter-by-oracle-itext ;
+: filter-radiance-text ( seq -- seq' ) "radiance" filter-by-oracle-itext ;
+: filter-raid-text ( seq -- seq' ) "raid" filter-by-oracle-itext ;
+: filter-rally-text ( seq -- seq' ) "rally" filter-by-oracle-itext ;
+: filter-rampage-text ( seq -- seq' ) "rampage" filter-by-oracle-itext ;
+: filter-ravenous-text ( seq -- seq' ) "ravenous" filter-by-oracle-itext ;
+: filter-reach-text ( seq -- seq' ) "reach" filter-by-oracle-itext ;
+: filter-read-ahead-text ( seq -- seq' ) "read ahead" filter-by-oracle-itext ;
+: filter-rebound-text ( seq -- seq' ) "rebound" filter-by-oracle-itext ;
+: filter-reconfigure-text ( seq -- seq' ) "reconfigure" filter-by-oracle-itext ;
+: filter-recover-text ( seq -- seq' ) "recover" filter-by-oracle-itext ;
+: filter-reinforce-text ( seq -- seq' ) "reinforce" filter-by-oracle-itext ;
+: filter-renown-text ( seq -- seq' ) "renown" filter-by-oracle-itext ;
+: filter-replicate-text ( seq -- seq' ) "replicate" filter-by-oracle-itext ;
+: filter-retrace-text ( seq -- seq' ) "retrace" filter-by-oracle-itext ;
+: filter-revolt-text ( seq -- seq' ) "revolt" filter-by-oracle-itext ;
+: filter-riot-text ( seq -- seq' ) "riot" filter-by-oracle-itext ;
+: filter-role-token-text ( seq -- seq' ) "role token" filter-by-oracle-itext ;
+: filter-saddle-text ( seq -- seq' ) "saddle" filter-by-oracle-itext ;
+: filter-scavenge-text ( seq -- seq' ) "scavenge" filter-by-oracle-itext ;
+: filter-scry-text ( seq -- seq' ) "scry" filter-by-oracle-itext ;
+: filter-seek-text ( seq -- seq' ) "seek" filter-by-oracle-itext ;
+: filter-shadow-text ( seq -- seq' ) "shadow" filter-by-oracle-itext ;
+: filter-shroud-text ( seq -- seq' ) "shroud" filter-by-oracle-itext ;
+: filter-skulk-text ( seq -- seq' ) "skulk" filter-by-oracle-itext ;
+: filter-soulbond-text ( seq -- seq' ) "soulbond" filter-by-oracle-itext ;
+: filter-soulshift-text ( seq -- seq' ) "soulshift" filter-by-oracle-itext ;
+: filter-specialize-text ( seq -- seq' ) "specialize" filter-by-oracle-itext ;
+: filter-spectacle-text ( seq -- seq' ) "spectacle" filter-by-oracle-itext ;
+: filter-spell-mastery-text ( seq -- seq' ) "spell mastery" filter-by-oracle-itext ;
+: filter-splice-text ( seq -- seq' ) "splice" filter-by-oracle-itext ;
+: filter-split-second-text ( seq -- seq' ) "split second" filter-by-oracle-itext ;
+: filter-spree-text ( seq -- seq' ) "spree" filter-by-oracle-itext ;
+: filter-squad-text ( seq -- seq' ) "squad" filter-by-oracle-itext ;
+: filter-storm-text ( seq -- seq' ) "storm" filter-by-oracle-itext ;
+: filter-strive-text ( seq -- seq' ) "strive" filter-by-oracle-itext ;
+: filter-sunburst-text ( seq -- seq' ) "sunburst" filter-by-oracle-itext ;
+: filter-support-text ( seq -- seq' ) "support" filter-by-oracle-itext ;
+: filter-surge-text ( seq -- seq' ) "surge" filter-by-oracle-itext ;
+: filter-surveil-text ( seq -- seq' ) "surveil" filter-by-oracle-itext ;
+: filter-suspect-text ( seq -- seq' ) "suspect" filter-by-oracle-itext ;
+: filter-suspend-text ( seq -- seq' ) "suspend" filter-by-oracle-itext ;
+: filter-swampcycling-text ( seq -- seq' ) "swampcycling" filter-by-oracle-itext ;
+: filter-swampwalk-text ( seq -- seq' ) "swampwalk" filter-by-oracle-itext ;
+: filter-threshold-text ( seq -- seq' ) "threshold" filter-by-oracle-itext ;
+: filter-time-travel-text ( seq -- seq' ) "time travel" filter-by-oracle-itext ;
+: filter-totem-armor-text ( seq -- seq' ) "totem armor" filter-by-oracle-itext ;
+: filter-toxic-text ( seq -- seq' ) "toxic" filter-by-oracle-itext ;
+: filter-training-text ( seq -- seq' ) "training" filter-by-oracle-itext ;
+: filter-trample-text ( seq -- seq' ) "trample" filter-by-oracle-itext ;
+: filter-transform-text ( seq -- seq' ) "transform" filter-by-oracle-itext ;
+: filter-transmute-text ( seq -- seq' ) "transmute" filter-by-oracle-itext ;
+: filter-treasure-text ( seq -- seq' ) "treasure" filter-by-oracle-itext ;
+: filter-tribute-text ( seq -- seq' ) "tribute" filter-by-oracle-itext ;
+: filter-typecycling-text ( seq -- seq' ) "typecycling" filter-by-oracle-itext ;
+: filter-undergrowth-text ( seq -- seq' ) "undergrowth" filter-by-oracle-itext ;
+: filter-undying-text ( seq -- seq' ) "undying" filter-by-oracle-itext ;
+: filter-unearth-text ( seq -- seq' ) "unearth" filter-by-oracle-itext ;
+: filter-unleash-text ( seq -- seq' ) "unleash" filter-by-oracle-itext ;
+: filter-vanishing-text ( seq -- seq' ) "vanishing" filter-by-oracle-itext ;
+: filter-venture-into-the-dungeon-text ( seq -- seq' ) "venture into the dungeon" filter-by-oracle-itext ;
+: filter-vigilance-text ( seq -- seq' ) "vigilance" filter-by-oracle-itext ;
+: filter-ward-text ( seq -- seq' ) "ward" filter-by-oracle-itext ;
+: filter-will-of-the-council-text ( seq -- seq' ) "will of the council" filter-by-oracle-itext ;
+: filter-wither-text ( seq -- seq' ) "wither" filter-by-oracle-itext ;
 
 : filter-day ( seq -- seq' ) "day" filter-by-oracle-itext ;
 : filter-night ( seq -- seq' ) "night" filter-by-oracle-itext ;
 : filter-daybound ( seq -- seq' ) "daybound" filter-by-oracle-itext ;
 : filter-nightbound ( seq -- seq' ) "nightbound" filter-by-oracle-itext ;
 
+: filter-cave ( seq -- seq' ) "cave" filter-land-subtype ;
+: filter-sphere ( seq -- seq' ) "sphere" filter-land-subtype ;
+
 : filter-mount ( seq -- seq' ) "mount" filter-by-oracle-itext ;
 : filter-outlaw ( seq -- seq' )
     { "Assassin" "Mercenary" "Pirate" "Rogue" "Warlock" } filter-subtype-intersects ;
@@ -421,6 +669,269 @@ MEMO: scryfall-rulings-json ( -- json )
 : filter-saddle ( seq -- seq' ) "saddle" filter-by-oracle-itext ;
 : filter-spree ( seq -- seq' ) "saddle" filter-by-oracle-itext ;
 
+: filter-adamant-keyword ( seq -- seq' ) "adamant" filter-by-keyword ;
+: filter-adapt-keyword ( seq -- seq' ) "adapt" filter-by-keyword ;
+: filter-addendum-keyword ( seq -- seq' ) "addendum" filter-by-keyword ;
+: filter-affinity-keyword ( seq -- seq' ) "affinity" filter-by-keyword ;
+: filter-afflict-keyword ( seq -- seq' ) "afflict" filter-by-keyword ;
+: filter-afterlife-keyword ( seq -- seq' ) "afterlife" filter-by-keyword ;
+: filter-aftermath-keyword ( seq -- seq' ) "aftermath" filter-by-keyword ;
+: filter-alliance-keyword ( seq -- seq' ) "alliance" filter-by-keyword ;
+: filter-amass-keyword ( seq -- seq' ) "amass" filter-by-keyword ;
+: filter-amplify-keyword ( seq -- seq' ) "amplify" filter-by-keyword ;
+: filter-annihilator-keyword ( seq -- seq' ) "annihilator" filter-by-keyword ;
+: filter-ascend-keyword ( seq -- seq' ) "ascend" filter-by-keyword ;
+: filter-assemble-keyword ( seq -- seq' ) "assemble" filter-by-keyword ;
+: filter-assist-keyword ( seq -- seq' ) "assist" filter-by-keyword ;
+: filter-augment-keyword ( seq -- seq' ) "augment" filter-by-keyword ;
+: filter-awaken-keyword ( seq -- seq' ) "awaken" filter-by-keyword ;
+: filter-backup-keyword ( seq -- seq' ) "backup" filter-by-keyword ;
+: filter-banding-keyword ( seq -- seq' ) "banding" filter-by-keyword ;
+: filter-bargain-keyword ( seq -- seq' ) "bargain" filter-by-keyword ;
+: filter-basic-landcycling-keyword ( seq -- seq' ) "basic-landcycling" filter-by-keyword ;
+: filter-battalion-keyword ( seq -- seq' ) "battalion" filter-by-keyword ;
+: filter-battle-cry-keyword ( seq -- seq' ) "battle-cry" filter-by-keyword ;
+: filter-bestow-keyword ( seq -- seq' ) "bestow" filter-by-keyword ;
+: filter-blitz-keyword ( seq -- seq' ) "blitz" filter-by-keyword ;
+: filter-bloodrush-keyword ( seq -- seq' ) "bloodrush" filter-by-keyword ;
+: filter-bloodthirst-keyword ( seq -- seq' ) "bloodthirst" filter-by-keyword ;
+: filter-boast-keyword ( seq -- seq' ) "boast" filter-by-keyword ;
+: filter-bolster-keyword ( seq -- seq' ) "bolster" filter-by-keyword ;
+: filter-bushido-keyword ( seq -- seq' ) "bushido" filter-by-keyword ;
+: filter-buyback-keyword ( seq -- seq' ) "buyback" filter-by-keyword ;
+: filter-cascade-keyword ( seq -- seq' ) "cascade" filter-by-keyword ;
+: filter-casualty-keyword ( seq -- seq' ) "casualty" filter-by-keyword ;
+: filter-celebration-keyword ( seq -- seq' ) "celebration" filter-by-keyword ;
+: filter-champion-keyword ( seq -- seq' ) "champion" filter-by-keyword ;
+: filter-changeling-keyword ( seq -- seq' ) "changeling" filter-by-keyword ;
+: filter-channel-keyword ( seq -- seq' ) "channel" filter-by-keyword ;
+: filter-choose-a-background-keyword ( seq -- seq' ) "choose-a-background" filter-by-keyword ;
+: filter-chroma-keyword ( seq -- seq' ) "chroma" filter-by-keyword ;
+: filter-cipher-keyword ( seq -- seq' ) "cipher" filter-by-keyword ;
+: filter-clash-keyword ( seq -- seq' ) "clash" filter-by-keyword ;
+: filter-cleave-keyword ( seq -- seq' ) "cleave" filter-by-keyword ;
+: filter-cloak-keyword ( seq -- seq' ) "cloak" filter-by-keyword ;
+: filter-cohort-keyword ( seq -- seq' ) "cohort" filter-by-keyword ;
+: filter-collect-evidence-keyword ( seq -- seq' ) "collect-evidence" filter-by-keyword ;
+: filter-companion-keyword ( seq -- seq' ) "companion" filter-by-keyword ;
+: filter-compleated-keyword ( seq -- seq' ) "compleated" filter-by-keyword ;
+: filter-conjure-keyword ( seq -- seq' ) "conjure" filter-by-keyword ;
+: filter-connive-keyword ( seq -- seq' ) "connive" filter-by-keyword ;
+: filter-conspire-keyword ( seq -- seq' ) "conspire" filter-by-keyword ;
+: filter-constellation-keyword ( seq -- seq' ) "constellation" filter-by-keyword ;
+: filter-converge-keyword ( seq -- seq' ) "converge" filter-by-keyword ;
+: filter-convert-keyword ( seq -- seq' ) "convert" filter-by-keyword ;
+: filter-convoke-keyword ( seq -- seq' ) "convoke" filter-by-keyword ;
+: filter-corrupted-keyword ( seq -- seq' ) "corrupted" filter-by-keyword ;
+: filter-council's-dilemma-keyword ( seq -- seq' ) "council's-dilemma" filter-by-keyword ;
+: filter-coven-keyword ( seq -- seq' ) "coven" filter-by-keyword ;
+: filter-craft-keyword ( seq -- seq' ) "craft" filter-by-keyword ;
+: filter-crew-keyword ( seq -- seq' ) "crew" filter-by-keyword ;
+: filter-cumulative-upkeep-keyword ( seq -- seq' ) "cumulative-upkeep" filter-by-keyword ;
+: filter-cycling-keyword ( seq -- seq' ) "cycling" filter-by-keyword ;
+: filter-dash-keyword ( seq -- seq' ) "dash" filter-by-keyword ;
+: filter-daybound-keyword ( seq -- seq' ) "daybound" filter-by-keyword ;
+: filter-deathtouch-keyword ( seq -- seq' ) "deathtouch" filter-by-keyword ;
+: filter-defender-keyword ( seq -- seq' ) "defender" filter-by-keyword ;
+: filter-delirium-keyword ( seq -- seq' ) "delirium" filter-by-keyword ;
+: filter-delve-keyword ( seq -- seq' ) "delve" filter-by-keyword ;
+: filter-descend-keyword ( seq -- seq' ) "descend" filter-by-keyword ;
+: filter-detain-keyword ( seq -- seq' ) "detain" filter-by-keyword ;
+: filter-dethrone-keyword ( seq -- seq' ) "dethrone" filter-by-keyword ;
+: filter-devoid-keyword ( seq -- seq' ) "devoid" filter-by-keyword ;
+: filter-devour-keyword ( seq -- seq' ) "devour" filter-by-keyword ;
+: filter-discover-keyword ( seq -- seq' ) "discover" filter-by-keyword ;
+: filter-disguise-keyword ( seq -- seq' ) "disguise" filter-by-keyword ;
+: filter-disturb-keyword ( seq -- seq' ) "disturb" filter-by-keyword ;
+: filter-doctor's-companion-keyword ( seq -- seq' ) "doctor's-companion" filter-by-keyword ;
+: filter-domain-keyword ( seq -- seq' ) "domain" filter-by-keyword ;
+: filter-double-strike-keyword ( seq -- seq' ) "double-strike" filter-by-keyword ;
+: filter-dredge-keyword ( seq -- seq' ) "dredge" filter-by-keyword ;
+: filter-echo-keyword ( seq -- seq' ) "echo" filter-by-keyword ;
+: filter-embalm-keyword ( seq -- seq' ) "embalm" filter-by-keyword ;
+: filter-emerge-keyword ( seq -- seq' ) "emerge" filter-by-keyword ;
+: filter-eminence-keyword ( seq -- seq' ) "eminence" filter-by-keyword ;
+: filter-enchant-keyword ( seq -- seq' ) "enchant" filter-by-keyword ;
+: filter-encore-keyword ( seq -- seq' ) "encore" filter-by-keyword ;
+: filter-enlist-keyword ( seq -- seq' ) "enlist" filter-by-keyword ;
+: filter-enrage-keyword ( seq -- seq' ) "enrage" filter-by-keyword ;
+: filter-entwine-keyword ( seq -- seq' ) "entwine" filter-by-keyword ;
+: filter-equip-keyword ( seq -- seq' ) "equip" filter-by-keyword ;
+: filter-escalate-keyword ( seq -- seq' ) "escalate" filter-by-keyword ;
+: filter-escape-keyword ( seq -- seq' ) "escape" filter-by-keyword ;
+: filter-eternalize-keyword ( seq -- seq' ) "eternalize" filter-by-keyword ;
+: filter-evoke-keyword ( seq -- seq' ) "evoke" filter-by-keyword ;
+: filter-evolve-keyword ( seq -- seq' ) "evolve" filter-by-keyword ;
+: filter-exalted-keyword ( seq -- seq' ) "exalted" filter-by-keyword ;
+: filter-exert-keyword ( seq -- seq' ) "exert" filter-by-keyword ;
+: filter-exploit-keyword ( seq -- seq' ) "exploit" filter-by-keyword ;
+: filter-explore-keyword ( seq -- seq' ) "explore" filter-by-keyword ;
+: filter-extort-keyword ( seq -- seq' ) "extort" filter-by-keyword ;
+: filter-fabricate-keyword ( seq -- seq' ) "fabricate" filter-by-keyword ;
+: filter-fading-keyword ( seq -- seq' ) "fading" filter-by-keyword ;
+: filter-fateful-hour-keyword ( seq -- seq' ) "fateful-hour" filter-by-keyword ;
+: filter-fathomless-descent-keyword ( seq -- seq' ) "fathomless-descent" filter-by-keyword ;
+: filter-fear-keyword ( seq -- seq' ) "fear" filter-by-keyword ;
+: filter-ferocious-keyword ( seq -- seq' ) "ferocious" filter-by-keyword ;
+: filter-fight-keyword ( seq -- seq' ) "fight" filter-by-keyword ;
+: filter-first-strike-keyword ( seq -- seq' ) "first-strike" filter-by-keyword ;
+: filter-flanking-keyword ( seq -- seq' ) "flanking" filter-by-keyword ;
+: filter-flash-keyword ( seq -- seq' ) "flash" filter-by-keyword ;
+: filter-flashback-keyword ( seq -- seq' ) "flashback" filter-by-keyword ;
+: filter-flying-keyword ( seq -- seq' ) "flying" filter-by-keyword ;
+: filter-food-keyword ( seq -- seq' ) "food" filter-by-keyword ;
+: filter-for-mirrodin!-keyword ( seq -- seq' ) "for-mirrodin!" filter-by-keyword ;
+: filter-forecast-keyword ( seq -- seq' ) "forecast" filter-by-keyword ;
+: filter-forestcycling-keyword ( seq -- seq' ) "forestcycling" filter-by-keyword ;
+: filter-forestwalk-keyword ( seq -- seq' ) "forestwalk" filter-by-keyword ;
+: filter-foretell-keyword ( seq -- seq' ) "foretell" filter-by-keyword ;
+: filter-formidable-keyword ( seq -- seq' ) "formidable" filter-by-keyword ;
+: filter-friends-forever-keyword ( seq -- seq' ) "friends-forever" filter-by-keyword ;
+: filter-fuse-keyword ( seq -- seq' ) "fuse" filter-by-keyword ;
+: filter-goad-keyword ( seq -- seq' ) "goad" filter-by-keyword ;
+: filter-graft-keyword ( seq -- seq' ) "graft" filter-by-keyword ;
+: filter-haste-keyword ( seq -- seq' ) "haste" filter-by-keyword ;
+: filter-haunt-keyword ( seq -- seq' ) "haunt" filter-by-keyword ;
+: filter-hellbent-keyword ( seq -- seq' ) "hellbent" filter-by-keyword ;
+: filter-hero's-reward-keyword ( seq -- seq' ) "hero's-reward" filter-by-keyword ;
+: filter-heroic-keyword ( seq -- seq' ) "heroic" filter-by-keyword ;
+: filter-hexproof-keyword ( seq -- seq' ) "hexproof" filter-by-keyword ;
+: filter-hexproof-from-keyword ( seq -- seq' ) "hexproof-from" filter-by-keyword ;
+: filter-hidden-agenda-keyword ( seq -- seq' ) "hidden-agenda" filter-by-keyword ;
+: filter-hideaway-keyword ( seq -- seq' ) "hideaway" filter-by-keyword ;
+: filter-horsemanship-keyword ( seq -- seq' ) "horsemanship" filter-by-keyword ;
+: filter-imprint-keyword ( seq -- seq' ) "imprint" filter-by-keyword ;
+: filter-improvise-keyword ( seq -- seq' ) "improvise" filter-by-keyword ;
+: filter-incubate-keyword ( seq -- seq' ) "incubate" filter-by-keyword ;
+: filter-indestructible-keyword ( seq -- seq' ) "indestructible" filter-by-keyword ;
+: filter-infect-keyword ( seq -- seq' ) "infect" filter-by-keyword ;
+: filter-ingest-keyword ( seq -- seq' ) "ingest" filter-by-keyword ;
+: filter-inspired-keyword ( seq -- seq' ) "inspired" filter-by-keyword ;
+: filter-intensity-keyword ( seq -- seq' ) "intensity" filter-by-keyword ;
+: filter-intimidate-keyword ( seq -- seq' ) "intimidate" filter-by-keyword ;
+: filter-investigate-keyword ( seq -- seq' ) "investigate" filter-by-keyword ;
+: filter-islandcycling-keyword ( seq -- seq' ) "islandcycling" filter-by-keyword ;
+: filter-islandwalk-keyword ( seq -- seq' ) "islandwalk" filter-by-keyword ;
+: filter-jump-start-keyword ( seq -- seq' ) "jump-start" filter-by-keyword ;
+: filter-kicker-keyword ( seq -- seq' ) "kicker" filter-by-keyword ;
+: filter-kinship-keyword ( seq -- seq' ) "kinship" filter-by-keyword ;
+: filter-landcycling-keyword ( seq -- seq' ) "landcycling" filter-by-keyword ;
+: filter-landfall-keyword ( seq -- seq' ) "landfall" filter-by-keyword ;
+: filter-landwalk-keyword ( seq -- seq' ) "landwalk" filter-by-keyword ;
+: filter-learn-keyword ( seq -- seq' ) "learn" filter-by-keyword ;
+: filter-level-up-keyword ( seq -- seq' ) "level-up" filter-by-keyword ;
+: filter-lieutenant-keyword ( seq -- seq' ) "lieutenant" filter-by-keyword ;
+: filter-lifelink-keyword ( seq -- seq' ) "lifelink" filter-by-keyword ;
+: filter-living-metal-keyword ( seq -- seq' ) "living-metal" filter-by-keyword ;
+: filter-living-weapon-keyword ( seq -- seq' ) "living-weapon" filter-by-keyword ;
+: filter-madness-keyword ( seq -- seq' ) "madness" filter-by-keyword ;
+: filter-magecraft-keyword ( seq -- seq' ) "magecraft" filter-by-keyword ;
+: filter-manifest-keyword ( seq -- seq' ) "manifest" filter-by-keyword ;
+: filter-megamorph-keyword ( seq -- seq' ) "megamorph" filter-by-keyword ;
+: filter-meld-keyword ( seq -- seq' ) "meld" filter-by-keyword ;
+: filter-melee-keyword ( seq -- seq' ) "melee" filter-by-keyword ;
+: filter-menace-keyword ( seq -- seq' ) "menace" filter-by-keyword ;
+: filter-mentor-keyword ( seq -- seq' ) "mentor" filter-by-keyword ;
+: filter-metalcraft-keyword ( seq -- seq' ) "metalcraft" filter-by-keyword ;
+: filter-mill-keyword ( seq -- seq' ) "mill" filter-by-keyword ;
+: filter-miracle-keyword ( seq -- seq' ) "miracle" filter-by-keyword ;
+: filter-modular-keyword ( seq -- seq' ) "modular" filter-by-keyword ;
+: filter-monstrosity-keyword ( seq -- seq' ) "monstrosity" filter-by-keyword ;
+: filter-morbid-keyword ( seq -- seq' ) "morbid" filter-by-keyword ;
+: filter-more-than-meets-the-eye-keyword ( seq -- seq' ) "more-than-meets-the-eye" filter-by-keyword ;
+: filter-morph-keyword ( seq -- seq' ) "morph" filter-by-keyword ;
+: filter-mountaincycling-keyword ( seq -- seq' ) "mountaincycling" filter-by-keyword ;
+: filter-mountainwalk-keyword ( seq -- seq' ) "mountainwalk" filter-by-keyword ;
+: filter-multikicker-keyword ( seq -- seq' ) "multikicker" filter-by-keyword ;
+: filter-mutate-keyword ( seq -- seq' ) "mutate" filter-by-keyword ;
+: filter-myriad-keyword ( seq -- seq' ) "myriad" filter-by-keyword ;
+: filter-nightbound-keyword ( seq -- seq' ) "nightbound" filter-by-keyword ;
+: filter-ninjutsu-keyword ( seq -- seq' ) "ninjutsu" filter-by-keyword ;
+: filter-offering-keyword ( seq -- seq' ) "offering" filter-by-keyword ;
+: filter-open-an-attraction-keyword ( seq -- seq' ) "open-an-attraction" filter-by-keyword ;
+: filter-outlast-keyword ( seq -- seq' ) "outlast" filter-by-keyword ;
+: filter-overload-keyword ( seq -- seq' ) "overload" filter-by-keyword ;
+: filter-pack-tactics-keyword ( seq -- seq' ) "pack-tactics" filter-by-keyword ;
+: filter-paradox-keyword ( seq -- seq' ) "paradox" filter-by-keyword ;
+: filter-parley-keyword ( seq -- seq' ) "parley" filter-by-keyword ;
+: filter-partner-keyword ( seq -- seq' ) "partner" filter-by-keyword ;
+: filter-partner-with-keyword ( seq -- seq' ) "partner-with" filter-by-keyword ;
+: filter-persist-keyword ( seq -- seq' ) "persist" filter-by-keyword ;
+: filter-phasing-keyword ( seq -- seq' ) "phasing" filter-by-keyword ;
+: filter-plainscycling-keyword ( seq -- seq' ) "plainscycling" filter-by-keyword ;
+: filter-plot-keyword ( seq -- seq' ) "plot" filter-by-keyword ;
+: filter-populate-keyword ( seq -- seq' ) "populate" filter-by-keyword ;
+: filter-proliferate-keyword ( seq -- seq' ) "proliferate" filter-by-keyword ;
+: filter-protection-keyword ( seq -- seq' ) "protection" filter-by-keyword ;
+: filter-prototype-keyword ( seq -- seq' ) "prototype" filter-by-keyword ;
+: filter-provoke-keyword ( seq -- seq' ) "provoke" filter-by-keyword ;
+: filter-prowess-keyword ( seq -- seq' ) "prowess" filter-by-keyword ;
+: filter-prowl-keyword ( seq -- seq' ) "prowl" filter-by-keyword ;
+: filter-radiance-keyword ( seq -- seq' ) "radiance" filter-by-keyword ;
+: filter-raid-keyword ( seq -- seq' ) "raid" filter-by-keyword ;
+: filter-rally-keyword ( seq -- seq' ) "rally" filter-by-keyword ;
+: filter-rampage-keyword ( seq -- seq' ) "rampage" filter-by-keyword ;
+: filter-ravenous-keyword ( seq -- seq' ) "ravenous" filter-by-keyword ;
+: filter-reach-keyword ( seq -- seq' ) "reach" filter-by-keyword ;
+: filter-read-ahead-keyword ( seq -- seq' ) "read-ahead" filter-by-keyword ;
+: filter-rebound-keyword ( seq -- seq' ) "rebound" filter-by-keyword ;
+: filter-reconfigure-keyword ( seq -- seq' ) "reconfigure" filter-by-keyword ;
+: filter-recover-keyword ( seq -- seq' ) "recover" filter-by-keyword ;
+: filter-reinforce-keyword ( seq -- seq' ) "reinforce" filter-by-keyword ;
+: filter-renown-keyword ( seq -- seq' ) "renown" filter-by-keyword ;
+: filter-replicate-keyword ( seq -- seq' ) "replicate" filter-by-keyword ;
+: filter-retrace-keyword ( seq -- seq' ) "retrace" filter-by-keyword ;
+: filter-revolt-keyword ( seq -- seq' ) "revolt" filter-by-keyword ;
+: filter-riot-keyword ( seq -- seq' ) "riot" filter-by-keyword ;
+: filter-role-token-keyword ( seq -- seq' ) "role-token" filter-by-keyword ;
+: filter-saddle-keyword ( seq -- seq' ) "saddle" filter-by-keyword ;
+: filter-scavenge-keyword ( seq -- seq' ) "scavenge" filter-by-keyword ;
+: filter-scry-keyword ( seq -- seq' ) "scry" filter-by-keyword ;
+: filter-seek-keyword ( seq -- seq' ) "seek" filter-by-keyword ;
+: filter-shadow-keyword ( seq -- seq' ) "shadow" filter-by-keyword ;
+: filter-shroud-keyword ( seq -- seq' ) "shroud" filter-by-keyword ;
+: filter-skulk-keyword ( seq -- seq' ) "skulk" filter-by-keyword ;
+: filter-soulbond-keyword ( seq -- seq' ) "soulbond" filter-by-keyword ;
+: filter-soulshift-keyword ( seq -- seq' ) "soulshift" filter-by-keyword ;
+: filter-specialize-keyword ( seq -- seq' ) "specialize" filter-by-keyword ;
+: filter-spectacle-keyword ( seq -- seq' ) "spectacle" filter-by-keyword ;
+: filter-spell-mastery-keyword ( seq -- seq' ) "spell-mastery" filter-by-keyword ;
+: filter-splice-keyword ( seq -- seq' ) "splice" filter-by-keyword ;
+: filter-split-second-keyword ( seq -- seq' ) "split-second" filter-by-keyword ;
+: filter-spree-keyword ( seq -- seq' ) "spree" filter-by-keyword ;
+: filter-squad-keyword ( seq -- seq' ) "squad" filter-by-keyword ;
+: filter-storm-keyword ( seq -- seq' ) "storm" filter-by-keyword ;
+: filter-strive-keyword ( seq -- seq' ) "strive" filter-by-keyword ;
+: filter-sunburst-keyword ( seq -- seq' ) "sunburst" filter-by-keyword ;
+: filter-support-keyword ( seq -- seq' ) "support" filter-by-keyword ;
+: filter-surge-keyword ( seq -- seq' ) "surge" filter-by-keyword ;
+: filter-surveil-keyword ( seq -- seq' ) "surveil" filter-by-keyword ;
+: filter-suspect-keyword ( seq -- seq' ) "suspect" filter-by-keyword ;
+: filter-suspend-keyword ( seq -- seq' ) "suspend" filter-by-keyword ;
+: filter-swampcycling-keyword ( seq -- seq' ) "swampcycling" filter-by-keyword ;
+: filter-swampwalk-keyword ( seq -- seq' ) "swampwalk" filter-by-keyword ;
+: filter-threshold-keyword ( seq -- seq' ) "threshold" filter-by-keyword ;
+: filter-time-travel-keyword ( seq -- seq' ) "time-travel" filter-by-keyword ;
+: filter-totem-armor-keyword ( seq -- seq' ) "totem-armor" filter-by-keyword ;
+: filter-toxic-keyword ( seq -- seq' ) "toxic" filter-by-keyword ;
+: filter-training-keyword ( seq -- seq' ) "training" filter-by-keyword ;
+: filter-trample-keyword ( seq -- seq' ) "trample" filter-by-keyword ;
+: filter-transform-keyword ( seq -- seq' ) "transform" filter-by-keyword ;
+: filter-transmute-keyword ( seq -- seq' ) "transmute" filter-by-keyword ;
+: filter-treasure-keyword ( seq -- seq' ) "treasure" filter-by-keyword ;
+: filter-tribute-keyword ( seq -- seq' ) "tribute" filter-by-keyword ;
+: filter-typecycling-keyword ( seq -- seq' ) "typecycling" filter-by-keyword ;
+: filter-undergrowth-keyword ( seq -- seq' ) "undergrowth" filter-by-keyword ;
+: filter-undying-keyword ( seq -- seq' ) "undying" filter-by-keyword ;
+: filter-unearth-keyword ( seq -- seq' ) "unearth" filter-by-keyword ;
+: filter-unleash-keyword ( seq -- seq' ) "unleash" filter-by-keyword ;
+: filter-vanishing-keyword ( seq -- seq' ) "vanishing" filter-by-keyword ;
+: filter-venture-into-the-dungeon-keyword ( seq -- seq' ) "venture-into-the-dungeon" filter-by-keyword ;
+: filter-vigilance-keyword ( seq -- seq' ) "vigilance" filter-by-keyword ;
+: filter-ward-keyword ( seq -- seq' ) "ward" filter-by-keyword ;
+: filter-will-of-the-council-keyword ( seq -- seq' ) "will-of-the-council" filter-by-keyword ;
+: filter-wither-keyword ( seq -- seq' ) "wither" filter-by-keyword ;
+
 : power>n ( string -- n/f )
     [ "*" = ] [ drop -1 ] [ string>number ] ?if ;
 
@@ -430,20 +941,20 @@ MEMO: scryfall-rulings-json ( -- json )
 : mtg>= ( string/n/f n -- seq' ) [ power>n ] dip { [ and ] [ >= ] } 2&& ;
 : mtg=  ( string/n/f n -- seq' ) [ power>n ] dip { [ and ] [ = ] } 2&& ;
 
-: filter-power=* ( seq -- seq' ) [ "power" of "*" = ] filter-card-faces ;
-: filter-toughness=* ( seq -- seq' ) [ "toughness" of "*" = ] filter-card-faces ;
+: filter-power=* ( seq -- seq' ) [ "power" of "*" = ] filter-card-faces-main-card ;
+: filter-toughness=* ( seq -- seq' ) [ "toughness" of "*" = ] filter-card-faces-main-card ;
 
-: filter-power= ( seq n -- seq' ) '[ "power" of _ mtg= ] filter-card-faces ;
-: filter-power< ( seq n -- seq' ) '[ "power" of _ mtg< ] filter-card-faces ;
-: filter-power> ( seq n -- seq' ) '[ "power" of _ mtg> ] filter-card-faces ;
-: filter-power<= ( seq n -- seq' ) '[ "power" of _ mtg<= ] filter-card-faces ;
-: filter-power>= ( seq n -- seq' ) '[ "power" of _ mtg>= ] filter-card-faces ;
+: filter-power= ( seq n -- seq' ) '[ "power" of _ mtg= ] filter-card-faces-main-card ;
+: filter-power< ( seq n -- seq' ) '[ "power" of _ mtg< ] filter-card-faces-main-card ;
+: filter-power> ( seq n -- seq' ) '[ "power" of _ mtg> ] filter-card-faces-main-card ;
+: filter-power<= ( seq n -- seq' ) '[ "power" of _ mtg<= ] filter-card-faces-main-card ;
+: filter-power>= ( seq n -- seq' ) '[ "power" of _ mtg>= ] filter-card-faces-main-card ;
 
-: filter-toughness= ( seq n -- seq' ) '[ "toughness" of _ mtg= ] filter-card-faces ;
-: filter-toughness< ( seq n -- seq' ) '[ "toughness" of _ mtg< ] filter-card-faces ;
-: filter-toughness> ( seq n -- seq' ) '[ "toughness" of _ mtg> ] filter-card-faces ;
-: filter-toughness<= ( seq n -- seq' ) '[ "toughness" of _ mtg<= ] filter-card-faces ;
-: filter-toughness>= ( seq n -- seq' ) '[ "toughness" of _ mtg>= ] filter-card-faces ;
+: filter-toughness= ( seq n -- seq' ) '[ "toughness" of _ mtg= ] filter-card-faces-main-card ;
+: filter-toughness< ( seq n -- seq' ) '[ "toughness" of _ mtg< ] filter-card-faces-main-card ;
+: filter-toughness> ( seq n -- seq' ) '[ "toughness" of _ mtg> ] filter-card-faces-main-card ;
+: filter-toughness<= ( seq n -- seq' ) '[ "toughness" of _ mtg<= ] filter-card-faces-main-card ;
+: filter-toughness>= ( seq n -- seq' ) '[ "toughness" of _ mtg>= ] filter-card-faces-main-card ;
 
 : map-props ( seq props -- seq' ) '[ _ intersect-keys ] map ;
 
@@ -467,6 +978,9 @@ MEMO: scryfall-rulings-json ( -- json )
     card>image-uris download-normal-images images. ;
 
 : normal-cards. ( seq -- ) [ normal-card. ] each ;
+: standard-cards. ( seq -- ) filter-standard normal-cards. ;
+: historic-cards. ( seq -- ) filter-historic normal-cards. ;
+: modern-cards. ( seq -- ) filter-modern normal-cards. ;
 
 ! rarity is only on main card `json` (if there are two faces)
 : card-face-summary. ( json seq -- )
@@ -608,19 +1122,143 @@ CONSTANT: rarity-to-number H{
 
 : cards-by-set-colors. ( seq -- ) sort-by-set-colors normal-cards. ;
 
-: cards-by-name ( seq name -- seq' ) filter-by-name-itext sort-by-release ;
-: cards-by-name. ( seq name -- ) cards-by-name [ "name" of ] sort-by normal-cards. ;
+: cards-by-name ( name -- seq' ) [ mtg-oracle-cards ] dip filter-by-name-itext sort-by-release ;
+: card-by-name ( name -- card )
+    [ mtg-oracle-cards ] dip >lower
+    [ '[ "name" of >lower _ = ] filter ?first ]
+    [ '[ "name" of >lower _ head? ] filter ?first ] 2bi or ;
+: cards-by-name. ( name -- ) cards-by-name normal-cards. ;
+: standard-cards-by-name. ( name -- ) cards-by-name standard-cards. ;
+: historic-cards-by-name. ( name -- ) cards-by-name historic-cards. ;
+: modern-cards-by-name. ( name -- ) cards-by-name modern-cards. ;
+
+: paren-set? ( string -- ? )
+    { [ "(" head? ] [ ")" tail? ] [ length 5 = ] } 1&& ;
+
+: remove-set-and-num ( string -- string' )
+    " " split
+    dup 2 ?lastn
+    [ paren-set? ] [ string>number ] bi* and [
+        2 head*
+    ] when " " join ;
+
+: assoc>cards ( assoc -- seq )
+    [ card-by-name <array> ] { } assoc>map concat ;
+
+: parse-mtga-card-line ( string -- array )
+    [ blank? ] trim
+    " " split1
+    [ string>number ]
+    [ remove-set-and-num card-by-name ] bi* <array> ;
+
+: parse-mtga-cards ( strings -- seq )
+    [ parse-mtga-card-line ] map concat ;
+
+TUPLE: mtga-deck name deck sideboard section ;
+
+: <mtga-deck> ( -- mtga-deck )
+    mtga-deck new "Deck" >>section ;
+
+: <moxfield-deck> ( name deck sideboard -- deck )
+    mtga-deck new
+        swap >>sideboard
+        swap >>deck
+        swap >>name ;
+
+ERROR: unknown-mtga-deck-section section ;
+: parse-mtga-deck ( string -- mtga-deck )
+    string-lines [ [ blank? ] trim ] map harvest
+    { "About" "Deck" "Sideboard" } split*
+    [ <mtga-deck> ] dip
+    [
+        dup { "About" "Deck" "Sideboard" } intersects? [
+            first >>section
+        ] [
+            over section>> {
+                { "About" [ first "Name " ?head drop [ blank? ] trim >>name ] }
+                { "Deck" [ parse-mtga-cards >>deck ] }
+                { "Sideboard" [ parse-mtga-cards >>sideboard ] }
+                [
+                    unknown-mtga-deck-section
+                ]
+            } case
+        ] if
+    ] each ;
+
+: sort-by-deck-order ( seq -- seq' )
+    [ "Land" any-type? not ] partition
+    [ sort-by-set-colors ] bi@ append ;
+
+: cards. ( seq -- ) sort-by-deck-order normal-cards. ;
+
+: sideboard. ( seq -- )
+    sideboard>> [ "Sideboard" print sort-by-deck-order normal-cards. ] when* ;
+
+GENERIC: deck. ( obj -- )
+
+M: string deck. parse-mtga-deck deck. ;
+
+M: mtga-deck deck. [ name>> ?print ] [ deck>> cards. ] bi ;
+
+M: sequence deck. cards. ;
+
+GENERIC: deck-and-sideboard. ( mtga-deck -- )
+
+M: string deck-and-sideboard. parse-mtga-deck deck-and-sideboard. ;
+
+M: mtga-deck deck-and-sideboard. [ deck. ] [ sideboard. ] bi ;
+
+M: sequence deck-and-sideboard. deck. ;
 
 : filter-mtg-cheat-sheet ( seq -- seq' )
     [
         {
             [ filter-instant ]
-            [ filter-flash ]
-            [ filter-cycling ]
-            [ filter-disguise ]
-            [ filter-madness ]
+            [ filter-flash-keyword ]
+            [ filter-cycling-keyword ]
+            [ filter-disguise-keyword ]
+            [ filter-madness-keyword ]
         } cleave
     ] { } append-outputs-as sort-by-colors ;
 
 : mtg-cheat-sheet. ( seq -- ) filter-mtg-cheat-sheet normal-cards. ;
 : mtg-cheat-sheet-text. ( seq -- ) filter-mtg-cheat-sheet card-summaries. ;
+
+MEMO: get-moxfield-user ( username -- json )
+    "https://api2.moxfield.com/v2/users/%s/decks?pageNumber=1&pageSize=100" sprintf http-get-json nip ;
+
+MEMO: get-moxfield-deck ( public-id -- json )
+    "https://api2.moxfield.com/v3/decks/all/" prepend http-get-json nip ;
+
+: moxfield-board>cards ( board -- seq )
+    "cards" of values [
+        [ "quantity" of ] [ "card" of "name" of ] bi 2array
+    ] map assoc>cards ;
+
+: json>moxfield-deck ( json -- mtga-deck )
+    [ "name" of ]
+    [
+        "boards" of
+        [ "mainboard" of moxfield-board>cards ]
+        [ "sideboard" of moxfield-board>cards ] bi
+    ] bi
+    <moxfield-deck> ;
+
+: moxfield-decks-for-username ( username -- json )
+    get-moxfield-user "data" of ;
+
+: moxfield-random-deck-for-username ( username -- json )
+    moxfield-decks-for-username
+    random "publicId" of get-moxfield-deck
+    json>moxfield-deck ;
+
+: moxfield-latest-deck-for-username ( username -- json )
+    get-moxfield-user
+    "data" of ?first "publicId" of get-moxfield-deck
+    json>moxfield-deck ;
+
+: moxfield-latest-deck-for-username. ( username -- )
+    moxfield-latest-deck-for-username deck. ;
+
+: moxfield-latest-deck-and-sideboard-for-username. ( username -- )
+    moxfield-latest-deck-for-username deck-and-sideboard. ;
index 1901f27a24507e2512d93a1f956aaaa0d2f05714..129dcb4701859fb2e0bed96c57cada07e10b79d4 100644 (file)
@@ -1 +1,2 @@
 Slava Pestov
+nomennescio
index 3a7d24f6ee41a354a25af91c07726dce9ba58073..78ca1f2217eba35711aa59fbc950b06d57eaed2b 100644 (file)
@@ -47,6 +47,27 @@ builder "BUILDERS" {
     { "status" "STATUS" TEXT }
 } define-persistent
 
+TUPLE: run
+run-id timestamp host-name os cpu git-id ;
+
+run "RUNS" {
+    { "run-id" "RUN_ID" INTEGER +db-assigned-id+ }
+    { "timestamp" "TIMESTAMP" TIMESTAMP }
+    { "host-name" "HOST_NAME" TEXT }
+    { "os" "OS" TEXT }
+    { "cpu" "CPU" TEXT }
+    { "git-id" "GIT_ID" TEXT }
+} define-persistent
+
+TUPLE: benchmark
+run-id name duration ;
+
+benchmark "BENCHMARKS" {
+    { "run-id" "RUN_ID" INTEGER +user-assigned-id+ }
+    { "name" "NAME" TEXT +user-assigned-id+ }
+    { "duration" "DURATION_NANOSECONDS" UNSIGNED-BIG-INTEGER }
+} define-persistent
+
 TUPLE: counter id value ;
 
 counter "COUNTER" {
@@ -88,4 +109,4 @@ counter "COUNTER" {
     mason-db [ with-transaction ] with-db ; inline
 
 : init-mason-db ( -- )
-    { builder counter } ensure-tables ;
+    { builder counter run benchmark } ensure-tables ;
diff --git a/extra/webapps/mason/benchmarks/authors.txt b/extra/webapps/mason/benchmarks/authors.txt
new file mode 100644 (file)
index 0000000..94b9049
--- /dev/null
@@ -0,0 +1 @@
+nomennescio
diff --git a/extra/webapps/mason/benchmarks/benchmarks.factor b/extra/webapps/mason/benchmarks/benchmarks.factor
new file mode 100644 (file)
index 0000000..01b497b
--- /dev/null
@@ -0,0 +1,24 @@
+! Copyright (C) 2024 nomennescio.
+! See https://factorcode.org/license.txt for BSD license.
+USING: accessors assocs calendar calendar.format combinators
+db.tuples formatting furnace.actions html.forms
+http.server.responses io io.streams.string kernel math.parser
+sequences webapps.mason.backend webapps.mason.utils ;
+IN: webapps.mason.benchmarks
+
+: benchmark-results ( -- response )
+    [
+        [ selected-benchmarks ] with-mason-db
+        "run,timestamp (UTC),host,os,cpu,git,name,duration (ns)" print
+        '[
+            [ run-id>> ] [ name>> ] [ duration>> ] tri
+            [ _ at { [ run-id>> ] [ timestamp>> timestamp>iso8601Z ] [ host-name>> ] [ os>> ] [ cpu>> ] [ git-id>> ] } cleave ] 2dip
+            "%s,%s,%s,%s,%s,%s,%s,%s\n" printf
+        ] each
+    ] with-string-writer
+    <text-content> ;
+
+: <benchmark-results-action> ( -- action )
+    <action>
+    [ validate-benchmark-selection ] >>init
+    [ benchmark-results ] >>display ;
index 5c9b2972e516e9153ee68cf579d4ee49c9efb79c..afaa8b6b1beee377b8be0715f6012105b4ab629e 100644 (file)
@@ -3,7 +3,7 @@
 USING: accessors furnace.actions furnace.auth furnace.db
 furnace.redirection http.server.dispatchers urls
 webapps.mason.backend webapps.mason.grids webapps.mason.package
-webapps.mason.release webapps.mason.report
+webapps.mason.release webapps.mason.report webapps.mason.benchmarks
 webapps.mason.downloads webapps.mason.counter
 webapps.mason.status-update webapps.mason.docs-update
 webapps.mason.dashboard webapps.mason.make-release
@@ -26,6 +26,9 @@ build-engineer? define-capability
     <build-report-action>
         "report" add-responder
 
+    <benchmark-results-action>
+        "benchmark-results" add-responder
+
     <download-package-action>
         { mason-app "download-package" } >>template
         "package" add-responder
index 5d259a3a0e5263280f95eaeec69dd2256c84cf43..f31c46c8d9825abf6543e7d982a46bca4f5a9a06 100644 (file)
@@ -1,8 +1,10 @@
 ! Copyright (C) 2010 Slava Pestov.
 ! See https://factorcode.org/license.txt for BSD license.
-USING: accessors calendar combinators db.tuples furnace.actions
-furnace.redirection html.forms http.server.responses io kernel
-namespaces validators webapps.mason.utils webapps.mason.backend ;
+USING: accessors assocs calendar combinators db.tuples
+furnace.actions furnace.redirection html.forms
+http.server.responses io kernel multiline namespaces parser
+prettyprint sequences splitting validators webapps.mason.backend
+webapps.mason.utils ;
 IN: webapps.mason.status-update
 
 : find-builder ( host-name os cpu -- builder )
@@ -12,6 +14,19 @@ IN: webapps.mason.status-update
         swap >>host-name
     [ select-tuple ] [ dup insert-tuple ] ?unless ;
 
+: update-runs ( builder -- run-id )
+    [ run new ] dip
+    { [ host-name>> >>host-name ]
+      [ os>> >>os ]
+      [ cpu>> >>cpu ]
+      [ current-timestamp>> >>timestamp ]
+      [ current-git-id>> >>git-id ] } cleave
+    dup insert-tuple run-id>> ;
+
+: update-benchmarks ( run-id benchmarks -- )
+    [ benchmark new swap >>run-id ] dip
+    [ first2 [ >>name ] dip >>duration insert-tuple ] with each ;
+
 : heartbeat ( builder -- )
     now >>heartbeat-timestamp
     drop ;
@@ -31,6 +46,10 @@ IN: webapps.mason.status-update
 
 : test ( builder -- ) +test+ status ;
 
+: benchmarks ( builder content -- )
+    [ update-runs ] dip
+    split-lines parse-fresh first update-benchmarks ;
+
 : report ( builder content status -- )
     [
         >>last-report
@@ -62,6 +81,7 @@ IN: webapps.mason.status-update
         { "boot" [ boot ] }
         { "test" [ test ] }
         { "report" [ "report" value "arg" value report ] }
+        { "benchmarks" [ "report" value benchmarks ] }
         { "upload" [ upload ] }
         { "finish" [ finish ] }
         { "release" [ "arg" value release ] }
index 3213d09573fc7362caf23b7a9fb3059d162f08c8..5598a0ab9c3179cbef873f9a53561c24c25134bb 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2010 Slava Pestov.
 ! See https://factorcode.org/license.txt for BSD license.
-USING: accessors arrays assocs db.tuples furnace.actions
-furnace.utilities html.forms kernel mason.config namespaces
+USING: accessors arrays assocs calendar calendar.format
+db.tuples furnace.actions furnace.utilities html.forms
+io.streams.string kernel mason.config math.parser namespaces
 sequences urls validators webapps.mason.backend
 webapps.mason.version.data xml.syntax ;
 IN: webapps.mason.utils
@@ -9,12 +10,43 @@ IN: webapps.mason.utils
 : link ( url label -- xml )
     [XML <a href=<->><-></a> XML] ;
 
+: timestamp>iso8601Z ( timestamp -- string )
+    [ >utc { YYYY MM DD "T" hhmm ss "Z" } formatted ] with-string-writer ;
+
 : validate-os/cpu ( -- )
     {
         { "os" [ v-one-line ] }
         { "cpu" [ v-one-line ] }
     } validate-params ;
 
+: validate-benchmark-selection ( -- )
+    {
+        { "host" [ [ v-one-line ] v-optional ] }
+        { "os" [ [ v-one-line ] v-optional ] }
+        { "cpu" [ [ v-one-line ] v-optional ] }
+        { "git" [ [ v-one-line ] v-optional ] }
+        { "run" [ [ v-one-line ] v-optional ] }
+        ! { "timestamp" [ [ v-one-line ] v-optional ] } ! parsing of ISO8601 is currently not supported
+        { "name" [ [ v-one-line ] v-optional ] }
+    } validate-params ;
+
+: selected-runs ( -- runs )
+    run new
+    "run" value dec> >>run-id
+    ! "timestamp" value >>timestamp ! parsing of ISO8601 is currently not supported
+    "host" value >>host-name
+    "os" value >>os
+    "cpu" value >>cpu
+    "git" value >>git-id
+    select-tuples ;
+
+: selected-benchmarks ( -- benchmarks runs )
+    selected-runs [ [ run-id>> ] keep ] map>alist
+    [
+        keys [ V{ } clone benchmark new "name" value >>name ] dip
+        [ >>run-id select-tuples append! ] with each
+    ] keep ;
+
 : current-builder ( -- builder/f )
     builder new "os" value >>os "cpu" value >>cpu select-tuple ;
 
index cfa8e8c52cd181475505b3aee633d975967417d7..aa7ecc55b1d13c8a91b70185d18733b62114a0f0 100644 (file)
@@ -1,6 +1,6 @@
 namespace factor {
 
-#define CALLSTACK_BOTTOM(ctx) (ctx->callstack_seg->end - sizeof(cell) * 5) // omg
+#define CALLSTACK_BOTTOM(ctx) (ctx->callstack_seg->end - sizeof(cell) * 6) // omg
 
 // void c_to_factor(cell quot);
 // void lazy_jit_compile(cell quot);
index 41056ab29cf0054145260f75593f11731d0d0636..070d8e9bca9b4325755e0a3749f86f78c8bbf322 100644 (file)
@@ -74,6 +74,10 @@ fixnum instruction_operand::load_value(cell relative_to) {
     case RC_RELATIVE_ARM64_BCOND:
       return load_value_masked(rel_relative_arm64_bcond_mask, 3, 11, 0) +
              relative_to;
+    case RC_ABSOLUTE_ARM64_MOVZ:
+      return load_value_masked(rel_absolute_arm64_movz_mask, 5, 16, 0);
+    case RC_RELATIVE_CELL:
+      return *(cell*)(pointer - sizeof(cell));
     default:
       critical_error("Bad rel class", rel.klass());
       return 0;
@@ -159,6 +163,12 @@ void instruction_operand::store_value(fixnum absolute_value) {
     case RC_RELATIVE_ARM64_BCOND:
       store_value_masked(relative_value, rel_relative_arm64_bcond_mask, 2, 5);
       break;
+    case RC_ABSOLUTE_ARM64_MOVZ:
+      store_value_masked(absolute_value, rel_absolute_arm64_movz_mask, 0, 5);
+      break;
+    case RC_RELATIVE_CELL:
+      *(cell*)(pointer - sizeof(cell)) = relative_value;
+      break;
     default:
       critical_error("Bad rel class", rel.klass());
       break;
index 72ea3df40ac217603d45186d153c0e25bcbd05c9..fa7168de2f4a822ef71fde89f2429a58063d8df0 100644 (file)
@@ -62,10 +62,14 @@ enum relocation_class {
   RC_ABSOLUTE_1,
   // absolute address in a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence
   RC_ABSOLUTE_PPC_2_2_2_2,
-  // relative address in an ARM64 B/BL instruction
+  // Relative address stored, divided by four, in bits 25:0 of an ARM64 instruction
   RC_RELATIVE_ARM64_BRANCH,
-  // relative address in an ARM64 B.cond instruction
+  // Relative address stored, divided by four, in bits 23:5 of an ARM64 instruction
   RC_RELATIVE_ARM64_BCOND,
+  // Absolute address stored in bits 20:5 of an ARM64 instruction
+  RC_ABSOLUTE_ARM64_MOVZ,
+  // relative address in a pointer-width location
+  RC_RELATIVE_CELL,
 };
 
 static const cell rel_absolute_ppc_2_mask = 0x0000ffff;
@@ -75,6 +79,7 @@ static const cell rel_indirect_arm_mask = 0x00000fff;
 static const cell rel_relative_arm_3_mask = 0x00ffffff;
 static const cell rel_relative_arm64_branch_mask = 0x03ffffff;
 static const cell rel_relative_arm64_bcond_mask = 0x00ffffe0;
+static const cell rel_absolute_arm64_movz_mask = 0x001fffe0;
 
 // code relocation table consists of a table of entries for each fixup
 struct relocation_entry {
index 39a6c388575c6af1286e039510fbdc0c0230e924..8e14b48ab23aa255dc7eea20d22ebd7e9d300887 100644 (file)
@@ -5,7 +5,7 @@
 namespace factor {
 
 #define CALLSTACK_BOTTOM(ctx) \
-  (ctx->callstack_seg->end - sizeof(cell) * 5)
+  (ctx->callstack_seg->end - sizeof(cell) * 6)
 
 static const fixnum xt_tail_pic_offset = 4 + 1;
 
index 13ef08c17eab9af6aeb9fad875612968ca64bd85..66ee290e78f847770ed29c135beb0b7957afec65 100644 (file)
@@ -3,25 +3,25 @@
 namespace factor {
 
 void flush_icache(cell start, cell len) {
-  int result;
+//   int result;
 
-  // XXX: why doesn't this work on Nokia n800? It should behave
-  //      identically to the below assembly.
-  // result = syscall(__ARM_NR_cacheflush,start,start + len,0);
+//   // XXX: why doesn't this work on Nokia n800? It should behave
+//   //      identically to the below assembly.
+//   // result = syscall(__ARM_NR_cacheflush,start,start + len,0);
 
-  // Assembly swiped from
-  // http://lists.arm.linux.org.uk/pipermail/linux-arm/2002-July/003931.html
-  __asm__ __volatile__("mov     r0, %1\n"
-                       "sub     r1, %2, #1\n"
-                       "mov     r2, #0\n"
-                       "swi     " __sys1(__ARM_NR_cacheflush) "\n"
-                                                              "mov     %0, r0\n"
-                       : "=r"(result)
-                       : "r"(start), "r"(start + len)
-                       : "r0", "r1", "r2");
+//   // Assembly swiped from
+//   // http://lists.arm.linux.org.uk/pipermail/linux-arm/2002-July/003931.html
+//   __asm__ __volatile__("mov     r0, %1\n"
+//                        "sub     r1, %2, #1\n"
+//                        "mov     r2, #0\n"
+//                        "swi     " __sys1(__ARM_NR_cacheflush) "\n"
+//                                                               "mov     %0, r0\n"
+//                        : "=r"(result)
+//                        : "r"(start), "r"(start + len)
+//                        : "r0", "r1", "r2");
 
-  if (result < 0)
-    critical_error("flush_icache() failed", result);
+//   if (result < 0)
+//     critical_error("flush_icache() failed", result);
 }
 
 }