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/lib/rltk/cfg.rb CHANGED
@@ -21,18 +21,20 @@ module RLTK # :nodoc:
21
21
 
22
22
  # An exception class that represents a problem with a context-free
23
23
  # grammar's definition.
24
- class GrammarError < Exception; end
24
+ class GrammarError < StandardError; end
25
25
 
26
26
  # The CFG class is used to represent context-free grammars. It is used by
27
27
  # the RLTK::Parser class to represent the parser's grammar, but can also be
28
28
  # used to manipulate arbitrary CFGs.
29
29
  class CFG
30
30
 
31
- # The start symbol for the grammar.
31
+ # @return [Symbol] The grammar's starting symbol.
32
32
  attr_reader :start_symbol
33
33
 
34
- # The current left-hand side symbol. This is used by the
35
- # CFG.production method to wrap CFG.clause calls.
34
+ # This is used by the {CFG#production} method to wrap {CFG#clause}
35
+ # calls.
36
+ #
37
+ # @return [Symbol] The current left-hand side symbol.
36
38
  attr_accessor :curr_lhs
37
39
 
38
40
  #################
@@ -41,12 +43,20 @@ module RLTK # :nodoc:
41
43
 
42
44
  # Tests to see if a symbol is a terminal symbol, as used by the CFG
43
45
  # class.
46
+ #
47
+ # @param [Symbol] sym The symbol to test.
48
+ #
49
+ # @return [Boolean]
44
50
  def self.is_terminal?(sym)
45
51
  sym and (s = sym.to_s) == s.upcase
46
52
  end
47
53
 
48
54
  # Tests to see if a symbol is a non-terminal symbol, as used by the
49
55
  # CFG class.
56
+ #
57
+ # @param [Symbol] sym The symbol to test.
58
+ #
59
+ # @return [Boolean]
50
60
  def self.is_nonterminal?(sym)
51
61
  sym and (s = sym.to_s) == s.downcase
52
62
  end
@@ -55,9 +65,11 @@ module RLTK # :nodoc:
55
65
  # Instance Methods #
56
66
  ####################
57
67
 
58
- # Instantiates a new CFG object that uses _callback_ to inform the
68
+ # Instantiates a new CFG object that uses *callback* to inform the
59
69
  # programmer of the generation of new productions due to EBNF
60
70
  # operators.
71
+ #
72
+ # @param [Proc] callback A Proc object to be called when EBNF operators are expanded.
61
73
  def initialize(&callback)
62
74
  @curr_lhs = nil
63
75
  @callback = callback || Proc.new {}
@@ -77,12 +89,20 @@ module RLTK # :nodoc:
77
89
  @follows = Hash.new { |h,k| h[k] = Array.new }
78
90
  end
79
91
 
80
- # Adds _production_ to the appropriate internal data structures.
92
+ # Adds *production* to the appropriate internal data structures.
93
+ #
94
+ # @param [Production] production The production to add to the grammar.
95
+ #
96
+ # @return [void]
81
97
  def add_production(production)
82
98
  @productions_sym[production.lhs] << (@productions_id[production.id] = production)
83
99
  end
84
100
 
85
- # Sets the EBNF callback to _callback_.
101
+ # Sets the EBNF callback to *callback*.
102
+ #
103
+ # @param [Proc] callback A Proc object to be called when EBNF operators are expanded.
104
+ #
105
+ # @return [void]
86
106
  def callback(&callback)
87
107
  @callback = callback || Proc.new {}
88
108
  end
@@ -91,6 +111,10 @@ module RLTK # :nodoc:
91
111
  # make a new production with the left-hand side specified by the
92
112
  # CFG.production call's argument. This is the function that is
93
113
  # responsible for removing EBNF symbols from the grammar.
114
+ #
115
+ # @param [String] expression The right-hand side of a CFG production.
116
+ #
117
+ # @return [Production]
94
118
  def clause(expression)
95
119
  if not @curr_lhs
96
120
  raise GrammarError, 'CFG.clause called outside of CFG.production block.'
@@ -150,11 +174,12 @@ module RLTK # :nodoc:
150
174
  return production
151
175
  end
152
176
 
153
- # Returns the _first_ set for _sentence_. _Sentence_ may be either a
154
- # single symbol or an array of symbols.
177
+ # @param [Symbol, Array<Symbol>] sentence Sentence to find the *first set* for.
178
+ #
179
+ # @return [Array<Symbol>] The *first set* for the given sentence.
155
180
  def first_set(sentence)
156
181
  if sentence.is_a?(Symbol)
157
- self.first_set_prime(sentence)
182
+ first_set_prime(sentence)
158
183
 
159
184
  elsif sentence.inject(true) { |m, sym| m and self.symbols.include?(sym) }
160
185
  set0 = []
@@ -167,14 +192,18 @@ module RLTK # :nodoc:
167
192
  end
168
193
 
169
194
  if all_have_empty then set0 + [:'ɛ'] else set0 end
170
- else
171
- nil
172
195
  end
173
196
  end
174
197
 
175
- # This function is responsible for calculating the _first_ set of
176
- # individual symbols. CFG.first_set is a wrapper around this function
177
- # to provide support for calculating the _first_ set for sentences.
198
+ # This function is responsible for calculating the *first* set of
199
+ # individual symbols. {CFG#first_set} is a wrapper around this
200
+ # function to provide support for calculating the *first* set for
201
+ # sentences.
202
+ #
203
+ # @param [Symbol] sym0 The symbol to find the *first set* of.
204
+ # @param [Array<Symbol>] seen_lh_sides Previously seen LHS symbols.
205
+ #
206
+ # @return [Array<Symbol>]
178
207
  def first_set_prime(sym0, seen_lh_sides = [])
179
208
  if self.symbols.include?(sym0)
180
209
  # Memoize the result for later.
@@ -202,7 +231,7 @@ module RLTK # :nodoc:
202
231
  # Grab the First set for the current
203
232
  # symbol in this production.
204
233
  if not seen_lh_sides.include?(sym1)
205
- set0 |= (set1 = self.first_set_prime(sym1, seen_lh_sides << sym1)) - [:'ɛ']
234
+ set0 |= (set1 = first_set_prime(sym1, seen_lh_sides << sym1)) - [:'ɛ']
206
235
  end
207
236
 
208
237
  break if not (all_have_empty = set1.include?(:'ɛ'))
@@ -218,13 +247,19 @@ module RLTK # :nodoc:
218
247
  set0.uniq
219
248
  end
220
249
  else
221
- nil
250
+ []
222
251
  end
223
252
  end
253
+ private :first_set_prime
224
254
 
225
- # Returns the _follow_ set for a given symbol. The second argument is
255
+ # Returns the *follow* set for a given symbol. The second argument is
226
256
  # used to avoid infinite recursion when mutually recursive rules are
227
257
  # encountered.
258
+ #
259
+ # @param [Symbol] sym0 The symbol to find the *follow set* for.
260
+ # @param [Array<Symbol>] seen_lh_sides Previously seen LHS symbols.
261
+ #
262
+ # @return [Array<Symbol>]
228
263
  def follow_set(sym0, seen_lh_sides = [])
229
264
 
230
265
  # Use the memoized set if possible.
@@ -262,6 +297,10 @@ module RLTK # :nodoc:
262
297
  end
263
298
 
264
299
  # Builds productions used to eliminate the + EBNF operator.
300
+ #
301
+ # @param [Symbol] symbol Symbol to expand.
302
+ #
303
+ # @return [Symbol]
265
304
  def get_plus(symbol)
266
305
  new_symbol = (symbol.to_s.downcase + '_plus').to_sym
267
306
 
@@ -286,6 +325,10 @@ module RLTK # :nodoc:
286
325
  end
287
326
 
288
327
  # Builds productions used to eliminate the ? EBNF operator.
328
+ #
329
+ # @param [Symbol] symbol Symbol to expand.
330
+ #
331
+ # @return [Symbol]
289
332
  def get_question(symbol)
290
333
  new_symbol = (symbol.to_s.downcase + '_question').to_sym
291
334
 
@@ -310,6 +353,10 @@ module RLTK # :nodoc:
310
353
  end
311
354
 
312
355
  # Builds productions used to eliminate the * EBNF operator.
356
+ #
357
+ # @param [Symbol] symbol Symbol to expand.
358
+ #
359
+ # @return [Symbol]
313
360
  def get_star(symbol)
314
361
  new_symbol = (symbol.to_s.downcase + '_star').to_sym
315
362
 
@@ -333,21 +380,26 @@ module RLTK # :nodoc:
333
380
  return new_symbol
334
381
  end
335
382
 
336
- # Returns the ID for the next production to be defined.
383
+ # @return [Integer] ID for the next production to be defined.
337
384
  def next_id
338
385
  @production_counter += 1
339
386
  end
340
387
 
341
- # Returns all of the non-terminal symbols used in the gramar's
342
- # definition.
388
+ # @return [Array<Symbol>] All terminal symbols used in the grammar's definition.
343
389
  def nonterms
344
390
  @nonterms.keys
345
391
  end
346
392
 
347
- # Builds a new production with the left-hand side value of _symbol_.
348
- # If _expression_ is specified it is take as the right-hand side of
349
- # production. If _expression_ is nil then _block_ is evaluated, and
350
- # expected to make one or more calls to CFG.clause.
393
+ # Builds a new production with the left-hand side value of *symbol*.
394
+ # If *expression* is specified it is take as the right-hand side of
395
+ # production. If *expression* is nil then *block* is evaluated, and
396
+ # expected to make one or more calls to {CFG#clause}.
397
+ #
398
+ # @param [Symbol] symbol The right-hand side of a production.
399
+ # @param [String] expression The left-hand side of a production.
400
+ # @param [Proc] block Optional block for defining production clauses.
401
+ #
402
+ # @return [Array<Production>]
351
403
  def production(symbol, expression = nil, &block)
352
404
  @production_buffer = Array.new
353
405
  @curr_lhs = symbol
@@ -362,10 +414,14 @@ module RLTK # :nodoc:
362
414
  return @production_buffer.clone
363
415
  end
364
416
 
365
- # If _by_ is :sym, returns a hash of the grammar's productions, using
366
- # the productions' left-hand side symbol as the key. If _by_ is :id
417
+ # If *by* is :sym, returns a hash of the grammar's productions, using
418
+ # the productions' left-hand side symbol as the key. If *by* is :id
367
419
  # an array of productions is returned in the order of their
368
420
  # definition.
421
+ #
422
+ # @param [:sym, :id] by The way in which productions should be returned.
423
+ #
424
+ # @return [Array<Production>, Hash{Symbol => Production}]
369
425
  def productions(by = :sym)
370
426
  if by == :sym
371
427
  @productions_sym
@@ -377,6 +433,10 @@ module RLTK # :nodoc:
377
433
  end
378
434
 
379
435
  # Sets the start symbol for this grammar.
436
+ #
437
+ # @param [Symbol] symbol The new start symbol.
438
+ #
439
+ # @return [Symbol]
380
440
  def start(symbol)
381
441
  if not CFG::is_nonterminal?(symbol)
382
442
  raise GrammarError, 'Start symbol must be a non-terminal.'
@@ -385,13 +445,12 @@ module RLTK # :nodoc:
385
445
  @start_symbol = symbol
386
446
  end
387
447
 
388
- # Returns a list of symbols encountered in the grammar's definition.
448
+ # @return [Array<Symbol>] All symbols used in the grammar's definition.
389
449
  def symbols
390
450
  self.terms + self.nonterms
391
451
  end
392
452
 
393
- # Returns a list of all terminal symbols encountered in the grammar's
394
- # definition.
453
+ # @return [Array<Symbol>] All terminal symbols used in the grammar's definition.
395
454
  def terms
396
455
  @terms.keys
397
456
  end
@@ -399,12 +458,21 @@ module RLTK # :nodoc:
399
458
  # Oddly enough, the Production class represents a production in a
400
459
  # context-free grammar.
401
460
  class Production
461
+ # @return [Integer] ID of this production.
402
462
  attr_reader :id
463
+
464
+ # @return [Symbol] Left-hand side of this production.
403
465
  attr_reader :lhs
466
+
467
+ # @return [Array<Symbol>] Right-hand side of this production.
404
468
  attr_reader :rhs
405
469
 
406
470
  # Instantiates a new Production object with the specified ID,
407
471
  # and left- and right-hand sides.
472
+ #
473
+ # @param [Integer] id ID number of this production.
474
+ # @param [Symbol] lhs Left-hand side of the production.
475
+ # @param [Array<Symbol>] rhs Right-hand side of the production.
408
476
  def initialize(id, lhs, rhs)
409
477
  @id = id
410
478
  @lhs = lhs
@@ -413,27 +481,34 @@ module RLTK # :nodoc:
413
481
 
414
482
  # Comparese on production to another. Returns true only if the
415
483
  # left- and right- hand sides match.
484
+ #
485
+ # @param [Production] other Another production to compare to.
486
+ #
487
+ # @return [Boolean]
416
488
  def ==(other)
417
489
  self.lhs == other.lhs and self.rhs == other.rhs
418
490
  end
419
491
 
420
- # Makes a new copy of the production.
492
+ # @return [Production] A new copy of this production.
421
493
  def copy
422
494
  Production.new(@id, @lhs, @rhs.clone)
423
495
  end
424
496
 
425
- # Locates the last terminal in the right-hand side of a
426
- # production.
497
+ # @return [Symbol] The last terminal in the right-hand side of the production.
427
498
  def last_terminal
428
499
  @rhs.inject(nil) { |m, sym| if CFG::is_terminal?(sym) then sym else m end }
429
500
  end
430
501
 
431
- # Returns a new Item based on this production.
502
+ # @return [Item] An Item based on this production.
432
503
  def to_item
433
504
  Item.new(0, @id, @lhs, @rhs)
434
505
  end
435
506
 
436
507
  # Returns a string representation of this production.
508
+ #
509
+ # @param [Integer] padding The ammount of padding spaces to add to the beginning of the string.
510
+ #
511
+ # @return [String]
437
512
  def to_s(padding = 0)
438
513
  "#{format("%-#{padding}s", @lhs)} -> #{@rhs.map { |s| s.to_s }.join(' ')}"
439
514
  end
@@ -441,12 +516,16 @@ module RLTK # :nodoc:
441
516
 
442
517
  # The Item class represents a CFG production with dot in it.
443
518
  class Item < Production
519
+ # @return [Integer] Index of the next symbol in this item.
444
520
  attr_reader :dot
445
521
 
446
522
  # Instantiates a new Item object with a dot located before the
447
- # symbol at index _dot_ of the right-hand side. The remaining
448
- # arguments (_args_) should be as specified by
449
- # Production.initialize.
523
+ # symbol at index *dot* of the right-hand side. The remaining
524
+ # arguments (*args*) should be as specified by
525
+ # {Production#initialize}.
526
+ #
527
+ # @param [Integer] dot Location of the dot in this Item.
528
+ # @param [Array<Object>] args (see {Production#initialize})
450
529
  def initialize(dot, *args)
451
530
  super(*args)
452
531
 
@@ -455,12 +534,18 @@ module RLTK # :nodoc:
455
534
  end
456
535
 
457
536
  # Compares two items.
537
+ #
538
+ # @param [Item] other Another item to compare to.
539
+ #
540
+ # @return [Boolean]
458
541
  def ==(other)
459
542
  self.dot == other.dot and self.lhs == other.lhs and self.rhs == other.rhs
460
543
  end
461
544
 
462
545
  # Moves the items dot forward by one if the end of the right-hand
463
546
  # side hasn't already been reached.
547
+ #
548
+ # @return [Integer, nil]
464
549
  def advance
465
550
  if @dot < @rhs.length
466
551
  @dot += 1
@@ -468,21 +553,29 @@ module RLTK # :nodoc:
468
553
  end
469
554
 
470
555
  # Tests to see if the dot is at the end of the right-hand side.
556
+ #
557
+ # @return [Boolean]
471
558
  def at_end?
472
559
  @dot == @rhs.length
473
560
  end
474
561
 
475
- # Produces a new copy of this item.
562
+ # @return [Item] A new copy of this item.
476
563
  def copy
477
564
  Item.new(@dot, @id, @lhs, @rhs.clone)
478
565
  end
479
566
 
480
567
  # Returns the symbol located after the dot.
568
+ #
569
+ # @return [Symbol] Symbol located after the dot (at the index indicated by the {#dot} attribute).
481
570
  def next_symbol
482
571
  @rhs[@dot]
483
572
  end
484
573
 
485
574
  # Returns a string representation of this item.
575
+ #
576
+ # @param [Integer] padding The ammount of padding spaces to add to the beginning of the string.
577
+ #
578
+ # @return [String]
486
579
  def to_s(padding = 0)
487
580
  "#{format("%-#{padding}s", @lhs)} -> #{@rhs.map { |s| s.to_s }.insert(@dot, '·').join(' ') }"
488
581
  end
@@ -0,0 +1,167 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/04/07
4
+ # Description: This file defines the BasicBlock class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+ require 'rltk/cg/context'
13
+ require 'rltk/cg/value'
14
+
15
+ #######################
16
+ # Classes and Modules #
17
+ #######################
18
+
19
+ module RLTK::CG # :nodoc:
20
+
21
+ # A BasicBlock is what instructions are inserted into and what functions
22
+ # are made of. BasicBlock objects may be created either using
23
+ # BasicBlock.new or using the {Function::BasicBlockCollection#append}
24
+ # method.
25
+ class BasicBlock < Value
26
+
27
+ # Create a new BasicBlock object. The way the block is created is
28
+ # determined by the *overloaded* parameter. If it is a Function
29
+ # object then the new block is appended to the end of the function.
30
+ # If *overloaded* is another BasicBlock object the new block will
31
+ # be inserted before that block.
32
+ #
33
+ # A block may be given to this function to be invoked by {#build}.
34
+ #
35
+ # @param [FFI::Pointer, Function, BasicBlock] overloaded Overloaded paramater that determines creation behaviour.
36
+ #
37
+ # @param [String] name Name of this BasicBlock.
38
+ # @param [Context, nil] context Context in which to create the block.
39
+ # @param [Builder, nil] builder Builder to be used by {#build}.
40
+ # @param [Array<Object>] block_args Arguments to be passed when block is invoked.
41
+ # @param [Proc] block Block to be invoked by {#build}.
42
+ def initialize(overloaded, name = '', context = nil, builder = nil, *block_args, &block)
43
+ check_type(context, Context, 'context') if context
44
+
45
+ @ptr =
46
+ case overloaded
47
+ when FFI::Pointer
48
+ overloaded
49
+
50
+ when Function
51
+ if context
52
+ Bindings.append_basic_block_in_context(context, overloaded, name)
53
+ else
54
+ Bindings.append_basic_block(overloaded, name)
55
+ end
56
+
57
+ when BasicBlock
58
+ if context
59
+ Bindings.insert_basic_block_in_context(context, overloaded, name)
60
+ else
61
+ Bindings.insert_basic_block(overloaded, name)
62
+ end
63
+ end
64
+
65
+ self.build(builder, *block_args, &block) if block
66
+ end
67
+
68
+ # Used to add instructions to a BasicBlock. The block given to this
69
+ # method is executed inside the context of a {Builder} object, either
70
+ # the one passed in the *builder* parameter or one created for this
71
+ # call. Arguments may be passed into this block via the *block_args*
72
+ # parameter.
73
+ #
74
+ # @example
75
+ # fun = Function.new(...)
76
+ # block.build do
77
+ # ret add(fun.params[0], fun.params[1])
78
+ # end
79
+ #
80
+ # @param [Builder, nil] builder Builder in which to execute this block.
81
+ # @param [Array<Object>] block_args Arguments to pass into block.
82
+ # @param [Proc] block Block to execute inside builder.
83
+ #
84
+ # @return [Object] Value the block evaluates to. Usually an {Instruction}
85
+ def build(builder = nil, *block_args, &block)
86
+ if builder
87
+ builder.build(self, *block_args, &block)
88
+
89
+ else
90
+ builder = Builder.new
91
+ last_inst = builder.build(self, *block_args, &block)
92
+
93
+ builder.dispose
94
+
95
+ last_inst
96
+ end
97
+ end
98
+
99
+ # Creates a new BasicBlock inserted immediately before this block.
100
+ #
101
+ # @param [String] name Name of this BasicBlock.
102
+ # @param [Context] context Context in which to create this BasicBlock.
103
+ #
104
+ # @return [BasicBlock]
105
+ def insert_before(name = '', context = nil)
106
+ BasicBlock.new(self, name, context)
107
+ end
108
+
109
+ # @return [InstructionCollect] Collection of all instructions inside this BasicBlock.
110
+ def instructions
111
+ @instructions ||= InstructionCollection.new(self)
112
+ end
113
+
114
+ # @return [BasicBlock, nil] BasicBlock that occures immediately after this block or nil.
115
+ def next
116
+ if (ptr = Bindings.get_next_basic_block(@ptr)).null? then nil else BasicBlock.new(ptr) end
117
+ end
118
+
119
+ # @return [Function] Function object that this BasicBlock belongs to.
120
+ def parent
121
+ if (ptr = Bindings.get_basic_block_parent(@ptr)).null? then nil else Function.new(ptr) end
122
+ end
123
+
124
+ # @return [BasicBlock, nil] BasicBlock that occures immediately before this block or nil.
125
+ def previous
126
+ if (ptr = Bindings.get_previous_basic_block(@ptr)).null? then nil else BasicBlock.new(ptr) end
127
+ end
128
+
129
+ # This class is used to access all of the {Instruction Instructions} that have been added to a {BasicBlock}.
130
+ class InstructionCollection
131
+ include Enumerable
132
+
133
+ # @param [BasicBlock] bb BasicBlock this collection belongs to.
134
+ def initialize(bb)
135
+ @bb = bb
136
+ end
137
+
138
+ # Iterate over each {Instruction} in this collection.
139
+ #
140
+ # @yieldparam inst [Instruction]
141
+ #
142
+ # @return [Enumerator] An Enumerator is returned if no block is given.
143
+ def each
144
+ return to_enum(:each) unless block_given?
145
+
146
+ inst = self.first
147
+
148
+ while inst
149
+ yield inst
150
+ inst = inst.next
151
+ end
152
+
153
+ self
154
+ end
155
+
156
+ # @return [Instruction] First instruction in this collection.
157
+ def first
158
+ if (ptr = Bindings.get_first_instruction(@bb)).null? then nil else Instruction.from_ptr(ptr) end
159
+ end
160
+
161
+ # @return [Instruction] Last instruction in this collection.
162
+ def last
163
+ if (ptr = Bindings.get_last_instruction(@bb)).null? then nil else Instruction.from_ptr(ptr) end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,136 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/08
4
+ # Description: This file holds bindings to LLVM.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Gems
11
+ require 'rubygems'
12
+ require 'ffi'
13
+
14
+ # Ruby Language Toolkit
15
+ require 'rltk/util/monkeys'
16
+ require 'rltk/version'
17
+ require 'rltk/cg'
18
+
19
+ #######################
20
+ # Classes and Modules #
21
+ #######################
22
+
23
+ module RLTK::CG # :nodoc:
24
+
25
+ # This module provides access to stored FFI::Pointer objects and allows a
26
+ # class to be passed directly into FFI methods. It also provides a
27
+ # pointer comparison method.
28
+ module BindingClass
29
+ # @return [FFI::Pointer]
30
+ attr_accessor :ptr
31
+ alias :to_ptr :ptr
32
+
33
+ # Compares one BindingClass object to another.
34
+ #
35
+ # @param [BindingClass] other Another BindingClass object to compare to.
36
+ #
37
+ # @return [Boolean]
38
+ def ==(other)
39
+ self.class == other.class and @ptr == other.ptr
40
+ end
41
+ end
42
+
43
+ # This module contains FFI bindings to LLVM.
44
+ module Bindings
45
+ extend FFI::Library
46
+ ffi_lib("LLVM-#{RLTK::LLVM_TARGET_VERSION}")
47
+
48
+ # Exception that is thrown when the LLVM target version does not
49
+ # match the version of LLVM present on the system.
50
+ class LibraryMismatch < Exception; end
51
+
52
+ # Require the generated bindings files while handling errors.
53
+ require 'rltk/cg/generated_bindings'
54
+
55
+ begin
56
+ require 'rltk/cg/generated_extended_bindings'
57
+
58
+ # Check to make sure that we have the same target version as the ECB.
59
+ if target_version() != RLTK::LLVM_TARGET_VERSION
60
+ raise LibraryMismatch,
61
+ "Extended bindings expected LLVM version #{target_version()}, " +
62
+ "RLTK expects LLVM version #{RLTK::LLVM_TARGET_VERSION}"
63
+ end
64
+
65
+ @ecb = true
66
+
67
+ rescue LoadError
68
+ @ecb = false
69
+ end
70
+
71
+ #############
72
+ # Constants #
73
+ #############
74
+
75
+ # List of architectures supported by LLVM.
76
+ ARCHS = [
77
+ :ARM,
78
+ :Alpha,
79
+ :Blackfin,
80
+ :CBackend,
81
+ :CellSPU,
82
+ :CppBackend,
83
+ :MBlaze,
84
+ :MSP430,
85
+ :Mips,
86
+ :PTX,
87
+ :PowerPC,
88
+ :Sparc,
89
+ :SystemZ,
90
+ :XCore,
91
+ :X86
92
+ ]
93
+
94
+ ###########
95
+ # Methods #
96
+ ###########
97
+
98
+ # @return [Boolean] If the Extended C Bindings for LLVM are present.
99
+ def self.ecb?
100
+ @ecb
101
+ end
102
+
103
+ # Converts a CamelCase string into an underscored string.
104
+ #
105
+ # @param [#to_s] name CamelCase string.
106
+ #
107
+ # @return [Symbol] Underscored string.
108
+ def self.get_bname(name)
109
+ name.to_s.
110
+ gsub(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2').
111
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
112
+ downcase.to_sym
113
+ end
114
+
115
+ # A wrapper class for FFI::Library.attach_function
116
+ #
117
+ # @param [Symbol] func Function name.
118
+ # @param [Array<Object>] args Argument types for FFI::Library.attach_function.
119
+ # @param [Object] returns Return type for FFI::Library.attach_function.
120
+ def self.add_binding(func, args, returns)
121
+ attach_function(get_bname(func.to_s[4..-1]), func, args, returns)
122
+ end
123
+
124
+ ####################
125
+ # Missing Bindings #
126
+ ####################
127
+
128
+ ARCHS.each do |arch|
129
+ add_binding("LLVMInitialize#{arch}Target", [], :void)
130
+ add_binding("LLVMInitialize#{arch}TargetInfo", [], :void)
131
+ add_binding("LLVMInitialize#{arch}TargetMC", [], :void)
132
+ end
133
+
134
+ add_binding(:LLVMDisposeMessage, [:pointer], :void)
135
+ end
136
+ end