Class: Tr8n::RulesEngine::Evaluator
- Inherits:
-
Object
- Object
- Tr8n::RulesEngine::Evaluator
- Defined in:
- lib/tr8n/rules_engine/evaluator.rb
Instance Attribute Summary collapse
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#vars ⇒ Object
readonly
Returns the value of attribute vars.
Instance Method Summary collapse
- #apply(fn, args) ⇒ Object
- #evaluate(expr) ⇒ Object
-
#initialize ⇒ Evaluator
constructor
A new instance of Evaluator.
- #regexp_from_string(str) ⇒ Object
- #reset! ⇒ Object
Constructor Details
#initialize ⇒ Evaluator
Returns a new instance of Evaluator.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/tr8n/rules_engine/evaluator.rb', line 31 def initialize @vars = {} @env = { # McCarthy's Elementary S-functions and Predicates 'label' => lambda { |l, r| @vars[l] = r }, 'quote' => lambda { |expr| expr }, 'car' => lambda { |list| list[1] }, 'cdr' => lambda { |list| list.drop(1) }, 'cons' => lambda { |e, cell| [e] + cell }, 'eq' => lambda { |l, r| l == r }, 'atom' => lambda { |expr| [Symbol, String, Fixnum, Float].include?(expr.class) }, 'cond' => lambda { |c, t, f| evaluate(c) ? evaluate(t) : evaluate(f) }, # Tr8n Extensions '=' => lambda { |l, r| l == r }, # ['=', 1, 2] '!=' => lambda { |l, r| l != r }, # ['!=', 1, 2] '<' => lambda { |l, r| l < r }, # ['<', 1, 2] '>' => lambda { |l, r| l > r }, # ['>', 1, 2] '+' => lambda { |l, r| l + r }, # ['+', 1, 2] '-' => lambda { |l, r| l - r }, # ['-', 1, 2] '*' => lambda { |l, r| l * r }, # ['*', 1, 2] '%' => lambda { |l, r| l % r }, # ['%', 14, 10] 'mod' => lambda { |l, r| l % r }, # ['mod', '@n', 10] '/' => lambda { |l, r| (l * 1.0) / r }, # ['/', 1, 2] '!' => lambda { |expr| not expr }, # ['!', ['true']] 'not' => lambda { |val| not val }, # ['not', ['true']] '&&' => lambda { |*expr| expr.all?{|e| evaluate(e)} }, # ['&&', [], [], ...] 'and' => lambda { |*expr| expr.all?{|e| evaluate(e)} }, # ['and', [], [], ...] '||' => lambda { |*expr| expr.any?{|e| evaluate(e)} }, # ['||', [], [], ...] 'or' => lambda { |*expr| expr.any?{|e| evaluate(e)} }, # ['or', [], [], ...] 'if' => lambda { |c, t, f| evaluate(c) ? evaluate(t) : evaluate(f) }, # ['if', 'cond', 'true', 'false'] 'let' => lambda { |l, r| @vars[l] = r }, # ['let', 'n', 5] 'true' => lambda { true }, # ['true'] 'false' => lambda { false }, # ['false'] 'date' => lambda { |date| Date.strptime(date, '%Y-%m-%d') }, # ['date', '2010-01-01'] 'today' => lambda { Time.now.to_date }, # ['today'] 'time' => lambda { |expr| Time.strptime(expr, '%Y-%m-%d %H:%M:%S') }, # ['time', '2010-01-01 10:10:05'] 'now' => lambda { Time.now }, # ['now'] 'append' => lambda { |l, r| r.to_s + l.to_s }, # ['append', 'world', 'hello '] 'prepend' => lambda { |l, r| l.to_s + r.to_s }, # ['prepend', 'hello ', 'world'] 'match' => lambda { |search, subject| # ['match', /a/, 'abc'] search = regexp_from_string(search) not search.match(subject).nil? }, 'in' => lambda { |values, search| # ['in', '1,2,3,5..10,20..24', '@n'] search = search.to_s.strip values.split(',').each do |e| if e.index('..') bounds = e.strip.split('..') return true if (bounds.first.strip..bounds.last.strip).include?(search) end return true if e.strip == search end false }, 'within' => lambda { |values, search| # ['within', '0..3', '@n'] bounds = values.split('..').map{|d| Integer(d)} (bounds.first..bounds.last).include?(search) }, 'replace' => lambda { |search, replace, subject| # ['replace', '/^a/', 'v', 'abc'] # handle regular expression if /\/i$/.match(search) replace = replace.gsub(/\$(\d+)/, '\\\\\1') # for compatibility with Perl notation end search = regexp_from_string(search) subject.gsub(search, replace) }, 'count' => lambda { |list| # ['count', '@genders'] (list.is_a?(String) ? vars[list] : list).count }, 'all' => lambda { |list, value| # ['all', '@genders', 'male'] list = (list.is_a?(String) ? vars[list] : list) list.is_a?(Array) ? list.all?{|e| e == value} : false }, 'any' => lambda { |list, value| # ['any', '@genders', 'female'] list = (list.is_a?(String) ? vars[list] : list) list.is_a?(Array) ? list.any?{|e| e == value} : false }, } end |
Instance Attribute Details
#env ⇒ Object (readonly)
Returns the value of attribute env.
29 30 31 |
# File 'lib/tr8n/rules_engine/evaluator.rb', line 29 def env @env end |
#vars ⇒ Object (readonly)
Returns the value of attribute vars.
29 30 31 |
# File 'lib/tr8n/rules_engine/evaluator.rb', line 29 def vars @vars end |
Instance Method Details
#apply(fn, args) ⇒ Object
132 133 134 135 |
# File 'lib/tr8n/rules_engine/evaluator.rb', line 132 def apply(fn, args) raise "undefined symbols #{fn}" unless @env.keys.include?(fn) @env[fn].call(*args) end |
#evaluate(expr) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/tr8n/rules_engine/evaluator.rb', line 137 def evaluate(expr) if @env['atom'].call(expr) return @vars[expr] if expr.is_a?(String) and @vars[expr] return expr end fn = expr[0] args = expr.drop(1) unless ['quote', 'car', 'cdr', 'cond', 'if', '&&', '||', 'and', 'or', 'true', 'false', 'let', 'count', 'all', 'any'].member?(fn) args = args.map { |a| self.evaluate(a) } end apply(fn, args) end |
#regexp_from_string(str) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/tr8n/rules_engine/evaluator.rb', line 114 def regexp_from_string(str) return Regexp.new(/#{str}/) unless /^\//.match(str) str = str.gsub(/^\//, '') if /\/i$/.match(str) str = str.gsub(/\/i$/, '') return Regexp.new(/#{str}/i) end str = str.gsub(/\/$/, '') Regexp.new(/#{str}/) end |
#reset! ⇒ Object
128 129 130 |
# File 'lib/tr8n/rules_engine/evaluator.rb', line 128 def reset! @vars = {} end |