90 lines
1.8 KiB
Ruby
90 lines
1.8 KiB
Ruby
require "pp"
|
|
|
|
class Node
|
|
def ==(other)
|
|
self.class == other.class &&
|
|
self.class::Keys.all? do |key|
|
|
instance_variable_get(:"@#{ key }") == other.send(key)
|
|
end
|
|
end
|
|
|
|
attr_accessor :tmp
|
|
|
|
def self.create(*keys)
|
|
klass = Class.new(Node)
|
|
klass.const_set(:Keys, keys)
|
|
klass.class_eval do
|
|
keys.each do |key|
|
|
attr_reader key
|
|
end
|
|
end
|
|
klass
|
|
end
|
|
|
|
def self.[](*values)
|
|
new(*values)
|
|
end
|
|
|
|
def initialize(*values)
|
|
self.class::Keys.zip(values) do |key, value|
|
|
instance_variable_set(:"@#{ key }", value)
|
|
end
|
|
end
|
|
|
|
def inspect
|
|
"#{ self.class }[#{
|
|
self.class::Keys.map do |key|
|
|
instance_variable_get(:"@#{ key }").inspect
|
|
end.join(", ")
|
|
}]"
|
|
end
|
|
|
|
def pretty_print(q)
|
|
q.group(2, "#{ self.class }[", "]") do
|
|
q.seplist(
|
|
self.class::Keys.map do |key|
|
|
instance_variable_get(:"@#{ key }")
|
|
end
|
|
) do |v|
|
|
q.pp v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
PRead = Node.create(:var)
|
|
PImm = Node.create(:num)
|
|
PNop = Node.create
|
|
|
|
PBinary = Node.create(:op, :e1, :e2)
|
|
PIfThenElse = Node.create(:cond, :e1, :e2)
|
|
|
|
PRShift = Node.create(:val, :shift)
|
|
PARef = Node.create(:e1, :e2) # e1[e2]
|
|
PSRef = Node.create(:e)
|
|
PIRef = Node.create(:e)
|
|
|
|
PSequence = Node.create(:seq, :e)
|
|
|
|
PASet = Node.create(:e1, :e2, :e3) # e1[e2] = e3
|
|
PAssign = Node.create(:var, :exp)
|
|
PLoop = Node.create(:cond, :body)
|
|
PExit = Node.create(:e)
|
|
POut = Node.create(:e)
|
|
PTest = Node.create(:e)
|
|
|
|
IRead = Node.create(:var)
|
|
IWrite = Node.create(:var)
|
|
IInc = Node.create(:var)
|
|
IDec = Node.create(:var)
|
|
INop = Node.create
|
|
IPush = Node.create(:num)
|
|
IBinary = Node.create(:op)
|
|
IARef = Node.create
|
|
IASet = Node.create
|
|
IExit = Node.create
|
|
IOut = Node.create
|
|
ITest = Node.create
|
|
IBranch = Node.create(:s1, :s2)
|
|
ILoop = Node.create(:s1, :s2)
|