keisan 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +49 -1
- data/keisan.gemspec +1 -0
- data/lib/keisan.rb +30 -0
- data/lib/keisan/ast/assignment.rb +44 -17
- data/lib/keisan/ast/block.rb +60 -0
- data/lib/keisan/ast/boolean.rb +5 -5
- data/lib/keisan/ast/builder.rb +10 -207
- data/lib/keisan/ast/cell.rb +60 -0
- data/lib/keisan/ast/constant_literal.rb +9 -0
- data/lib/keisan/ast/exponent.rb +6 -6
- data/lib/keisan/ast/function.rb +12 -8
- data/lib/keisan/ast/indexing.rb +25 -15
- data/lib/keisan/ast/line_builder.rb +230 -0
- data/lib/keisan/ast/list.rb +28 -1
- data/lib/keisan/ast/literal.rb +0 -8
- data/lib/keisan/ast/logical_and.rb +1 -1
- data/lib/keisan/ast/logical_or.rb +1 -1
- data/lib/keisan/ast/multi_line.rb +28 -0
- data/lib/keisan/ast/node.rb +32 -24
- data/lib/keisan/ast/number.rb +31 -31
- data/lib/keisan/ast/operator.rb +12 -4
- data/lib/keisan/ast/parent.rb +4 -4
- data/lib/keisan/ast/plus.rb +10 -10
- data/lib/keisan/ast/string.rb +3 -3
- data/lib/keisan/ast/times.rb +8 -8
- data/lib/keisan/ast/unary_identity.rb +1 -1
- data/lib/keisan/ast/unary_inverse.rb +7 -7
- data/lib/keisan/ast/unary_minus.rb +5 -5
- data/lib/keisan/ast/unary_operator.rb +2 -2
- data/lib/keisan/ast/unary_plus.rb +2 -2
- data/lib/keisan/ast/variable.rb +26 -10
- data/lib/keisan/context.rb +5 -5
- data/lib/keisan/evaluator.rb +15 -8
- data/lib/keisan/function.rb +24 -6
- data/lib/keisan/functions/cbrt.rb +1 -1
- data/lib/keisan/functions/cos.rb +1 -1
- data/lib/keisan/functions/cosh.rb +1 -1
- data/lib/keisan/functions/cot.rb +1 -1
- data/lib/keisan/functions/coth.rb +1 -1
- data/lib/keisan/functions/csc.rb +1 -1
- data/lib/keisan/functions/csch.rb +1 -1
- data/lib/keisan/functions/default_registry.rb +53 -74
- data/lib/keisan/functions/diff.rb +18 -14
- data/lib/keisan/functions/erf.rb +15 -0
- data/lib/keisan/functions/exp.rb +1 -1
- data/lib/keisan/functions/expression_function.rb +15 -21
- data/lib/keisan/functions/filter.rb +13 -15
- data/lib/keisan/functions/if.rb +14 -20
- data/lib/keisan/functions/let.rb +36 -0
- data/lib/keisan/functions/map.rb +11 -13
- data/lib/keisan/functions/math_function.rb +2 -2
- data/lib/keisan/functions/proc_function.rb +10 -6
- data/lib/keisan/functions/rand.rb +2 -1
- data/lib/keisan/functions/range.rb +74 -0
- data/lib/keisan/functions/reduce.rb +12 -14
- data/lib/keisan/functions/registry.rb +7 -7
- data/lib/keisan/functions/replace.rb +8 -8
- data/lib/keisan/functions/sample.rb +2 -1
- data/lib/keisan/functions/sec.rb +1 -1
- data/lib/keisan/functions/sech.rb +1 -1
- data/lib/keisan/functions/sin.rb +1 -1
- data/lib/keisan/functions/sinh.rb +1 -1
- data/lib/keisan/functions/sqrt.rb +1 -1
- data/lib/keisan/functions/tan.rb +1 -1
- data/lib/keisan/functions/tanh.rb +1 -1
- data/lib/keisan/functions/while.rb +46 -0
- data/lib/keisan/parser.rb +121 -79
- data/lib/keisan/parsing/assignment.rb +1 -1
- data/lib/keisan/parsing/bitwise_and.rb +1 -1
- data/lib/keisan/parsing/bitwise_not.rb +1 -1
- data/lib/keisan/parsing/bitwise_not_not.rb +1 -1
- data/lib/keisan/parsing/bitwise_or.rb +1 -1
- data/lib/keisan/parsing/bitwise_xor.rb +1 -1
- data/lib/keisan/parsing/curly_group.rb +6 -0
- data/lib/keisan/parsing/divide.rb +1 -1
- data/lib/keisan/parsing/exponent.rb +1 -1
- data/lib/keisan/parsing/function.rb +1 -1
- data/lib/keisan/parsing/group.rb +1 -1
- data/lib/keisan/parsing/indexing.rb +1 -1
- data/lib/keisan/parsing/line_separator.rb +6 -0
- data/lib/keisan/parsing/logical_and.rb +1 -1
- data/lib/keisan/parsing/logical_equal.rb +1 -1
- data/lib/keisan/parsing/logical_greater_than.rb +1 -1
- data/lib/keisan/parsing/logical_greater_than_or_equal_to.rb +1 -1
- data/lib/keisan/parsing/logical_less_than.rb +1 -1
- data/lib/keisan/parsing/logical_less_than_or_equal_to.rb +1 -1
- data/lib/keisan/parsing/logical_not.rb +1 -1
- data/lib/keisan/parsing/logical_not_equal.rb +1 -1
- data/lib/keisan/parsing/logical_not_not.rb +1 -1
- data/lib/keisan/parsing/logical_or.rb +1 -1
- data/lib/keisan/parsing/minus.rb +1 -1
- data/lib/keisan/parsing/modulo.rb +1 -1
- data/lib/keisan/parsing/operator.rb +1 -1
- data/lib/keisan/parsing/plus.rb +1 -1
- data/lib/keisan/parsing/times.rb +1 -1
- data/lib/keisan/parsing/unary_minus.rb +1 -1
- data/lib/keisan/parsing/unary_operator.rb +1 -1
- data/lib/keisan/parsing/unary_plus.rb +1 -1
- data/lib/keisan/repl.rb +1 -1
- data/lib/keisan/tokenizer.rb +4 -9
- data/lib/keisan/tokens/group.rb +3 -1
- data/lib/keisan/tokens/line_separator.rb +11 -0
- data/lib/keisan/variables/default_registry.rb +0 -5
- data/lib/keisan/variables/registry.rb +7 -7
- data/lib/keisan/version.rb +1 -1
- metadata +27 -2
data/lib/keisan/functions/cos.rb
CHANGED
data/lib/keisan/functions/cot.rb
CHANGED
data/lib/keisan/functions/csc.rb
CHANGED
@@ -8,7 +8,7 @@ module Keisan
|
|
8
8
|
protected
|
9
9
|
|
10
10
|
def self.derivative(argument)
|
11
|
-
-
|
11
|
+
-AST::Function.new([argument], "cos") * AST::Exponent.new([AST::Function.new([argument], "sin"), -2])
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -8,7 +8,7 @@ module Keisan
|
|
8
8
|
protected
|
9
9
|
|
10
10
|
def self.derivative(argument)
|
11
|
-
-
|
11
|
+
-AST::Function.new([argument], "cosh") * AST::Exponent.new([AST::Function.new([argument], "sinh"), -2])
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -1,6 +1,10 @@
|
|
1
|
+
require_relative "let"
|
2
|
+
|
1
3
|
require_relative "if"
|
4
|
+
require_relative "while"
|
2
5
|
require_relative "diff"
|
3
6
|
require_relative "replace"
|
7
|
+
require_relative "range"
|
4
8
|
require_relative "map"
|
5
9
|
require_relative "filter"
|
6
10
|
require_relative "reduce"
|
@@ -8,6 +12,7 @@ require_relative "rand"
|
|
8
12
|
require_relative "sample"
|
9
13
|
require_relative "math_function"
|
10
14
|
require_relative "cmath_function"
|
15
|
+
require_relative "erf"
|
11
16
|
require_relative "exp"
|
12
17
|
require_relative "log"
|
13
18
|
require_relative "sin"
|
@@ -40,43 +45,27 @@ module Keisan
|
|
40
45
|
private
|
41
46
|
|
42
47
|
def self.register_defaults!(registry)
|
43
|
-
registry.register!(:
|
44
|
-
|
45
|
-
registry.register!(:
|
46
|
-
registry.register!(:
|
47
|
-
registry.register!(:
|
48
|
-
registry.register!(:
|
49
|
-
registry.register!(:
|
50
|
-
registry.register!(:
|
51
|
-
registry.register!(:
|
52
|
-
|
53
|
-
|
48
|
+
registry.register!(:let, Let.new, force: true)
|
49
|
+
|
50
|
+
registry.register!(:if, If.new, force: true)
|
51
|
+
registry.register!(:while, While.new, force: true)
|
52
|
+
registry.register!(:diff, Diff.new, force: true)
|
53
|
+
registry.register!(:replace, Replace.new, force: true)
|
54
|
+
registry.register!(:map, Map.new, force: true)
|
55
|
+
registry.register!(:collect, Map.new, force: true)
|
56
|
+
registry.register!(:filter, Filter.new, force: true)
|
57
|
+
registry.register!(:select, Filter.new, force: true)
|
58
|
+
registry.register!(:reduce, Reduce.new, force: true)
|
59
|
+
registry.register!(:inject, Reduce.new, force: true)
|
60
|
+
|
61
|
+
register_math!(registry)
|
54
62
|
register_array_methods!(registry)
|
55
63
|
register_random_methods!(registry)
|
64
|
+
end
|
56
65
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
registry.register!(:sin, Keisan::Functions::Sin.new, force: true)
|
61
|
-
registry.register!(:cos, Keisan::Functions::Cos.new, force: true)
|
62
|
-
registry.register!(:tan, Keisan::Functions::Tan.new, force: true)
|
63
|
-
registry.register!(:cot, Keisan::Functions::Cot.new, force: true)
|
64
|
-
registry.register!(:sec, Keisan::Functions::Sec.new, force: true)
|
65
|
-
registry.register!(:csc, Keisan::Functions::Csc.new, force: true)
|
66
|
-
|
67
|
-
registry.register!(:sinh, Keisan::Functions::Sinh.new, force: true)
|
68
|
-
registry.register!(:cosh, Keisan::Functions::Cosh.new, force: true)
|
69
|
-
registry.register!(:tanh, Keisan::Functions::Tanh.new, force: true)
|
70
|
-
registry.register!(:coth, Keisan::Functions::Coth.new, force: true)
|
71
|
-
registry.register!(:sech, Keisan::Functions::Sech.new, force: true)
|
72
|
-
registry.register!(:csch, Keisan::Functions::Csch.new, force: true)
|
73
|
-
|
74
|
-
registry.register!(:sqrt, Keisan::Functions::Sqrt.new, force: true)
|
75
|
-
registry.register!(:cbrt, Keisan::Functions::Cbrt.new, force: true)
|
76
|
-
|
77
|
-
registry.register!(:abs, Keisan::Functions::Abs.new, force: true)
|
78
|
-
registry.register!(:real, Keisan::Functions::Real.new, force: true)
|
79
|
-
registry.register!(:imag, Keisan::Functions::Imag.new, force: true)
|
66
|
+
def self.register_math!(registry)
|
67
|
+
register_builtin_math!(registry)
|
68
|
+
register_custom_math!(registry)
|
80
69
|
end
|
81
70
|
|
82
71
|
def self.register_builtin_math!(registry)
|
@@ -92,54 +81,44 @@ module Keisan
|
|
92
81
|
end
|
93
82
|
end
|
94
83
|
|
84
|
+
CUSTOM_MATH_FUNCTIONS = %i(erf exp log sin cos tan cot sec csc sinh cosh tanh coth sech csch sqrt cbrt abs real imag).freeze
|
85
|
+
|
86
|
+
def self.register_custom_math!(registry)
|
87
|
+
factorial = Proc.new {|n|
|
88
|
+
(1..n).inject(1) do |res, i|
|
89
|
+
res * i
|
90
|
+
end
|
91
|
+
}
|
92
|
+
nPk = Proc.new {|n, k|
|
93
|
+
factorial.call(n) / factorial.call(n-k)
|
94
|
+
}
|
95
|
+
nCk = Proc.new {|n, k|
|
96
|
+
factorial.call(n) / factorial.call(k) / factorial.call(n-k)
|
97
|
+
}
|
98
|
+
|
99
|
+
registry.register!(:factorial, factorial, force: true)
|
100
|
+
registry.register!(:nPk, nPk, force: true)
|
101
|
+
registry.register!(:permute, nPk, force: true)
|
102
|
+
registry.register!(:nCk, nCk, force: true)
|
103
|
+
registry.register!(:choose, nCk, force: true)
|
104
|
+
|
105
|
+
CUSTOM_MATH_FUNCTIONS.each do |method|
|
106
|
+
klass = Keisan::Functions.const_get(method.to_s.capitalize)
|
107
|
+
registry.register!(method, klass.new, force: true)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
95
111
|
def self.register_array_methods!(registry)
|
96
112
|
%i(min max size flatten reverse).each do |method|
|
97
113
|
registry.register!(method, Proc.new {|a| a.send(method)}, force: true)
|
98
114
|
end
|
99
115
|
|
100
|
-
|
101
|
-
# range(5, 15) => Integers from 5 inclusive to 15 exclusive
|
102
|
-
# range(10, -1, -2) => Integers from 10 inclusive to -1 exclusive, decreasing by twos
|
103
|
-
# i.e.: [10, 8, 6, 4, 2, 0]
|
104
|
-
registry.register!("range", Proc.new {|*args|
|
105
|
-
case args.count
|
106
|
-
when 1
|
107
|
-
(0...args[0]).to_a
|
108
|
-
when 2
|
109
|
-
(args[0]...args[1]).to_a
|
110
|
-
when 3
|
111
|
-
current = args[0]
|
112
|
-
final = args[1]
|
113
|
-
shift = args[2]
|
114
|
-
|
115
|
-
if shift == 0 or !shift.is_a?(Integer)
|
116
|
-
raise Keisan::Exceptions::InvalidFunctionError.new("range's 3rd argument must be non-zero integer")
|
117
|
-
end
|
118
|
-
|
119
|
-
result = []
|
120
|
-
|
121
|
-
if shift > 0
|
122
|
-
while current < final
|
123
|
-
result << current
|
124
|
-
current += shift
|
125
|
-
end
|
126
|
-
else
|
127
|
-
while current > final
|
128
|
-
result << current
|
129
|
-
current += shift
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
result
|
134
|
-
else
|
135
|
-
raise Keisan::Exceptions::InvalidFunctionError.new("range takes 1 to 3 arguments")
|
136
|
-
end
|
137
|
-
}, force: true)
|
116
|
+
registry.register!("range", Functions::Range.new, force: true)
|
138
117
|
end
|
139
118
|
|
140
119
|
def self.register_random_methods!(registry)
|
141
|
-
registry.register!(:rand,
|
142
|
-
registry.register!(:sample,
|
120
|
+
registry.register!(:rand, Rand.new, force: true)
|
121
|
+
registry.register!(:sample, Sample.new, force: true)
|
143
122
|
end
|
144
123
|
end
|
145
124
|
end
|
@@ -1,23 +1,26 @@
|
|
1
1
|
module Keisan
|
2
2
|
module Functions
|
3
|
-
class Diff <
|
3
|
+
class Diff < Function
|
4
4
|
def initialize
|
5
|
+
super("diff", -1)
|
5
6
|
@name = "diff"
|
6
7
|
end
|
7
8
|
|
8
9
|
def value(ast_function, context = nil)
|
9
|
-
|
10
|
+
validate_arguments!(ast_function.children.count)
|
11
|
+
context ||= Context.new
|
10
12
|
evaluation = evaluate(ast_function, context)
|
11
13
|
|
12
14
|
if is_ast_derivative?(evaluation)
|
13
|
-
raise
|
15
|
+
raise Exceptions::NonDifferentiableError.new
|
14
16
|
else
|
15
17
|
evaluation.value(context)
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
21
|
def evaluate(ast_function, context = nil)
|
20
|
-
|
22
|
+
validate_arguments!(ast_function.children.count)
|
23
|
+
context ||= Context.new
|
21
24
|
function, variables = function_and_variables(ast_function)
|
22
25
|
local = context_from(variables, context)
|
23
26
|
|
@@ -30,7 +33,7 @@ module Keisan
|
|
30
33
|
end
|
31
34
|
|
32
35
|
case result
|
33
|
-
when
|
36
|
+
when AST::Function
|
34
37
|
result.name == "diff" ? result : result.simplify(context)
|
35
38
|
else
|
36
39
|
result.simplify(context)
|
@@ -38,9 +41,10 @@ module Keisan
|
|
38
41
|
end
|
39
42
|
|
40
43
|
def simplify(ast_function, context = nil)
|
41
|
-
|
44
|
+
validate_arguments!(ast_function.children.count)
|
45
|
+
raise Exceptions::InternalError.new("received non-diff function") unless ast_function.name == "diff"
|
42
46
|
function, variables = function_and_variables(ast_function)
|
43
|
-
context ||=
|
47
|
+
context ||= Context.new
|
44
48
|
local = context_from(variables, context)
|
45
49
|
|
46
50
|
result = variables.inject(function.simplify(local)) do |result, variable|
|
@@ -52,7 +56,7 @@ module Keisan
|
|
52
56
|
end
|
53
57
|
|
54
58
|
case result
|
55
|
-
when
|
59
|
+
when AST::Function
|
56
60
|
result.name == "diff" ? result : result.simplify(context)
|
57
61
|
else
|
58
62
|
result.simplify(context)
|
@@ -62,7 +66,7 @@ module Keisan
|
|
62
66
|
private
|
63
67
|
|
64
68
|
def is_ast_derivative?(node)
|
65
|
-
node.is_a?(
|
69
|
+
node.is_a?(AST::Function) && node.name == name
|
66
70
|
end
|
67
71
|
|
68
72
|
def differentiate(node, variable, context)
|
@@ -71,7 +75,7 @@ module Keisan
|
|
71
75
|
else
|
72
76
|
return AST::Number.new(0)
|
73
77
|
end
|
74
|
-
rescue
|
78
|
+
rescue Exceptions::NonDifferentiableError => e
|
75
79
|
return AST::Function.new(
|
76
80
|
[node, variable],
|
77
81
|
"diff"
|
@@ -79,14 +83,14 @@ module Keisan
|
|
79
83
|
end
|
80
84
|
|
81
85
|
def function_and_variables(ast_function)
|
82
|
-
unless ast_function.is_a?(
|
83
|
-
raise
|
86
|
+
unless ast_function.is_a?(AST::Function) && ast_function.name == name
|
87
|
+
raise Exceptions::InvalidFunctionError.new("Must receive diff function")
|
84
88
|
end
|
85
89
|
|
86
90
|
variables = ast_function.children[1..-1]
|
87
91
|
|
88
92
|
unless variables.all? {|var| var.is_a?(AST::Variable)}
|
89
|
-
raise
|
93
|
+
raise Exceptions::InvalidFunctionError.new("Diff must differentiate with respect to variables")
|
90
94
|
end
|
91
95
|
|
92
96
|
[
|
@@ -96,7 +100,7 @@ module Keisan
|
|
96
100
|
end
|
97
101
|
|
98
102
|
def context_from(variables, context = nil)
|
99
|
-
context ||=
|
103
|
+
context ||= Context.new(shadowed: variables.map(&:name))
|
100
104
|
context.spawn_child(shadowed: variables.map(&:name))
|
101
105
|
end
|
102
106
|
end
|
data/lib/keisan/functions/exp.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module Keisan
|
2
2
|
module Functions
|
3
|
-
class ExpressionFunction <
|
3
|
+
class ExpressionFunction < Function
|
4
4
|
attr_reader :arguments, :expression
|
5
5
|
|
6
6
|
def initialize(name, arguments, expression, transient_definitions)
|
7
|
-
super(name)
|
7
|
+
super(name, arguments.count)
|
8
8
|
@expression = expression.deep_dup
|
9
9
|
@arguments = arguments
|
10
10
|
@transient_definitions = transient_definitions
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(context, *args)
|
14
|
-
|
14
|
+
validate_arguments!(args.count)
|
15
15
|
|
16
16
|
local = local_context_for(context)
|
17
17
|
arguments.each.with_index do |arg_name, i|
|
@@ -22,17 +22,17 @@ module Keisan
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def value(ast_function, context = nil)
|
25
|
-
|
25
|
+
validate_arguments!(ast_function.children.count)
|
26
26
|
|
27
|
-
context ||=
|
27
|
+
context ||= Context.new
|
28
28
|
argument_values = ast_function.children.map {|child| child.value(context)}
|
29
29
|
call(context, *argument_values)
|
30
30
|
end
|
31
31
|
|
32
32
|
def evaluate(ast_function, context = nil)
|
33
|
-
|
33
|
+
validate_arguments!(ast_function.children.count)
|
34
34
|
|
35
|
-
context ||=
|
35
|
+
context ||= Context.new
|
36
36
|
local = local_context_for(context)
|
37
37
|
|
38
38
|
argument_values = ast_function.children.map {|child| child.evaluate(context)}
|
@@ -41,18 +41,18 @@ module Keisan
|
|
41
41
|
local.register_variable!(arg_name, argument_values[i].evaluate(context))
|
42
42
|
end
|
43
43
|
|
44
|
-
expression.
|
44
|
+
expression.evaluated(local)
|
45
45
|
end
|
46
46
|
|
47
47
|
def simplify(ast_function, context = nil)
|
48
|
-
|
48
|
+
validate_arguments!(ast_function.children.count)
|
49
49
|
|
50
50
|
ast_function.instance_variable_set(
|
51
51
|
:@children,
|
52
52
|
ast_function.children.map {|child| child.evaluate(context)}
|
53
53
|
)
|
54
54
|
|
55
|
-
if ast_function.children.all? {|child| child.is_a?(
|
55
|
+
if ast_function.children.all? {|child| child.is_a?(AST::ConstantLiteral)}
|
56
56
|
value(ast_function, context).to_node.simplify(context)
|
57
57
|
else
|
58
58
|
ast_function
|
@@ -66,7 +66,7 @@ module Keisan
|
|
66
66
|
# dx(t)/dt * f_x(x(t), y(t)) + dy(t)/dt * f_y(x(t), y(t)),
|
67
67
|
# where f_x and f_y are the x and y partial derivatives respectively.
|
68
68
|
def differentiate(ast_function, variable, context = nil)
|
69
|
-
|
69
|
+
validate_arguments!(ast_function.children.count)
|
70
70
|
|
71
71
|
local = local_context_for(context)
|
72
72
|
|
@@ -78,10 +78,10 @@ module Keisan
|
|
78
78
|
child.differentiate(variable, context)
|
79
79
|
end
|
80
80
|
|
81
|
-
|
81
|
+
AST::Plus.new(
|
82
82
|
argument_derivatives.map.with_index {|argument_derivative, i|
|
83
83
|
partial_derivative = partial_derivatives[i].replace(argument_variables[i], argument_values[i])
|
84
|
-
|
84
|
+
AST::Times.new([argument_derivative, partial_derivative])
|
85
85
|
}
|
86
86
|
)
|
87
87
|
end
|
@@ -89,7 +89,7 @@ module Keisan
|
|
89
89
|
private
|
90
90
|
|
91
91
|
def argument_variables
|
92
|
-
@argument_variables ||= arguments.map {|argument|
|
92
|
+
@argument_variables ||= arguments.map {|argument| AST::Variable.new(argument)}
|
93
93
|
end
|
94
94
|
|
95
95
|
def partial_derivatives
|
@@ -98,14 +98,8 @@ module Keisan
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
def verify_argument_size!(argument_size)
|
102
|
-
unless @arguments.count == argument_size
|
103
|
-
raise Keisan::Exceptions::InvalidFunctionError.new("Invalid number of arguments for #{name} function")
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
101
|
def local_context_for(context = nil)
|
108
|
-
context ||=
|
102
|
+
context ||= Context.new
|
109
103
|
context.spawn_child(definitions: @transient_definitions, shadowed: @arguments, transient: true)
|
110
104
|
end
|
111
105
|
end
|