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

Returns a new instance of Context.



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

def initialize(parent: nil,
               random: nil,
               allow_recursive: false,
               allow_multiline: true,
               allow_blocks: true,
               allow_random: 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
  @allow_random      = allow_random
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_randomObject (readonly)

Returns the value of attribute allow_random.



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

def allow_random
  @allow_random
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



27
28
29
# File 'lib/keisan/context.rb', line 27

def allow_recursive!
  @allow_recursive = true
end

#freezeObject



31
32
33
34
35
# File 'lib/keisan/context.rb', line 31

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

#function(name) ⇒ Object



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

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

#function_is_modifiable?(name) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/keisan/context.rb', line 104

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

#has_function?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#has_variable?(name) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#randomObject



116
117
118
119
# File 'lib/keisan/context.rb', line 116

def random
  raise Keisan::Exceptions::InvalidExpression.new("Context does not permit expressions with randomness") unless allow_random
  @random ||= @parent&.random || Random.new
end

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



108
109
110
111
112
113
114
# File 'lib/keisan/context.rb', line 108

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



88
89
90
91
92
93
94
# File 'lib/keisan/context.rb', line 88

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

#set_random(random) ⇒ Object



121
122
123
124
# File 'lib/keisan/context.rb', line 121

def set_random(random)
  raise Keisan::Exceptions::InvalidExpression.new("Context does not permit expressions with randomness") unless allow_random
  @random = random
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.



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

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)


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

def transient?
  !!@transient
end

#transient_definitionsObject



62
63
64
65
66
67
68
69
70
# File 'lib/keisan/context.rb', line 62

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



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

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

#variable_is_modifiable?(name) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/keisan/context.rb', line 84

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