fastruby 0.0.12 → 0.0.13
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 +8 -0
- data/README +0 -1
- data/Rakefile +1 -1
- data/lib/fastruby/builder.rb +9 -2
- data/lib/fastruby/translator/modules/block.rb +92 -0
- data/lib/fastruby/translator/modules/call.rb +137 -0
- data/lib/fastruby/translator/modules/defn.rb +221 -0
- data/lib/fastruby/translator/modules/exceptions.rb +134 -0
- data/lib/fastruby/translator/modules/flow.rb +91 -0
- data/lib/fastruby/translator/modules/iter.rb +584 -0
- data/lib/fastruby/translator/modules/literal.rb +86 -0
- data/lib/fastruby/translator/modules/logical.rb +38 -0
- data/lib/fastruby/translator/modules/method_group.rb +174 -0
- data/lib/fastruby/translator/modules/nonlocal.rb +96 -0
- data/lib/fastruby/translator/modules/variable.rb +190 -0
- data/lib/fastruby/translator/translator.rb +1171 -0
- data/lib/fastruby/translator/translator_modules.rb +49 -0
- data/lib/fastruby.rb +1 -1
- data/spec/call/multiple_args_spec.rb +87 -0
- data/spec/defn/multiple_args_spec.rb +271 -0
- metadata +19 -7
- data/lib/fastruby/translator/call.rb +0 -2594
- data/lib/fastruby/translator/iter.rb +0 -2594
- data/lib/fastruby/translator.rb +0 -2594
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
0.0.13 Argument splat method calls (not optimized yet)
|
2
|
+
|
3
|
+
Array arguments on methods (optional arguments, variable number of arguments)
|
4
|
+
|
5
|
+
Fixed bug of return when trying to return from a proc (illegal overwrite of memory on stack when trying to flag frame as targetted)
|
6
|
+
|
7
|
+
Internal refactor
|
8
|
+
|
1
9
|
0.0.12 Completed exception support (multiple rescue clauses, multiple exceptions in only one rescue, assign exceptions to variables and fastruby internal exceptions)
|
2
10
|
|
3
11
|
0.0.11 Fixed packaging error
|
data/README
CHANGED
@@ -61,7 +61,6 @@ I will stabilize the API and document it for next releases. I promise
|
|
61
61
|
* callcc is not supported, it works but using it may result in unexpected behaviour
|
62
62
|
* recursive methods will be slow since the optimization of method calls only works with already defined methods
|
63
63
|
* 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)
|
64
|
-
* does not support methods with variable number of arguments
|
65
64
|
|
66
65
|
== Usage
|
67
66
|
|
data/Rakefile
CHANGED
data/lib/fastruby/builder.rb
CHANGED
@@ -88,7 +88,14 @@ module FastRuby
|
|
88
88
|
end
|
89
89
|
|
90
90
|
if method_tree
|
91
|
-
|
91
|
+
|
92
|
+
args_tree = method_tree[2]
|
93
|
+
|
94
|
+
if args_tree.any?{|x|x.to_s.match(/\*/)}
|
95
|
+
:fastruby_array
|
96
|
+
else
|
97
|
+
:fastruby
|
98
|
+
end
|
92
99
|
else
|
93
100
|
:cruby
|
94
101
|
end
|
@@ -98,7 +105,7 @@ module FastRuby
|
|
98
105
|
end
|
99
106
|
|
100
107
|
def build(signature, noreturn = false)
|
101
|
-
require "fastruby/translator"
|
108
|
+
require "fastruby/translator/translator"
|
102
109
|
require "rubygems"
|
103
110
|
require "inline"
|
104
111
|
|
@@ -0,0 +1,92 @@
|
|
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 FastRuby
|
22
|
+
module BlockTranslator
|
23
|
+
|
24
|
+
register_translator_module self
|
25
|
+
|
26
|
+
def to_c_yield(tree)
|
27
|
+
|
28
|
+
block_code = proc { |name| "
|
29
|
+
static VALUE #{name}(VALUE frame_param, VALUE* block_args) {
|
30
|
+
|
31
|
+
#{@locals_struct} *plocals;
|
32
|
+
#{@frame_struct} *pframe;
|
33
|
+
pframe = (void*)frame_param;
|
34
|
+
plocals = (void*)pframe->plocals;
|
35
|
+
|
36
|
+
if (FIX2LONG(plocals->block_function_address) == 0) {
|
37
|
+
#{_raise("rb_eLocalJumpError", "no block given")};
|
38
|
+
} else {
|
39
|
+
return ((VALUE(*)(int,VALUE*,VALUE,VALUE))FIX2LONG(plocals->block_function_address))(#{tree.size-1}, block_args, FIX2LONG(plocals->block_function_param), (VALUE)pframe);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
"
|
43
|
+
}
|
44
|
+
|
45
|
+
new_yield_signature = tree[1..-1].map{|subtree| infer_type subtree}
|
46
|
+
# merge the new_yield_signature with the new
|
47
|
+
if @yield_signature
|
48
|
+
if new_yield_signature.size == @yield_signature.size
|
49
|
+
(0..new_yield_signature.size-1).each do |i|
|
50
|
+
if @yield_signature[i] != new_yield_signature[i]
|
51
|
+
@yield_signature[i] = nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
else
|
55
|
+
@yield_signature = new_yield_signature.map{|x| nil}
|
56
|
+
end
|
57
|
+
else
|
58
|
+
@yield_signature = new_yield_signature
|
59
|
+
end
|
60
|
+
|
61
|
+
ret = if tree.size > 1
|
62
|
+
anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}})"
|
63
|
+
else
|
64
|
+
anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){})"
|
65
|
+
end
|
66
|
+
|
67
|
+
protected_block(ret, false)
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_c_block(tree)
|
71
|
+
|
72
|
+
str = ""
|
73
|
+
str = tree[1..-2].map{ |subtree|
|
74
|
+
to_c(subtree)
|
75
|
+
}.join(";")
|
76
|
+
|
77
|
+
if tree[-1]
|
78
|
+
|
79
|
+
if tree[-1][0] != :return
|
80
|
+
str = str + ";last_expression = #{to_c(tree[-1])};"
|
81
|
+
else
|
82
|
+
str = str + ";#{to_c(tree[-1])};"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
str << "return last_expression;"
|
87
|
+
|
88
|
+
inline_block str
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,137 @@
|
|
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 FastRuby
|
22
|
+
module CallTranslator
|
23
|
+
|
24
|
+
register_translator_module self
|
25
|
+
|
26
|
+
def to_c_call(tree, repass_var = nil)
|
27
|
+
directive_code = directive(tree)
|
28
|
+
if directive_code
|
29
|
+
return directive_code
|
30
|
+
end
|
31
|
+
|
32
|
+
if tree[2] == :require
|
33
|
+
tree[2] = :fastruby_require
|
34
|
+
elsif tree[2] == :raise
|
35
|
+
# raise code
|
36
|
+
args = tree[3]
|
37
|
+
return _raise(args[1],args[2])
|
38
|
+
end
|
39
|
+
|
40
|
+
recv = tree[1]
|
41
|
+
mname = tree[2]
|
42
|
+
args = tree[3]
|
43
|
+
|
44
|
+
mname = :require_fastruby if mname == :require
|
45
|
+
|
46
|
+
argnum = args.size - 1
|
47
|
+
|
48
|
+
recv = recv || s(:self)
|
49
|
+
|
50
|
+
recvtype = infer_type(recv)
|
51
|
+
|
52
|
+
if args.size > 1
|
53
|
+
if args.last[0] == :splat
|
54
|
+
return protected_block(
|
55
|
+
inline_block(
|
56
|
+
"
|
57
|
+
|
58
|
+
VALUE array = #{to_c args.last[1]};
|
59
|
+
|
60
|
+
if (TYPE(array) != T_ARRAY) {
|
61
|
+
array = rb_ary_new4(1,&array);
|
62
|
+
}
|
63
|
+
|
64
|
+
int argc = #{args.size-2};
|
65
|
+
VALUE argv[#{args.size} + RARRAY(array)->len];
|
66
|
+
|
67
|
+
#{
|
68
|
+
i = -1
|
69
|
+
args[1..-2].map {|arg|
|
70
|
+
i = i + 1
|
71
|
+
"argv[#{i}] = #{to_c arg}"
|
72
|
+
}.join(";\n")
|
73
|
+
};
|
74
|
+
|
75
|
+
int array_len = RARRAY(array)->len;
|
76
|
+
|
77
|
+
int i;
|
78
|
+
for (i=0; i<array_len;i++) {
|
79
|
+
argv[argc] = rb_ary_entry(array,i);
|
80
|
+
argc++;
|
81
|
+
}
|
82
|
+
|
83
|
+
return rb_funcall2(#{to_c recv}, #{intern_num tree[2]}, argc, argv);
|
84
|
+
"
|
85
|
+
), true, repass_var)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
strargs = args[1..-1].map{|arg| to_c arg}.join(",")
|
90
|
+
|
91
|
+
if recvtype
|
92
|
+
|
93
|
+
address = nil
|
94
|
+
mobject = nil
|
95
|
+
|
96
|
+
inference_complete = true
|
97
|
+
signature = [recvtype]
|
98
|
+
|
99
|
+
args[1..-1].each do |arg|
|
100
|
+
argtype = infer_type(arg)
|
101
|
+
if argtype
|
102
|
+
signature << argtype
|
103
|
+
else
|
104
|
+
inference_complete = false
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
if repass_var
|
109
|
+
extraargs = ","+repass_var
|
110
|
+
extraargs_signature = ",VALUE " + repass_var
|
111
|
+
else
|
112
|
+
extraargs = ""
|
113
|
+
extraargs_signature = ""
|
114
|
+
end
|
115
|
+
|
116
|
+
if argnum == 0
|
117
|
+
value_cast = "VALUE,VALUE,VALUE"
|
118
|
+
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
|
119
|
+
else
|
120
|
+
value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
|
121
|
+
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
|
122
|
+
end
|
123
|
+
|
124
|
+
else # else recvtype
|
125
|
+
if argnum == 0
|
126
|
+
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
|
127
|
+
else
|
128
|
+
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", true, repass_var)
|
129
|
+
end
|
130
|
+
end # if recvtype
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_c_attrasgn(tree)
|
134
|
+
to_c_call(tree)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,221 @@
|
|
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 FastRuby
|
22
|
+
module DefnTranslator
|
23
|
+
register_translator_module self
|
24
|
+
|
25
|
+
def to_c_defn(tree)
|
26
|
+
|
27
|
+
method_name = tree[1]
|
28
|
+
args_tree = tree[2]
|
29
|
+
|
30
|
+
global_klass_variable = add_global_name("VALUE", "Qnil");
|
31
|
+
|
32
|
+
hash = Hash.new
|
33
|
+
value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
|
34
|
+
|
35
|
+
multiple_arguments = args_tree[1..-1].find{|x| x.to_s =~ /\*/}
|
36
|
+
|
37
|
+
args_array_accessors = if multiple_arguments
|
38
|
+
(0..args_tree.size-3).map{|x| "argv[#{x}]"} + ["argarray"]
|
39
|
+
else
|
40
|
+
(0..args_tree.size-2).map{|x| "argv[#{x}]"}
|
41
|
+
end
|
42
|
+
|
43
|
+
strmethodargs = ""
|
44
|
+
|
45
|
+
if args_tree.size > 1
|
46
|
+
strmethodargs = "self,block,(VALUE)&frame,#{args_array_accessors.map(&:to_s).join(",") }"
|
47
|
+
else
|
48
|
+
strmethodargs = "self,block,(VALUE)&frame"
|
49
|
+
end
|
50
|
+
|
51
|
+
strmakecall = if multiple_arguments
|
52
|
+
"
|
53
|
+
if (argc_ > #{args_tree.size-2}) {
|
54
|
+
VALUE argarray = rb_ary_new4(argc_-#{args_tree.size-2}, argv+#{args_tree.size-2});
|
55
|
+
return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
|
56
|
+
} else if (argc_ == #{args_tree.size-2}) {
|
57
|
+
// pass pre-calculated method arguments plus an empty array
|
58
|
+
VALUE argarray = rb_ary_new();
|
59
|
+
return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
|
60
|
+
} else {
|
61
|
+
rb_raise(rb_eArgError, \"wrong number of arguments (%d for #{args_tree.size-2}))\", argc_);
|
62
|
+
}
|
63
|
+
"
|
64
|
+
else
|
65
|
+
"if (argc_ == #{args_tree.size-1} && argc == #{args_tree.size+1}) {
|
66
|
+
return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
|
67
|
+
} else {
|
68
|
+
rb_raise(rb_eArgError, \"wrong number of arguments (%d for #{args_tree.size-1}))\", argc_);
|
69
|
+
}"
|
70
|
+
end
|
71
|
+
|
72
|
+
anonymous_method_name = anonymous_function{ |anonymous_method_name| "VALUE #{anonymous_method_name}(int argc_, VALUE* argv, VALUE self) {
|
73
|
+
|
74
|
+
VALUE klass = #{global_klass_variable};
|
75
|
+
char method_name[0x100];
|
76
|
+
|
77
|
+
method_name[0] = '_';
|
78
|
+
method_name[1] = 0;
|
79
|
+
|
80
|
+
sprintf(method_name+1, \"#{method_name}\");
|
81
|
+
|
82
|
+
int i;
|
83
|
+
for (i=0; i<argc_; i++) {
|
84
|
+
sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(argv[i]))));
|
85
|
+
}
|
86
|
+
|
87
|
+
NODE* body;
|
88
|
+
ID id;
|
89
|
+
|
90
|
+
id = rb_intern(method_name);
|
91
|
+
body = rb_method_node(klass,id);
|
92
|
+
|
93
|
+
if (body == 0) {
|
94
|
+
VALUE argv_class[argc_+1];
|
95
|
+
|
96
|
+
argv_class[0] = CLASS_OF(self);
|
97
|
+
for (i=0; i<argc_; i++) {
|
98
|
+
argv_class[i+1] = CLASS_OF(argv[i]);
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE signature = rb_ary_new4(argc_+1,argv_class);
|
102
|
+
VALUE mobject = rb_funcall(#{global_klass_variable}, #{intern_num :build}, 2, signature,rb_str_new2(#{method_name.to_s.inspect}));
|
103
|
+
|
104
|
+
struct METHOD {
|
105
|
+
VALUE klass, rklass;
|
106
|
+
VALUE recv;
|
107
|
+
ID id, oid;
|
108
|
+
int safe_level;
|
109
|
+
NODE *body;
|
110
|
+
};
|
111
|
+
|
112
|
+
struct METHOD *data;
|
113
|
+
Data_Get_Struct(mobject, struct METHOD, data);
|
114
|
+
body = data->body;
|
115
|
+
|
116
|
+
if (body == 0) {
|
117
|
+
rb_raise(rb_eRuntimeError,\"method not found after build: '%s'\", method_name);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
if (nd_type(body) == NODE_CFUNC) {
|
122
|
+
struct {
|
123
|
+
void* parent_frame;
|
124
|
+
void* plocals;
|
125
|
+
jmp_buf jmp;
|
126
|
+
VALUE return_value;
|
127
|
+
int rescue;
|
128
|
+
VALUE last_error;
|
129
|
+
VALUE next_recv;
|
130
|
+
int targetted;
|
131
|
+
struct FASTRUBYTHREADDATA* thread_data;
|
132
|
+
} frame;
|
133
|
+
|
134
|
+
frame.parent_frame = 0;
|
135
|
+
frame.rescue = 0;
|
136
|
+
frame.return_value = Qnil;
|
137
|
+
frame.thread_data = rb_current_thread_data();
|
138
|
+
frame.targetted = 0;
|
139
|
+
|
140
|
+
int argc = body->nd_argc;
|
141
|
+
|
142
|
+
VALUE block = Qfalse;
|
143
|
+
|
144
|
+
if (rb_block_given_p()) {
|
145
|
+
struct {
|
146
|
+
void *block_function_address;
|
147
|
+
void *block_function_param;
|
148
|
+
} block_struct;
|
149
|
+
|
150
|
+
block_struct.block_function_address = re_yield;
|
151
|
+
block_struct.block_function_param = 0;
|
152
|
+
|
153
|
+
block = (VALUE)&block_struct;
|
154
|
+
}
|
155
|
+
|
156
|
+
int aux = setjmp(frame.jmp);
|
157
|
+
if (aux != 0) {
|
158
|
+
if (aux == FASTRUBY_TAG_RAISE) {
|
159
|
+
rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
160
|
+
}
|
161
|
+
|
162
|
+
if (frame.targetted == 0) {
|
163
|
+
rb_jump_tag(aux);
|
164
|
+
}
|
165
|
+
|
166
|
+
return Qnil;
|
167
|
+
}
|
168
|
+
|
169
|
+
#{strmakecall}
|
170
|
+
}
|
171
|
+
|
172
|
+
return Qnil;
|
173
|
+
}"
|
174
|
+
}
|
175
|
+
|
176
|
+
alt_options = options.dup
|
177
|
+
|
178
|
+
alt_options.delete(:self)
|
179
|
+
alt_options.delete(:main)
|
180
|
+
|
181
|
+
inline_block "
|
182
|
+
#{global_klass_variable} = plocals->self;
|
183
|
+
|
184
|
+
// set tree
|
185
|
+
rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
|
186
|
+
#{global_klass_variable},
|
187
|
+
rb_str_new2(#{method_name.to_s.inspect}),
|
188
|
+
#{literal_value tree},
|
189
|
+
#{literal_value snippet_hash},
|
190
|
+
#{literal_value alt_options}
|
191
|
+
|
192
|
+
);
|
193
|
+
|
194
|
+
rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
|
195
|
+
"
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
def to_c_defs(tree)
|
200
|
+
args_tree = tree[3];
|
201
|
+
|
202
|
+
tmp = FastRuby.build_defs(tree)
|
203
|
+
|
204
|
+
extra_code << tmp[0]
|
205
|
+
@init_extra = @init_extra + tmp[2]
|
206
|
+
|
207
|
+
inline_block "
|
208
|
+
rb_define_singleton_method(#{to_c tree[1]}, \"#{tree[2].to_s}\", (void*)#{tmp[1]}, #{args_tree.size-1});
|
209
|
+
return Qnil;
|
210
|
+
"
|
211
|
+
end
|
212
|
+
|
213
|
+
def to_c_scope(tree)
|
214
|
+
if tree[1]
|
215
|
+
to_c(tree[1])
|
216
|
+
else
|
217
|
+
"Qnil"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
@@ -0,0 +1,134 @@
|
|
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 FastRuby
|
22
|
+
module ExceptionsTranslator
|
23
|
+
register_translator_module self
|
24
|
+
|
25
|
+
|
26
|
+
def to_c_rescue(tree)
|
27
|
+
if tree[1][0] == :resbody
|
28
|
+
else_tree = tree[2]
|
29
|
+
|
30
|
+
if else_tree
|
31
|
+
to_c else_tree
|
32
|
+
else
|
33
|
+
"Qnil"
|
34
|
+
end
|
35
|
+
else
|
36
|
+
resbody_tree = tree[2]
|
37
|
+
else_tree = nil
|
38
|
+
if tree[-1]
|
39
|
+
if tree[-1][0] != :resbody
|
40
|
+
else_tree = tree[-1]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
catch_condition_array = []
|
45
|
+
lasgn_code = ""
|
46
|
+
resbody_code = to_c(resbody_tree[2])
|
47
|
+
|
48
|
+
rescue_code = ""
|
49
|
+
|
50
|
+
tree[1..-1].each do |resbody_tree|
|
51
|
+
next if resbody_tree[0] != :resbody
|
52
|
+
|
53
|
+
if resbody_tree[1].size == 1
|
54
|
+
resbody_tree[1][1] = [:const, :Exception]
|
55
|
+
end
|
56
|
+
|
57
|
+
if resbody_tree[1].last[0] == :lasgn
|
58
|
+
lasgn_code = to_c(resbody_tree[1].last)
|
59
|
+
end
|
60
|
+
|
61
|
+
resbody_tree[1][1..-1].each do |xtree|
|
62
|
+
if xtree[0] != :lasgn
|
63
|
+
trapcode = "rb_eException";
|
64
|
+
|
65
|
+
if xtree
|
66
|
+
trapcode = to_c(xtree)
|
67
|
+
end
|
68
|
+
|
69
|
+
catch_condition_array << "(rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
rescue_code << "
|
74
|
+
if (aux == FASTRUBY_TAG_RAISE) {
|
75
|
+
if (#{catch_condition_array.join(" || ")})
|
76
|
+
{
|
77
|
+
// trap exception
|
78
|
+
frame.targetted = 1;
|
79
|
+
|
80
|
+
#{lasgn_code};
|
81
|
+
|
82
|
+
#{resbody_code};
|
83
|
+
}
|
84
|
+
}
|
85
|
+
"
|
86
|
+
end
|
87
|
+
|
88
|
+
frame_call(
|
89
|
+
frame(to_c(tree[1])+";","
|
90
|
+
#{rescue_code}
|
91
|
+
", else_tree ? to_c(else_tree) : nil, 1)
|
92
|
+
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_c_ensure(tree)
|
98
|
+
if tree.size == 2
|
99
|
+
to_c tree[1]
|
100
|
+
else
|
101
|
+
ensured_code = to_c tree[2]
|
102
|
+
inline_block "
|
103
|
+
#{frame(to_c(tree[1]),ensured_code,ensured_code,1)};
|
104
|
+
"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def _raise(class_tree, message_tree = nil)
|
109
|
+
class_tree = to_c class_tree unless class_tree.instance_of? String
|
110
|
+
|
111
|
+
if message_tree.instance_of? String
|
112
|
+
message_tree = "rb_str_new2(#{message_tree.inspect})"
|
113
|
+
else
|
114
|
+
message_tree = to_c message_tree
|
115
|
+
end
|
116
|
+
|
117
|
+
if message_tree
|
118
|
+
return inline_block("
|
119
|
+
pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},1,#{message_tree});
|
120
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
|
121
|
+
return Qnil;
|
122
|
+
")
|
123
|
+
else
|
124
|
+
return inline_block("
|
125
|
+
pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},0);
|
126
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
|
127
|
+
return Qnil;
|
128
|
+
")
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|