rltk 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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|