Skip to content

Instantly share code, notes, and snippets.

@CoderPuppy
Created August 23, 2012 21:56
Show Gist options
  • Save CoderPuppy/3442450 to your computer and use it in GitHub Desktop.
Save CoderPuppy/3442450 to your computer and use it in GitHub Desktop.
Instruction Set
# Vote which one is best
# No Data Registers, Current
set reg(0) => raw("Hello, ")
add 0, raw("Drew")
add reg(0), raw("!!!")
# Array of Data Registers
set "Hello, "
set "Drew"
add
set "!!!"
add
# Multiple Data Registers
original "Hello, " # Set the original value; aka `orig`
modifier "Drew" # Set the modifier; aka `mod`
add # Add them together
# Original is now "Hello, Drew"
modifier "!!!"
add
# Original is now "Hello, Drew!!!"
# Single Data Register
set "Hello, "
save 0
set "Drew"
save 1
load 0
add 1
save 0
set "!!!"
save 1
load 0
add 1
save 0
# or
set "!!!"
save 0
set "Drew"
add 0
save 0
set "Hello, "
add 0
save 0
class BasicMachine
attr_reader :registers
def initialize(&block)
instance_eval &block if block_given?
end
def [](register)
if register.raw?
register
elsif @registers && @registers[register]
@registers[register]
else
raise "No such register `#{register}` for #{self.inspect}:#{self.class}"
end
end
def []=(register, val)
@registers ||= {}
@registers[register] = val
end
end
module Instructions
def self.included(mod)
mod.extend self
end
def self.extended(mod)
mod.send(:extend, ClassMethods)
mod.send(:include, InstanceMethods)
end
module ClassMethods
def instructions(instructions)
@instructions = instructions
self
end
end
module InstanceMethods
def eval_instruction(ins, *args)
instructions = self.class.instance_variable_get(:@instructions)
if instructions[ins]
send instructions[ins], *args
else
raise NoMethodError.new("undefined instruction `#{ins}` for #{self.inspect}:#{self.class}", ins, args)
end
end
def eval_instructions(instructions)
instructions.map do |ins|
eval_instruction *ins
end
end
end
end
class Machine < BasicMachine
include Instructions
instructions 0 => :set,
# math
1 => :add,
# array
2 => :array,
3 => :push,
# sub-routines
4 => :call,
5 => :sub
def set(reg, val = nil)
if reg.is_a? Hash
reg.each { |key, val| self[key] = val }
else
self[reg] = val
end
self
end
def add(orig, mod)
self[orig] += self[mod]
self
end
def push(arr, register)
self[arr].push self[register]
self
end
def array(reg)
self[reg] = []
self
end
def call(method, args)
instance_exec(*self[args], &self[method])
self
end
def sub(register, &block)
set register => block
self
end
end
module Raw
$define_proxy_class = proc do
::Object.method(:instance_methods).unbind.bind(self).call.each { |name| undef_method name }
def initialize(o)
@o = o
end
def o; @o; end
def raw?; true; end
def method_missing(*args) @o.send *args; end
end
class Object < BasicObject; end
class String < Object; instance_eval &$define_proxy_class; end
class Numeric < Object; instance_eval &$define_proxy_class; end
Array = Class.new &$define_proxy_class
end
class Object
def raw?; false; end
end
def raw(o)
if o.raw?
o
else
if o.is_a? Numeric
Raw::Numeric.new o
elsif o.is_a? String
Raw::String.new o
elsif o.is_a? Array
Raw::Array.new o
end
end
end
def reg(o)
if o.is_a? Raw::Object
o.o
else
o
end
end
machine = Machine.new do
sub :hello do |name|
set result: "Hello, #{name}!!!"
end
call :hello, raw([ "Drew" ])
puts self[:result]
end
puts machine.registers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment