Skip to content

Instantly share code, notes, and snippets.

@0x0dea 0x0dea/hspal
Last active Aug 29, 2015

Embed
What would you like to do?
This is a Ruby interpreter for Hexadecimal Stacking Pseudo-Assembly Language, an esolang devised by ‎SuperJedi224. With its single register and multitude of independent stacks, it feels a bit like Whitespace turned inside-out.
#!/usr/bin/env ruby
class HSPAL
# Enforce unsigned 16-bit data by clamping all entries.
class Stack < Array
def << val
super [0, val, 0xFFFF].sort[1]
end
end
Guards = {1 => [*1..3, 0x12, 0x13, 0x41, 0x42],
2 => [*0x21..0x25, *0x30..0x35]}
def initialize src = ARGF.read
@insns = src.scan(/\h{6}/).map { |hex| [hex].pack('H6').bytes }
end
def run
ip, reg, labels = -1, 0, {}
@S = Array.new(256) { Stack.new }
while (ip += 1) < @insns.size
op, a, b = @insns[ip]
c = a * 256 + b
Guards.each do |min, cov|
if cov.include?(op) && @S[a].size < min
raise "Too few stack items for opcode #{op}!"
end
end
case op
# flow control
when 0x00; labels[c] = ip
when 0x01; raise "Nonexistent label!" unless ip = labels[c]
when 0x02; raise "Nonexistent label!" unless ip = labels[@S[a].pop]
when 0x03; ip += 1 if @S[a].pop > 0
when 0x04; raise "Halted with status #{c}."
# IO
when 0x10; @S[a] << (STDIN.getc || 0).ord
when 0x11; @S[a] << gets.to_i
when 0x12; print @S[a].pop
when 0x13; print '' << @S[a].pop
when 0x14; print '' << @S[a].pop until @S[a].empty?
# arithmetic
when 0x20; reg = c
when 0x21..0x25
n, m = @S[a].pop(2)
@S[a] << m.send(%w[+ - * / **][op - 0x21], n)
when 0x26; reg = rand(c)
# logic
when 0x30..0x35
n, m = @S[a].pop(2)
@S[b] << m.send(%w[== > < | & ^][op - 0x30], n) ? 1 : 0
when 0x36; @S[a] << reg == 0 ? 1 : 0
# misc
when 0x40; @S[a] << reg and reg = 0
when 0x41..0x43
reg = @S[a].send %w[pop last size][op - 0x41]
else raise "Illegal opcode: #{op} "
end
end
end
end
HSPAL.new.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.