Module: Ea::Ocl::Evaluator

Defined in:
lib/ea/ocl/evaluator.rb

Overview

Evaluates an AST produced by Parser against a context object (the model element under test). Dispatches on node class.

Defined Under Namespace

Classes: VarBinding

Class Method Summary collapse

Class Method Details

.attribute_value(context, name) ⇒ Object



28
29
30
31
32
# File 'lib/ea/ocl/evaluator.rb', line 28

def attribute_value(context, name)
  return nil unless context

  context.public_send(name)
end

.eval_binary(ast, context) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/ea/ocl/evaluator.rb', line 61

def eval_binary(ast, context)
  left = evaluate(ast.left, context)
  right = evaluate(ast.right, context)
  case ast.op
  when :and then left && right
  when :or then left || right
  else raise UnsupportedError, "Unknown binary op: #{ast.op}"
  end
end

.eval_exists(ast, context) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/ea/ocl/evaluator.rb', line 39

def eval_exists(ast, context)
  collection = evaluate(ast.collection, context)
  return false unless collection.is_a?(Array)

  var_name = ast.var
  predicate = ast.predicate
  collection.any? do |element|
    evaluate(predicate, var_binding(context, var_name, element))
  end
end

.eval_for_all(ast, context) ⇒ Object



50
51
52
53
54
55
56
57
58
59
# File 'lib/ea/ocl/evaluator.rb', line 50

def eval_for_all(ast, context)
  collection = evaluate(ast.collection, context)
  return true unless collection.is_a?(Array)

  var_name = ast.var
  predicate = ast.predicate
  collection.all? do |element|
    evaluate(predicate, var_binding(context, var_name, element))
  end
end

.eval_string_matches(ast, context) ⇒ Object



34
35
36
37
# File 'lib/ea/ocl/evaluator.rb', line 34

def eval_string_matches(ast, context)
  target = evaluate(ast.string, context).to_s
  Regexp.new(ast.pattern).match?(target)
end

.eval_unary(ast, context) ⇒ Object



71
72
73
74
75
76
# File 'lib/ea/ocl/evaluator.rb', line 71

def eval_unary(ast, context)
  case ast.op
  when :not then !evaluate(ast.operand, context)
  else raise UnsupportedError, "Unknown unary op: #{ast.op}"
  end
end

.evaluate(ast, context) ⇒ Boolean, Object

Returns result of evaluation.

Parameters:

  • ast (Nodes::*)
  • context (Object)

    the model element (self)

Returns:

  • (Boolean, Object)

    result of evaluation



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/ea/ocl/evaluator.rb', line 13

def evaluate(ast, context)
  case ast
  when Nodes::Literal then ast.value
  when Nodes::AttributeAccess then attribute_value(context, ast.name)
  when Nodes::StringMatches then eval_string_matches(ast, context)
  when Nodes::CollectionExists then eval_exists(ast, context)
  when Nodes::CollectionForAll then eval_for_all(ast, context)
  when Nodes::BinaryOp then eval_binary(ast, context)
  when Nodes::UnaryOp then eval_unary(ast, context)
  else
    raise UnsupportedError,
          "Cannot evaluate AST node: #{ast.class}"
  end
end

.var_binding(context, var_name, value) ⇒ Object



89
90
91
# File 'lib/ea/ocl/evaluator.rb', line 89

def var_binding(context, var_name, value)
  VarBinding.new(context: context, var_name: var_name, value: value)
end