Thanks to the help the other day with the strange concatentation result.

I was referring to a BF interpreter I was working on, in pure SQLite SQL.
Well, here it is, working.

Hopefully no-one finds this useful,
Gary

WITH RECURSIVE
  program AS
     (SELECT 
'++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
 AS p,
        '' AS input, 3 AS width
    ),
  jumpdepth AS
     (SELECT 0 AS idx, 0 AS jumpdepth, '' AS jumplist, NULL as jumpback, NULL 
AS direction, p || '0' AS p, width FROM program
          UNION ALL
        SELECT idx+1, CASE SUBSTR(p, idx+1, 1)
                WHEN '[' THEN jumpdepth+1
                WHEN ']' THEN jumpdepth-1
                ELSE jumpdepth END,
        CASE SUBSTR(p, idx+1, 1)
                WHEN '[' THEN SUBSTR('0000000' || (idx+1), -width) || jumplist
                WHEN ']' THEN SUBSTR(jumplist,width+1)
                ELSE jumplist END,
        CASE SUBSTR(p, idx+1, 1)
                WHEN ']' THEN CAST(SUBSTR(jumplist,1,width) AS INTEGER)
                ELSE NULL END,
        CASE SUBSTR(p, idx+1, 1)
                WHEN '[' THEN 'L'
                WHEN ']' THEN 'R'
                ELSE NULL END,
        p, width
          FROM jumpdepth
          WHERE LENGTH(p)>=idx),
  jumptable(a,b,dir) AS
      (SELECT idx,jumpback,'L' FROM jumpdepth WHERE jumpback IS NOT NULL
          UNION ALL
       SELECT jumpback,idx+1,'R' FROM jumpdepth WHERE jumpback IS NOT NULL),
  bf(ep, p, width, defaulttapeentry, ip, dp, instruction, output, input, tape) 
AS
       (SELECT 0, p, width, SUBSTR('0000000', -width), 1, 1, '', '', input, 
SUBSTR('000000', -width)
           FROM program
        UNION ALL
        SELECT ep+1, p, width, defaulttapeentry, CASE WHEN jumptable.b IS NOT 
NULL AND
                ((dir='R' AND CAST(SUBSTR(tape, width*(dp-1)+1, width) AS 
INTEGER)=0)
                    OR
                 (dir='L' AND CAST(SUBSTR(tape, width*(dp-1)+1, width) AS 
INTEGER)!=0)) THEN jumptable.b
              ELSE ip+1 END,
        CASE SUBSTR(p, ip, 1)
               WHEN '>' THEN dp+1
               WHEN '<' THEN MAX(dp-1,1)
                       ELSE dp END,
        SUBSTR(p, ip, 1),
        CASE WHEN SUBSTR(p, ip, 1)='.' THEN (output || CHAR(SUBSTR(tape, 
(dp-1)*width+1, width))) ELSE output END,
        CASE WHEN SUBSTR(p, ip, 1)=',' THEN SUBSTR(input, 2) ELSE input END,
        CASE SUBSTR(p, ip, 1)
                WHEN '<' THEN CASE WHEN dp=1 THEN defaulttapeentry || tape ELSE 
tape END
                WHEN '>' THEN CASE WHEN dp*width=LENGTH(tape) THEN tape || 
defaulttapeentry ELSE tape END
                WHEN '+' THEN SUBSTR(tape,1,width*(dp-1)) || SUBSTR('0000000' 
|| (CAST(SUBSTR(tape,width*(dp-1)+1,width) AS INTEGER)+1), -width) || 
SUBSTR(tape,width*dp+1)
                WHEN '-' THEN SUBSTR(tape,1,width*(dp-1)) || SUBSTR('0000000' 
|| (CAST(SUBSTR(tape,width*(dp-1)+1,width) AS INTEGER)-1), -width) || 
SUBSTR(tape,width*dp+1)
                WHEN ',' THEN SUBSTR(tape,1,width*(dp-1)) || SUBSTR('0000000' 
|| (UNICODE(SUBSTR(input,1,1))), -width) || SUBSTR(tape,width*(dp+1))
                ELSE tape END
  FROM bf LEFT JOIN jumptable ON jumptable.a=ip WHERE LENGTH(p) >= ip)
SELECT output FROM bf ORDER BY ep DESC LIMIT 1;

_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to