Class: Calculus::Expression

Inherits:
Object
  • Object
show all
Includes:
Latex
Defined in:
lib/calculus/expression.rb

Constant Summary

Constants included from Latex

Latex::TEMPLATE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Latex

#missing_commands, #to_png

Constructor Details

#initialize(source, options = {}) ⇒ Expression

Returns a new instance of Expression.

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
21
# File 'lib/calculus/expression.rb', line 14

def initialize(source, options = {})
  options = {:parse => true}.merge(options)
  @source = source
  @postfix_notation = options[:parse] ? Parser.new(source).parse : []
  raise ArgumentError, "Should be no more that one equals sign" if @postfix_notation.count(:eql) > 1
  @variables = extract_variables
  update_sha1
end

Instance Attribute Details

#postfix_notationObject (readonly) Also known as: rpn

Returns the value of attribute postfix_notation.



11
12
13
# File 'lib/calculus/expression.rb', line 11

def postfix_notation
  @postfix_notation
end

#sha1Object (readonly)

Returns the value of attribute sha1.



8
9
10
# File 'lib/calculus/expression.rb', line 8

def sha1
  @sha1
end

#sourceObject (readonly)

Returns the value of attribute source.



9
10
11
# File 'lib/calculus/expression.rb', line 9

def source
  @source
end

Instance Method Details

#[](name) ⇒ Object

Raises:

  • (ArgumentError)


35
36
37
38
# File 'lib/calculus/expression.rb', line 35

def [](name)
  raise ArgumentError, "No such variable defined: #{name}" unless @variables.keys.include?(name)
  @variables[name]
end

#[]=(name, value) ⇒ Object

Raises:

  • (ArgumentError)


40
41
42
43
44
# File 'lib/calculus/expression.rb', line 40

def []=(name, value)
  raise ArgumentError, "No such variable defined: #{name}" unless @variables.keys.include?(name)
  @variables[name] = value
  update_sha1
end

#abstract_syntax_treeObject Also known as: ast



82
83
84
85
86
# File 'lib/calculus/expression.rb', line 82

def abstract_syntax_tree
  traverse do |operation, left, right, stack|
    [operation, left, right]
  end
end

#calculateObject

Raises:

  • (NotImplementedError)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/calculus/expression.rb', line 62

def calculate
  raise NotImplementedError, "Equation detected. This class can't calculate equations yet." if equation?
  raise UnboundVariableError, "Can't calculate. Unbound variables found: #{unbound_variables.join(', ')}" unless unbound_variables.empty?

  traverse do |operation, left, right, stack|
    case operation
    when :sqrt  then left ** (1.0 / right) # could cause some rounding errors
    when :exp   then left ** right
    when :plus  then left + right
    when :minus then left - right
    when :mul   then left * right
    when :div   then left / right
    end
  end
end

#equation?Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/calculus/expression.rb', line 78

def equation?
  @postfix_notation.include?(:eql)
end

#inspectObject



100
101
102
# File 'lib/calculus/expression.rb', line 100

def inspect
  "#<Expression:#{@sha1} postfix_notation=#{@postfix_notation.inspect} variables=#{@variables.inspect}>"
end

#parsed?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/calculus/expression.rb', line 23

def parsed?
  !@postfix_notation.empty?
end

#to_sObject



89
90
91
92
93
94
95
96
97
98
# File 'lib/calculus/expression.rb', line 89

def to_s
  result = source.dup
  (variables - unbound_variables).each do |var|
    result.gsub!(/(\W)#{var}(\W)/, "\\1#{@variables[var]}\\2")
    result.gsub!(/^#{var}(\W)/, "#{@variables[var]}\\1")
    result.gsub!(/(\W)#{var}$/, "\\1#{@variables[var]}")
    result.gsub!(/^#{var}$/, @variables[var].to_s)
  end
  result
end

#traverse(&block) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/calculus/expression.rb', line 46

def traverse(&block)
  stack = []
  @postfix_notation.each do |node|
    case node
    when Symbol
      operation, right, left = node, stack.pop, stack.pop
      stack.push(yield(operation, left, right, stack))
    when Numeric
      stack.push(node)
    when String
      stack.push(@variables[node] || node)
    end
  end
  stack.pop
end

#unbound_variablesObject



31
32
33
# File 'lib/calculus/expression.rb', line 31

def unbound_variables
  @variables.keys.select{|k| @variables[k].nil?}
end

#variablesObject



27
28
29
# File 'lib/calculus/expression.rb', line 27

def variables
  @variables.keys
end