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.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/CODE_OF_CONDUCT.md +49 -0
  3. data/README.md +32 -1
  4. data/fOOrth.gemspec +3 -3
  5. data/integration/array_lib_tests.rb +10 -0
  6. data/integration/compile_lib_tests.rb +67 -1
  7. data/integration/exception_lib_tests.rb +4 -0
  8. data/integration/hash_lib_tests.rb +9 -0
  9. data/integration/numeric_lib_tests.rb +326 -321
  10. data/integration/procedure_lib_tests.rb +16 -0
  11. data/integration/queue_lib_tests.rb +2 -1
  12. data/integration/stack_lib_tests.rb +2 -1
  13. data/integration/stdio_lib_tests.rb +62 -0
  14. data/integration/string_lib_tests.rb +11 -0
  15. data/integration/thread_lib_tests.rb +19 -5
  16. data/lib/fOOrth.rb +0 -2
  17. data/lib/fOOrth/compiler/context.rb +64 -64
  18. data/lib/fOOrth/compiler/context/locals.rb +34 -34
  19. data/lib/fOOrth/compiler/context/map_name.rb +85 -74
  20. data/lib/fOOrth/compiler/context/tags.rb +60 -48
  21. data/lib/fOOrth/compiler/process/generate.rb +1 -1
  22. data/lib/fOOrth/compiler/process/procedure.rb +40 -0
  23. data/lib/fOOrth/compiler/word_specs.rb +3 -3
  24. data/lib/fOOrth/core/object.rb +1 -1
  25. data/lib/fOOrth/library.rb +3 -0
  26. data/lib/fOOrth/library/alias_library.rb +126 -0
  27. data/lib/fOOrth/library/array_library.rb +41 -21
  28. data/lib/fOOrth/library/command_library.rb +1 -1
  29. data/lib/fOOrth/library/compile_library.rb +266 -264
  30. data/lib/fOOrth/library/complex_library.rb +82 -80
  31. data/lib/fOOrth/library/float_library.rb +37 -0
  32. data/lib/fOOrth/library/formatting/array.rb +90 -0
  33. data/lib/fOOrth/library/formatting/bullets.rb +15 -79
  34. data/lib/fOOrth/library/formatting/columns.rb +20 -42
  35. data/lib/fOOrth/library/formatting/hash.rb +29 -0
  36. data/lib/fOOrth/library/formatting/nil.rb +13 -0
  37. data/lib/fOOrth/library/formatting/object.rb +18 -0
  38. data/lib/fOOrth/library/formatting/string.rb +46 -0
  39. data/lib/fOOrth/library/hash_library.rb +14 -6
  40. data/lib/fOOrth/library/introspection/class.rb +20 -18
  41. data/lib/fOOrth/library/introspection/context.rb +3 -2
  42. data/lib/fOOrth/library/introspection/object.rb +42 -20
  43. data/lib/fOOrth/library/introspection/string.rb +21 -5
  44. data/lib/fOOrth/library/introspection/vm.rb +17 -29
  45. data/lib/fOOrth/library/mutex_library.rb +8 -1
  46. data/lib/fOOrth/library/numeric_library.rb +359 -380
  47. data/lib/fOOrth/library/procedure_library.rb +69 -65
  48. data/lib/fOOrth/library/queue_library.rb +6 -1
  49. data/lib/fOOrth/library/rational_library.rb +89 -89
  50. data/lib/fOOrth/library/stack_library.rb +6 -1
  51. data/lib/fOOrth/library/stdio_library.rb +11 -8
  52. data/lib/fOOrth/library/string_library.rb +21 -6
  53. data/lib/fOOrth/library/stubs_library.rb +49 -0
  54. data/lib/fOOrth/monkey_patch/exceptions.rb +2 -6
  55. data/lib/fOOrth/monkey_patch/object.rb +7 -0
  56. data/lib/fOOrth/version.rb +1 -1
  57. data/reek.txt +1 -59
  58. data/sire.rb +0 -1
  59. data/tests/compiler/context_tests.rb +188 -177
  60. data/tests/compiler/file_source_tests.rb +130 -130
  61. data/tests/compiler/parser_tests.rb +4 -4
  62. data/tests/compiler/string_source_tests.rb +4 -4
  63. data/tests/core_tests.rb +138 -138
  64. data/tests/monkey_patch/complex_test.rb +24 -24
  65. data/tests/monkey_patch/object_test.rb +49 -49
  66. data/tests/monkey_patch/string_test.rb +61 -61
  67. metadata +20 -13
@@ -43,4 +43,20 @@ class ProcedureLibraryTester < Minitest::Test
43
43
  foorth_equal('{{ 42 var: a a @ }} .call', [42])
44
44
  end
45
45
 
46
+ def test_instance_data
47
+ foorth_run('42 Object .new .with{{ val@: @test self val$: $t_i_d_1 }}')
48
+ foorth_run('$t_i_d_1 .:: .mulby @test * ; ')
49
+ foorth_equal('2 $t_i_d_1 .mulby', [84])
50
+
51
+ foorth_run('99 $t_i_d_1 .with{{ var@: @boot }} ')
52
+ foorth_run('$t_i_d_1 .:: .addby @boot @ + ; ')
53
+ foorth_equal('2 $t_i_d_1 .addby', [101])
54
+
55
+ foorth_run('$t_i_d_1 .:: .set_boot @boot ! ;')
56
+ foorth_run('56 $t_i_d_1 .set_boot')
57
+ foorth_equal('2 $t_i_d_1 .addby', [58])
58
+
59
+ foorth_run('128 $t_i_d_1 .set_boot')
60
+ foorth_equal('64 $t_i_d_1 .addby', [192])
61
+ end
46
62
  end
@@ -42,8 +42,9 @@ class QueueLibraryTester < Minitest::Test
42
42
 
43
43
  foorth_equal('5 $q .push', [])
44
44
  foorth_equal('$q .empty?', [false])
45
+ foorth_equal('$q .present?', [true])
45
46
  foorth_equal('$q .length', [1])
46
- foorth_equal('$q .clear', [])
47
+ foorth_equal('$q .clear!', [])
47
48
  foorth_equal('$q .empty?', [true])
48
49
  foorth_equal('$q .length', [0])
49
50
 
@@ -60,8 +60,9 @@ class StackLibraryTester < Minitest::Test
60
60
  foorth_run('42 $s .push')
61
61
  foorth_equal('$s .empty?', [false])
62
62
  foorth_equal('$s .peek', [42])
63
+ foorth_equal('$s .present?', [true])
63
64
 
64
- foorth_run('$s .clear')
65
+ foorth_run('$s .clear!')
65
66
 
66
67
  foorth_equal('$s .empty?', [true])
67
68
  foorth_raises('$s .peek')
@@ -49,4 +49,66 @@ class StdioLibraryTester < Minitest::Test
49
49
  foorth_raises('1+1i .emit')
50
50
  end
51
51
 
52
+ #Looks like some unit testing has crept into integration testing. OK.
53
+ def test_some_formatting
54
+ assert_equal("1 4\n2 5\n3 ", [1,2,3,4,5].format_foorth_columns(false, 5))
55
+ assert_equal(["1 4", "2 5", "3 "], [1,2,3,4,5].format_description(5))
56
+
57
+ assert_equal(["1 2", "3 4", "5"], "1 2 3 4 5".format_description(5))
58
+
59
+ assert_equal([], [].format_description(5))
60
+ assert_equal([], nil.format_description(5))
61
+
62
+ result =
63
+ "1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 97 \n" +
64
+ "2 6 10 14 18 22 26 30 34 38 42 46 50 54 58 62 66 70 74 78 82 86 90 94 98 \n" +
65
+ "3 7 11 15 19 23 27 31 35 39 43 47 51 55 59 63 67 71 75 79 83 87 91 95 99 \n" +
66
+ "4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100"
67
+
68
+ assert_equal(result, (1..100).to_a.format_foorth_columns(false, 80) )
69
+
70
+ data =
71
+ [["key_largo", "/long_folder_name_one/long_folder_name_two/long_folder_name_three/fine_descriptive_name"],
72
+ ["key_west", "Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. "],
73
+ ["counting", Array.new(100) {|i| i} ],
74
+ ["pie", Math::PI]
75
+ ]
76
+
77
+ result =
78
+ "key_largo /long_folder_name_one/long_folder_name_two/long_folder_name_three/fin\n" +
79
+ " e_descriptive_name\n" +
80
+ "key_west Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. Semper\n" +
81
+ " ubi sub ubi.\n" +
82
+ "counting 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95\n" +
83
+ " 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 86 91 96\n" +
84
+ " 2 7 12 17 22 27 32 37 42 47 52 57 62 67 72 77 82 87 92 97\n" +
85
+ " 3 8 13 18 23 28 33 38 43 48 53 58 63 68 73 78 83 88 93 98\n" +
86
+ " 4 9 14 19 24 29 34 39 44 49 54 59 64 69 74 79 84 89 94 99\n" +
87
+ "pie 3.141592653589793"
88
+
89
+ assert_equal(result, data.foorth_format_bullets(80))
90
+
91
+ assert_equal("", [].foorth_format_bullets(80))
92
+
93
+
94
+ data =
95
+ {"key_largo" => "/long_folder_name_one/long_folder_name_two/long_folder_name_three/fine_descriptive_name",
96
+ "key_west" => "Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. ",
97
+ "counting" => Array.new(100) {|i| i},
98
+ "pie" => Math::PI
99
+ }
100
+
101
+ assert_equal(result, data.foorth_format_bullets(80))
102
+
103
+ end
104
+
105
+ def test_formatting_some_more
106
+ foorth_run('5 $chars_per_line !')
107
+ foorth_equal('[ 1 2 3 4 5 ] .format_columns', ["1 4\n2 5\n3 "])
108
+
109
+ foorth_run('80 $chars_per_line !')
110
+ foorth_equal('[ [ 1 "apple" ] [ 2 "cherry" ] [ 3 "prune" ] ] .format_bullets',
111
+ ["1 apple\n2 cherry\n3 prune"])
112
+ end
113
+
52
114
  end
@@ -523,4 +523,15 @@ class StringLibraryTester < Minitest::Test
523
523
  foorth_equal('"Hello World" p"%s %s" .map{{ v .mutable? }}', [[false, false]])
524
524
  end
525
525
 
526
+ def test_string_emptiness
527
+ foorth_equal('"" .empty?', [true])
528
+ foorth_equal('"1" .empty?', [false])
529
+
530
+ foorth_equal('"" .present?', [false])
531
+ foorth_equal('"1" .present?', [true])
532
+
533
+ foorth_equal('"1"* dup .clear!', [""])
534
+ end
535
+
536
+
526
537
  end
@@ -72,12 +72,26 @@ class ThreadLibraryTester < Minitest::Test
72
72
  foorth_equal('$tmtx .do{{ 3 4 + }}', [7])
73
73
 
74
74
  foorth_run('""* val$: $tmtx_str')
75
- foorth_equal('{{ $tmtx .do{{ 0 10 do $tmtx_str "@" << loop }} }} ' +
76
- '.start drop $tmtx .do{{ $tmtx_str }} ', ["@"*10])
77
75
 
78
- foorth_run('""* val$: $tmtx_str')
79
- foorth_equal('{{ Mutex .do{{ 0 10 do $tmtx_str "@" << loop }} }} ' +
80
- '.start drop Mutex .do{{ $tmtx_str }} ', ["@"*10])
76
+ code = ': test_mutex_one $tmtx_str .clear! ' +
77
+ '{{ $tmtx .do{{ 0 10 do $tmtx_str "@" << loop }} }} .start drop ' +
78
+ 'begin $tmtx .do{{ $tmtx_str }} .present? until $tmtx_str ;'
79
+
80
+ foorth_run(code)
81
+
82
+ 10.times do
83
+ foorth_equal('test_mutex_one', ["@"*10])
84
+ end
85
+
86
+ code = ': test_mutex_two $tmtx_str .clear! ' +
87
+ '{{ Mutex .do{{ 0 10 do $tmtx_str "@" << loop }} }} .start drop ' +
88
+ 'begin Mutex .do{{ $tmtx_str }} .present? until $tmtx_str ;'
89
+
90
+ foorth_run(code)
91
+
92
+ 10.times do
93
+ foorth_equal('test_mutex_two', ["@"*10])
94
+ end
81
95
  end
82
96
 
83
97
  end
data/lib/fOOrth.rb CHANGED
@@ -10,8 +10,6 @@ require 'ruby_sscanf'
10
10
  require 'English'
11
11
 
12
12
  require 'pp'
13
-
14
- $no_alias_read_line_module = true
15
13
  require 'mini_readline'
16
14
 
17
15
  require_relative 'fOOrth/version'
@@ -1,64 +1,64 @@
1
- # coding: utf-8
2
-
3
- require_relative 'context/map_name'
4
- require_relative 'context/tags'
5
- require_relative 'context/locals'
6
-
7
- #* compiler/context.rb - The compile progress context manager of the fOOrth
8
- # language system.
9
- module XfOOrth
10
-
11
- #A class for the management of global, hierarchical, and nested compile time contexts.
12
- #* compiler/context.rb - \Context constructor, tag support, and local defs.
13
- class Context
14
-
15
- #The previous context object that this one builds on. Set to nil if there
16
- #is none.
17
- attr_reader :previous
18
-
19
- #Setup an instance of compiler context.
20
- #<br>Parameters:
21
- #* previous - The previous context object or nil if there is none.
22
- #* data - A hash of context data.
23
- def initialize(previous, data={})
24
- @previous, @data = previous, data
25
- end
26
-
27
- #How many levels of nested context are there?
28
- def depth
29
- 1 + (previous ? previous.depth : 0)
30
- end
31
-
32
- #Is the current nesting level what is expected?
33
- #<br>Parameters
34
- #* expected_depth - the expected nesting depth.
35
- #<br>Notes
36
- #* Raises an error (F12) on incorrect nesting.
37
- def check_depth(expected_depth)
38
- if expected_depth - self.depth != 0
39
- error "F12: Error, Invalid control/structure nesting."
40
- end
41
- end
42
-
43
- #Get the current target.
44
- def target
45
- self[:obj] || self[:cls] || self[:vm] || no_target_error
46
- end
47
-
48
- #Get the current target object.
49
- def target_object
50
- self[:obj] || no_target_error
51
- end
52
-
53
- #Get the current target class.
54
- def target_class
55
- self[:cls] || no_target_error
56
- end
57
-
58
- #Signal that no receiver was found in this context.
59
- #This is an internal error indication.
60
- def no_target_error
61
- error("F90: No target found in context.")
62
- end
63
- end
64
- end
1
+ # coding: utf-8
2
+
3
+ require_relative 'context/map_name'
4
+ require_relative 'context/tags'
5
+ require_relative 'context/locals'
6
+
7
+ #* compiler/context.rb - The compile progress context manager of the fOOrth
8
+ # language system.
9
+ module XfOOrth
10
+
11
+ #A class for the management of global, hierarchical, and nested compile time contexts.
12
+ #* compiler/context.rb - \Context constructor, tag support, and local defs.
13
+ class Context
14
+
15
+ #The previous context object that this one builds on. Set to nil if there
16
+ #is none.
17
+ attr_reader :previous
18
+
19
+ #Setup an instance of compiler context.
20
+ #<br>Parameters:
21
+ #* previous - The previous context object or nil if there is none.
22
+ #* data - A hash of context data.
23
+ def initialize(previous, data={})
24
+ @previous, @data = previous, data
25
+ end
26
+
27
+ #How many levels of nested context are there?
28
+ def depth
29
+ 1 + (previous ? previous.depth : 0)
30
+ end
31
+
32
+ #Is the current nesting level what is expected?
33
+ #<br>Parameters
34
+ #* expected_depth - the expected nesting depth.
35
+ #<br>Notes
36
+ #* Raises an error (F12) on incorrect nesting.
37
+ def check_depth(expected_depth)
38
+ if expected_depth - self.depth != 0
39
+ error "F12: Error, Invalid control/structure nesting."
40
+ end
41
+ end
42
+
43
+ #Get the current target.
44
+ def target
45
+ self[:obj] || self[:cls] || self[:vm] || no_target_error
46
+ end
47
+
48
+ #Get the current target object.
49
+ def target_object
50
+ self[:obj] || no_target_error
51
+ end
52
+
53
+ #Get the current target class.
54
+ def target_class
55
+ self[:cls] || no_target_error
56
+ end
57
+
58
+ #Signal that no receiver was found in this context.
59
+ #This is an internal error indication.
60
+ def no_target_error
61
+ error("F90: No target found in context.")
62
+ end
63
+ end
64
+ end
@@ -1,34 +1,34 @@
1
- # coding: utf-8
2
-
3
- #* compiler/context/locals.rb - Support local methods in context.
4
- module XfOOrth
5
-
6
- #* compiler/context/locals.rb - Support local methods in context.
7
- class Context
8
-
9
- #Create a local method on this context.
10
- #<br>Parameters:
11
- #* name - The name of the method to create.
12
- #* spec_class - The specification class to use.
13
- #* options - An array of options.
14
- #* block - A block to associate with the name.
15
- #<br>Returns
16
- #* The spec created for the shared method.
17
- def create_local_method(name, spec_class, options, &block)
18
- sym = SymbolMap.add_entry(name)
19
- self[sym] = spec_class.new(name, sym, options, &block)
20
- end
21
-
22
- #Remove a local method on this context.
23
- #<br>Parameters:
24
- #* The name of the method to remove.
25
- def remove_local_method(name)
26
- if (sym = SymbolMap.map(name))
27
- @data.delete(sym)
28
- else
29
- error "F90: Unable to remove local method #{name}"
30
- end
31
- end
32
-
33
- end
34
- end
1
+ # coding: utf-8
2
+
3
+ #* compiler/context/locals.rb - Support local methods in context.
4
+ module XfOOrth
5
+
6
+ #* compiler/context/locals.rb - Support local methods in context.
7
+ class Context
8
+
9
+ #Create a local method on this context.
10
+ #<br>Parameters:
11
+ #* name - The name of the method to create.
12
+ #* spec_class - The specification class to use.
13
+ #* options - An array of options.
14
+ #* block - A block to associate with the name.
15
+ #<br>Returns
16
+ #* The spec created for the shared method.
17
+ def create_local_method(name, spec_class, options, &block)
18
+ sym = SymbolMap.add_entry(name)
19
+ self[sym] = spec_class.new(name, sym, options, &block)
20
+ end
21
+
22
+ #Remove a local method on this context.
23
+ #<br>Parameters:
24
+ #* The name of the method to remove.
25
+ def remove_local_method(name)
26
+ if (sym = SymbolMap.map(name))
27
+ @data.delete(sym)
28
+ else
29
+ error "F90: Unable to remove local method #{name}"
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -1,74 +1,85 @@
1
- # coding: utf-8
2
-
3
- #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
4
- module XfOOrth
5
-
6
- #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
7
- class Context
8
-
9
- #Map a name to a specification.
10
- #<br>Parameters:
11
- #* name - The string to be mapped.
12
- #<br>Returns:
13
- #* The specification that corresponds to the name or nil if none found.
14
- def map(name, allow_defaults=:allow)
15
- if (@symbol = SymbolMap.map(@name = name))
16
- do_map_name(allow_defaults)
17
- end
18
- end
19
-
20
- #Private methods follow.
21
- private
22
-
23
- #Do a search of dictionaries based on the syntax of the name.
24
- def do_map_name(allow_defaults)
25
- self[@symbol] ||
26
- do_target_class_map ||
27
- do_target_object_map ||
28
- do_target_vm_map ||
29
- do_object_class_map ||
30
- do_global_map ||
31
- (allow_defaults && case @name[0]
32
- when '.'
33
- TosSpec.new(@name, @symbol, [:temp])
34
-
35
- when '~'
36
- SelfSpec.new(@name, @symbol, [:temp])
37
-
38
- else
39
- spec_error
40
- end)
41
- end
42
-
43
- #Do a search of the Object class for the item.
44
- def do_object_class_map
45
- Object.map_foorth_shared(@symbol)
46
- end
47
-
48
- #Do a search of the :cls tag if it is specified.
49
- def do_target_class_map
50
- (tc = self[:cls]) && tc.map_foorth_shared(@symbol)
51
- end
52
-
53
- #Do a search of the :obj tag if it is specified.
54
- def do_target_object_map
55
- (to = self[:obj]) && to.map_foorth_exclusive(@symbol)
56
- end
57
-
58
- #Do a search of the :vm tag if it is specified.
59
- def do_target_vm_map
60
- (vm = self[:vm]) && vm.map_foorth_exclusive(@symbol)
61
- end
62
-
63
- #Do a search of the globals.
64
- def do_global_map
65
- $FOORTH_GLOBALS[@symbol]
66
- end
67
-
68
- #Error: Unable to find a specification.
69
- def spec_error
70
- error "F11: ?#{@name}?"
71
- end
72
-
73
- end
74
- end
1
+ # coding: utf-8
2
+
3
+ #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
4
+ module XfOOrth
5
+
6
+ #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
7
+ class Context
8
+
9
+ #Map a name to a specification.
10
+ #<br>Parameters:
11
+ #* name - The string to be mapped.
12
+ #<br>Returns:
13
+ #* The specification that corresponds to the name or nil if none found.
14
+ def map_with_defaults(name)
15
+ if (@symbol = SymbolMap.map(@name = name))
16
+ do_map_name ||
17
+ case @name[0]
18
+ when '.'
19
+ TosSpec.new(@name, @symbol, [:temp])
20
+
21
+ when '~'
22
+ SelfSpec.new(@name, @symbol, [:temp])
23
+
24
+ else
25
+ spec_error
26
+ end
27
+ end
28
+ end
29
+
30
+ #Map a name to a specification.
31
+ #<br>Parameters:
32
+ #* name - The string to be mapped.
33
+ #<br>Returns:
34
+ #* The specification that corresponds to the name or nil if none found.
35
+ def map_without_defaults(name)
36
+ if (@symbol = SymbolMap.map(@name = name))
37
+ do_map_name
38
+ end
39
+ end
40
+
41
+ #Private methods follow.
42
+ private
43
+
44
+ #Do a search of dictionaries based on the syntax of the name.
45
+ def do_map_name
46
+ self[@symbol] ||
47
+ do_target_class_map ||
48
+ do_target_object_map ||
49
+ do_target_vm_map ||
50
+ do_object_class_map ||
51
+ do_global_map
52
+ end
53
+
54
+ #Do a search of the Object class for the item.
55
+ def do_object_class_map
56
+ Object.map_foorth_shared(@symbol)
57
+ end
58
+
59
+ #Do a search of the :cls tag if it is specified.
60
+ def do_target_class_map
61
+ (tc = self[:cls]) && tc.map_foorth_shared(@symbol)
62
+ end
63
+
64
+ #Do a search of the :obj tag if it is specified.
65
+ def do_target_object_map
66
+ (to = self[:obj]) && to.map_foorth_exclusive(@symbol)
67
+ end
68
+
69
+ #Do a search of the :vm tag if it is specified.
70
+ def do_target_vm_map
71
+ (vm = self[:vm]) && vm.map_foorth_exclusive(@symbol)
72
+ end
73
+
74
+ #Do a search of the globals.
75
+ def do_global_map
76
+ $FOORTH_GLOBALS[@symbol]
77
+ end
78
+
79
+ #Error: Unable to find a specification.
80
+ def spec_error
81
+ error "F11: ?#{@name}?"
82
+ end
83
+
84
+ end
85
+ end