#!/bin/perl

# Armpi3 assembly source to BASIC converter.

# Usage: s2bas <source_file>

# Tab characters must be converted to spaces. This is automatically done if
# the output is sent to a taskwindow and if you save the content to a file.

while (<>)
  { &conv($_) }
die "WHILE without WEND\n" if ($wh ne '');
print "DIM code% 2048, D% 13\n",$rn;
print <<EOF;
LR=14
FOR pass%=0 TO 2 STEP 2
P%=code%
[		OPT	pass%
.calpi		STMFD	R13!, {R0, R1, R3, LR}
		MOV	R0, #1
		MOV	R1, R3
		SWI	"OS_Word"
		LDMFD	R13, {R0, R1}
		BL	start
		MOV	R0, #1
		LDR	R1, [SP, #8]
		ADD	R1, R1, #8
		SWI	"OS_Word"
		LDMFD	R13!, {R0, R2, R3}
		ADD	R3, R0, R2
.calpi_loop	LDR	R0, [R3, #-1]!
		ORR	R0, R0, #&30
		SWI	"OS_WriteC"
		CMP	R2, R3
		BNE	calpi_loop
		SWI	&10D
		SWI	&10A
		LDR	PC, [SP], #4
$out]
NEXT
\@%="G0"
INPUT A%
IF A% < 4 THEN END
DIM B% 4*((29*A%) DIV 48)+1548
IF A% MOD 4 = 0 THEN CALL calpi : PRINT "Temps = "(D%!8-D%!0)/100" s."
EOF

sub conv
  { $_ = $_[0];
    if ($wh ne '' && /^\s+WEND\s+/)
      { $ww = 1;
        while (eval $wh)
          { foreach (@wh)
              { conv($_) }
          }
        ($wh, $ww, @wh) = (); }
    elsif ($wh ne '' && !$ww)
      { push @wh, $_ }
    elsif (/^(\w*)\s+\[\s+(.+)/)
      { die "| or ] expected\n" if ($if);
        $out .= ".$1\n" if ($1 ne '');
        ($expr = $2) =~ s/\b([A-Za-z_]\w*)/\$$1/go;
        $cond = eval $expr;
        $if = 1; }
    elsif (/^(\w*)\s+\|\s+/)
      { $out .= ".$1\n" if ($1 ne '' && $cond);
        $cond = !$cond; }
    elsif (/^(\w*)\s+]\s+/)
      { $out .= ".$1\n" if ($1 ne '' && $cond);
        $if = ''; }
    elsif (!$if || $cond)
      { if (substr($_,0,1) eq ';')
          { $out .= 'REM'.substr($_,1) }
        elsif (/^(\w+)\s+RN\s+(\d+)/o)
          { $rn .= "$1=$2\n";
            $reg{$1} = "R$2"; }
        elsif (/^(\w*)\s+GBLA\s+(\w+)/o)
          { eval "\$$2=0" }
        elsif (($var,$expr) = /^(\w+)\s+SETA\s+(.+)/o)
          { $expr =~ s/\b([A-Za-z_]\w*)/\$$1/go;
            eval "\$$var=$expr"; }
        elsif (/^(\w*)\s+WHILE\s+(.+)/o)
          { die "WEND expected\n" if ($wh ne '');
            $out .= ".$1\n" if ($1 ne '');
            ($wh = $2) =~ s/\b([A-Za-z_]\w*)/\$$1/go; }
        elsif (/^(\w+)(\s+)(DC.\s+)(.+?),(.+)\n/)
          { $out .= ".$1".(substr($2,0,1) eq ' ' ? substr($2,1) : $2)."$3$4\n";
            foreach (split /,/, $5)
              { $out .= "\t\t$3$_\n" }
          }
        elsif (/^(\w*)\s+ADR\s+(\w+)\s*,\s*(\w+)\s+$/)
          { $out .= ".$1\n" if ($1 ne '');
            $adrn = 'adr'.++$adr;
            $out .= ".$adrn\t\tADD\t$2, PC, #(($3-$adrn-8)DIV64)*64\n\t\tADD\t$2, $2, #(($3-$adrn-8)MOD64)\n"; }
        else
          { s/(\w+)!/$reg{$1}!/;
            $out .= /^(\w+)(\s*)(.*\n)/o ?
              ".$1".(substr($2,0,1) eq ' ' ? substr($2,1) : $2).$3 : $_ }
      }
  }