71 lines
2.1 KiB
Raku
71 lines
2.1 KiB
Raku
class SNUSP {
|
|
|
|
has @!inst-pointer;
|
|
has @!call-stack;
|
|
has @!direction;
|
|
has @!memory;
|
|
has $!mem-pointer;
|
|
|
|
method run ($code) {
|
|
init();
|
|
my @code = pad( |$code.lines );
|
|
for @code.kv -> $r, @l {
|
|
my $index = @l.grep( /'$'/, :k );
|
|
if $index {
|
|
@!inst-pointer = $r, $index;
|
|
last
|
|
}
|
|
}
|
|
|
|
loop {
|
|
my $instruction = @code[@!inst-pointer[0]; @!inst-pointer[1]];
|
|
given $instruction {
|
|
when '>' { $!mem-pointer++ }
|
|
when '<' { $!mem-pointer-- }
|
|
when '+' { @!memory[$!mem-pointer]++ }
|
|
when '-' { @!memory[$!mem-pointer]-- }
|
|
when '.' { print @!memory[$!mem-pointer].chr }
|
|
when ',' { @!memory[$!mem-pointer] = $*IN.getc.ord }
|
|
when '/' { @!direction = @!direction.reverse «*» -1 }
|
|
when '\\' { @!direction = @!direction.reverse }
|
|
when '!' { nexti() }
|
|
when '?' { nexti() unless @!memory[$!mem-pointer] }
|
|
when '@' { @!call-stack.push: @!inst-pointer.Array }
|
|
when '#' {
|
|
last unless +@!call-stack;
|
|
@!inst-pointer = |@!call-stack.pop;
|
|
nexti();
|
|
}
|
|
}
|
|
nexti();
|
|
last if @!inst-pointer[0] > +@code or
|
|
@!inst-pointer[1] > +@code[0];
|
|
}
|
|
|
|
sub init () {
|
|
@!inst-pointer = 0, 0;
|
|
@!direction = 0, 1;
|
|
$!mem-pointer = 0;
|
|
@!memory = ()
|
|
}
|
|
|
|
sub nexti () { @!inst-pointer Z+= @!direction }
|
|
|
|
sub pad ( *@lines ) {
|
|
my $max = max @lines».chars;
|
|
my @pad = @lines.map: $max - *.chars;
|
|
map -> $i { flat @lines[$i].comb, ' ' xx @pad[$i] }, ^@lines;
|
|
}
|
|
}
|
|
}
|
|
|
|
# TESTING
|
|
my $hw = q:to/END/;
|
|
/++++!/===========?\>++.>+.+++++++..+++\
|
|
\+++\ | /+>+++++++>/ /++++++++++<<.++>./
|
|
$+++/ | \+++++++++>\ \+++++.>.+++.-----\
|
|
\==-<<<<+>+++/ /=.>.+>.--------.-/
|
|
END
|
|
|
|
my $snusp = SNUSP.new;
|
|
$snusp.run($hw)
|