fOOrth 0.6.6 → 0.6.11
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 +5 -5
- data/CODE_OF_CONDUCT.md +49 -0
- data/README.md +32 -1
- data/fOOrth.gemspec +3 -3
- data/integration/array_lib_tests.rb +10 -0
- data/integration/compile_lib_tests.rb +67 -1
- data/integration/exception_lib_tests.rb +4 -0
- data/integration/hash_lib_tests.rb +9 -0
- data/integration/numeric_lib_tests.rb +326 -321
- data/integration/procedure_lib_tests.rb +16 -0
- data/integration/queue_lib_tests.rb +2 -1
- data/integration/stack_lib_tests.rb +2 -1
- data/integration/stdio_lib_tests.rb +62 -0
- data/integration/string_lib_tests.rb +11 -0
- data/integration/thread_lib_tests.rb +19 -5
- data/lib/fOOrth.rb +0 -2
- data/lib/fOOrth/compiler/context.rb +64 -64
- data/lib/fOOrth/compiler/context/locals.rb +34 -34
- data/lib/fOOrth/compiler/context/map_name.rb +85 -74
- data/lib/fOOrth/compiler/context/tags.rb +60 -48
- data/lib/fOOrth/compiler/process/generate.rb +1 -1
- data/lib/fOOrth/compiler/process/procedure.rb +40 -0
- data/lib/fOOrth/compiler/word_specs.rb +3 -3
- data/lib/fOOrth/core/object.rb +1 -1
- data/lib/fOOrth/library.rb +3 -0
- data/lib/fOOrth/library/alias_library.rb +126 -0
- data/lib/fOOrth/library/array_library.rb +41 -21
- data/lib/fOOrth/library/command_library.rb +1 -1
- data/lib/fOOrth/library/compile_library.rb +266 -264
- data/lib/fOOrth/library/complex_library.rb +82 -80
- data/lib/fOOrth/library/float_library.rb +37 -0
- data/lib/fOOrth/library/formatting/array.rb +90 -0
- data/lib/fOOrth/library/formatting/bullets.rb +15 -79
- data/lib/fOOrth/library/formatting/columns.rb +20 -42
- data/lib/fOOrth/library/formatting/hash.rb +29 -0
- data/lib/fOOrth/library/formatting/nil.rb +13 -0
- data/lib/fOOrth/library/formatting/object.rb +18 -0
- data/lib/fOOrth/library/formatting/string.rb +46 -0
- data/lib/fOOrth/library/hash_library.rb +14 -6
- data/lib/fOOrth/library/introspection/class.rb +20 -18
- data/lib/fOOrth/library/introspection/context.rb +3 -2
- data/lib/fOOrth/library/introspection/object.rb +42 -20
- data/lib/fOOrth/library/introspection/string.rb +21 -5
- data/lib/fOOrth/library/introspection/vm.rb +17 -29
- data/lib/fOOrth/library/mutex_library.rb +8 -1
- data/lib/fOOrth/library/numeric_library.rb +359 -380
- data/lib/fOOrth/library/procedure_library.rb +69 -65
- data/lib/fOOrth/library/queue_library.rb +6 -1
- data/lib/fOOrth/library/rational_library.rb +89 -89
- data/lib/fOOrth/library/stack_library.rb +6 -1
- data/lib/fOOrth/library/stdio_library.rb +11 -8
- data/lib/fOOrth/library/string_library.rb +21 -6
- data/lib/fOOrth/library/stubs_library.rb +49 -0
- data/lib/fOOrth/monkey_patch/exceptions.rb +2 -6
- data/lib/fOOrth/monkey_patch/object.rb +7 -0
- data/lib/fOOrth/version.rb +1 -1
- data/reek.txt +1 -59
- data/sire.rb +0 -1
- data/tests/compiler/context_tests.rb +188 -177
- data/tests/compiler/file_source_tests.rb +130 -130
- data/tests/compiler/parser_tests.rb +4 -4
- data/tests/compiler/string_source_tests.rb +4 -4
- data/tests/core_tests.rb +138 -138
- data/tests/monkey_patch/complex_test.rb +24 -24
- data/tests/monkey_patch/object_test.rb +49 -49
- data/tests/monkey_patch/string_test.rb +61 -61
- metadata +20 -13
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#* library/formatting/hash.rb - Hash support for displaying data formatted neatly.
|
4
|
+
class Hash
|
5
|
+
|
6
|
+
# Bullets ========================================================
|
7
|
+
|
8
|
+
#Print out the array as bullet points.
|
9
|
+
def puts_foorth_bullets(page_width)
|
10
|
+
puts foorth_format_bullets(page_width)
|
11
|
+
end
|
12
|
+
|
13
|
+
#Convert the array to strings with bullet points.
|
14
|
+
#<br>Returns
|
15
|
+
#* A string.
|
16
|
+
def foorth_format_bullets(page_width)
|
17
|
+
return "" if empty?
|
18
|
+
|
19
|
+
builder = XfOOrth::BulletPoints.new(page_width)
|
20
|
+
|
21
|
+
self.each do |pair|
|
22
|
+
builder.add(*pair)
|
23
|
+
end
|
24
|
+
|
25
|
+
builder.render.join("\n").freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#* library/formatting/object.rb - Support for displaying data formatted neatly.
|
4
|
+
class Object
|
5
|
+
|
6
|
+
#Create a bullet point description from this object.
|
7
|
+
def format_description(max_width)
|
8
|
+
self.to_s.format_description(max_width)
|
9
|
+
end
|
10
|
+
|
11
|
+
#Get data ready for being in a bullet point.
|
12
|
+
def prepare_bullet_data
|
13
|
+
["*", self]
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#* library/formatting/string.rb - Support for displaying data formatted neatly.
|
4
|
+
class String
|
5
|
+
|
6
|
+
#Create a bullet point description from this string.
|
7
|
+
def format_description(max_width)
|
8
|
+
do_format_description(split(' ').each, max_width)
|
9
|
+
end
|
10
|
+
|
11
|
+
#Do the formatting legwork.
|
12
|
+
def do_format_description(input, max_width)
|
13
|
+
result, build = [], ""
|
14
|
+
|
15
|
+
loop do
|
16
|
+
build = build.split_if_over(input.next, max_width, result)
|
17
|
+
.split_if_huge(max_width, result)
|
18
|
+
end
|
19
|
+
|
20
|
+
result << build
|
21
|
+
end
|
22
|
+
|
23
|
+
#Split if adding a word goes over a little.
|
24
|
+
def split_if_over(word, max_width, buffer)
|
25
|
+
word.prepend(" ") unless self.empty?
|
26
|
+
word_len = word.length
|
27
|
+
|
28
|
+
if (length + word_len) >= max_width && word_len < max_width
|
29
|
+
buffer << self
|
30
|
+
word.lstrip
|
31
|
+
else
|
32
|
+
self + word
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
#Split up a overlong blob of text.
|
38
|
+
def split_if_huge(max_width, buffer)
|
39
|
+
while length >= max_width
|
40
|
+
buffer << slice!(0, max_width)
|
41
|
+
end
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -70,27 +70,35 @@ module XfOOrth
|
|
70
70
|
|
71
71
|
# [i h] .[]@ [h[i]]
|
72
72
|
Hash.create_shared_method('.[]@', TosSpec, [],
|
73
|
-
&lambda {|vm| vm.poke(self[vm.peek])
|
73
|
+
&lambda {|vm| vm.poke(self[vm.peek]) })
|
74
74
|
|
75
75
|
# [v i h] .[]! []; h[i]=v
|
76
76
|
Hash.create_shared_method('.[]!', TosSpec, [],
|
77
|
-
&lambda {|vm| value, index = vm.popm(2); self[index] = value
|
77
|
+
&lambda {|vm| value, index = vm.popm(2); self[index] = value })
|
78
78
|
|
79
79
|
# [{"a"=>1, "b"=>2}] .length [2]]
|
80
80
|
Hash.create_shared_method('.length', TosSpec, [],
|
81
|
-
&lambda {|vm| vm.push(self.length)
|
81
|
+
&lambda {|vm| vm.push(self.length) })
|
82
82
|
|
83
83
|
# [a_hash] .empty? [a_boolean]]
|
84
84
|
Hash.create_shared_method('.empty?', TosSpec, [],
|
85
|
-
&lambda {|vm| vm.push(self.empty?)
|
85
|
+
&lambda {|vm| vm.push(self.empty?) })
|
86
|
+
|
87
|
+
# [a_hash] .present? [a_boolean]]
|
88
|
+
Hash.create_shared_method('.present?', TosSpec, [],
|
89
|
+
&lambda {|vm| vm.push(!self.empty?) })
|
90
|
+
|
91
|
+
# [a_hash] .clear! []]
|
92
|
+
Hash.create_shared_method('.clear!', TosSpec, [],
|
93
|
+
&lambda {|vm| self.clear })
|
86
94
|
|
87
95
|
# [h] .keys [[keys]]
|
88
96
|
Hash.create_shared_method('.keys', TosSpec, [],
|
89
|
-
&lambda {|vm| vm.push(self.keys)
|
97
|
+
&lambda {|vm| vm.push(self.keys) })
|
90
98
|
|
91
99
|
# [h] .values [[values]]
|
92
100
|
Hash.create_shared_method('.values', TosSpec, [],
|
93
|
-
&lambda {|vm| vm.push(self.values)
|
101
|
+
&lambda {|vm| vm.push(self.values) })
|
94
102
|
|
95
103
|
# [h] .strmax2 [widest_key widest_value]
|
96
104
|
Hash.create_shared_method('.strmax2', TosSpec, [], &lambda {|vm|
|
@@ -30,17 +30,11 @@ class Class
|
|
30
30
|
found = false
|
31
31
|
|
32
32
|
if symbol
|
33
|
-
|
34
|
-
|
35
|
-
if spec && !spec.has_tag?(:stub)
|
36
|
-
(results << ["", ""]).concat(info).concat(spec.get_info)
|
33
|
+
if scrape_method_info(results, *map_foorth_shared_info(symbol))
|
37
34
|
found = true
|
38
35
|
end
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
if spec && !spec.has_tag?(:stub)
|
43
|
-
(results << ["", ""]).concat(info).concat(spec.get_info)
|
37
|
+
if scrape_method_info(results, *map_foorth_exclusive_info(symbol, "Class"))
|
44
38
|
found = true
|
45
39
|
end
|
46
40
|
|
@@ -54,18 +48,28 @@ class Class
|
|
54
48
|
def get_info
|
55
49
|
results = [["Lineage", lineage]]
|
56
50
|
|
57
|
-
|
58
|
-
|
51
|
+
get_exclusive_method_info(results, "Class")
|
52
|
+
get_shared_method_info(results)
|
59
53
|
|
60
|
-
|
61
|
-
|
62
|
-
(results << ["", ""]).concat(info)
|
54
|
+
results
|
55
|
+
end
|
63
56
|
|
64
|
-
|
65
|
-
|
66
|
-
|
57
|
+
private
|
58
|
+
|
59
|
+
#Get method information
|
60
|
+
#<br>Endemic Code Smells
|
61
|
+
#* :reek:UtilityFunction
|
62
|
+
def scrape_method_info(results, spec, info)
|
63
|
+
if spec && !spec.has_tag?(:stub)
|
64
|
+
(results << ["", ""]).concat(info).concat(spec.get_info)
|
65
|
+
true
|
66
|
+
else
|
67
|
+
false
|
67
68
|
end
|
69
|
+
end
|
68
70
|
|
71
|
+
#Get shared method info
|
72
|
+
def get_shared_method_info(results)
|
69
73
|
unless foorth_shared.empty?
|
70
74
|
results.concat([["", ""], ["Methods", "Shared"]])
|
71
75
|
|
@@ -77,8 +81,6 @@ class Class
|
|
77
81
|
results.concat(info).concat(spec.get_info)
|
78
82
|
end
|
79
83
|
end
|
80
|
-
|
81
|
-
results
|
82
84
|
end
|
83
85
|
|
84
86
|
end
|
@@ -7,6 +7,8 @@ module XfOOrth
|
|
7
7
|
class Context
|
8
8
|
|
9
9
|
#Get introspection info.
|
10
|
+
#<br>Endemic Code Smells
|
11
|
+
#* :reek:FeatureEnvy :reek:TooManyStatements
|
10
12
|
def get_info
|
11
13
|
results = [["Level", depth]]
|
12
14
|
|
@@ -25,8 +27,7 @@ module XfOOrth
|
|
25
27
|
end
|
26
28
|
|
27
29
|
if (prev = self.previous)
|
28
|
-
results
|
29
|
-
results.concat(prev.get_info)
|
30
|
+
results.concat([["", ""]]).concat(prev.get_info)
|
30
31
|
end
|
31
32
|
|
32
33
|
results
|
@@ -17,31 +17,15 @@ class Object
|
|
17
17
|
#Get introspection info.
|
18
18
|
def get_info
|
19
19
|
results = [["Type", foorth_name]]
|
20
|
-
|
21
|
-
|
22
|
-
results.concat([["", ""], ["Data", "Instance"], ["", ""]])
|
23
|
-
|
24
|
-
vars.sort.each do |name|
|
25
|
-
var_name = XfOOrth::SymbolMap.unmap(name[1..-1].to_sym) || name
|
26
|
-
results << [var_name, instance_variable_get(name)]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
if foorth_has_exclusive?
|
31
|
-
results.concat([["", ""], ["Methods", "Exclusive"]])
|
32
|
-
|
33
|
-
foorth_exclusive.extract_method_names(:all).sort.each do |name|
|
34
|
-
symbol, info = XfOOrth::SymbolMap.map_info(name)
|
35
|
-
results.concat([["", ""], ["Name", name], info])
|
36
|
-
spec, info = map_foorth_exclusive_info(symbol, :shallow)
|
37
|
-
results.concat(info).concat(spec.get_info)
|
38
|
-
end
|
39
|
-
end
|
20
|
+
get_instance_variable_info(results)
|
21
|
+
get_exclusive_method_info(results, "Exclusive")
|
40
22
|
|
41
23
|
results
|
42
24
|
end
|
43
25
|
|
44
26
|
#Investigate a method of this object.
|
27
|
+
#<br>Endemic Code Smells
|
28
|
+
#* :reek:FeatureEnvy
|
45
29
|
def foorth_method_info(name)
|
46
30
|
symbol, results = XfOOrth::SymbolMap.map_info(name)
|
47
31
|
found = false
|
@@ -65,5 +49,43 @@ class Object
|
|
65
49
|
foorth_name + " < " + self.class.lineage
|
66
50
|
end
|
67
51
|
|
52
|
+
private
|
53
|
+
|
54
|
+
#Get information about instance variables
|
55
|
+
def get_instance_variable_info(results)
|
56
|
+
names = instance_variables.map do |sym|
|
57
|
+
if (name = XfOOrth::SymbolMap.unmap(sym.to_s[1..-1].to_sym))
|
58
|
+
[name, sym]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
.compact
|
62
|
+
.sort {|first, second| first[0] <=> second[0] }
|
63
|
+
|
64
|
+
unless names.empty?
|
65
|
+
results.concat([["", ""], ["Data", "Instance"], ["", ""]])
|
66
|
+
|
67
|
+
names.each do |name, sym|
|
68
|
+
results << [name, instance_variable_get(sym)]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
#Get exclusive method info
|
75
|
+
def get_exclusive_method_info(results, designation)
|
76
|
+
if foorth_has_exclusive?
|
77
|
+
results.concat([["", ""], ["Methods", designation]])
|
78
|
+
|
79
|
+
foorth_exclusive.extract_method_names(:all).sort.each do |name|
|
80
|
+
symbol, info = XfOOrth::SymbolMap.map_info(name)
|
81
|
+
(results << ["", ""]).concat(info)
|
82
|
+
|
83
|
+
spec, info = map_foorth_exclusive_info(symbol, :shallow)
|
84
|
+
results.concat(info).concat(spec.get_info)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
68
90
|
|
69
91
|
end
|
@@ -4,6 +4,8 @@
|
|
4
4
|
class String
|
5
5
|
|
6
6
|
#Scan all classes for information about a method.
|
7
|
+
#<br>Endemic Code Smells
|
8
|
+
#* :reek:DuplicateMethodCall :reek:FeatureEnvy :reek:TooManyStatements
|
7
9
|
def foorth_method_scan
|
8
10
|
symbol, results = XfOOrth::SymbolMap.map_info(self)
|
9
11
|
found = false
|
@@ -11,13 +13,27 @@ class String
|
|
11
13
|
symbol && $FOORTH_GLOBALS.values
|
12
14
|
.select {|entry| entry.has_tag?(:class)}
|
13
15
|
.collect {|spec| spec.new_class}
|
14
|
-
.sort {|
|
16
|
+
.sort {|first, second| first.foorth_name <=> second.foorth_name}
|
15
17
|
.each do |klass|
|
16
|
-
|
17
|
-
found |= spec && (results << ["", ""]).concat(info).concat(spec.get_info)
|
18
|
+
shared_spec, shared_info = klass.map_foorth_shared_info(symbol, :shallow)
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
if shared_spec
|
21
|
+
results
|
22
|
+
.concat([["", ""]])
|
23
|
+
.concat(shared_info)
|
24
|
+
.concat(shared_spec.get_info)
|
25
|
+
end
|
26
|
+
|
27
|
+
excl_spec, excl_info = klass.map_foorth_exclusive_info(symbol, :shallow)
|
28
|
+
|
29
|
+
if excl_spec
|
30
|
+
results
|
31
|
+
.concat([["", ""]])
|
32
|
+
.concat(excl_info)
|
33
|
+
.concat(excl_spec.get_info)
|
34
|
+
end
|
35
|
+
|
36
|
+
found ||= (shared_spec || excl_spec)
|
21
37
|
end
|
22
38
|
|
23
39
|
results << ["Scope", "not found in any class."] if symbol && !found
|
@@ -8,6 +8,18 @@ module XfOOrth
|
|
8
8
|
|
9
9
|
#Get introspection info.
|
10
10
|
def get_info
|
11
|
+
results = get_basic_vm_info
|
12
|
+
get_instance_variable_info(results)
|
13
|
+
get_vm_thread_data_info(results)
|
14
|
+
get_exclusive_method_info(results, "Exclusive")
|
15
|
+
|
16
|
+
results
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
#Get the vm basic stuff first.
|
22
|
+
def get_basic_vm_info
|
11
23
|
results = [["Name", foorth_name],
|
12
24
|
["Ruby", self.to_s],
|
13
25
|
["Stack", @data_stack.inspect],
|
@@ -22,47 +34,23 @@ module XfOOrth
|
|
22
34
|
results << ["Buffer", source.read_buffer.inspect]
|
23
35
|
end
|
24
36
|
|
25
|
-
|
26
|
-
|
27
|
-
[name, sym]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
names.compact!
|
32
|
-
|
33
|
-
unless names.empty?
|
34
|
-
results.concat([["", ""], ["Data", "Instance"], ["", ""]])
|
35
|
-
|
36
|
-
names.each do |name, sym|
|
37
|
-
results << [name, instance_variable_get(sym)]
|
38
|
-
end
|
39
|
-
end
|
37
|
+
results
|
38
|
+
end
|
40
39
|
|
40
|
+
#Get the thread data info.
|
41
|
+
def get_vm_thread_data_info(results)
|
41
42
|
unless @data.empty?
|
42
43
|
results.concat([["", ""], ["Data", "Thread"], ["", ""]])
|
43
44
|
|
44
45
|
@data
|
45
46
|
.keys
|
46
47
|
.map{|symbol| [SymbolMap.unmap(symbol), symbol]}
|
47
|
-
.sort{|
|
48
|
+
.sort{|first, second| first[0] <=> second[0]}
|
48
49
|
.map{|name, symbol| [name, @data[symbol]]}
|
49
50
|
.each do |name, value|
|
50
51
|
results << [name, value.inspect]
|
51
52
|
end
|
52
53
|
end
|
53
|
-
|
54
|
-
if foorth_has_exclusive?
|
55
|
-
results.concat([["", ""], ["Methods", "Exclusive"]])
|
56
|
-
|
57
|
-
foorth_exclusive.extract_method_names(:all).sort.each do |name|
|
58
|
-
symbol, info = SymbolMap.map_info(name)
|
59
|
-
results.concat([["", ""], ["Name", name], info])
|
60
|
-
spec, info = map_foorth_exclusive_info(symbol, :shallow)
|
61
|
-
results.concat(info).concat(spec.get_info)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
results
|
66
54
|
end
|
67
55
|
|
68
56
|
end
|
@@ -9,7 +9,7 @@ module XfOOrth
|
|
9
9
|
# [Mutex] .do{{ ... }} [] (Releases a lock on the mutex)
|
10
10
|
Mutex.create_exclusive_method('.do{{', NosSpec, [], &lambda {|vm|
|
11
11
|
block = vm.pop
|
12
|
-
|
12
|
+
foorth_shared_mutex.synchronize { block.call(vm, nil, nil) }
|
13
13
|
})
|
14
14
|
|
15
15
|
# [a_mutex] .lock [] (Acquires a lock on the mutex)
|
@@ -29,3 +29,10 @@ module XfOOrth
|
|
29
29
|
})
|
30
30
|
|
31
31
|
end
|
32
|
+
|
33
|
+
# Create a shared mutex instance.
|
34
|
+
class Mutex
|
35
|
+
def self.foorth_shared_mutex
|
36
|
+
@foorth_shared_mutex ||= Mutex.new
|
37
|
+
end
|
38
|
+
end
|