Skip to content

Instantly share code, notes, and snippets.

@seki
Last active April 30, 2018 16:56
Show Gist options
  • Save seki/fe689be12330888d48f9a542ef02de87 to your computer and use it in GitHub Desktop.
Save seki/fe689be12330888d48f9a542ef02de87 to your computer and use it in GitHub Desktop.
minruby + STM
require 'my_drip'
MyDrip.invoke
def root
Root.new
end
class Root
class VersionMismatchError < RuntimeError; end
def initialize
@visited = {}
end
def visited
@visited.collect do |key, age|
[key, age]
end
end
def [](key)
found ,= MyDrip.head(1, key)
age, value, = found
@visited[key] = age || 0
value
end
def []=(key, value)
it = MyDrip.write_if_latest(visited, value, key)
raise(VersionMismatchError) if it.nil?
@visited[key] = it
value
end
end
require "minruby"
require "root"
def mark_tail(tree, genv)
case tree && tree[0]
when "func_call"
mhd = genv[tree[1]]
if mhd == nil || mhd[0] == "user_defined"
tree[0] = "tail"
end
when "stmts"
mark_tail(tree[-1], genv)
when "if"
mark_tail(tree[2], genv)
mark_tail(tree[3], genv)
end
end
def evaluate(tree, genv, lenv)
sleep(rand * 0.3)
case tree[0]
when "lit"
tree[1]
when "+"
evaluate(tree[1], genv, lenv) + evaluate(tree[2], genv, lenv)
when "-"
evaluate(tree[1], genv, lenv) - evaluate(tree[2], genv, lenv)
when "*"
evaluate(tree[1], genv, lenv) * evaluate(tree[2], genv, lenv)
when "/"
evaluate(tree[1], genv, lenv) / evaluate(tree[2], genv, lenv)
when "%"
evaluate(tree[1], genv, lenv) % evaluate(tree[2], genv, lenv)
when "<"
evaluate(tree[1], genv, lenv) < evaluate(tree[2], genv, lenv)
when "<="
evaluate(tree[1], genv, lenv) <= evaluate(tree[2], genv, lenv)
when "=="
evaluate(tree[1], genv, lenv) == evaluate(tree[2], genv, lenv)
when "!="
evaluate(tree[1], genv, lenv) != evaluate(tree[2], genv, lenv)
when ">="
evaluate(tree[1], genv, lenv) >= evaluate(tree[2], genv, lenv)
when ">"
evaluate(tree[1], genv, lenv) > evaluate(tree[2], genv, lenv)
when "||"
evaluate(tree[1], genv, lenv) || evaluate(tree[2], genv, lenv)
when "&&"
evaluate(tree[1], genv, lenv) && evaluate(tree[2], genv, lenv)
when "stmts"
i = 1
last = nil
while tree[i]
last = evaluate(tree[i], genv, lenv)
i = i + 1
end
last
when "var_assign"
lenv[tree[1]] = evaluate(tree[2], genv, lenv)
when "var_ref"
lenv[tree[1]]
when "if"
if evaluate(tree[1], genv, lenv)
evaluate(tree[2], genv, lenv)
else
if tree[3]
evaluate(tree[3], genv, lenv)
end
end
when "while"
while evaluate(tree[1], genv, lenv)
evaluate(tree[2], genv, lenv)
end
when "tail"
mhd = genv[tree[1]]
new_lenv = {}
params = mhd[1]
i = 0
while params[i]
new_lenv[params[i]] = evaluate(tree[i + 2], genv, lenv)
i = i + 1
end
genv["(jump)"] = [new_lenv, mhd[2]]
true
when "func_def"
mark_tail(tree[3], genv)
genv[tree[1]] = ["user_defined", tree[2], tree[3]]
when "func_call"
mhd = genv[tree[1]]
if mhd[0] == "builtin"
args = []
i = 0
while tree[i + 2]
args[i] = evaluate(tree[i + 2], genv, lenv)
i = i + 1
end
minruby_call(mhd[1], args)
else
new_lenv = {}
params = mhd[1]
i = 0
while params[i]
new_lenv[params[i]] = evaluate(tree[i + 2], genv, lenv)
i = i + 1
end
last = evaluate(mhd[2], genv, new_lenv)
while genv["(jump)"]
new_lenv = genv["(jump)"][0]
jump = genv["(jump)"][1]
genv["(jump)"] = nil
last = evaluate(jump, genv, new_lenv)
end
last
end
when "ary_new"
ary = []
i = 0
while tree[i + 1]
ary[i] = evaluate(tree[i + 1], genv, lenv)
i = i + 1
end
ary
when "ary_ref"
ary = evaluate(tree[1], genv, lenv)
idx = evaluate(tree[2], genv, lenv)
ary[idx]
when "ary_assign"
ary = evaluate(tree[1], genv, lenv)
idx = evaluate(tree[2], genv, lenv)
val = evaluate(tree[3], genv, lenv)
ary[idx] = val
when "hash_new"
hsh = {}
i = 0
while tree[i + 1]
key = evaluate(tree[i + 1], genv, lenv)
val = evaluate(tree[i + 2], genv, lenv)
hsh[key] = val
i = i + 2
end
hsh
end
end
str = minruby_load()
begin
tree = minruby_parse(str)
genv = {
"p" => ["builtin", "p"],
"require" => ["builtin", "require"],
"minruby_parse" => ["builtin", "minruby_parse"],
"minruby_load" => ["builtin", "minruby_load"],
"minruby_call" => ["builtin", "minruby_call"],
"root" => ["builtin", "root"]
}
lenv = {
}
evaluate(tree, genv, lenv)
rescue Root::VersionMismatchError
p :retry
retry
end
db = root()
count = db['count'] = db['count'] + 1
p count
db = root()
n = 10
while n > 0
count = db['count'] = db['count'] + 1
p [count, n]
n = n - 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment