! Crossword helper V0.0
%external %integer %fn %spec Get Store %alias "IMP_GET_SPACE"(%integer bytes)
!%external %integer %fn %spec Get Store %alias "XAllocate" (%integer Size)
%external %integer %fn %spec LoadFile(%string(255) Name,
                                      %integer BuffSize,
                                      %integer address)
%begin
%const %string(255) dict name = "adfs:&.words.lexicon"

%routine Read line(%byte %array %name t)
%integer ti = 0, sym
  %cycle
    Read symbol(sym)
    t(ti) = sym
    ti = ti+1
  %repeat %until sym=NL
%end

%string(63) %fn str(%integer sp)
%string(63) s = ""
  %while BYTE(sp) # NL %cycle
    s = s.BYTE(sp); sp = sp+1
  %repeat
  %result = s
%end

%integer %fn prevword(%integer rp)
  rp = rp-1 %until BYTE(rp)=NL
  %result = rp+1
%end

%byte %array literal(0:63), target(0:63)
%constant %integer dict size = 386432,
                   higher=1, lower=0,
                   on = 1, off = 0
! [a] [NL] [abacus] .... [zygote] [NL]
! ^fbeg                           ^fend
%integer fbeg = Get Store(dict size+1+64)+1, fend = fbeg + dict size - 1,
         tp, fp, pp,
         wlp, wrp,
         lp, rp, splitp,
         success, comp

%routine Init
  Print string("Word finder V0.0".nl)
!  Print string("Dict fbegs at ".itos(fbeg,0).nl)
  success = LoadFile(dict name, dict size, fbeg)
  BYTE(fbeg-1) = NL
  %if success < 0 %then %start
    Print string("Cannot load dictionary".nl)
    %stop
  %finish
%end

%predicate word exists(%byte %array %name target)
%integer ofp,otp,fsym,sym,wp
  fp=fbeg-1
  tp=ADDR(target(0))
  pp=fend+1
  %cycle
    sym=BYTE(tp);
    BYTE(pp)=sym
    %exit %if sym=NL
    pp=pp+1;tp=tp+1
  %repeat
  tp=ADDR(target(0))
printstring(NL."Searching for '".str(tp)."'".NL)
  fsym=target(0)
  %cycle
    fp=fp+1 %while BYTE(fp)#NL; fp=fp+1; wp=fp
    %if BYTE(fp)=fsym %or fsym='?' %start
      otp=tp; ofp=fp
      %cycle
        otp=otp+1;ofp=ofp+1
        sym=BYTE(otp)
        %unless BYTE(ofp)=sym %or (sym='?' %and BYTE(ofp)#NL) %then %exit
        %if sym=NL %then %start
          %if fp=fend+1 %then %start
            printstring("No more matches".NL)
            %false
          %else
            printstring("'".str(wp)."' found".NL)
            %exit
          %finish
        %finish
      %repeat
    %finish
  %repeat
%end

%routine transfer garbage
%integer sym
  %cycle
    %exit %if end of input
    sym = next symbol
    %if 'a'<=sym<='z' %or 'A'<=sym<='Z' %or sym='?' %then %exit
    skip symbol
  %repeat
%end

%routine Read Word ;! Assert - next char IS a letter
%integer sym, i = 0
  %cycle
    %exit %if end of input
    sym = next symbol
    %unless 'a'<=sym<='z' %or 'A'<=sym<='Z' %or sym='?' %then %exit
    skip symbol
    literal(i) = sym
    %if sym#'?' %then target(i) = sym!32 %else target(i)=sym
    i=i+1
  %repeat
  target(i)=NL; literal(i)=NL
%end

%routine print word(%byte %array %name t)
  Print string(str(ADDR(t(0))))
%end

%routine Highlight(%integer onoff)
  %if onoff=on %then %start
    printsymbol(17);printsymbol(0);printsymbol(17);printsymbol(129)
  %else
    printsymbol(17);printsymbol(1);printsymbol(17);printsymbol(128)
  %finish
%end

%routine Check
  %cycle
    Transfer Garbage
    %exit %if end of input
    Read Word
    %if %not word exists(target) %start
!      Highlight(on)
!      Print word(literal)
!      Highlight(off)
    %else
!      Print word(literal)
    %finish
    %exit %if end of input
  %repeat
%end

!
Init
Check
!
%endofprogram
