Last active
June 10, 2021 03:46
-
-
Save 0x0dea/b243ecaaaedaaa58b264 to your computer and use it in GitHub Desktop.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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