use v6-alpha; class l33t-0.0.3; =kwid l33t interpreter This isn't supposed to be particularly obfuscated code; but it is an interpreter for the esoteric language l33t: L Which I think warrants its inclusion in this directory. =cut #our $MEMSIZE = 64 * 1024; our $MEMSIZE = 200; # use this till pugs becomes faster. :-( our $CELLSIZE = 256; our $INSULT = 'j00 4r3 teh 5ux0r'; has int8 @!mem; # program and data memory space has Int $.ip; # instruction pointer has Int $.mp; # memory pointer has Socket $con; # "connection"; stdio when undef has Bool $!trace; has Bool $!debug; has Bool $!step; has Bool %!breakpoints; has Str $!last_db_command; has Str $!coninfo; submethod BUILD { #say "BUILD"; @!mem[$_] = 0 for 0 .. ($MEMSIZE-1); $.ip = 0; $.mp = 0; $!trace = $!step = $!debug; say "BUILD done" if $!debug; } submethod trace( Str $msg) { say $msg if $!trace; } method load($self: Str $program is copy) { self.trace("loading >>\n $program\n<<"); $program ~~ s:P5/^\s*//; for split rx:P5/\s+/, $program -> $word { my $val = ([+] $word ~~ rx:P5:g/(\d)/) // 0; self.trace("word [$word] = $val"); @!mem[$.mp++] = $val; $.mp %= $MEMSIZE; } $.mp++; $.mp %= $MEMSIZE; return $self; } submethod IIP() { # increment instruction pointer $.ip++; $.ip %= $MEMSIZE; } submethod DIP() { # decrement instruction pointer $.ip--; $.ip %= $MEMSIZE; } method run() { say "\nl33t d3bu993r - h1t 'h' 4 h31p / 'i' 4 inf0\n" if $!debug; #try { loop { self.debug if $!debug; # XXX: figure out how to bind this once given @!mem[$.ip] { when 0 { self.IIP }; # NOP when 1 { self.write; }; # WRT when 2 { self.read; }; # RD when 3 { self.bracket(3, 4) }; # IF when 4 { self.bracket(4, 3) }; # EIF when 5 { self.mem($.mp, wrap=>$MEMSIZE) }; # FWD when 6 { self.mem($.mp, wrap=>$MEMSIZE, :down) }; # BAK when 7 { self.mem(@!mem[$.mp], wrap=>$CELLSIZE) }; # INC when 8 { self.mem(@!mem[$.mp], wrap=>$CELLSIZE, :down) }; # DEC when 9 { self.con }; # CON when 10 { # END $.con.close if defined $.con; last; }; # unknown opcode. this is NOT a (fatal) syntax error. say "$INSULT: wtf iz $_?"; self.IIP; } } #CATCH "Debugger::QUIT" { say "qu1t" } #}; #die $! if $!; } method con() { @!mem[$MEMSIZE .. $MEMSIZE+5] = @.mem[0 .. 5]; # ch33tz! 101 my $ip = join ".", @!mem[$.mp .. $.mp+3]; my $port = @!mem[$.mp+4] * 256 + @.mem[$.mp+5]; # >> f1x0rz v1m my $newcon = connect($ip, $port); if $newcon { $.con.close if $.con; $.con = $newcon; $!coninfo = "$ip:$port"; } self.IIP; $.mp += 6; $.mp %= $MAXSIZE; }; method mem($target is rw, :$wrap!, $down?) { self.IIP; $target += (@!mem[$.ip] + 1) * ($down ?? -1 !! 1); $target %= $wrap; self.IIP; } method bracket(: $own, $matching) { my $move = (($own == 3) ?? {self.IIP} !! {self.DIP}); # mover in the right direction if (($own == 3 && @!mem[$.mp] == 0) || ($own == 4 && @.mem[$.mp] != 0)) { my $iflevel = 1; loop { $move(); given @!mem[$.ip] { when $own { $iflevel++ }; when $matching { self.IIP, last unless --$iflevel }; } } } else { self.IIP; } } method write() { print chr @!mem[$.mp]; self.IIP; } method read() { @!mem[$.mp] = ord getc; self.IIP; } method demo(Class $class: ) { #say("demo starting"); #$class.new.load(l33t::Samples.hello).run; $class.new(:debug).load($class.hello).run; } method debug() { repeat { self.debug_trace } until self.debug_interactive; } # true return == stay at this line method debug_interactive() returns Bool { if %!breakpoints{$.ip} { say "<6r34k>"; } elsif !$!step { return Bool::True; } repeat { print "$.ip> " } until (self.debug_action(=<>) || $!runnable); return $!runnable; } method debug_help { say qq:to/END/; h (help) - print this message B - list breakpoints b (break) - toggle breakpoint here b ADDR - toggle breakpoint at location ADDR C (clear) - clear all breakpoints i (info) - print misc. info (connection, etc.) ip ADDR - change IP to ADDR ip +|-NUM - move IP NUM positions back or forward l (list) - list program (near context, starting here) l ADDR - list program starting at ADDR mp ADDR - change MP to ADDR mp +|-NUM - move MP NUM positions back or forward q (quit) - end program r (run) - continue running until next breakpoint s (step) - single step [enter to keep stepping] t (trace) - toggle trace prints [currently {$!trace ?? "ON" !! "OFF"}] w PROG - write program fragment PROG beginning at MP (changes MP) END } # : f1x0rz v1m method debug_action(Str $cmd is copy) returns Bool { $!runnable = False; $cmd ||= $!last_db_command; $!last_db_command = $cmd; given $cmd { when rx:P5/^\s*[Hh]|\?/ { # h help self.debug_help; }; #when 'B' { say %!breakpoints.keys.sort:{$^a<=>$^b} }; when 'B' { say %!breakpoints.keys.join(" "); }; when rx:P5/^\s*b\s*(\d+)?$/ { my $addr = $0 // $.ip; %!breakpoints{$addr} ^^= 1; %!breakpoints.delete($addr) unless %!breakpoints{$addr}; }; when 'C' { # C (clear) undefine %!breakpoints; say "6r34p01ntz (134r3"; }; when 'i' { say "(urr3nt (0nn3xxx10n: " ~ ($!coninfo // "stdio"); say "tr4(3 m0de: " ~ ($!trace ?? "0n" !! "0ff"); return Bool::True; }; when rx:P5/^\s*[iI][pP]\s*(([-+])?\d+)/ { if $1 { $.ip += $0 } else { $.ip = $0 } $.ip %= $MEMSIZE; return Bool::True; }; when rx:P5/^\s*[mM][pP]\s*(([-+])?\d+)/ { if $1 { $.mp += $0 } else { $.mp = $0 } $.mp %= $MEMSIZE; return Bool::True; }; when rx:P5/^\s*r/ { # r run $!step = False; $!runnable = True; }; when rx:P5/^\s*[lL]\s*(\d+)?/ { # l list my $from = $0 // $.ip; @!mem[$MEMSIZE .. $MEMSIZE+63] = @.mem[0 .. 63]; # ch33tz! 101 for 0 .. 3 -> $off { say "[{($from+$off*16)%$MEMSIZE}] " ~ @!mem[($from+$off*16) .. (($from+$off*16)+15)].join(" "); } }; when 's' { # s step $!step = True; $!runnable = True; }; when 't' { # t trace $!trace ^^= 1; }; when 'q' { die "Debugger::QUIT" }; # q quit when rx:P5/^\s*[wW]\s*(.+)/ { # w write self.load($0); return True; }; say "$INSULT: wft iz $_?"; return True; } return False; } method debug_trace() { return unless $!trace; say("IP: $.ip => @!mem[$.ip] MP: $.mp => @.mem[$.mp]"); my $msg; # I want rvalue given. given @!mem[$.ip] { when 0 { $msg = "NOP" }; when 1 { $msg = "WRT @!mem[$.mp]" }; when 2 { $msg = "RD => $.mp [01d v4l = @!mem[$.mp]" }; when 3 { $msg = "IF [{@!mem[$.mp] ?? 'tru3' !! 'f4l53'}]" }; when 4 { $msg = "EIF [{@!mem[$.mp] ?? 'f4l53' !! 'tru3'}]" }; when 5 { my $nmp = ($.mp + @!mem[($.ip+1) % $MEMSIZE] + 1) % $MEMSIZE; $msg = "FWD {@!mem[($.ip+1) % $MEMSIZE]} => $nmp [@.mem[$.mp]]" }; when 6 { my $nmp = ($.mp - @!mem[($.ip+1) % $MEMSIZE] + 1) % $MEMSIZE; $msg = "BAK {@!mem[($.ip+1) % $MEMSIZE]} => $nmp [@.mem[$.mp]]" }; when 7 { my $val = @!mem[($.ip+1) % $MEMSIZE]; $msg = "INC $val => {(@!mem[$.mp]+$val+1) % $CELLSIZE}" }; when 8 { my $val = @!mem[($.ip+1) % $MEMSIZE]; $msg = "INC $val => {(@!mem[$.mp]-$val+1) % $CELLSIZE}" }; when 9 { @!mem[$MEMSIZE .. $MEMSIZE+5] = @.mem[0 .. 5]; # ch33tz! 101 my $ip = join ".", @!mem[$.mp .. $.mp+3]; my $port = @!mem[$.mp+4] * 256 + @.mem[$.mp+5]; # >> f1x0rz v1m $msg = "CON $ip:$port"; # 41nt 1 t3h sw33t }; when 10 { $msg = "END" }; $msg = "$_ [unknown opcode]"; }; say $msg; } if !caller() { l33t.demo } #class l33t::Samples-0.0.1; method crazy_eights(Class $class :) { return q{ 7hink y0uR t0uGh? Ar3 y0U 5ure? 5tEp uP 7hEn!! f3e11 t3h buRn!! 7akE it!!!1 y0u l1kE? We'LL PlAy CrAzY 8's bItCh!!!11 I'll 0wN yOuR f4t A55!!!! }; } method ascii_loop(Class $class :) { return q{ ph34r my l3Et 5kIlLZ!!!!!! nErDs 41n't cool 3v3ry1!!! y0u b1g g33kS r teh g33kY sux0rs! PHE4R! LOLOLOLOLOLOL!!! }; } # Sayeth the original source code: # "Hello World" by Stephen McGreal. # Note that the views expressed in this source code do not necessarily # coincide with those of the author :o) method hello(Class $class :) { return q{ Gr34t l33tN3$$? M3h... iT 41n't s0 7rIckY. l33t sP33k is U8er keWl 4nD eA5y wehn u 7hink 1t tHr0uGh. 1f u w4nn4be UB3R-l33t u d3f1n1t3lY w4nt in 0n a b4d4sS h4xX0r1ng s1tE!!! ;p w4r3Z c0ll3cT10n2 r 7eh l3Et3r! Qu4k3 cL4nS r 7eh bE5t tH1ng 1n teh 3nTIr3 w0rlD!!! g4m3s wh3r3 u g3t to 5h00t ppl r 70tAl1_y w1cK1d!! I'M teh fr4GM4stEr aN I'lL t0t41_1Ly wIpE teh phr34k1ng fL00r ***j3d1 5tYlE*** wItH y0uR h1dE!!!! L0L0L0L! t3lEphR4gG1nG l4m3rs wit mY m8tes r34lLy k1kK$ A$$ l33t hAxX0r$ CrE4t3 u8er- k3wL 5tUff lIkE n34t pR0gR4mm1nG lAnguidGe$... s0m3tIm3$ teh l4nGu4gES l00k jUst l1k3 rE41_ 0neS 7o mAkE ppl Th1nk th3y'r3 ju$t n0rMal lEE7 5pEEk but th3y're 5ecRetLy c0dE!!!! n080DY unDer5tAnD$ l33t SpEaK 4p4rT fr0m j3d1!!!!! 50mE kId 0n A me$$4gEb04rD m1ghT 8E a r0xX0r1nG hAxX0r wH0 w4nT2 t0 bR34k 5tuFf, 0r mAyb3 ju5t sh0w 7eh wAy5 l33t ppl cAn 8E m0re lIkE y0d4!!! hE i5 teh u8ER!!!! 1t m1ght 8E 5omE v1rus 0r a Pl4ySt4tI0n ch34t c0dE. 1t 3v3n MiTe jUs7 s4y "H3LL0 W0RLD!!!" u ju5t cAn'T gu3s5. tH3r3's n3v3r anY p0iNt l00KiNg sC3pT1c4l c0s th4t, be1_1Ev3 iT 0r n0t, 1s whAt th1s 1s!!!!! 5uxX0r5!!!L0L0L0L0L!!!!!!! }; }