Class: Keisan::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/keisan/context.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent: nil, random: nil, allow_recursive: false, shadowed: []) ⇒ Context

Returns a new instance of Context.



5
6
7
8
9
10
11
# File 'lib/keisan/context.rb', line 5

def initialize(parent: nil, random: nil, allow_recursive: false, shadowed: [])
  @parent = parent
  @function_registry = Functions::Registry.new(parent: @parent.try(:function_registry))
  @variable_registry = Variables::Registry.new(parent: @parent.try(:variable_registry), shadowed: shadowed)
  @random            = random
  @allow_recursive   = allow_recursive
end

Instance Attribute Details

#allow_recursiveObject (readonly)

Returns the value of attribute allow_recursive.



3
4
5
# File 'lib/keisan/context.rb', line 3

def allow_recursive
  @allow_recursive
end

#function_registryObject (readonly)

Returns the value of attribute function_registry.



3
4
5
# File 'lib/keisan/context.rb', line 3

def function_registry
  @function_registry
end

#variable_registryObject (readonly)

Returns the value of attribute variable_registry.



3
4
5
# File 'lib/keisan/context.rb', line 3

def variable_registry
  @variable_registry
end

Instance Method Details

#allow_recursive!Object



13
14
15
# File 'lib/keisan/context.rb', line 13

def allow_recursive!
  @allow_recursive = true
end

#freezeObject



17
18
19
20
21
# File 'lib/keisan/context.rb', line 17

def freeze
  super
  @function_registry.freeze
  @variable_registry.freeze
end

#function(name) ⇒ Object



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

def function(name)
  @function_registry[name.to_s]
end

#function_is_modifiable?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

def function_is_modifiable?(name)
  @function_registry.modifiable?(name)
end

#has_function?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

def has_function?(name)
  @function_registry.has?(name)
end

#has_variable?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

def has_variable?(name)
  @variable_registry.has?(name)
end

#randomObject



102
103
104
# File 'lib/keisan/context.rb', line 102

def random
  @random || @parent.try(:random) || Random.new
end

#register_function!(name, function, local: false) ⇒ Object



94
95
96
97
98
99
100
# File 'lib/keisan/context.rb', line 94

def register_function!(name, function, local: false)
  if transient? || !local && @parent&.function_is_modifiable?(name)
    @parent.register_function!(name, function)
  else
    @function_registry.register!(name.to_s, function)
  end
end

#register_variable!(name, value, local: false) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/keisan/context.rb', line 74

def register_variable!(name, value, local: false)
  if !@variable_registry.shadowed.member?(name) && (transient? || !local && @parent&.variable_is_modifiable?(name))
    @parent.register_variable!(name, value)
  else
    @variable_registry.register!(name, value)
  end
end

#spawn_child(definitions: {}, shadowed: [], transient: nil) ⇒ Object

A transient context does not persist variables and functions in this context, but rather store them one level higher in the parent context. When evaluating a string, the entire operation is done in a transient context that is unique from the calculators current context, but such that variable/function definitions can be persisted in the calculator.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/keisan/context.rb', line 28

def spawn_child(definitions: {}, shadowed: [], transient: nil)
  child = pure_child(shadowed: shadowed)

  definitions.each do |name, value|
    case value
    when Proc
      child.register_function!(name, value)
    when Functions::ProcFunction
      child.register_function!(name, value.function_proc)
    else
      child.register_variable!(name, value)
    end
  end

  if transient.nil? && self.transient? || transient == true
    child.set_transient!
  end
  child
end

#transient?Boolean

Returns:

  • (Boolean)


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

def transient?
  !!@transient
end

#transient_definitionsObject



48
49
50
51
52
53
54
55
56
# File 'lib/keisan/context.rb', line 48

def transient_definitions
  return {} unless @transient
  parent_definitions = @parent.present? ? @parent.transient_definitions : {}
  parent_definitions.merge(
    @variable_registry.locals
  ).merge(
    @function_registry.locals
  )
end

#variable(name) ⇒ Object



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

def variable(name)
  @variable_registry[name.to_s]
end

#variable_is_modifiable?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

def variable_is_modifiable?(name)
  @variable_registry.modifiable?(name)
end