rltk 1.2.0 → 2.0.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.
data/Rakefile CHANGED
@@ -7,35 +7,33 @@
7
7
  # Rake Tasks #
8
8
  ##############
9
9
 
10
+ # Gems
10
11
  require 'rake/testtask'
11
12
  require 'bundler'
12
13
 
13
- begin
14
- require 'rdoc/task'
15
-
16
- RDoc::Task.new do |t|
17
- t.title = 'The Ruby Language Toolkit'
18
- t.main = 'README'
19
- t.rdoc_dir = 'doc'
20
-
21
- t.rdoc_files.include('README', 'lib/*.rb', 'lib/rltk/*.rb', 'lib/rltk/**/*.rb')
22
- end
23
-
24
- rescue LoadError
25
- warn 'RDoc is not installed.'
26
- end
14
+ require File.expand_path("../lib/rltk/version", __FILE__)
27
15
 
28
16
  begin
29
- require 'rcov/rcovtask'
30
-
31
- Rcov::RcovTask.new do |t|
32
- t.libs << 'test'
33
- t.rcov_opts << '--exclude gems,ruby'
34
- t.test_files = FileList['test/tc_*.rb']
17
+ require 'yard'
18
+
19
+ YARD::Rake::YardocTask.new do |t|
20
+ yardlib = File.join(File.dirname(__FILE__), 'yardlib/rltk.rb')
21
+
22
+ t.options = [
23
+ '-e', yardlib,
24
+ '--title', 'The Ruby Language Toolkit',
25
+ '-m', 'markdown',
26
+ '-M', 'redcarpet',
27
+ '-c', '.yardoc/cache',
28
+ '--private'
29
+ ]
30
+
31
+
32
+ t.files = Dir['lib/**/*.rb'] + ['-'] + Dir['examples/kazoo/**/*.md'].sort
35
33
  end
36
34
 
37
35
  rescue LoadError
38
- warn 'Rcov not installed.'
36
+ warn 'Yard is not installed. `gem install yard` to build documentation.'
39
37
  end
40
38
 
41
39
  Rake::TestTask.new do |t|
@@ -44,4 +42,141 @@ Rake::TestTask.new do |t|
44
42
  t.test_files = FileList['test/ts_rltk.rb']
45
43
  end
46
44
 
45
+ if RUBY_VERSION[0..2] == '1.8'
46
+ begin
47
+ require 'rcov/rcovtask'
48
+
49
+ Rcov::RcovTask.new do |t|
50
+ t.libs << 'test'
51
+ t.rcov_opts << '--exclude gems,ruby'
52
+
53
+ t.test_files = FileList['test/tc_*.rb']
54
+ end
55
+
56
+ rescue LoadError
57
+ warn 'Rcov not installed.'
58
+ end
59
+ end
60
+
61
+ # Bundler tasks.
47
62
  Bundler::GemHelper.install_tasks
63
+
64
+ # Rubygems Taks
65
+ begin
66
+ require 'rubygems/tasks'
67
+
68
+ Gem::Tasks.new do |t|
69
+ t.console.command = 'pry'
70
+ end
71
+
72
+ rescue LoadError
73
+ 'rubygems-tasks not installed.'
74
+ end
75
+
76
+ desc 'Generate the bindings for LLVM.'
77
+ task :gen_bindings do
78
+ require 'ffi_gen'
79
+
80
+ # Generate the standard LLVM bindings.
81
+
82
+ blacklist = [
83
+ 'LLVMGetMDNodeOperand',
84
+ 'LLVMGetMDNodeNumOperands',
85
+ 'LLVMInitializeAllTargetInfos',
86
+ 'LLVMInitializeAllTargets',
87
+ 'LLVMInitializeNativeTarget'
88
+ ]
89
+
90
+ deprecated = [
91
+ # BitReader.h
92
+ 'LLVMGetBitcodeModuleProviderInContext',
93
+ 'LLVMGetBitcodeModuleProvider',
94
+
95
+ # BitWriter.h
96
+ 'LLVMWriteBitcodeToFileHandle',
97
+
98
+ # Core.h
99
+ 'LLVMCreateFunctionPassManager',
100
+
101
+ # ExectionEngine.h
102
+ 'LLVMCreateExecutionEngine',
103
+ 'LLVMCreateInterpreter',
104
+ 'LLVMCreateJITCompiler',
105
+ 'LLVMAddModuleProvider',
106
+ 'LLVMRemoveModuleProvider'
107
+ ]
108
+
109
+ headers = [
110
+ 'llvm-c/Core.h',
111
+
112
+ 'llvm-c/Analysis.h',
113
+ 'llvm-c/BitReader.h',
114
+ 'llvm-c/BitWriter.h',
115
+ 'llvm-c/Disassembler.h',
116
+ 'llvm-c/ExecutionEngine.h',
117
+ 'llvm-c/Initialization.h',
118
+ 'llvm-c/Object.h',
119
+ 'llvm-c/Target.h',
120
+
121
+ 'llvm-c/Transforms/IPO.h',
122
+ 'llvm-c/Transforms/Scalar.h'
123
+ ]
124
+
125
+ FFIGen.generate(
126
+ :module_name => 'RLTK::CG::Bindings',
127
+ :ffi_lib => "LLVM-#{RLTK::LLVM_TARGET_VERSION}",
128
+ :headers => headers,
129
+ :cflags => `llvm-config --cflags`.split,
130
+ :prefixes => ['LLVM'],
131
+ :blacklist => blacklist + deprecated,
132
+ :output => 'lib/rltk/cg/generated_bindings.rb'
133
+ )
134
+
135
+ # Generate the extended LLVM bindings.
136
+
137
+ headers = [
138
+ 'llvm-ecb.h',
139
+
140
+ 'llvm-ecb/support.h'
141
+ ]
142
+
143
+ begin
144
+ FFIGen.generate(
145
+ :module_name => 'RLTK::CG::Bindings',
146
+ :ffi_lib => "LLVM-ECB-#{RLTK::LLVM_TARGET_VERSION}",
147
+ :headers => headers,
148
+ :cflags => `llvm-config --cflags`.split,
149
+ :prefixes => ['LLVM'],
150
+ :output => 'lib/rltk/cg/generated_extended_bindings.rb'
151
+ )
152
+ rescue
153
+ end
154
+ end
155
+
156
+ desc 'Find LLVM bindings with a regular expression.'
157
+ task :find_bind, :part do |t, args|
158
+
159
+ # Get the task argument.
160
+ part = Regexp.new(args[:part])
161
+
162
+ # Require the Bindings module.
163
+ require 'rltk/cg/bindings'
164
+
165
+ syms =
166
+ Symbol.all_symbols.select do |sym|
167
+ sym = sym.to_s.downcase
168
+
169
+ sym[0..3] == 'llvm' and sym[4..-1] =~ part
170
+ end.sort
171
+
172
+ puts
173
+ if not syms.empty?
174
+ puts "Matching bindings [#{syms.length}]:"
175
+ syms.each { |sym| puts "\t#{sym}" }
176
+
177
+ else
178
+ puts 'No matching bindings.'
179
+ end
180
+ puts
181
+ end
182
+
data/lib/rltk/ast.rb CHANGED
@@ -3,45 +3,52 @@
3
3
  # Date: 2011/01/19
4
4
  # Description: This file provides a base Node class for ASTs.
5
5
 
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/util/monkeys'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
6
17
  module RLTK # :nodoc:
7
- # A TypeMismatch is thrown when an object being set as a child or value of
18
+ # A TypeMismatch is raised when an object being set as a child or value of
8
19
  # an ASTNode is of the wrong type.
9
- class TypeMismatch < Exception
20
+ class TypeMismatch < StandardError
10
21
 
11
- # Instantiates a new TypeMismatch object. The first argument is the
12
- # expected type and the second argument is the actual type of the
13
- # object.
22
+ # Instantiates a new TypeMismatch object.
23
+ #
24
+ # @param [Class] expected Expected type.
25
+ # @param [Klass] actual Actual type of object.
14
26
  def initialize(expected, actual)
15
27
  @expected = expected
16
28
  @actual = actual
17
29
  end
18
30
 
19
- # Converts the exception to a string.
31
+ # @return [String] String representation of the error.
20
32
  def to_s
21
33
  "Type Mismatch: Expected #{@expected} but received #{@actual}."
22
34
  end
23
35
  end
24
36
 
25
- # Returns true if klass0 is a subclass of klass1; false otherwise.
26
- def self.subclass_of?(klass0, klass1)
27
- begin
28
- return true if klass0 == klass1
29
- end while klass0 = klass0.superclass
30
-
31
- return false
32
- end
33
-
34
37
  # This class is a good start for all your abstract syntax tree node needs.
35
38
  class ASTNode
36
- # A reference to the parent node.
39
+ # @return [ASTNode] Reference to the parent node.
37
40
  attr_accessor :parent
38
41
 
39
42
  #################
40
43
  # Class Methods #
41
44
  #################
42
45
 
43
- def ASTNode.inherited(klass)
44
- klass.class_exec do
46
+ class << self
47
+
48
+ # Installs instance class varialbes into a class.
49
+ #
50
+ # @return [void]
51
+ def install_icvars
45
52
  if self.superclass == ASTNode
46
53
  @child_names = Array.new
47
54
  @value_names = Array.new
@@ -49,126 +56,153 @@ module RLTK # :nodoc:
49
56
  @child_names = self.superclass.child_names.clone
50
57
  @value_names = self.superclass.value_names.clone
51
58
  end
59
+ end
60
+ protected :install_icvars
61
+
62
+ # Called when the Lexer class is sub-classed, it installes
63
+ # necessary instance class variables.
64
+ #
65
+ # @param [Class] klass The class is inheriting from this class.
66
+ #
67
+ # @return [void]
68
+ def inherited(klass)
69
+ klass.install_icvars
70
+ end
71
+
72
+ # Defined a child for this AST class and its subclasses.
73
+ # The name of the child will be used to define accessor
74
+ # methods that include type checking. The type of this
75
+ # child must be a subclass of the ASTNode class.
76
+ #
77
+ # @param [String, Symbol] name Name of child node.
78
+ # @param [Class] type Type of child node. Must be a subclass of ASTNode.
79
+ #
80
+ # @return [void]
81
+ def child(name, type)
82
+ if type.is_a?(Array) and type.length == 1
83
+ t = type.first
52
84
 
53
- # Defined a child for this AST class and its subclasses.
54
- # The name of the child will be used to define accessor
55
- # methods that include type checking. The type of this
56
- # child must be a subclass of the ASTNode class.
57
- def self.child(name, type)
58
- if type.is_a?(Array) and type.length == 1
59
- t = type.first
85
+ elsif type.is_a?(Class)
86
+ t = type
60
87
 
61
- elsif type.is_a?(Class)
62
- t = type
63
-
64
- else
65
- raise Exception, 'Child and Value types must be a class name or an array with a single class name element.'
66
- end
67
-
68
- # Check to make sure that type is a subclass of
69
- # ASTNode.
70
- if not RLTK::subclass_of?(t, ASTNode)
71
- raise Exception, "A child's type specification must be a subclass of ASTNode."
72
- end
73
-
74
- @child_names << name
75
- self.define_accessor(name, type, true)
88
+ else
89
+ raise 'Child and Value types must be a class name or an array with a single class name element.'
76
90
  end
77
91
 
78
- # Returns an array of the names of this node's children.
79
- def self.child_names
80
- @child_names
92
+ # Check to make sure that type is a subclass of
93
+ # ASTNode.
94
+ if not t.subclass_of?(ASTNode)
95
+ raise "A child's type specification must be a subclass of ASTNode."
81
96
  end
82
97
 
83
- # This method defines a type checking accessor named _name_
84
- # with type _type_.
85
- def self.define_accessor(name, type, set_parent = false)
86
- ivar_name = ('@' + name.to_s).to_sym
87
-
88
- define_method(name) do
89
- self.instance_variable_get(ivar_name)
90
- end
91
-
92
- if type.is_a?(Class)
93
- if set_parent
94
- define_method((name.to_s + '=').to_sym) do |value|
95
- if value.is_a?(type) or value == nil
96
- self.instance_variable_set(ivar_name, value)
97
-
98
- value.parent = self if value
99
- else
100
- raise TypeMismatch.new(type, value.class)
101
- end
102
- end
98
+ @child_names << name
99
+ define_accessor(name, type, true)
100
+ end
101
+
102
+ # @return [Array<Symbol>] Array of the names of this node class's children.
103
+ def child_names
104
+ @child_names
105
+ end
106
+
107
+ # This method defines a type checking accessor named *name*
108
+ # with type *type*.
109
+ #
110
+ # @param [String, Symbol] name Name of accessor.
111
+ # @param [Class] type Class used for type checking.
112
+ # @param [Boolean] set_parent Set the parent variable or not.
113
+ #
114
+ # @return [void]
115
+ def define_accessor(name, type, set_parent = false)
116
+ ivar_name = ('@' + name.to_s).to_sym
117
+
118
+ define_method(name) do
119
+ self.instance_variable_get(ivar_name)
120
+ end
121
+
122
+ if type.is_a?(Class)
123
+ if set_parent
124
+ define_method((name.to_s + '=').to_sym) do |value|
125
+ if value.is_a?(type) or value == nil
126
+ self.instance_variable_set(ivar_name, value)
103
127
 
104
- else
105
- define_method((name.to_s + '=').to_sym) do |value|
106
- if value.is_a?(type) or value == nil
107
- self.instance_variable_set(ivar_name, value)
108
-
109
- else
110
- raise TypeMismatch.new(type, value.class)
111
- end
128
+ value.parent = self if value
129
+ else
130
+ raise TypeMismatch.new(type, value.class)
112
131
  end
113
132
  end
114
133
 
115
134
  else
116
- type = type.first
117
-
118
- if set_parent
119
- define_method((name.to_s + '=').to_sym) do |value|
120
- if value.inject(true) { |m, o| m and o.is_a?(type) }
121
- self.instance_variable_set(ivar_name, value)
135
+ define_method((name.to_s + '=').to_sym) do |value|
136
+ if value.is_a?(type) or value == nil
137
+ self.instance_variable_set(ivar_name, value)
122
138
 
123
- value.each { |c| c.parent = self }
124
- else
125
- raise TypeMismatch.new(type, value.class)
126
- end
139
+ else
140
+ raise TypeMismatch.new(type, value.class)
127
141
  end
142
+ end
143
+ end
144
+
145
+ else
146
+ type = type.first
147
+
148
+ if set_parent
149
+ define_method((name.to_s + '=').to_sym) do |value|
150
+ if value.inject(true) { |m, o| m and o.is_a?(type) }
151
+ self.instance_variable_set(ivar_name, value)
128
152
 
129
- else
130
- define_method((name.to_s + '=').to_sym) do |value|
131
- if value.inject(true) { |m, o| m and o.is_a?(type) }
132
- self.instance_variable_set(ivar_name, value)
133
-
134
- else
135
- raise TypeMismatch.new(type, value.class)
136
- end
153
+ value.each { |c| c.parent = self }
154
+ else
155
+ raise TypeMismatch.new(type, value.class)
137
156
  end
138
157
  end
139
158
 
159
+ else
160
+ define_method((name.to_s + '=').to_sym) do |value|
161
+ if value.inject(true) { |m, o| m and o.is_a?(type) }
162
+ self.instance_variable_set(ivar_name, value)
163
+
164
+ else
165
+ raise TypeMismatch.new(type, value.class)
166
+ end
167
+ end
140
168
  end
141
169
  end
170
+ end
171
+ private :define_accessor
172
+
173
+ # Defined a value for this AST class and its subclasses.
174
+ # The name of the value will be used to define accessor
175
+ # methods that include type checking. The type of this
176
+ # value must NOT be a subclass of the ASTNode class.
177
+ #
178
+ # @param [String, Symbol] name Name of value.
179
+ # @param [Class] type Type of value. Must NOT be a subclass of ASTNode.
180
+ #
181
+ # @return [void]
182
+ def value(name, type)
183
+ if type.is_a?(Array) and type.length == 1
184
+ t = type.first
142
185
 
143
- # Defined a value for this AST class and its subclasses.
144
- # The name of the value will be used to define accessor
145
- # methods that include type checking. The type of this
146
- # value must NOT be a subclass of the ASTNode class.
147
- def self.value(name, type)
148
- if type.is_a?(Array) and type.length == 1
149
- t = type.first
186
+ elsif type.is_a?(Class)
187
+ t = type
150
188
 
151
- elsif type.is_a?(Class)
152
- t = type
153
-
154
- else
155
- raise Exception, 'Child and Value types must be a class name or an array with a single class name element.'
156
- end
157
-
158
- # Check to make sure that type is NOT a subclass of
159
- # ASTNode.
160
- if RLTK::subclass_of?(t, ASTNode)
161
- raise Exception, "A value's type specification must NOT be a subclass of ASTNode."
162
- end
163
-
164
- @value_names << name
165
- self.define_accessor(name, type)
189
+ else
190
+ raise 'Child and Value types must be a class name or an array with a single class name element.'
166
191
  end
167
192
 
168
- # Returns an array of the names of this node's values.
169
- def self.value_names
170
- @value_names
193
+ # Check to make sure that type is NOT a subclass of
194
+ # ASTNode.
195
+ if t.subclass_of?(ASTNode)
196
+ raise "A value's type specification must NOT be a subclass of ASTNode."
171
197
  end
198
+
199
+ @value_names << name
200
+ define_accessor(name, type)
201
+ end
202
+
203
+ # @return [Array<Symbol>] Array of the names of this node class's values.
204
+ def value_names
205
+ @value_names
172
206
  end
173
207
  end
174
208
 
@@ -177,31 +211,39 @@ module RLTK # :nodoc:
177
211
  ####################
178
212
 
179
213
  # Used for AST comparison, this function will return true if the two
180
- # nodes are of the same class and all of their values and children are
181
- # equal.
214
+ # nodes are of the same class and all of their values and children
215
+ # are equal.
216
+ #
217
+ # @param [ASTNode] other The ASTNode to compare to.
218
+ #
219
+ # @return [Boolean]
182
220
  def ==(other)
183
221
  self.class == other.class and self.values == other.values and self.children == other.children
184
222
  end
185
223
 
186
- # Returns the note with name _key_.
224
+ # @return [Object] Note with the name *key*.
187
225
  def [](key)
188
226
  @notes[key]
189
227
  end
190
228
 
191
- # Sets the note named _key_ to _value_.
229
+ # Sets the note named *key* to *value*.
192
230
  def []=(key, value)
193
231
  @notes[key] = value
194
232
  end
195
233
 
196
- # Returns an array of this node's children.
234
+ # @return [Array<ASTNode>] Array of this node's children.
197
235
  def children
198
236
  self.class.child_names.map { |name| self.send(name) }
199
237
  end
200
238
 
201
239
  # Assigns an array of AST nodes as the children of this node.
240
+ #
241
+ # @param [Array<ASTNode>] children Children to be assigned to this node.
242
+ #
243
+ # @return [void]
202
244
  def children=(children)
203
245
  if children.length != self.class.child_names.length
204
- raise Exception, 'Wrong number of children specified.'
246
+ raise 'Wrong number of children specified.'
205
247
  end
206
248
 
207
249
  self.class.child_names.each_with_index do |name, i|
@@ -209,8 +251,11 @@ module RLTK # :nodoc:
209
251
  end
210
252
  end
211
253
 
212
- # Removes the note _key_ from this node. If the _recursive_ argument
254
+ # Removes the note *key* from this node. If the *recursive* argument
213
255
  # is true it will also remove the note from the node's children.
256
+ #
257
+ # @param [Object] key The key of the note to remove.
258
+ # @param [Boolean] recursive Do a recursive removal or not.
214
259
  def delete_note(key, recursive = true)
215
260
  if recursive
216
261
  self.children.each do |child|
@@ -228,15 +273,16 @@ module RLTK # :nodoc:
228
273
  end
229
274
 
230
275
  # An iterator over the node's children.
276
+ #
277
+ # @return [void]
231
278
  def each
232
279
  self.children.each { |c| yield c }
233
280
  end
234
281
 
235
- # Tests to see if a note named _key_ is present at this node.
282
+ # Tests to see if a note named *key* is present at this node.
236
283
  def has_note?(key)
237
284
  @notes.has_key?(key)
238
285
  end
239
-
240
286
  alias :'note?' :'has_note?'
241
287
 
242
288
  # Instantiates a new ASTNode object. The arguments to this method are
@@ -245,9 +291,11 @@ module RLTK # :nodoc:
245
291
  # pass the values in as the first two arguments (in the order they
246
292
  # were declared) and then the children as the remaining arguments (in
247
293
  # the order they were declared).
294
+ #
295
+ # @param [Array<Object>] objects The values and children of this node.
248
296
  def initialize(*objects)
249
297
  if self.class == RLTK::ASTNode
250
- raise Exception, 'Attempting to instantiate the RLTK::ASTNode class.'
298
+ raise 'Attempting to instantiate the RLTK::ASTNode class.'
251
299
  else
252
300
  @notes = Hash.new()
253
301
  @parent = nil
@@ -260,24 +308,28 @@ module RLTK # :nodoc:
260
308
  end
261
309
 
262
310
  # Maps the children of the ASTNode from one value to another.
311
+ #
312
+ # @return [void]
263
313
  def map
264
314
  self.children = self.children.map { |c| yield c }
265
315
  end
266
316
 
267
- # Find the root of an AST.
317
+ # @return [ASTNode] Root of the abstract syntax tree.
268
318
  def root
269
319
  if @parent then @parent.root else self end
270
320
  end
271
321
 
272
- # Returns an array of this node's values.
322
+ # @return [Array<Object>] Array of this node's values.
273
323
  def values
274
324
  self.class.value_names.map { |name| self.send(name) }
275
325
  end
276
326
 
277
327
  # Assigns an array of objects as the values of this node.
328
+ #
329
+ # @param [Array<Object>] values The values to be assigned to this node.
278
330
  def values=(values)
279
331
  if values.length != self.class.value_names.length
280
- raise Exception, 'Wrong number of values specified.'
332
+ raise 'Wrong number of values specified.'
281
333
  end
282
334
 
283
335
  self.class.value_names.each_with_index do |name, i|