Fixed 2swap bug, added ?do, fixed +loop.
authorTim Vaughan <tgvaughan@gmail.com>
Thu, 28 Apr 2016 12:28:15 +0000 (00:28 +1200)
committerTim Vaughan <tgvaughan@gmail.com>
Thu, 28 Apr 2016 12:29:02 +0000 (00:29 +1200)
Also, Mandelbrot Set example now works.

examples/mandelbrot.4th
src/forth.jl
src/lib.4th

index 5707acb..d31b028 100644 (file)
 
 : csq 2dup c* ;
 
+
+: conj ( x y -- x -y )
+    negate
+;
+
 : cmagsq ( x1 y1 -- mag )
-    csq abs
+    2dup conj c* +
 ;
 
 ( --- Mandelbrot set calculations  --- )
 
 : iterate ( cr ci zr zi -- cr ci z'r z'i )
-    csq c+
+    2over 2swap csq c+
 ;
 
 : inSet? ( cr ci -- res )
-    DEBUGON
-
     0 0     ( z_0 = 0 )
     
     true    ( flag indicating set membership )
@@ -53,7 +56,7 @@
 
         iterate
         2dup cmagsq
-        4 >scaled > if
+        4 >scaled > if
             false ( not in set )
             leave
         then
 ;
 
 : xsteps 100 ;
-: ysteps 50 ;
+: ysteps 30 ;
 
 ( Draw the Mandelbrot Set!)
 : mandel ( x1 y1 x2 y2 -- )
 
-    1 pick 4 pick -
-    2 pick 5 pick do
-        i 0 inSet? if
-            42 emit
-        else
-            '.' emit
-        then
+    0 pick 3 pick - ysteps /
+    1 pick 4 pick do
+
+        2 pick 5 pick - xsteps /
+        3 pick 6 pick do
+
+            i j inSet? if
+                42 emit
+            else
+                space
+            then
+
+        dup +loop
+        drop
+
+        cr
+
     dup +loop
+    drop
 ;
 
 ( Clean up - hide non-standard multiplication def. )
index fba2375..e7faf97 100644 (file)
@@ -284,8 +284,17 @@ TWOSWAP = defPrimWord("2SWAP", () -> begin
     d = popPS()
     pushPS(b)
     pushPS(a)
-    pushPS(c)
     pushPS(d)
+    pushPS(c)
+    return NEXT
+end)
+
+TWOOVER = defPrimWord("2OVER", () -> begin
+    ensurePSDepth(4)
+    a = mem[reg.PSP-3]
+    b = mem[reg.PSP-2]
+    pushPS(a)
+    pushPS(b)
     return NEXT
 end)
 
index ea4e7de..b9bfcca 100644 (file)
 ;
 
 : DO IMMEDIATE
+        ' LIT , -1 , [COMPILE] IF
+        ' >R , ' >R ,
+        ' LIT , HERE @ 0 , ' >R ,
+        HERE @
+;
+
+: ?DO IMMEDIATE
+        ' 2DUP , ' - , [COMPILE] IF
         ' >R , ' >R ,
         ' LIT , HERE @ 0 , ' >R ,
         HERE @
 ;
 
 : +LOOP IMMEDIATE
+        ' DUP , \ Store copy of increment
+
         ' R> , ' SWAP , ' R> , ' SWAP , ' R> , ' SWAP , ' + , ' 2DUP , ' - ,
         ' SWAP , ' >R , ' SWAP , ' >R , ' SWAP , ' >R ,
-        ' 0<= , ' 0BRANCH ,
-        HERE @ - ,
+
+        \ Condition differently depending on sign of increment
+        ' SWAP , ' 0>= , [COMPILE] IF
+            ' 0<= ,
+        [COMPILE] ELSE
+            ' 0> ,
+        [COMPILE] THEN
+
+        \ Branch back to begining of loop kernel
+        ' 0BRANCH , HERE @ - ,
+
+        \ Clean up
         ' RDROP , ' RDROP , ' RDROP ,
+
+        \ Record address of loop end for any LEAVEs to use
         HERE @ SWAP !
+
+        [COMPILE] ELSE
+            ' 2DROP , \ Clean up if loop was entirely skipped (?DO)
+        [COMPILE] THEN
 ;
 
 : LOOP IMMEDIATE
         PSP@ SWAP -     ( add to the stack pointer )
         @               ( and fetch )
 ;
+: ROLL ( x_u x_u-1... x_0 u -- x_u-1 ... x_0 x_u )
+        1+ DUP PICK SWAP    ( x_u x_u-1 ... x_0 x_u u+1 )
+        PSP@ 1- SWAP - PSP@ 2- SWAP
+        DO
+            i 1+ @ i !
+        LOOP
+        SWAP DROP
+;
 
 ( With the looping constructs, we can now write SPACES, which writes n spaces to stdout. )
 : SPACES        ( n -- )
-        0 DO
-            SPACE
-        LOOP
+        DUP 0> IF
+            0 DO SPACE LOOP
+        ELSE
+            DROP
+        THEN
 ;
 
 ( Standard words for manipulating BASE. )
                 FALSE
         THEN
 ;
-
-: ROLL ( x_u x_u-1... x_0 u -- x_u-1 ... x_0 x_u )
-        1+ DUP PICK SWAP    ( x_u x_u-1 ... x_0 x_u u+1 )
-        PSP@ 1- SWAP - PSP@ 2- SWAP
-        DO
-            i 1+ @ i !
-        LOOP
-        SWAP DROP
-;
-
-include ../examples/mandelbrot.4th