fastruby 0.0.3 → 0.0.4

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/CHANGELOG ADDED
@@ -0,0 +1,21 @@
1
+ 0.0.4 Basic support fot non-local goto: return, break, next
2
+
3
+ Basic support for exceptions
4
+
5
+ Support for defined?
6
+
7
+ Support for modules
8
+
9
+ Support for singleton methods
10
+
11
+ 0.0.3 Implemented global array to make references to literal objects used in code
12
+
13
+ Added support to write and read constants
14
+
15
+ Added support to execution of complete ruby code (entire clases o any ruby code)
16
+
17
+ Refactored code to avoid use sexp_processor
18
+
19
+ 0.0.2 Added missing sexp_processor dependency
20
+
21
+ 0.0.1 First test release
data/README CHANGED
@@ -55,11 +55,10 @@ I will stabilize the API and document it for next releases. I promise
55
55
 
56
56
  == Known Limitations & Issues
57
57
 
58
+ * Bootstrap is very slow since this is a Poc :P
58
59
  * monkey patching does not work with fastruby methods
59
60
  * calls with blocks to ruby or cruby methods are almost as slow as normal ruby (if the called method is defined by fastruby, the call it's pretty fast)
60
- * does not support singleton methods (both define & call)
61
61
  * does not support methods with variable number of arguments
62
- * does not support exception handling (rescue, ensure, etc...)
63
62
 
64
63
  == Usage
65
64
 
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require "rspec/core/rake_task"
7
7
 
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'fastruby'
10
- s.version = '0.0.3'
10
+ s.version = '0.0.4'
11
11
  s.author = 'Dario Seminara'
12
12
  s.email = 'robertodarioseminara@gmail.com'
13
13
  s.platform = Gem::Platform::RUBY
@@ -19,7 +19,7 @@ spec = Gem::Specification.new do |s|
19
19
  s.extra_rdoc_files = [ 'README' ]
20
20
  # s.rdoc_options << '--main' << 'README'
21
21
  s.files = Dir.glob("{benchmarks,examples,lib,spec}/**/*") +
22
- [ 'LICENSE', 'AUTHORS', 'README', 'Rakefile', 'TODO' ]
22
+ [ 'LICENSE', 'AUTHORS', 'README', 'Rakefile', 'TODO', 'CHANGELOG' ]
23
23
  end
24
24
 
25
25
  desc 'Run tests'
data/TODO CHANGED
@@ -1,10 +1,8 @@
1
1
  Basic functionality:
2
2
 
3
3
  * Flow control setences: case
4
- * Exceptions
5
4
  * Defining and call of methods with variable number of arguments
6
5
  * Blocks with variable number of arguments
7
- * call to monkey patched methods from fastruby code
8
6
  * callcc
9
7
 
10
8
  To improve:
@@ -22,9 +22,27 @@ require "fastruby/translator"
22
22
  require "fastruby/inline_extension"
23
23
  require "fastruby/method_extension"
24
24
  require "fastruby/logging"
25
+ require "fastruby/getlocals"
25
26
 
26
27
  module FastRuby
27
28
 
29
+ def self.build_defs(tree, *options)
30
+ method_name = tree[2].to_s
31
+
32
+ FastRuby.logger.info "Building singleton method #{self}::#{@method_name}"
33
+
34
+ locals = GetLocalsProcessor.get_locals(tree)
35
+ locals << :self
36
+
37
+ context = FastRuby::Context.new(false)
38
+ context.locals = locals
39
+ context.options = options
40
+
41
+ context.alt_method_name = "singleton_" + method_name + rand(100000000).to_s
42
+
43
+ [context.extra_code + context.to_c_method_defs(tree), context.alt_method_name]
44
+ end
45
+
28
46
  class Method
29
47
  attr_accessor :tree
30
48
  attr_accessor :locals
@@ -43,7 +61,7 @@ module FastRuby
43
61
  begin
44
62
  if (@owner.instance_method(mname))
45
63
  FastRuby.logger.info "NOT Building #{self}::#{@method_name} for signature #{signature.inspect}, it's already done"
46
- return
64
+ return @owner.instance_method(mname)
47
65
  end
48
66
  rescue NameError
49
67
  FastRuby.logger.info "Building #{self}::#{@method_name} for signature #{signature.inspect}"
@@ -0,0 +1,48 @@
1
+ =begin
2
+
3
+ This file is part of the fastruby project, http://github.com/tario/fastruby
4
+
5
+ Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ fastruby is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ fastruby is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ module Kernel
22
+ def fastruby_require(path)
23
+ if path =~ /\.so$/
24
+ require(path)
25
+ else
26
+ FastRuby.logger.info "trying to load '#{path}'"
27
+
28
+ complete_path = path + (path =~ /\.rb$/ ? "" : ".rb")
29
+
30
+ $LOAD_PATH.each do |load_path|
31
+ begin
32
+ source = nil
33
+ File.open(load_path + "/" + complete_path) do |file|
34
+ source = file.read
35
+ end
36
+
37
+ FastRuby.logger.info "loading '#{load_path + "/" + complete_path}'"
38
+
39
+ fastruby source
40
+ return true
41
+ rescue Errno::ENOENT
42
+ end
43
+ end
44
+
45
+ raise LoadError
46
+ end
47
+ end
48
+ end
@@ -62,13 +62,25 @@ class Object
62
62
  raise ArgumentError
63
63
  end
64
64
 
65
+ return unless tree
66
+
65
67
  if tree[0] == :class
66
68
  classname = Object.to_class_name tree[1]
67
69
 
68
- eval("
69
- class #{classname}
70
+ if tree[2]
71
+ superclassname = Object.to_class_name tree[2]
72
+
73
+ eval("
74
+ class #{classname} < #{superclassname}
75
+ end
76
+ ", $top_level_binding)
77
+
78
+ else
79
+ eval("
80
+ class #{classname}
81
+ end
82
+ ", $top_level_binding)
70
83
  end
71
- ", $top_level_binding)
72
84
 
73
85
  klass = eval(classname)
74
86
 
@@ -83,6 +95,29 @@ class Object
83
95
  end
84
96
 
85
97
  klass.send(method_name)
98
+ elsif tree[0] == :module
99
+ modulename = Object.to_class_name tree[1]
100
+
101
+ eval("
102
+ module #{modulename}
103
+ end
104
+ ", $top_level_binding)
105
+
106
+ klass = eval(modulename)
107
+
108
+ method_name = "_anonymous_" + rand(100000000000).to_s
109
+ $generated_tree = FastRuby.encapsulate_tree(tree[2],method_name)
110
+ $options_hashes = options_hashes
111
+
112
+ klass.class_eval do
113
+ class << self
114
+ fastruby $generated_tree, *$options_hashes
115
+ end
116
+ end
117
+
118
+ klass.send(method_name)
119
+ elsif tree[0] == :defn
120
+ Object.fastruby_defn(tree, *options_hashes)
86
121
  else
87
122
  method_name = "_anonymous_" + rand(100000000000).to_s
88
123
  Object.fastruby(FastRuby.encapsulate_tree(tree,method_name), *options_hashes)
@@ -90,6 +125,10 @@ class Object
90
125
  end
91
126
  end
92
127
 
128
+ def self.fastruby_defs(*args)
129
+ raise NoMethodError, "not implemented yet"
130
+ end
131
+
93
132
  def self.fastruby(argument,*options_hashes)
94
133
 
95
134
  tree = nil
@@ -102,6 +141,8 @@ class Object
102
141
  raise ArgumentError
103
142
  end
104
143
 
144
+ return unless tree
145
+
105
146
  if tree.node_type == :defn
106
147
  fastruby_defn(tree,*options_hashes)
107
148
  else
@@ -173,7 +214,7 @@ class Object
173
214
 
174
215
  eval("#{hashname} = hash")
175
216
 
176
- value_cast = ( ["VALUE"]*(args_tree.size+1) ).join(",")
217
+ value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
177
218
 
178
219
  main_signature_argument = args_tree[1..-1].first || "self"
179
220
 
@@ -181,9 +222,9 @@ class Object
181
222
  strmethodargs_class = (["self"] + args_tree[1..-1]).map{|arg| "CLASS_OF(#{arg.to_s})"}.join(",")
182
223
 
183
224
  if args_tree.size > 1
184
- strmethodargs = "self,block,#{args_tree[1..-1].map(&:to_s).join(",") }"
225
+ strmethodargs = "self,block,(VALUE)&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
185
226
  else
186
- strmethodargs = "self,block"
227
+ strmethodargs = "self,block,(VALUE)&frame"
187
228
  end
188
229
 
189
230
  strmethod_signature = (["self"] + args_tree[1..-1]).map { |arg|
@@ -217,6 +258,22 @@ class Object
217
258
  }
218
259
 
219
260
  if (nd_type(body) == NODE_CFUNC) {
261
+ struct {
262
+ void* parent_frame;
263
+ void* target_frame;
264
+ void* plocals;
265
+ jmp_buf jmp;
266
+ VALUE return_value;
267
+ VALUE exception;
268
+ int rescue;
269
+ } frame;
270
+
271
+ frame.target_frame = 0;
272
+ frame.parent_frame = 0;
273
+ frame.rescue = 0;
274
+ frame.exception = Qnil;
275
+ frame.return_value = Qnil;
276
+
220
277
  int argc = body->nd_argc;
221
278
 
222
279
  VALUE block = Qfalse;
@@ -233,13 +290,19 @@ class Object
233
290
  block = (VALUE)&block_struct;
234
291
  }
235
292
 
236
- if (argc == #{args_tree.size}) {
293
+ int aux = setjmp(frame.jmp);
294
+ if (aux != 0) {
295
+ rb_funcall(self, #{:raise.to_i}, 1, frame.exception);
296
+ return Qnil;
297
+ }
298
+
299
+ if (argc == #{args_tree.size+1}) {
237
300
  return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
238
301
  } else if (argc == -1) {
239
- VALUE argv[] = {#{(["block"]+args_tree[1..-1]).map(&:to_s).join(",")} };
302
+ VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
240
303
  return ((VALUE(*)(int,VALUE*,VALUE))body->nd_cfnc)(#{args_tree.size},argv,self);
241
304
  } else if (argc == -2) {
242
- VALUE argv[] = {#{(["block"]+args_tree[1..-1]).map(&:to_s).join(",")} };
305
+ VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
243
306
  return ((VALUE(*)(VALUE,VALUE))body->nd_cfnc)(self, rb_ary_new4(#{args_tree.size},argv));
244
307
  } else {
245
308
  rb_raise(rb_eArgError, \"wrong number of arguments (#{args_tree.size-1} for %d)\", argc);
@@ -251,7 +314,7 @@ class Object
251
314
 
252
315
  inline :C do |builder|
253
316
  builder.include "<node.h>"
254
- builder.inc << "static VALUE re_yield(int argc, VALUE* argv, VALUE param) {
317
+ builder.inc << "static VALUE re_yield(int argc, VALUE* argv, VALUE param, VALUE _parent_frame) {
255
318
  return rb_yield_splat(rb_ary_new4(argc,argv));
256
319
  }"
257
320
  builder.c c_code