Class: Keisan::AST::Operator

Inherits:
Parent show all
Defined in:
lib/keisan/ast/operator.rb

Constant Summary collapse

ARITY_PRIORITY_ASSOCIATIVITY =

NOTE: operators with same priority must have same associativity

{
  "u!": [1, 100, :right],  # Logical not
  "u~": [1, 100, :right],  # Bitwise not
  "u+": [1, 100, :right],  # Unary plus
  "**": [2,  95, :right],  # Exponent
  "u-": [1,  90, :right],  # Unary minus
  "*":  [2,  85, :left],   # Times
  # "/":  [2,  85, :left], # Divide
  "%":  [2,  85, :left],   # Modulo
  "+":  [2,  80, :left],   # Plus
  # "-":  [2,  80, :left], # Minus
  "&":  [2,  70, :left],   # Bitwise and
  "^":  [2,  65, :left],   # Bitwise xor
  "|":  [2,  65, :left],   # Bitwise or
  ">":  [2,  60, :left],   # Greater than
  ">=": [2,  60, :left],   # Greater than or equal to
  "<":  [2,  60, :left],   # Less than
  "<=": [2,  60, :left],   # Less than or equal to
  "==": [2,  55, :none],   # Equal
  "!=": [2,  55, :none],   # Not equal
  "&&": [2,  50, :left],   # Logical and
  "||": [2,  45, :left],   # Logical or
  "=":  [2,  40, :right] # TODO: handle and test
}.freeze
ARITIES =
Hash[ARITY_PRIORITY_ASSOCIATIVITY.map {|sym, ary| [sym, ary[0]]}].freeze
PRIORITIES =
Hash[ARITY_PRIORITY_ASSOCIATIVITY.map {|sym, ary| [sym, ary[1]]}].freeze
ASSOCIATIVITIES =
Hash[ARITY_PRIORITY_ASSOCIATIVITY.map {|sym, ary| [sym, ary[2]]}].freeze
ASSOCIATIVITY_OF_PRIORITY =
ARITY_PRIORITY_ASSOCIATIVITY.inject({}) do |h, (symbol,arity_priority_associativity)|
  h[arity_priority_associativity[1]] = arity_priority_associativity[2]
  h
end.freeze

Instance Attribute Summary

Attributes inherited from Parent

#children

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Parent

#==, #deep_dup, #evaluate, #freeze, #replace, #simplify, #unbound_functions, #unbound_variables

Methods inherited from Node

#!, #%, #&, #*, #**, #+, #+@, #-, #-@, #/, #<, #<=, #>, #>=, #^, #and, #coerce, #deep_dup, #differentiate, #equal, #evaluate, #evaluated, #false?, #not_equal, #or, #replace, #simplified, #simplify, #to_cell, #to_node, #true?, #unbound_functions, #unbound_variables, #well_defined?, #|, #~

Constructor Details

#initialize(children = [], parsing_operators = []) ⇒ Operator

Returns a new instance of Operator.



39
40
41
42
43
44
45
46
47
48
# File 'lib/keisan/ast/operator.rb', line 39

def initialize(children = [], parsing_operators = [])
  unless parsing_operators.empty? || children.count == parsing_operators.count + 1
    raise Exceptions::ASTError.new("Mismatch of children and operators")
  end

  children = Array.wrap(children)
  super(children)

  @parsing_operators = parsing_operators
end

Class Method Details

.arityObject



66
67
68
# File 'lib/keisan/ast/operator.rb', line 66

def self.arity
  ARITIES[symbol]
end

.associativityObject



82
83
84
# File 'lib/keisan/ast/operator.rb', line 82

def self.associativity
  ASSOCIATIVITIES[symbol]
end

.associativity_of_priority(priority) ⇒ Object



58
59
60
# File 'lib/keisan/ast/operator.rb', line 58

def self.associativity_of_priority(priority)
  ASSOCIATIVITY_OF_PRIORITY[priority]
end

.priorityObject



74
75
76
# File 'lib/keisan/ast/operator.rb', line 74

def self.priority
  PRIORITIES[symbol]
end

.symbolObject



90
91
92
# File 'lib/keisan/ast/operator.rb', line 90

def self.symbol
  raise Exceptions::NotImplementedError.new
end

Instance Method Details

#arityObject



62
63
64
# File 'lib/keisan/ast/operator.rb', line 62

def arity
  self.class.arity
end

#associativityObject



78
79
80
# File 'lib/keisan/ast/operator.rb', line 78

def associativity
  self.class.associativity
end

#blank_valueObject



94
95
96
# File 'lib/keisan/ast/operator.rb', line 94

def blank_value
  raise Exceptions::NotImplementedError.new
end

#evaluate_assignments(context = nil) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/keisan/ast/operator.rb', line 50

def evaluate_assignments(context = nil)
  context ||= Context.new
  @children = children.map do |child|
    child.evaluate_assignments(context)
  end
  self
end

#priorityObject



70
71
72
# File 'lib/keisan/ast/operator.rb', line 70

def priority
  self.class.priority
end

#symbolObject



86
87
88
# File 'lib/keisan/ast/operator.rb', line 86

def symbol
  self.class.symbol
end

#to_sObject



111
112
113
114
115
116
117
118
119
120
# File 'lib/keisan/ast/operator.rb', line 111

def to_s
  children.map do |child|
    case child
    when Operator
      "(#{child.to_s})"
    else
      "#{child.to_s}"
    end
  end.join(symbol.to_s)
end

#value(context = nil) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/keisan/ast/operator.rb', line 98

def value(context = nil)
  args = children
  args = args.reverse if associativity == :right

  args.inject(blank_value) do |result, child|
    if associativity == :left
      result.send(symbol, child.value(context))
    else
      child.value(context).send(symbol, result)
    end
  end
end