69 lines
1.2 KiB
Ruby
69 lines
1.2 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
require 'simp_rules'
|
||
|
|
||
|
# TODO: natural numbers :)
|
||
|
# TODO: little lang that transpiles to ruby
|
||
|
|
||
|
# unnecessary if i standardize on parenthezing every binary op anyway!
|
||
|
def lispify(bla)
|
||
|
if bla.is_a? Array
|
||
|
l = bla[0]
|
||
|
op = bla[1]
|
||
|
r = bla[2]
|
||
|
[op, [lispify(l), lispify(r)]]
|
||
|
else
|
||
|
bla
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# doesn't account for actually important stuff, gonna need to do equal'
|
||
|
def simp_rule(); end
|
||
|
|
||
|
def simp(expr, rules = SIMP_RULES, limit: 413)
|
||
|
expr = expr.dup
|
||
|
|
||
|
limit.times do
|
||
|
rules.each do |rule|
|
||
|
expr = simp_single(expr, rule)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
expr
|
||
|
end
|
||
|
|
||
|
def simp_single(expr, rule)
|
||
|
if rule.concrete?
|
||
|
expr = simp_applied_rule(expr, rule)
|
||
|
else
|
||
|
targets = potential_rule_targets(expr)
|
||
|
targets.each do |target|
|
||
|
concrete_rule = rule.clone.concrete(target)
|
||
|
expr = simp_single(expr, concrete_rule)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
expr
|
||
|
end
|
||
|
|
||
|
def simp_applied_rule(expr, rule)
|
||
|
lhs = rule.lhs
|
||
|
rhs = rule.rhs
|
||
|
|
||
|
if expr == lhs
|
||
|
rhs
|
||
|
elsif expr.is_a? Array
|
||
|
expr.map { |expr| simp_applied_rule(expr, rule) }
|
||
|
else
|
||
|
expr
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def potential_rule_targets(expr)
|
||
|
if expr.is_a? Array
|
||
|
(expr + expr.flatten).uniq
|
||
|
else
|
||
|
[expr]
|
||
|
end
|
||
|
end
|