rubex 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +14 -0
  4. data/CONTRIBUTING.md +101 -0
  5. data/HISTORY.md +3 -0
  6. data/README.md +112 -297
  7. data/REFERENCE.md +753 -0
  8. data/Rakefile +4 -1
  9. data/TUTORIAL.md +234 -0
  10. data/bin/rubex +1 -1
  11. data/docs/_config.yml +1 -0
  12. data/docs/index.html +1 -0
  13. data/examples/c_struct_interface/c_struct_interface.rb +6 -0
  14. data/examples/c_struct_interface/c_struct_interface.rubex +47 -0
  15. data/examples/linked_list/linked_list.rubex +39 -0
  16. data/examples/linked_list/rb_linked_list.rb +8 -0
  17. data/examples/rcsv wrapper/rcsv/README.md +1 -0
  18. data/examples/rcsv wrapper/rcsv/Rakefile +7 -0
  19. data/examples/rcsv wrapper/rcsv/ext/rcsv/extconf.rb +3 -0
  20. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.c +302 -0
  21. data/examples/rcsv wrapper/rcsv/ext/rcsv/rcsv.rubex +124 -0
  22. data/examples/rcsv wrapper/rcsv/lib/rcsv.rb +8 -0
  23. data/examples/rcsv wrapper/rcsv/lib/rcsv.so +0 -0
  24. data/examples/rcsv wrapper/rcsv/lib/rcsv/version.rb +1 -0
  25. data/examples/rcsv wrapper/rcsv/rcsv.gemspec +27 -0
  26. data/examples/rcsv wrapper/rcsv/spec/rcsv.csv +5 -0
  27. data/examples/rcsv wrapper/rcsv/spec/rcsv_spec.rb +17 -0
  28. data/examples/rcsv wrapper/rcsv/spec/spec_helper.rb +6 -0
  29. data/{spec/fixtures/basic_ruby_method/Makefile → examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/Makefile } +20 -20
  30. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.o +0 -0
  31. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/rcsv/2.3.3/rcsv.so +0 -0
  32. data/examples/rcsv wrapper/rcsv/tmp/x86_64-linux/stage/lib/rcsv.so +0 -0
  33. data/lib/rubex.rb +6 -50
  34. data/lib/rubex/ast.rb +1 -3
  35. data/lib/rubex/ast/expression.rb +1257 -8
  36. data/lib/rubex/ast/node.rb +226 -28
  37. data/lib/rubex/ast/statement.rb +1162 -35
  38. data/lib/rubex/ast/top_statement.rb +815 -0
  39. data/lib/rubex/code_writer.rb +103 -26
  40. data/lib/rubex/compiler.rb +72 -0
  41. data/lib/rubex/compiler_config.rb +19 -0
  42. data/lib/rubex/constants.rb +145 -8
  43. data/lib/rubex/data_type.rb +667 -4
  44. data/lib/rubex/error.rb +15 -0
  45. data/lib/rubex/helpers.rb +154 -0
  46. data/lib/rubex/lexer.rex +186 -22
  47. data/lib/rubex/lexer.rex.rb +261 -35
  48. data/lib/rubex/parser.racc +876 -28
  49. data/lib/rubex/parser.racc.rb +2845 -90
  50. data/lib/rubex/rake_task.rb +34 -0
  51. data/lib/rubex/symbol_table/entry.rb +17 -3
  52. data/lib/rubex/symbol_table/scope.rb +298 -25
  53. data/lib/rubex/version.rb +1 -1
  54. data/rubex.gemspec +11 -3
  55. data/spec/basic_ruby_method_spec.rb +15 -21
  56. data/spec/binding_ptr_args_spec.rb +33 -0
  57. data/spec/bitwise_operators_spec.rb +40 -0
  58. data/spec/blocks_spec.rb +35 -0
  59. data/spec/c_bindings_spec.rb +36 -0
  60. data/spec/c_constants_spec.rb +33 -0
  61. data/spec/c_function_ptrs_spec.rb +38 -0
  62. data/spec/c_functions_spec.rb +35 -0
  63. data/spec/c_struct_interface_spec.rb +38 -0
  64. data/spec/call_by_reference_spec.rb +33 -0
  65. data/spec/class_methods_spec.rb +33 -0
  66. data/spec/class_spec.rb +40 -0
  67. data/spec/comments_spec.rb +33 -0
  68. data/spec/default_args_spec.rb +37 -0
  69. data/spec/error_handling_spec.rb +42 -0
  70. data/spec/examples_spec.rb +52 -0
  71. data/spec/expressions_spec.rb +33 -0
  72. data/spec/fixtures/basic_ruby_method/basic_ruby_method.rubex +2 -0
  73. data/spec/fixtures/binding_ptr_args/binding_ptr_args.rubex +30 -0
  74. data/spec/fixtures/bitwise_operators/bitwise_operators.rubex +40 -0
  75. data/spec/fixtures/blocks/blocks.rubex +11 -0
  76. data/spec/fixtures/c_bindings/c_bindings.rubex +58 -0
  77. data/spec/fixtures/c_constants/c_constants.rubex +7 -0
  78. data/spec/fixtures/c_function_ptrs/c_function_ptrs.rubex +52 -0
  79. data/spec/fixtures/c_functions/c_functions.rubex +25 -0
  80. data/spec/fixtures/c_struct_interface/c_struct_interface.rubex +34 -0
  81. data/spec/fixtures/call_by_reference/call_by_reference.rubex +30 -0
  82. data/spec/fixtures/class/class.rubex +20 -0
  83. data/spec/fixtures/class_methods/class_methods.rubex +12 -0
  84. data/spec/fixtures/comments/comments.rubex +9 -0
  85. data/spec/fixtures/default_args/default_args.rubex +11 -0
  86. data/spec/fixtures/error_handling/error_handling.rubex +54 -0
  87. data/spec/fixtures/examples/array_to_hash.rubex +14 -0
  88. data/spec/fixtures/examples/rcsv.csv +5 -0
  89. data/spec/fixtures/examples/rcsv.rubex +329 -0
  90. data/spec/fixtures/expressions/expressions.rubex +10 -0
  91. data/spec/fixtures/if_else/if_else.rubex +77 -0
  92. data/spec/fixtures/implicit_lib_include/implicit_lib_include.rubex +15 -0
  93. data/spec/fixtures/init_ruby_objects_with_literal_syntax/init_ruby_objects_with_literal_syntax.rubex +17 -0
  94. data/spec/fixtures/loops/loops.rubex +33 -0
  95. data/spec/fixtures/recursion/recursion.rubex +9 -0
  96. data/spec/fixtures/ruby_constant_method_calls/ruby_constant_method_calls.rubex +17 -0
  97. data/spec/fixtures/ruby_operators/ruby_operators.rubex +29 -0
  98. data/spec/fixtures/ruby_raise/ruby_raise.rubex +13 -0
  99. data/spec/fixtures/ruby_strings/ruby_strings.rubex +19 -0
  100. data/spec/fixtures/ruby_strings/string_blank_bm.rb +37 -0
  101. data/spec/fixtures/ruby_symbols/ruby_symbols.rubex +12 -0
  102. data/spec/fixtures/ruby_types/ruby_types.rubex +15 -0
  103. data/spec/fixtures/statement_expression/statement_expression.rubex +23 -0
  104. data/spec/fixtures/static_array/static_array.rubex +20 -0
  105. data/spec/fixtures/string_literals/string_literals.rubex +15 -0
  106. data/spec/fixtures/struct/struct.rubex +82 -0
  107. data/spec/fixtures/typecasting/typecasting.rubex +23 -0
  108. data/spec/fixtures/var_declarations/var_declarations.rubex +39 -0
  109. data/spec/if_else_spec.rb +39 -0
  110. data/spec/implicit_lib_include_spec.rb +33 -0
  111. data/spec/init_ruby_objects_with_literal_syntax_spec.rb +39 -0
  112. data/spec/loops_spec.rb +34 -0
  113. data/spec/recursion_spec.rb +35 -0
  114. data/spec/ruby_constant_method_calls_spec.rb +35 -0
  115. data/spec/ruby_operators_spec.rb +40 -0
  116. data/spec/ruby_raise_spec.rb +35 -0
  117. data/spec/ruby_strings_spec.rb +33 -0
  118. data/spec/ruby_symbols_spec.rb +37 -0
  119. data/spec/ruby_types_spec.rb +35 -0
  120. data/spec/spec_helper.rb +54 -1
  121. data/spec/statement_expression_spec.rb +34 -0
  122. data/spec/static_array_spec.rb +33 -0
  123. data/spec/string_literals_spec.rb +34 -0
  124. data/spec/struct_spec.rb +36 -0
  125. data/spec/typecasting_spec.rb +38 -0
  126. data/spec/var_declarions_spec.rb +35 -0
  127. metadata +255 -29
  128. data/lib/rubex/ast/argument_list.rb +0 -20
  129. data/lib/rubex/ast/c_base_type.rb +0 -11
  130. data/lib/rubex/ast/ruby_method_def.rb +0 -84
  131. data/spec/fixtures/basic_ruby_method/basic.rb +0 -3
  132. data/spec/fixtures/basic_ruby_method/basic_ruby_method.c +0 -16
  133. data/spec/fixtures/basic_ruby_method/basic_ruby_method.o +0 -0
  134. data/spec/fixtures/basic_ruby_method/basic_ruby_method.so +0 -0
  135. data/spec/fixtures/basic_ruby_method/extconf.rb +0 -3
data/Rakefile CHANGED
@@ -13,6 +13,9 @@ task :parser => :lexer do
13
13
  `racc lib/rubex/parser.racc -o lib/rubex/parser.racc.rb`
14
14
  end
15
15
 
16
+ # -v -> verbose
17
+ # -t -> with debugging output
18
+
16
19
  RSpec::Core::RakeTask.new(:spec)
17
20
 
18
- task :spec => :parser
21
+ task :spec => :parser
@@ -0,0 +1,234 @@
1
+ # Rubex tutorial
2
+
3
+ Here's a quick tutorial of Rubex to get you up and started. Once you're through, take a moment to convert one of your C extensions to Rubex and see the difference in speed of development and simplicity.
4
+
5
+ <!-- MarkdownTOC autolink="true" bracket="round" -->
6
+
7
+ - [Basics of Rubex](#basics-of-rubex)
8
+ - [Rubex Hello World](#rubex-hello-world)
9
+ - [String#blank?](#stringblank)
10
+ - [Calling C Functions](#calling-c-functions)
11
+ - [C Functions](#c-functions)
12
+ - ['Attach' Classes](#attach-classes)
13
+ - [Error Handling](#error-handling)
14
+ - [Using Rubex Inside A Gem](#using-rubex-inside-a-gem)
15
+ - [Examples](#examples)
16
+ - [Interfacing C structs](#interfacing-c-structs)
17
+ - [Fully Functional Ruby Gem](#fully-functional-ruby-gem)
18
+
19
+ <!-- /MarkdownTOC -->
20
+
21
+ # Basics of Rubex
22
+
23
+ The Rubex syntax is very close to that of Ruby. In most use cases you can simply add a static types to variables and you're good to go. Rubex files have an extension `.rubex`.
24
+
25
+ Before starting, make sure you've installed Rubex with `gem install rubex`.
26
+
27
+ ## Rubex Hello World
28
+
29
+ In a Rubex file titled `hello_word.rubex` paste the following code:
30
+ ``` ruby
31
+ def hello_world
32
+ print "Hello world!"
33
+ end
34
+ ```
35
+
36
+ Now the use the `rubex` binary to compile the above program:
37
+ ```
38
+ rubex hello_world.rubex
39
+ ```
40
+
41
+ This will generate a folder called `hello_world` that will contain the files `extconf.rb` and `hello_world.c`. Now run the following:
42
+ ```
43
+ cd hello_world
44
+ ruby extconf.rb
45
+ make
46
+ ```
47
+
48
+ This will generate a shared object file called `hello_world.so` that can be used in any normal Ruby script like so:
49
+ ``` ruby
50
+ require_relative 'hello_world.so'
51
+
52
+ hello_world
53
+ ```
54
+
55
+ ## String#blank?
56
+
57
+ Sam Saffron's famous [`fast_blank`](https://github.com/SamSaffron/fast_blank) gem is something that most Rubyists probably use a lot of times in their daily life. It is also a classic example of porting a Ruby gem to a C extension for reasons of speed.
58
+
59
+ Here's the Rubex version of fast_blank:
60
+ ``` ruby
61
+ class String
62
+ def blank?(string)
63
+ char *s = string
64
+ int i = 0
65
+
66
+ while i < string.size do
67
+ return false if s[i] != ' '
68
+ end
69
+
70
+ return true
71
+ end
72
+ end
73
+ ```
74
+
75
+ As you can see above, Rubex can implicitly convert between Ruby objects and C data types (like a Ruby `String` into a `char*` C array).
76
+
77
+ # Calling C Functions
78
+
79
+ One of the primary uses of Rubex is making it easy for interfacing with C libraries. This can be done by using the `lib` keyword at the top of a Rubex file.
80
+
81
+ So say for example, you want to interface some functions from the `math.h` C header file. In order to do this, you first list out the prototypes of the functions that you want to interface inside `lib`, and then you can use these functions in your program.
82
+ ``` ruby
83
+ lib "<math.h>"
84
+ double cos(double)
85
+ double sin(double)
86
+ end
87
+
88
+ class CMath
89
+ def f_sin(num)
90
+ return sin(num)
91
+ end
92
+
93
+ def f_cos(num)
94
+ return cos(num)
95
+ end
96
+ end
97
+ ```
98
+
99
+ These functions can be used in a similar manner to our hello_world program above. Keep in mind that you cannot (yet) have function names in your Rubex program that have the same name as that of the external C functions. This will cause name clashes and malfunction.
100
+
101
+ Read what you can do more with `lib` in the [REFERENCE](REFERENCE.md).
102
+
103
+ # C Functions
104
+
105
+ Apart from Ruby class methods and instance methods, Rubex allows you to define 'C functions' that are only accessible inside classes from within Rubex. These functions _cannot_ be accessed from an external Ruby script.
106
+
107
+ C functions are defined used the `cfunc` keyword. You also need to specify the return type of the function along with its definition. For example:
108
+ ``` ruby
109
+ class CFunctionTest
110
+ def foo(int n)
111
+ return bar(n)
112
+ end
113
+
114
+ # bar is a C function.
115
+ cfunc int bar(int n)
116
+ return n + 5
117
+ end
118
+ end
119
+ ```
120
+
121
+ # 'Attach' Classes
122
+
123
+ Rubex introduces a special syntax that allows you to directly interface Ruby with C structs using some special language constructs, called 'attach' classes. These are normal Ruby classes and can be instantiated and used just like any other Ruby class, but with one caveat - they are permanently attached to a C struct and implicitly interface this struct with the Ruby VM.
124
+
125
+ Let me demonstrate with an example:
126
+ ``` ruby
127
+ # file: structs.rubex
128
+ lib "rubex/ruby"; end
129
+
130
+ struct mp3info
131
+ int id
132
+ char* title
133
+ end
134
+
135
+ class Music attach mp3info
136
+ def initialize(id, title)
137
+ mp3info* mp3 = data$.mp3info
138
+
139
+ mp3.id = id
140
+ mp3.title = title
141
+ end
142
+
143
+ def id
144
+ return data$.mp3info.id
145
+ end
146
+
147
+ def title
148
+ return data$.mp3info.title
149
+ end
150
+
151
+ cfunc void deallocate
152
+ xfree(data$.mp3info)
153
+ end
154
+ end
155
+ ```
156
+ This program can be used in a Ruby script like this:
157
+ ``` ruby
158
+ require 'structs.so'
159
+
160
+ id = 1
161
+ title = "CAFO"
162
+ m = Music.new id, title
163
+ puts m.id, m.title
164
+ ```
165
+
166
+ The above example has some notable Rubex constructs:
167
+
168
+ ### The attach keyword
169
+
170
+ The 'attach' keyword is a special keyword that is used for associating a particular struct with a Ruby class. Once this keyword is used, the Rubex compiler will take care of allocation, deallocation and fetching of the struct (more about this in the [REFERENCE](REFERENCE.md)). The user only needs to concern themselves with using and allocating the data inside the struct.
171
+
172
+ In the above case, `attach` creates tells the class `Music` that it will be associated with a C struct of type `mp3info`.
173
+
174
+ ### The data$ variable
175
+
176
+ The `data$` variable is a special variable keyword that is available _only_ inside attach classes. The `data$` variable allows access to the `mp3info` struct. In order to do this, it makes available a **pointer** to the struct that is of the same name as the struct (i.e. `mp3info` for `struct mp3info` or `foo` for `struct foo`). This pointer to the struct can then be used for reading or writing elements in the struct.
177
+
178
+ ### The deallocate C function
179
+
180
+ Once you are done using an instance of your newly created attach class, Ruby's GC will want to clean up the memory used by it so that it can be used by other objects. In order to not have any memory leaks later, it is important to tell the GC that the memory that was used up by the `mp3info` struct needs to be freed. This freeing up of memory should be done inside the `deallocate` function.
181
+
182
+ The `xfree` function, which is the standard memory freeing function provided by the Ruby interpreter is used for this purpose.
183
+
184
+ # Error Handling
185
+
186
+ Rubex greatly simplifies error handling for C extensions. It now gives you the full power of a Ruby `begin-rescue-else-ensure` block. You can also define variables inside these blocks!
187
+
188
+ Here's an example:
189
+ ``` ruby
190
+ def error_example(int n)
191
+ begin
192
+ raise ArgumentError if n == 1
193
+ raise SyntaxError if n == 2
194
+ rescue ArgumentError
195
+ n += 10
196
+ rescue SyntaxError
197
+ n += 20
198
+ ensure
199
+ n += 5
200
+ end
201
+
202
+ return n
203
+ end
204
+ ```
205
+
206
+ # Using Rubex Inside A Gem
207
+
208
+ Rubex ships with pre-built rake tasks that can be for compiling a Rubex file. In order to use these, simply drop in the following code into your `Rakefile`:
209
+ ``` ruby
210
+ require 'rubex/rake_task'
211
+
212
+ Rubex::RakeTask.new('hello_world')
213
+ ```
214
+
215
+ Above rake task assumes that you use the standard Ruby gem structure:
216
+ ```
217
+ |-- ext
218
+ | `-- hello_world
219
+ | `-- hello_world.rubex
220
+ |-- lib
221
+ `-- Rakefile
222
+ ```
223
+
224
+ Calling `rake compile` will generate `hello_world.c` and `extconf.rb` in your `ext` folder and place `hello_world.so` in your `lib/` folder which you directly use with a simple `require`.
225
+
226
+ # Examples
227
+
228
+ ## Interfacing C structs
229
+
230
+ [This example](https://github.com/v0dro/rubex/tree/master/examples/c_struct_interface) is a program that interfaces with a C struct and creates reader and writer methods for C struct elements through a Ruby interface.
231
+
232
+ ## Fully Functional Ruby Gem
233
+
234
+ See the [rcsv example](https://github.com/v0dro/rubex/tree/master/examples/rcsv%20wrapper/rcsv) for a fully functional rubygem that wraps around the [libcsv](https://sourceforge.net/projects/libcsv/) C library for parsing CSV files.
data/bin/rubex CHANGED
@@ -7,4 +7,4 @@ if File.exists? file_name
7
7
  file_name = Dir.pwd + "/#{file_name}"
8
8
  end
9
9
 
10
- Rubex.compile file_name
10
+ Rubex::Compiler.compile file_name
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-dinky
@@ -0,0 +1 @@
1
+ <h1>Docs go here!</h1>
@@ -0,0 +1,6 @@
1
+ require_relative 'c_struct_interface/c_struct_interface.so'
2
+
3
+ m = Music.new("Periphery", "Marigold", 1)
4
+
5
+ puts m.artist
6
+ puts m.title
@@ -0,0 +1,47 @@
1
+ lib "rubex/ruby"; end
2
+
3
+ struct mp3info
4
+ char *artist, *title
5
+ int id
6
+ end
7
+
8
+ # The class that will be 'attached' to the struct and will make it possible to
9
+ # initialize instances of the struct. There will be a variable called `data`
10
+ # which will be made available to the user which will be of type
11
+ # 'struct __rubex_data_Music'. This variable will be available throughout the class.
12
+ #
13
+ # The allocate function will be defined implicitly, and calls to `TypeData_*`
14
+ # macros will also be implicit.
15
+ #
16
+ # The data variable is analogous to the 'params' variable in Sinatra routes.
17
+ class Music attach mp3info
18
+ def initialize(artist, title, id)
19
+ mp3info* mp3 = data$.mp3info
20
+ int a_size = artist.size
21
+ int t_size = title.size
22
+
23
+ mp3.artist = artist # implicit conversion of Ruby String to char*
24
+ mp3.title = title # implicit conversion of Ruby String to char*
25
+ mp3.id = id # implicit typecast to int
26
+ end
27
+
28
+ # The deallocate function will be used by TypeData_* macros as a function
29
+ # for freeing memory once this class has been GC'd. It will be a compulsory
30
+ # method for such 'attach' classes and will not be callable through Ruby
31
+ # scripts.
32
+ cfunc void deallocate
33
+ xfree(data$.mp3info)
34
+ end
35
+
36
+ def artist
37
+ return data$.mp3info.artist # typecast to ruby string
38
+ end
39
+
40
+ def title
41
+ return data$.mp3info.title # typecast to ruby string
42
+ end
43
+
44
+ def id
45
+ return data$.mp3info.id
46
+ end
47
+ end
@@ -0,0 +1,39 @@
1
+ struct node
2
+ int data
3
+ object next
4
+ end
5
+
6
+ class LLNode attach node
7
+ def initialize(int d)
8
+ node n = data.node
9
+
10
+ n.data = d
11
+ n.next = nil
12
+ endturn
13
+
14
+ def add_node d
15
+ node n = data.node
16
+
17
+ new_node = LLNode.new(d)
18
+ n.next = new_node
19
+ end
20
+
21
+ def print_list
22
+ node n = data.node
23
+
24
+ temp = self
25
+ print "The linked list is: \n"
26
+ while next_node do
27
+ print temp.get_data
28
+ temp = n.next_node
29
+ end
30
+ end
31
+
32
+ def get_data
33
+ return data.node.data
34
+ end
35
+
36
+ def next_node
37
+ return data.node.next
38
+ end
39
+ end
@@ -0,0 +1,8 @@
1
+ require 'linked_list.so'
2
+
3
+ list = LLNode.new(0)
4
+ 10.times do |a|
5
+ list.add_node(a)
6
+ end
7
+
8
+ list.print_list
@@ -0,0 +1 @@
1
+ Rubex wrapper over libcsv.
@@ -0,0 +1,7 @@
1
+ require 'rubex/rake_task'
2
+ require 'rspec/core/rake_task'
3
+
4
+ Rubex::RakeTask.new('rcsv')
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :spec => :compile
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ $libs += " -lcsv"
3
+ create_makefile('ext/rcsv/rcsv')
@@ -0,0 +1,302 @@
1
+ /* C extension for rcsv.
2
+ This file in generated by Rubex::Compiler. Do not change!
3
+ File generation time: 2017-08-28 23:47:06 +0530.*/
4
+
5
+ #include <ruby.h>
6
+ #include <stdint.h>
7
+ #include <stdbool.h>
8
+ #include <ruby.h>
9
+ #include <ruby/encoding.h>
10
+ #include <stdlib.h>
11
+ #include "csv.h"
12
+
13
+ #define __rubex_INT2BOOL(arg) (arg ? Qtrue : Qfalse)
14
+
15
+
16
+
17
+ typedef struct rcsv_metadata
18
+ {
19
+ int __rubex_v_skip_current_row;
20
+ size_t __rubex_v_current_col;
21
+ size_t __rubex_v_current_row;
22
+ VALUE __rubex_v_last_entry;
23
+ VALUE __rubex_v_result;
24
+ } __rubex_t_Object_rcsv_metadata;
25
+
26
+
27
+
28
+ VALUE rb_cObject;
29
+ VALUE rb_eStandardError;
30
+ VALUE __rubex_rb_cls_RcsvParseError;
31
+ VALUE __rubex_rb_cls_Rcsv;
32
+ static VALUE global_begin_block_Rcsv_parse_1__rubex_arg_dummy;
33
+ static VALUE global_begin_block_Rcsv_parse_1__rubex_v_csvstr;
34
+ static VALUE global_begin_block_Rcsv_parse_1__rubex_v_csvio;
35
+ static char* global_begin_block_Rcsv_parse_1__rubex_ptr_csv_string;
36
+ static int global_begin_block_Rcsv_parse_1__rubex_v_csv_string_len;
37
+ static struct csv_parser global_begin_block_Rcsv_parse_1__rubex_v_cp;
38
+ static __rubex_t_Object_rcsv_metadata global_begin_block_Rcsv_parse_1__rubex_v_meta;
39
+ static int global_begin_block_Rcsv_parse_1__rubex_v_error;
40
+ static VALUE __rubex_rb_f_Rcsv_parse (int argc,VALUE* argv,VALUE __rubex_arg_self);
41
+ static void __rubex_c_f_Rcsv_end_of_field_callback (void* __rubex_arg_field,size_t __rubex_arg_field_size,void* __rubex_arg_data,VALUE __rubex_arg_self);
42
+ static void __rubex_c_f_Rcsv_end_of_line_callback (int __rubex_arg_last_char,void* __rubex_arg_data,VALUE __rubex_arg_self);
43
+ static VALUE __rubex_c_f_Rcsv_ENCODED_STR_NEW (char* __rubex_arg_string,int __rubex_arg_length,VALUE __rubex_arg_self);
44
+ static void __rubex_c_f_Rcsv_setup_rcsv_metadata_defaults (__rubex_t_Object_rcsv_metadata* __rubex_arg_p_meta,VALUE __rubex_arg_self);
45
+ static VALUE __rubex_c_f_begin_block_Rcsv_parse_1 (VALUE global_begin_block_Rcsv_parse_1__rubex_arg_dummy);
46
+
47
+ VALUE __rubex_char2rubystr(char ch);
48
+ VALUE __rubex_char2rubystr(char ch)
49
+ {
50
+ char s[2];
51
+ s[0] = ch;
52
+ s[1] = '\0';
53
+ return rb_str_new2(s);
54
+ }
55
+
56
+
57
+ static VALUE __rubex_c_f_begin_block_Rcsv_parse_1 (VALUE global_begin_block_Rcsv_parse_1__rubex_arg_dummy)
58
+ {
59
+ VALUE __rubex_v_ensure_container;
60
+ VALUE __rubex_temp_1;
61
+ while (Qtrue)
62
+ {
63
+
64
+ /* Rubex file location: ext/rcsv/rcsv.rubex:93 */
65
+ global_begin_block_Rcsv_parse_1__rubex_v_csvstr = rb_funcall(global_begin_block_Rcsv_parse_1__rubex_v_csvio, rb_intern("read"), 0, NULL);
66
+ if (RTEST(( __rubex_INT2BOOL(RTEST(rb_funcall(global_begin_block_Rcsv_parse_1__rubex_v_csvstr, rb_intern("nil?"), 0, NULL)) || RTEST(( rb_funcall(rb_funcall(global_begin_block_Rcsv_parse_1__rubex_v_csvstr, rb_intern("size"), 0, NULL), rb_intern("==") , 1, INT2NUM(0)) ))) )))
67
+ {
68
+
69
+ /* Rubex file location: ext/rcsv/rcsv.rubex:95 */
70
+ break;
71
+
72
+ }
73
+
74
+ global_begin_block_Rcsv_parse_1__rubex_ptr_csv_string = StringValueCStr(global_begin_block_Rcsv_parse_1__rubex_v_csvstr);
75
+
76
+ /* Rubex file location: ext/rcsv/rcsv.rubex:98 */
77
+ global_begin_block_Rcsv_parse_1__rubex_v_csv_string_len = NUM2INT(rb_funcall(global_begin_block_Rcsv_parse_1__rubex_v_csvstr, rb_intern("size"), 0, NULL));
78
+ if (( global_begin_block_Rcsv_parse_1__rubex_v_csv_string_len != csv_parse(&global_begin_block_Rcsv_parse_1__rubex_v_cp,global_begin_block_Rcsv_parse_1__rubex_ptr_csv_string,global_begin_block_Rcsv_parse_1__rubex_v_csv_string_len,&__rubex_c_f_Rcsv_end_of_field_callback,&__rubex_c_f_Rcsv_end_of_line_callback,&global_begin_block_Rcsv_parse_1__rubex_v_meta) ))
79
+ {
80
+ global_begin_block_Rcsv_parse_1__rubex_v_error = csv_error(&global_begin_block_Rcsv_parse_1__rubex_v_cp);
81
+
82
+ if (( global_begin_block_Rcsv_parse_1__rubex_v_error == CSV_EPARSE ))
83
+ {
84
+ __rubex_temp_1 = rb_str_new2("Error when parsing malformed data.");
85
+ rb_raise(__rubex_rb_cls_RcsvParseError,"%s" ,RSTRING_PTR(rb_funcall(__rubex_temp_1, rb_intern("inspect"), 0, NULL)));
86
+ __rubex_temp_1 = 0;
87
+
88
+ }
89
+
90
+ else if (( global_begin_block_Rcsv_parse_1__rubex_v_error == CSV_ENOMEM ))
91
+ {
92
+ __rubex_temp_1 = rb_str_new2("No memory.");
93
+ rb_raise(__rubex_rb_cls_RcsvParseError,"%s" ,RSTRING_PTR(rb_funcall(__rubex_temp_1, rb_intern("inspect"), 0, NULL)));
94
+ __rubex_temp_1 = 0;
95
+
96
+ }
97
+
98
+ else if (( global_begin_block_Rcsv_parse_1__rubex_v_error == CSV_ETOOBIG ))
99
+ {
100
+ __rubex_temp_1 = rb_str_new2("Field data data is too large.");
101
+ rb_raise(__rubex_rb_cls_RcsvParseError,"%s" ,RSTRING_PTR(rb_funcall(__rubex_temp_1, rb_intern("inspect"), 0, NULL)));
102
+ __rubex_temp_1 = 0;
103
+
104
+ }
105
+
106
+ else if (( global_begin_block_Rcsv_parse_1__rubex_v_error == CSV_EINVALID ))
107
+ {
108
+ rb_raise(__rubex_rb_cls_RcsvParseError,"");
109
+
110
+ }
111
+
112
+ else
113
+ {
114
+ __rubex_temp_1 = rb_str_new2("Something went wrong.");
115
+ rb_raise(__rubex_rb_cls_RcsvParseError,"%s" ,RSTRING_PTR(rb_funcall(__rubex_temp_1, rb_intern("inspect"), 0, NULL)));
116
+ __rubex_temp_1 = 0;
117
+
118
+ }
119
+
120
+
121
+ }
122
+
123
+ }
124
+
125
+
126
+ /* Rubex file location: ext/rcsv/rcsv.rubex:117 */
127
+ csv_fini(&global_begin_block_Rcsv_parse_1__rubex_v_cp,&__rubex_c_f_Rcsv_end_of_field_callback,&__rubex_c_f_Rcsv_end_of_line_callback,&global_begin_block_Rcsv_parse_1__rubex_v_meta);
128
+ }
129
+
130
+ static void __rubex_c_f_Rcsv_end_of_field_callback (void* __rubex_arg_field,size_t __rubex_arg_field_size,void* __rubex_arg_data,VALUE __rubex_arg_self)
131
+ {
132
+ char* __rubex_ptr_field_str;
133
+ __rubex_t_Object_rcsv_metadata* __rubex_ptr_meta_p;
134
+ __rubex_t_Object_rcsv_metadata __rubex_v_meta;
135
+ char __rubex_v_row_conversion;
136
+ VALUE __rubex_v_parsed_field;
137
+ __rubex_ptr_field_str = (char*)__rubex_arg_field;
138
+ __rubex_ptr_meta_p = (__rubex_t_Object_rcsv_metadata*)__rubex_arg_data;
139
+ __rubex_v_meta = __rubex_ptr_meta_p[0];
140
+ __rubex_v_row_conversion = 0;
141
+
142
+ /* Rubex file location: ext/rcsv/rcsv.rubex:48 */
143
+ __rubex_v_parsed_field = __rubex_c_f_Rcsv_ENCODED_STR_NEW(__rubex_ptr_field_str,__rubex_arg_field_size,__rubex_arg_self);
144
+
145
+ /* Rubex file location: ext/rcsv/rcsv.rubex:50 */
146
+ rb_funcall(__rubex_ptr_meta_p[0].__rubex_v_last_entry, rb_intern("push"), 1 ,__rubex_v_parsed_field);
147
+
148
+ /* Rubex file location: ext/rcsv/rcsv.rubex:51 */
149
+ __rubex_ptr_meta_p[0].__rubex_v_current_col = ( __rubex_ptr_meta_p[0].__rubex_v_current_col + 1 );
150
+
151
+ /* Rubex file location: ext/rcsv/rcsv.rubex:52 */
152
+ return ;
153
+ }
154
+
155
+ static void __rubex_c_f_Rcsv_end_of_line_callback (int __rubex_arg_last_char,void* __rubex_arg_data,VALUE __rubex_arg_self)
156
+ {
157
+ __rubex_t_Object_rcsv_metadata* __rubex_ptr_meta;
158
+ VALUE __rubex_temp_1;
159
+ __rubex_ptr_meta = (__rubex_t_Object_rcsv_metadata*)__rubex_arg_data;
160
+
161
+ /* Rubex file location: ext/rcsv/rcsv.rubex:58 */
162
+ rb_funcall(__rubex_ptr_meta->__rubex_v_result, rb_intern("push"), 1 ,__rubex_ptr_meta->__rubex_v_last_entry);
163
+ if (( __rubex_arg_last_char != -1 ))
164
+ {
165
+
166
+ /* Rubex file location: ext/rcsv/rcsv.rubex:59 */
167
+ __rubex_temp_1 = rb_ary_new2(0);
168
+ __rubex_ptr_meta->__rubex_v_last_entry = __rubex_temp_1;
169
+ __rubex_temp_1 = 0;
170
+
171
+ }
172
+
173
+
174
+ /* Rubex file location: ext/rcsv/rcsv.rubex:60 */
175
+ __rubex_ptr_meta->__rubex_v_current_col = 0;
176
+
177
+ /* Rubex file location: ext/rcsv/rcsv.rubex:61 */
178
+ __rubex_ptr_meta->__rubex_v_current_row = ( __rubex_ptr_meta->__rubex_v_current_row + 1 );
179
+ }
180
+
181
+ static VALUE __rubex_c_f_Rcsv_ENCODED_STR_NEW (char* __rubex_arg_string,int __rubex_arg_length,VALUE __rubex_arg_self)
182
+ {
183
+
184
+ /* Rubex file location: ext/rcsv/rcsv.rubex:65 */
185
+ return rb_str_new(__rubex_arg_string,__rubex_arg_length);
186
+ }
187
+
188
+ static void __rubex_c_f_Rcsv_setup_rcsv_metadata_defaults (__rubex_t_Object_rcsv_metadata* __rubex_arg_p_meta,VALUE __rubex_arg_self)
189
+ {
190
+ VALUE __rubex_temp_1;
191
+
192
+ /* Rubex file location: ext/rcsv/rcsv.rubex:69 */
193
+ __rubex_arg_p_meta->__rubex_v_skip_current_row = 0;
194
+
195
+ /* Rubex file location: ext/rcsv/rcsv.rubex:70 */
196
+ __rubex_arg_p_meta->__rubex_v_current_col = 0;
197
+
198
+ /* Rubex file location: ext/rcsv/rcsv.rubex:71 */
199
+ __rubex_arg_p_meta->__rubex_v_current_row = 0;
200
+
201
+ /* Rubex file location: ext/rcsv/rcsv.rubex:72 */
202
+ __rubex_temp_1 = rb_ary_new2(0);
203
+ __rubex_arg_p_meta->__rubex_v_result = __rubex_temp_1;
204
+ __rubex_temp_1 = 0;
205
+ }
206
+
207
+ static VALUE __rubex_rb_f_Rcsv_parse (int argc,VALUE* argv,VALUE __rubex_arg_self)
208
+ {
209
+ VALUE __rubex_arg_file_name;
210
+ VALUE __rubex_arg_opts;
211
+ VALUE __rubex_v_options;
212
+ VALUE __rubex_v_option;
213
+ unsigned char __rubex_v_csv_options;
214
+ int __rubex_v_begin_block_1_state;
215
+ VALUE __rubex_v_begin_block_1_exec;
216
+ int __rubex_v_begin_block_1_unhandled_error;
217
+ VALUE __rubex_v_ensure_container;
218
+ VALUE __rubex_temp_1;
219
+ if (argc < 2)
220
+ {
221
+ rb_raise(rb_eArgError, "Need 2 args, not %d", argc);
222
+ }
223
+
224
+ __rubex_arg_file_name=argv[0];
225
+ __rubex_arg_opts=argv[1];
226
+
227
+ /* Rubex file location: ext/rcsv/rcsv.rubex:79 */
228
+ __rubex_temp_1 = rb_ary_new2(0);
229
+ __rubex_v_ensure_container = __rubex_temp_1;
230
+ __rubex_temp_1 = 0;
231
+ __rubex_temp_1 = 0;
232
+ __rubex_v_csv_options = ( CSV_STRICT_FINI | CSV_APPEND_NULL );
233
+
234
+ /* Rubex file location: ext/rcsv/rcsv.rubex:83 */
235
+ __rubex_c_f_Rcsv_setup_rcsv_metadata_defaults(&global_begin_block_Rcsv_parse_1__rubex_v_meta,__rubex_arg_self);
236
+
237
+ /* Rubex file location: ext/rcsv/rcsv.rubex:84 */
238
+ global_begin_block_Rcsv_parse_1__rubex_v_csvio = rb_funcall(rb_const_get(CLASS_OF(__rubex_arg_self), rb_intern("StringIO")), rb_intern("new"), 1 ,__rubex_arg_file_name);
239
+ if (( csv_init(&global_begin_block_Rcsv_parse_1__rubex_v_cp,__rubex_v_csv_options) == -1 ))
240
+ {
241
+ __rubex_temp_1 = rb_str_new2("Failed to initialize libcsv.");
242
+ rb_raise(__rubex_rb_cls_RcsvParseError,"%s" ,RSTRING_PTR(rb_funcall(__rubex_temp_1, rb_intern("inspect"), 0, NULL)));
243
+ __rubex_temp_1 = 0;
244
+
245
+ }
246
+
247
+
248
+ /* Rubex file location: ext/rcsv/rcsv.rubex:89 */
249
+ __rubex_temp_1 = rb_ary_new2(0);
250
+ global_begin_block_Rcsv_parse_1__rubex_v_meta.__rubex_v_last_entry = __rubex_temp_1;
251
+ __rubex_temp_1 = 0;
252
+
253
+ /* begin-rescue-else-ensure-end block begins: */
254
+
255
+ /* Rubex file location: ext/rcsv/rcsv.rubex:120 */
256
+ __rubex_v_begin_block_1_state = 0;
257
+ rb_protect(__rubex_c_f_begin_block_Rcsv_parse_1, Qnil, &__rubex_v_begin_block_1_state);
258
+ __rubex_v_begin_block_1_exec = rb_errinfo();
259
+ __rubex_v_begin_block_1_unhandled_error = 0;
260
+ if (0) {}
261
+ else
262
+ {
263
+ /* If exception not among those captured in raise */
264
+ if (__rubex_v_begin_block_1_state)
265
+ {
266
+ __rubex_v_begin_block_1_unhandled_error = 1;
267
+ }
268
+
269
+ }
270
+
271
+ if (&global_begin_block_Rcsv_parse_1__rubex_v_cp)
272
+ {
273
+
274
+ /* Rubex file location: ext/rcsv/rcsv.rubex:119 */
275
+ csv_free(&global_begin_block_Rcsv_parse_1__rubex_v_cp);
276
+
277
+ }
278
+
279
+ if (__rubex_v_begin_block_1_unhandled_error)
280
+ {
281
+ rb_jump_tag(__rubex_v_begin_block_1_state);
282
+ }
283
+
284
+ rb_set_errinfo(Qnil);
285
+
286
+ /* Rubex file location: ext/rcsv/rcsv.rubex:122 */
287
+ return global_begin_block_Rcsv_parse_1__rubex_v_meta.__rubex_v_result;
288
+ }
289
+
290
+
291
+ void Init_rcsv ();
292
+ void Init_rcsv ()
293
+ {
294
+ VALUE __rubex_rb_cls_RcsvParseError;
295
+ VALUE __rubex_rb_cls_Rcsv;
296
+
297
+ __rubex_rb_cls_RcsvParseError = rb_define_class("RcsvParseError", rb_eStandardError);
298
+ __rubex_rb_cls_Rcsv = rb_define_class("Rcsv", rb_cObject);
299
+
300
+ rb_define_singleton_method(__rubex_rb_cls_Rcsv ,"parse", __rubex_rb_f_Rcsv_parse, -1);
301
+ }
302
+