kxi 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kxi.rb +44 -39
- data/lib/kxi/application/config.rb +177 -177
- data/lib/kxi/application/config_reader.rb +16 -16
- data/lib/kxi/application/event.rb +35 -35
- data/lib/kxi/application/logger.rb +155 -155
- data/lib/kxi/application/version.rb +106 -74
- data/lib/kxi/application/version_expression.rb +94 -69
- data/lib/kxi/application/workspace.rb +105 -0
- data/lib/kxi/cli/anonymous_argument.rb +50 -50
- data/lib/kxi/cli/argument.rb +56 -56
- data/lib/kxi/cli/argument_values.rb +83 -83
- data/lib/kxi/cli/explicit_argument.rb +38 -38
- data/lib/kxi/cli/flag_argument.rb +15 -15
- data/lib/kxi/cli/named_argument.rb +59 -59
- data/lib/kxi/cli/property_list.rb +57 -48
- data/lib/kxi/cli/table.rb +82 -62
- data/lib/kxi/cli/verb.rb +282 -280
- data/lib/kxi/collections/array_collection.rb +106 -106
- data/lib/kxi/collections/enumerable.rb +527 -527
- data/lib/kxi/collections/enumerator.rb +31 -31
- data/lib/kxi/collections/hash_collection.rb +100 -100
- data/lib/kxi/collections/protected_collection.rb +20 -19
- data/lib/kxi/exceptions/abstract_exception.rb +34 -34
- data/lib/kxi/exceptions/argument_exception.rb +21 -21
- data/lib/kxi/exceptions/collection_exception.rb +13 -13
- data/lib/kxi/exceptions/configuration_exception.rb +36 -25
- data/lib/kxi/exceptions/dimension_mismatch_exception.rb +29 -0
- data/lib/kxi/exceptions/invalid_type_exception.rb +32 -32
- data/lib/kxi/exceptions/no_argument_exception.rb +20 -20
- data/lib/kxi/exceptions/not_implemented_exception.rb +12 -12
- data/lib/kxi/exceptions/out_of_range_exception.rb +43 -43
- data/lib/kxi/exceptions/parse_exception.rb +28 -20
- data/lib/kxi/exceptions/verb_expected_exception.rb +20 -20
- data/lib/kxi/exceptions/workspace_collision_exception.rb +21 -0
- data/lib/kxi/math/math.rb +45 -0
- data/lib/kxi/math/matrix.rb +303 -0
- data/lib/kxi/math/polynomial.rb +141 -101
- data/lib/kxi/math/vector.rb +181 -0
- data/lib/kxi/platform.rb +103 -57
- data/lib/kxi/reflection/stack_frame.rb +80 -80
- data/lib/kxi/version.rb +4 -4
- metadata +8 -3
- data/lib/kxi/exceptions/invalid_operation_exception.rb +0 -11
@@ -0,0 +1,181 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-04-14.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module Math
|
5
|
+
# Represents a vector
|
6
|
+
class Vector
|
7
|
+
# Returns the dimension of vector
|
8
|
+
# @return [Integer] Dimension of vector
|
9
|
+
def dimension
|
10
|
+
@dim
|
11
|
+
end
|
12
|
+
|
13
|
+
# Instantiates the {KXI::Math::Vector} class
|
14
|
+
# @param [Integer] dim Dimension of vector
|
15
|
+
# @yield [d] Generator function
|
16
|
+
# @yieldparam Dimension to generate
|
17
|
+
# @yieldreturn [Numeric] Result of generator
|
18
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When generator function returns value of invalid type
|
19
|
+
def initialize(dim)
|
20
|
+
@dim = dim
|
21
|
+
if block_given?
|
22
|
+
@data = []
|
23
|
+
dim.times do |d|
|
24
|
+
val = yield(d)
|
25
|
+
raise(KXI::Exceptions::InvalidTypeException.new(val.type, Numeric)) unless val.is_a?(Numeric)
|
26
|
+
@data.push(val.to_f)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
@data = [0.0] * dim
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def str(num)
|
34
|
+
return (num == num.to_i ? num.to_i : num).to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
# Gets the value of vector at specific dimension
|
38
|
+
# @param [Integer] idx Dimension to return
|
39
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When dimension is out of range
|
40
|
+
# @return [Numeric] Value of vector at given dimension
|
41
|
+
def [](idx)
|
42
|
+
raise(KXI::Exceptions::OutOfRangeException.new(idx, 0, @dim - 1)) if idx < 0 or idx >= @dim
|
43
|
+
raise(KXI::Exceptions::InvalidTypeException.new(value.type, Numeric)) unless value.is_a?(Numeric)
|
44
|
+
return @data[idx]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sets the value of vector at specific dimension
|
48
|
+
# @overload []=(idx, val)
|
49
|
+
# Sets the value of vector at specific dimension
|
50
|
+
# @param [Integer] idx Dimension to set
|
51
|
+
# @param [Integer] val Value to set the dimension to
|
52
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When dimension is out of range
|
53
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When value has invalid type
|
54
|
+
# @return [Numeric] Value passed to function
|
55
|
+
# @overload []=(idx, val)
|
56
|
+
# Sets the values of vector to range of values starting from specific dimension
|
57
|
+
# @param [Integer] idx Dimension to start at
|
58
|
+
# @param [Array] val Values to set the dimensions to
|
59
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When dimension is out of range
|
60
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When value has invalid type
|
61
|
+
# @return [Numeric] Value passed to function
|
62
|
+
def []=(idx, val)
|
63
|
+
raise(KXI::Exceptions::OutOfRangeException.new(idx, 0, @dim - 1)) if idx < 0 or idx >= @dim
|
64
|
+
if val.is_a?(Numeric)
|
65
|
+
@data[idx] = val.to_f
|
66
|
+
elsif val.is_a?(Array)
|
67
|
+
i = 0
|
68
|
+
while idx + i < @dim and i < val.length
|
69
|
+
v = val[i]
|
70
|
+
raise(KXI::Exceptions::InvalidTypeException.new(v.type, Numeric)) unless v.is_a?(Numeric)
|
71
|
+
@data[idx + i] = v.to_f
|
72
|
+
end
|
73
|
+
else
|
74
|
+
raise(KXI::Exceptions::InvalidTypeException.new(val.type, Numeric, Array))
|
75
|
+
end
|
76
|
+
return val
|
77
|
+
end
|
78
|
+
|
79
|
+
# Iterates over each element of vector
|
80
|
+
# @yield [d, val] Iterator function
|
81
|
+
# @yieldparam [Integer] d Dimension passed to iterator
|
82
|
+
# @yieldparam [Numeric] val Value at that specific dimension
|
83
|
+
def each
|
84
|
+
return unless block_given?
|
85
|
+
@dim.times do |d|
|
86
|
+
yield(d, @data[d])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Dot multiplies vectors
|
91
|
+
# @param [KXI::Math::Vector] vec Vector to multiply with
|
92
|
+
# @return [Numeric] Dot product of vectors
|
93
|
+
def dot(vec)
|
94
|
+
raise(KXI::Exception::DimensionMismatchException.new(vec.dimension, dimension)) unless vec.dimension == dimension
|
95
|
+
sum = 0
|
96
|
+
@dim.times { |d| sum += @data[d] * vec[d] }
|
97
|
+
return sum
|
98
|
+
end
|
99
|
+
|
100
|
+
# Converts vector to string
|
101
|
+
# @param [Boolean] d Determines whether string should be decorated
|
102
|
+
# @return [String] String representation of vector
|
103
|
+
def to_s(d = true)
|
104
|
+
just = 0
|
105
|
+
@dim.times { |m| len = str(@data[m]).length; just = len if len > just }
|
106
|
+
ret = ''
|
107
|
+
@dim.times do |m|
|
108
|
+
ret += $/ if m > 0
|
109
|
+
ret += '|' if d
|
110
|
+
ret += str(@data[m]).rjust(just, ' ')
|
111
|
+
ret += '|' if d
|
112
|
+
end
|
113
|
+
return ret
|
114
|
+
end
|
115
|
+
|
116
|
+
# Adds vectors
|
117
|
+
# @param [Vector] other Vector to add
|
118
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When type of value is invalid
|
119
|
+
# @return [KXI::Math::Vector] New vector equivalent to the sum of vectors
|
120
|
+
def +(other)
|
121
|
+
if other.is_a?(KXI::Math::Vector)
|
122
|
+
return KXI::Math::Vector.new(@dim) { |d| @data[d] + other[d] }
|
123
|
+
else
|
124
|
+
raise(KXI::Exceptions::InvalidTypeException.new(other.class, Numeric))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Subtracts vectors
|
129
|
+
# @param [Vector] other Vector to subtract
|
130
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When type of value is invalid
|
131
|
+
# @return [KXI::Math::Vector] New vector equivalent to the difference of vectors
|
132
|
+
def -(other)
|
133
|
+
if other.is_a?(KXI::Math::Vector)
|
134
|
+
return KXI::Math::Vector.new(@dim) { |d| @data[d] - other[d] }
|
135
|
+
else
|
136
|
+
raise(KXI::Exceptions::InvalidTypeException.new(other.class, Numeric))
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Multiplies the vector with -1
|
141
|
+
# @return [KXI::Math::Vector] New opposite vector
|
142
|
+
def -@
|
143
|
+
return KXI::Math::Vector.new(@dim) { |d| -@data[d] }
|
144
|
+
end
|
145
|
+
|
146
|
+
# Multiplies vector
|
147
|
+
# @overload *(other)
|
148
|
+
# Preforms scalar-vector multiplication
|
149
|
+
# @param [Numeric] other Scalar to multiply with
|
150
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When other value is of invalid type
|
151
|
+
# @return [KXI::Math::Vector] New vector equivalent to the scaled vector
|
152
|
+
# @overload *(other)
|
153
|
+
# Preforms vector-vector multiplication
|
154
|
+
# @param [Numeric] other Vector to multiply with
|
155
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When other value is of invalid type
|
156
|
+
# @return [KXI::Math::Vector] New vector equivalent to the multiplied vector
|
157
|
+
def *(other)
|
158
|
+
if other.is_a?(Numeric)
|
159
|
+
return KXI::Math::Vector.new(@dim) { |d| other * @data[d] }
|
160
|
+
elsif other.is_a?(KXI::Math::Vector)
|
161
|
+
return KXI::Math::Vector.new(@dim) { |d| @data[d] * other[d] }
|
162
|
+
elsif raise(KXI::Exceptions::InvalidTypeException.new(other.class, Numeric, KXI::Math::Vector))
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Compares vector
|
167
|
+
# @param [void] other Value to compare to
|
168
|
+
# @return [Boolean] True if vector is equivalent to given value; false otherwise
|
169
|
+
def ==(other)
|
170
|
+
return false unless other.is_a?(KXI::Math::Vector)
|
171
|
+
return false if @dim != other.dimension
|
172
|
+
@dim.times do |d|
|
173
|
+
return false if @data[d] != other[d]
|
174
|
+
end
|
175
|
+
return true
|
176
|
+
end
|
177
|
+
|
178
|
+
private :str
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
data/lib/kxi/platform.rb
CHANGED
@@ -1,58 +1,104 @@
|
|
1
|
-
# Created by Matyáš Pokorný on 2018-01-28.
|
2
|
-
|
3
|
-
module KXI
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@version
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-28.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
# Represents an platform of execution
|
5
|
+
class Platform
|
6
|
+
@@this = nil
|
7
|
+
# Microsoft Windows
|
8
|
+
WINDOWS = 'windows'
|
9
|
+
# Apple macOS
|
10
|
+
OSX = 'osx'
|
11
|
+
# Linux-based system
|
12
|
+
LINUX = 'linux'
|
13
|
+
|
14
|
+
# Gets the name of platform
|
15
|
+
# @return [string] Name of platform
|
16
|
+
def name
|
17
|
+
@name
|
18
|
+
end
|
19
|
+
|
20
|
+
# Gets the version of platform
|
21
|
+
# @return [KXI::Application::Version] Version of platform
|
22
|
+
def version
|
23
|
+
@version
|
24
|
+
end
|
25
|
+
|
26
|
+
# Gets the file extensions of libraries
|
27
|
+
# @return [Array<string>] File extensions of libraries
|
28
|
+
def library_extensions
|
29
|
+
@libs
|
30
|
+
end
|
31
|
+
|
32
|
+
# Gets the separator of paths
|
33
|
+
# @return [string] Separator of paths
|
34
|
+
def path_separator
|
35
|
+
@ps
|
36
|
+
end
|
37
|
+
|
38
|
+
# Gets the separator of directories within a path
|
39
|
+
# @return [string] Separator of directories
|
40
|
+
def directory_separator
|
41
|
+
@ds
|
42
|
+
end
|
43
|
+
|
44
|
+
# Determines whether paths are case-sensitive
|
45
|
+
# @return [bool] True if paths are case-sensitive; false otherwise
|
46
|
+
def path_case_sensitive?
|
47
|
+
@cs
|
48
|
+
end
|
49
|
+
|
50
|
+
# Instantiates the {KXI::Platform} class
|
51
|
+
# @param [string] nm Name of platform
|
52
|
+
# @param [string] ver Version of platform
|
53
|
+
# @param [string] ds Directory separator
|
54
|
+
# @param [string] ps Path separator
|
55
|
+
# @param [string] cs Determines whether paths are case-sensitive
|
56
|
+
# @param [string] libs File extensions of libraries
|
57
|
+
def initialize(nm, ver, ds, ps, cs, *libs)
|
58
|
+
@name = nm
|
59
|
+
@version = KXI::Application::Version.parse(ver)
|
60
|
+
@ds = ds
|
61
|
+
@ps = ps
|
62
|
+
@cs = cs
|
63
|
+
@libs = libs
|
64
|
+
end
|
65
|
+
|
66
|
+
# Gets the current platform
|
67
|
+
# @return [KXI::Platform] Current platform
|
68
|
+
def self.this
|
69
|
+
return @@this if @@this != nil
|
70
|
+
if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
71
|
+
@@this = Platform.new(WINDOWS, `wmic os get Version /value`.split('=').last.strip.chomp, '\\', ';', false, 'dll')
|
72
|
+
elsif /darwin/ =~ RUBY_PLATFORM
|
73
|
+
@@this = Platform.new(OSX, `defaults read loginwindow SystemVersionStampAsString`, '/', ':', true, 'dylib')
|
74
|
+
else
|
75
|
+
@@this = Platform.new(LINUX, `uname -r`.split('-')[0], '/', ':', true, 'so')
|
76
|
+
end
|
77
|
+
return @@this
|
78
|
+
end
|
79
|
+
|
80
|
+
# Finds an executable within the PATH of platform
|
81
|
+
# @return [string,nil] Path of executable if found; otherwise nil
|
82
|
+
def exec(name, *dir)
|
83
|
+
dir = Platform.env('path').split(@ps) if dir.length == 0
|
84
|
+
ext = Platform.env('pathext')
|
85
|
+
(ext != nil ? ext.split(@ps) + [''] : ['']).each do |e|
|
86
|
+
dir.each do |d|
|
87
|
+
f = File.join(d, "#{name}#{e}")
|
88
|
+
return f if File.exists?(f)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
return nil
|
92
|
+
end
|
93
|
+
|
94
|
+
# Gets an environment variable
|
95
|
+
# @return [string] Value of environment variable if found; otherwise nil
|
96
|
+
def self.env(key)
|
97
|
+
key = key.downcase
|
98
|
+
ENV.each_pair do |k, v|
|
99
|
+
return v if k.downcase == key
|
100
|
+
end
|
101
|
+
return nil
|
102
|
+
end
|
103
|
+
end
|
58
104
|
end
|
@@ -1,81 +1,81 @@
|
|
1
|
-
# Created by Matyáš Pokorný on 2017-12-28.
|
2
|
-
module KXI
|
3
|
-
module Reflection
|
4
|
-
# Represents frame of call stack
|
5
|
-
class StackFrame
|
6
|
-
# Returns the file of frame
|
7
|
-
# @return [String] File of frame
|
8
|
-
def file
|
9
|
-
@file
|
10
|
-
end
|
11
|
-
|
12
|
-
# Returns the line number of frame
|
13
|
-
# @return [Number] Line number of frame
|
14
|
-
def line
|
15
|
-
@line
|
16
|
-
end
|
17
|
-
|
18
|
-
# Returns the context of frame
|
19
|
-
# @return [String] Context of frame
|
20
|
-
def context
|
21
|
-
@context
|
22
|
-
end
|
23
|
-
|
24
|
-
# Indicates whether frame is block
|
25
|
-
# @return [Bool] True if stack frame represents call to block; false otherwise
|
26
|
-
def block?
|
27
|
-
@block != nil
|
28
|
-
end
|
29
|
-
|
30
|
-
# Returns containing method of frame; nil if none
|
31
|
-
# @return [String, nil] Name of method that the stack frame represents
|
32
|
-
def method
|
33
|
-
return nil if @block != nil and @block[0] == '<' and @block[@block.length - 1] == '>'
|
34
|
-
return @block unless @block == nil
|
35
|
-
return nil if @context != nil and @context[0] == '<' and @context[@context.length - 1] == '>'
|
36
|
-
@context
|
37
|
-
end
|
38
|
-
|
39
|
-
# Instantiates the {KXI::Reflection::StackFrame} class
|
40
|
-
# @param file [String] File of frame
|
41
|
-
# @param line [Number] Line number of frame
|
42
|
-
# @param context [String, nil] Context of frame
|
43
|
-
def initialize(file, line, context = nil)
|
44
|
-
@file = file
|
45
|
-
@line = line
|
46
|
-
@context = context
|
47
|
-
if context == nil
|
48
|
-
@block = nil
|
49
|
-
else
|
50
|
-
mt = /^block (\((?'levels'\d+) levels\) )?in (?'method'.+)$/mi.match(context)
|
51
|
-
@block = mt == nil ? nil : mt['method']
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Converts class to string
|
56
|
-
# @return [String] Equivalent string
|
57
|
-
def to_s
|
58
|
-
"#{@file}:#{@line}#{(@context != nil ? ": in `#{@context}'" : '')}"
|
59
|
-
end
|
60
|
-
|
61
|
-
# Parses callstack into array of {KXI::Reflection::StackFrame}
|
62
|
-
# @param skip [Number] Number of callstack records to ignore
|
63
|
-
# @return [Array<KXI::Reflection::StackFrame>] Equivalent array of stack frames
|
64
|
-
def self.callstack(skip = 1)
|
65
|
-
ret = []
|
66
|
-
caller(skip).each do |bt|
|
67
|
-
ret.push(from_backtrace(bt))
|
68
|
-
end
|
69
|
-
return ret
|
70
|
-
end
|
71
|
-
|
72
|
-
# Parses backtrace line into {KXI::Reflection::StackFrame}
|
73
|
-
# @param bt [String] Backtrace line
|
74
|
-
# @return [KXI::Reflection::StackFrame] Equivalent stack frame
|
75
|
-
def self.from_backtrace(bt)
|
76
|
-
mt = /(?'file'.+?):(?'line'\d+)(:\s*in\s*`(?'context'.+?)')?/.match(bt)
|
77
|
-
StackFrame.new(mt['file'], mt['line'].to_i, mt['context'])
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
1
|
+
# Created by Matyáš Pokorný on 2017-12-28.
|
2
|
+
module KXI
|
3
|
+
module Reflection
|
4
|
+
# Represents frame of call stack
|
5
|
+
class StackFrame
|
6
|
+
# Returns the file of frame
|
7
|
+
# @return [String] File of frame
|
8
|
+
def file
|
9
|
+
@file
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the line number of frame
|
13
|
+
# @return [Number] Line number of frame
|
14
|
+
def line
|
15
|
+
@line
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the context of frame
|
19
|
+
# @return [String] Context of frame
|
20
|
+
def context
|
21
|
+
@context
|
22
|
+
end
|
23
|
+
|
24
|
+
# Indicates whether frame is block
|
25
|
+
# @return [Bool] True if stack frame represents call to block; false otherwise
|
26
|
+
def block?
|
27
|
+
@block != nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns containing method of frame; nil if none
|
31
|
+
# @return [String, nil] Name of method that the stack frame represents
|
32
|
+
def method
|
33
|
+
return nil if @block != nil and @block[0] == '<' and @block[@block.length - 1] == '>'
|
34
|
+
return @block unless @block == nil
|
35
|
+
return nil if @context != nil and @context[0] == '<' and @context[@context.length - 1] == '>'
|
36
|
+
@context
|
37
|
+
end
|
38
|
+
|
39
|
+
# Instantiates the {KXI::Reflection::StackFrame} class
|
40
|
+
# @param file [String] File of frame
|
41
|
+
# @param line [Number] Line number of frame
|
42
|
+
# @param context [String, nil] Context of frame
|
43
|
+
def initialize(file, line, context = nil)
|
44
|
+
@file = file
|
45
|
+
@line = line
|
46
|
+
@context = context
|
47
|
+
if context == nil
|
48
|
+
@block = nil
|
49
|
+
else
|
50
|
+
mt = /^block (\((?'levels'\d+) levels\) )?in (?'method'.+)$/mi.match(context)
|
51
|
+
@block = mt == nil ? nil : mt['method']
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Converts class to string
|
56
|
+
# @return [String] Equivalent string
|
57
|
+
def to_s
|
58
|
+
"#{@file}:#{@line}#{(@context != nil ? ": in `#{@context}'" : '')}"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Parses callstack into array of {KXI::Reflection::StackFrame}
|
62
|
+
# @param skip [Number] Number of callstack records to ignore
|
63
|
+
# @return [Array<KXI::Reflection::StackFrame>] Equivalent array of stack frames
|
64
|
+
def self.callstack(skip = 1)
|
65
|
+
ret = []
|
66
|
+
caller(skip).each do |bt|
|
67
|
+
ret.push(from_backtrace(bt))
|
68
|
+
end
|
69
|
+
return ret
|
70
|
+
end
|
71
|
+
|
72
|
+
# Parses backtrace line into {KXI::Reflection::StackFrame}
|
73
|
+
# @param bt [String] Backtrace line
|
74
|
+
# @return [KXI::Reflection::StackFrame] Equivalent stack frame
|
75
|
+
def self.from_backtrace(bt)
|
76
|
+
mt = /(?'file'.+?):(?'line'\d+)(:\s*in\s*`(?'context'.+?)')?/.match(bt)
|
77
|
+
StackFrame.new(mt['file'], mt['line'].to_i, mt['context'])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
81
|
end
|