Skip to content

Instantly share code, notes, and snippets.

@seki
Created May 27, 2018 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seki/159f840ba3ffb775c868ce07070e2cfb to your computer and use it in GitHub Desktop.
Save seki/159f840ba3ffb775c868ce07070e2cfb to your computer and use it in GitHub Desktop.
MinRuby with Rinda
write("fact", 1, 1)
n = 2
while n <= 10
eval("fact", n, take("fact", n - 1, nil)[2] * n)
n = n + 1
end
p take("fact", 10, nil)
require 'drb/drb'
require 'rinda/tuplespace'
def spawn_worker
p "spawn"
system("ruby -I. rinda_interp.rb &")
end
ts = Rinda::TupleSpace.new
DRb.start_service('drbunix:/tmp/my_ts', ts)
Thread.new do
while true
it = ts.take([:ts_eval, nil, nil, nil, nil])
it[0] = :ts_call
ts.write(it)
spawn_worker
end
end
ts.take([:quit])
require "drb/drb"
require "rinda/tuplespace"
require "securerandom"
$ts = DRbObject.new_with_uri('drbunix:/tmp/my_ts')
def ts_take(*ary)
$ts.take(ary)
end
def ts_read(*ary)
$ts.read(ary)
end
def ts_write(*ary)
$ts.write(ary)
ary
end
def ts_eval(genv, lenv, tree)
new_tree = ["func_call", "ts_do_eval", ["lit", [genv, lenv, tree]]]
$ts.write([:ts_eval, nil, genv, lenv, new_tree])
end
def ts_do_eval(context)
genv, lenv, args = context
keys = args.collect do |tree|
case tree[0]
when "lit"
tree
when "var_ref"
["lit", lenv[tree[1]]]
else
key = SecureRandom.random_number(1 << 64)
$ts.write([:ts_eval, key, genv, lenv, tree])
[:ts_eval, key]
end
end
tuple = keys.collect do |tree_or_key|
case tree_or_key[0]
when "lit"
tree_or_key[1]
else
_, _, value = $ts.take([:ts_done, tree_or_key[1], nil])
value
end
end
$ts.write(tuple)
true
end
def ts_load()
if ARGV.size == 0
_, req, genv, lenv, tree = $ts.take([:ts_call, nil, nil, nil, nil])
[req, genv, lenv, tree]
else
nil
end
end
def ts_result(req, value)
if req
$ts.write([:ts_done, req, value])
end
end
def check(size, board, q, col)
k = 0
succ = true
while k < col
case board[k] - q
when 0
succ = false
k = col
when col - k
succ = false
k = col
when k - col
succ = false
k = col
else
end
k = k + 1
end
succ
end
def nq(size, board, col)
if size == col
1
else
found = 0
q = 0
while q < size
if check(size, board, q, col)
board[col] = q
found = found + nq(size, board, col + 1)
end
q = q + 1
end
found
end
end
def nq2(size, q)
p ["nq2", size, q]
if check(size, [], q, 0)
nq(size, [q], 1)
else
0
end
end
size = 10
n = 0
while n < size
eval("nq2", size, n, nq2(size, n))
n = n + 1
end
n = 0
found = 0
while n < size
found = found + take("nq2", size, n, nil)[3]
n = n + 1
end
p found
require "minruby"
require "my_rinda"
def mark_tail(tree, genv)
case tree && tree[0]
when "func_call"
mhd = genv[tree[1]]
if mhd == nil || mhd[0] == "user_defined"
p ["tail", tree[1]]
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)
case tree && 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)
elsif tree[3]
evaluate(tree[3], genv, lenv)
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)
elsif mhd[0] == "quote_builtin"
args = []
i = 0
while tree[i + 2]
args[i] = tree[i + 2]
i = i + 1
end
minruby_call(mhd[1], [genv, lenv, 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
context = ts_load()
if context
value = evaluate(context[3], context[1], context[2])
ts_result(context[0], value)
else
str = minruby_load()
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"],
"ts_load" => ["builtin", "ts_load"],
"ts_result" => ["builtin", "ts_load"],
"eval" => ["quote_builtin", "ts_eval"],
"ts_do_eval" => ["builtin", "ts_do_eval"],
"read" => ["builtin", "ts_read"],
"take" => ["builtin", "ts_take"],
"write" => ["builtin", "ts_write"]
}
lenv = {}
evaluate(tree, genv, lenv)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment