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, allow_multiline: true, allow_blocks: true, shadowed: []) ⇒ Context

Returns a new instance of Context.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/keisan/context.rb', line 9

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

Instance Attribute Details

#allow_blocksObject (readonly)

Returns the value of attribute allow_blocks.



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

def allow_blocks
  @allow_blocks
end

#allow_multilineObject (readonly)

Returns the value of attribute allow_multiline.



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

def allow_multiline
  @allow_multiline
end

#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



24
25
26
# File 'lib/keisan/context.rb', line 24

def allow_recursive!
  @allow_recursive = true
end

#freezeObject



28
29
30
31
32
# File 'lib/keisan/context.rb', line 28

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

#function(name) ⇒ Object



93
94
95
# File 'lib/keisan/context.rb', line 93

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

#function_is_modifiable?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#has_function?(name) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/keisan/context.rb', line 97

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

#has_variable?(name) ⇒ Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/keisan/context.rb', line 77

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

#randomObject



113
114
115
# File 'lib/keisan/context.rb', line 113

def random
  @random || @parent&.random || Random.new
end

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



105
106
107
108
109
110
111
# File 'lib/keisan/context.rb', line 105

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

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



85
86
87
88
89
90
91
# File 'lib/keisan/context.rb', line 85

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, local: local)
  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.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/keisan/context.rb', line 39

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)


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

def transient?
  !!@transient
end

#transient_definitionsObject



59
60
61
62
63
64
65
66
67
# File 'lib/keisan/context.rb', line 59

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

#variable(name) ⇒ Object



73
74
75
# File 'lib/keisan/context.rb', line 73

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

#variable_is_modifiable?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

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