annotate bin/shove @ 7094:4a2788609dc2

<b_jonas> learn Elendil decided to try to save Numenor from its awful end by navigating to the undying lands and appealing to the Valar, but then he changed his mind, saved his family only and founded a new empire in Middle-earth.
author HackBot
date Sat, 05 Mar 2016 22:07:12 +0000
parents 7914d7e0b500
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2114
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
1 #!/usr/bin/env perl
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
2 # -*- cperl -*-
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
3 # Shove interpreter. By Alex Smith.
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
4
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
5 # Commands:
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
6 # ' " Quote a string ('' strings nest inside "" strings and vice versa)
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
7 # < v > ^ Change direction of execution
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
8 # A V ( ) Pop a string onto the playfield
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
9 # space NOP
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
10
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
11 # ! NOP, but tells the compiler that everything behind the IP will
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
12 # never be used (a useful optimisation)
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
13 # S NOP, but outputs TOS (without popping) on systems with output
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
14 # n NOP, but outputs a newline on systems with output
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
15
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
16 use strict;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
17
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
18 # Read in the program
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
19
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
20 my $debug = ($#ARGV >= 0 and $ARGV[0] eq '-d' and shift and 1);
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
21 my @program = ($#ARGV >= 0 and ($ARGV[0] ne '-f' or (shift and 0)))
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
22 ? @ARGV : <>;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
23 chomp for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
24
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
25 my $x = 0;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
26 my $y = 0;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
27 my $width = 0; $width = ($width < length $_ ? length $_ : $width) for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
28 my $height = scalar @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
29 my $totalrotation = 0;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
30 my @stack = ();
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
31 # always going right, we rotate the program if necessary to ensure this
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
32
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
33 # Pads its argument to width $width.
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
34 sub widthpad {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
35 my $s = shift;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
36 return $s . (' ' x ($width - length $s));
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
37 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
38
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
39 # Rotates the program clockwise (arg = 1), 180 degrees (arg = 2),
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
40 # or anticlockwise (arg = 3)
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
41 sub rotateprogram {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
42 my $amount = shift;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
43 $amount or return;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
44 $totalrotation += $amount;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
45 $totalrotation %= 4;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
46 if ($amount >= 2) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
47 @program = reverse @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
48 $_ = reverse widthpad $_ for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
49 $x = $width - 1 - $x;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
50 $y = $height - 1 - $y;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
51 tr/<v>^AV()/>^<vVA)(/ for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
52 $amount == 2 and return;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
53 } else {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
54 $_ = widthpad $_ for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
55 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
56 my @newprog = ();
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
57 # We repeatedly move the leftmost column of @program to the top row
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
58 # of @newprog.
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
59 while (length $program[0]) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
60 my $build='';
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
61 $build = (substr $_, 0, 1, '') . $build for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
62 push @newprog, $build;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
63 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
64 @program = @newprog;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
65 tr/<^>v(A)V/^>v<A)V(/ for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
66 ($width, $height) = ($height, $width);
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
67 ($x, $y) = ($width - 1 - $y, $x);
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
68 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
69
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
70 sub shove {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
71 my $sx = shift;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
72 my $sy = shift;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
73 if($sx < 0) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
74 $_ = ' '.$_ for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
75 $x++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
76 $sx++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
77 $width++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
78 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
79 if($sx >= $width) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
80 $width++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
81 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
82 if($sy < 0) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
83 unshift @program, "";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
84 $y++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
85 $sy++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
86 $height++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
87 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
88 if($sy >= $height) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
89 push @program, "";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
90 $height++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
91 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
92 scalar @stack or die "Empty stack when shoving.";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
93 $program[$sy] = widthpad $program[$sy];
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
94 ($x > $sx && $y == $sy) and $x += length $stack[0];
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
95 substr $program[$sy], $sx, 0, shift @stack;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
96 $program[$sy] =~ s/\ +$//;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
97 $width < length $program[$sy] and $width = length $program[$sy];
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
98 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
99
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
100 sub showprogram {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
101 my $tr = $totalrotation;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
102 print "\nactual size: ($width, $height), pos: ($x, $y)\n";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
103 rotateprogram ((4-$tr)%4);
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
104 $program[$y] = widthpad $program[$y];
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
105 my $c = substr $program[$y], $x, 1, '*';
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
106 print "rotated for viewing; pos: ($x, $y), dir: $tr\n";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
107 print "stack: ";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
108 print "{$_} " for @stack;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
109 print "\n";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
110 print "$_\n" for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
111 substr $program[$y], $x, 1, $c;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
112 rotateprogram $tr;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
113 scalar <STDIN>;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
114 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
115
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
116 while ($x < $width && $y < $height && $x >= 0 && $y >= 0) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
117 showprogram if $debug;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
118 my $cmd = substr $program[$y], $x, 1;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
119 # $cmd eq '>' is a nop
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
120 $cmd eq '^' and rotateprogram 1;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
121 $cmd eq '<' and rotateprogram 2;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
122 $cmd eq 'v' and rotateprogram 3;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
123 $cmd eq '(' and shove $x-1, $y;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
124 $cmd eq ')' and shove $x+1, $y;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
125 $cmd eq 'A' and shove $x, $y-1;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
126 $cmd eq 'V' and shove $x, $y+1;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
127 $cmd eq 'S' and print $stack[0];
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
128 $cmd eq 'n' and print '\n';
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
129 if ($cmd eq '!') {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
130 substr $_, 0, $x, '' for @program;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
131 $width -= $x;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
132 $x = 0;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
133 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
134 if ($cmd eq '"' || $cmd eq "'") {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
135 my $quotecount = 1;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
136 my $lws = $cmd eq "'";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
137 my $newpush = "";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
138 while($quotecount) {
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
139 $x++;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
140 $x < $width or die "Unterminated string.";
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
141 $cmd = substr $program[$y], $x, 1;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
142 $cmd eq "'" and ($quotecount += ($lws ? -1 : 1)), ($lws = !$lws);
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
143 $cmd eq '"' and ($quotecount += ($lws ? 1 : -1)), ($lws = !$lws);
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
144 $quotecount and $newpush .= $cmd;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
145 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
146 unshift @stack, $newpush;
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
147 }
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
148 $x++; # move to next command
7914d7e0b500 <ais523> revert 87c64ef250a0
HackBot
parents:
diff changeset
149 }