fastruby 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,86 @@
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 LiteralTranslator
23
+ register_translator_module self
24
+
25
+ def to_c_lit(tree)
26
+ literal_value tree[1]
27
+ end
28
+
29
+ def to_c_nil(tree)
30
+ "Qnil"
31
+ end
32
+
33
+ def to_c_str(tree)
34
+ literal_value tree[1]
35
+ end
36
+
37
+ def to_c_hash(tree)
38
+
39
+ hash_aset_code = ""
40
+ (0..(tree.size-3)/2).each do |i|
41
+ strkey = to_c tree[1 + i * 2]
42
+ strvalue = to_c tree[2 + i * 2]
43
+ hash_aset_code << "rb_hash_aset(hash, #{strkey}, #{strvalue});"
44
+ end
45
+
46
+ anonymous_function{ |name| "
47
+ static VALUE #{name}(VALUE value_params) {
48
+ #{@frame_struct} *pframe;
49
+ #{@locals_struct} *plocals;
50
+ pframe = (void*)value_params;
51
+ plocals = (void*)pframe->plocals;
52
+
53
+ VALUE hash = rb_hash_new();
54
+ #{hash_aset_code}
55
+ return hash;
56
+ }
57
+ " } + "((VALUE)pframe)"
58
+ end
59
+
60
+ def to_c_array(tree)
61
+ if tree.size > 1
62
+ strargs = tree[1..-1].map{|subtree| to_c subtree}.join(",")
63
+ "rb_ary_new3(#{tree.size-1}, #{strargs})"
64
+ else
65
+ "rb_ary_new3(0)"
66
+ end
67
+ end
68
+
69
+ def to_c_self(tree)
70
+ locals_accessor + "self"
71
+ end
72
+
73
+ def to_c_false(tree)
74
+ "Qfalse"
75
+ end
76
+
77
+ def to_c_true(tree)
78
+ "Qtrue"
79
+ end
80
+
81
+ def to_c_dot2(tree)
82
+ "rb_range_new(#{to_c tree[1]}, #{to_c tree[2]},0)"
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,38 @@
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 LogicalOperatorTranslator
23
+ register_translator_module self
24
+
25
+ def to_c_and(tree)
26
+ "(RTEST(#{to_c tree[1]}) && RTEST(#{to_c tree[2]})) ? Qtrue : Qfalse"
27
+ end
28
+
29
+ def to_c_or(tree)
30
+ "(RTEST(#{to_c tree[1]}) || RTEST(#{to_c tree[2]})) ? Qtrue : Qfalse"
31
+ end
32
+
33
+ def to_c_not(tree)
34
+ "RTEST(#{to_c tree[1]}) ? Qfalse : Qtrue"
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,174 @@
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
+ register_translator_module self
24
+
25
+ def to_c_class(tree)
26
+ str_class_name = get_class_name(tree[1])
27
+ container_tree = get_container_tree(tree[1])
28
+
29
+ if container_tree == s(:self)
30
+ method_group("
31
+ VALUE tmpklass = rb_define_class(
32
+ #{str_class_name.inspect},
33
+ #{tree[2] ? to_c(tree[2]) : "rb_cObject"}
34
+ );
35
+ ", tree[3])
36
+ else
37
+ method_group("
38
+ VALUE container_klass = #{to_c(container_tree)};
39
+ VALUE tmpklass = rb_define_class_under(
40
+ container_klass,
41
+ #{str_class_name.inspect},
42
+ #{tree[2] ? to_c(tree[2]) : "rb_cObject"}
43
+ );
44
+ ", tree[3])
45
+ end
46
+ end
47
+
48
+ def to_c_module(tree)
49
+ str_class_name = get_class_name(tree[1])
50
+ container_tree = get_container_tree(tree[1])
51
+
52
+ if container_tree == s(:self)
53
+ method_group("
54
+ VALUE tmpklass = rb_define_module(#{str_class_name.inspect});
55
+ ", tree[2])
56
+ else
57
+ method_group("
58
+ VALUE container_klass = #{to_c(container_tree)};
59
+ VALUE tmpklass = rb_define_module_under(container_klass,#{str_class_name.inspect});
60
+ ", tree[2])
61
+ end
62
+ end
63
+
64
+ private
65
+ def method_group(init_code, tree)
66
+
67
+ alt_locals = Set.new
68
+ alt_locals << :self
69
+
70
+ FastRuby::GetLocalsProcessor.get_locals(tree).each do |local|
71
+ alt_locals << local
72
+ end
73
+
74
+ fun = nil
75
+
76
+ locals_scope(alt_locals) do
77
+ fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
78
+
79
+ #{@frame_struct} frame;
80
+ typeof(&frame) pframe = &frame;
81
+ #{@locals_struct} *plocals;
82
+
83
+ frame.parent_frame = 0;
84
+ frame.return_value = Qnil;
85
+ frame.rescue = 0;
86
+ frame.targetted = 0;
87
+ frame.thread_data = rb_current_thread_data();
88
+
89
+ int stack_chunk_instantiated = 0;
90
+ VALUE rb_previous_stack_chunk = Qnil;
91
+ VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
92
+ struct STACKCHUNK* stack_chunk = 0;
93
+
94
+ if (rb_stack_chunk != Qnil) {
95
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
96
+ }
97
+
98
+ if (stack_chunk == 0 || (stack_chunk == 0 ? 0 : stack_chunk_frozen(stack_chunk)) ) {
99
+ rb_previous_stack_chunk = rb_stack_chunk;
100
+ rb_gc_register_address(&rb_stack_chunk);
101
+ stack_chunk_instantiated = 1;
102
+
103
+ rb_stack_chunk = rb_stack_chunk_create(Qnil);
104
+ frame.thread_data->rb_stack_chunk = rb_stack_chunk;
105
+
106
+ rb_ivar_set(rb_stack_chunk, #{intern_num :_parent_stack_chunk}, rb_previous_stack_chunk);
107
+
108
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
109
+ }
110
+
111
+ int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
112
+
113
+ plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
114
+
115
+ frame.plocals = plocals;
116
+ plocals->active = Qtrue;
117
+ plocals->self = self;
118
+ plocals->targetted = Qfalse;
119
+ plocals->call_frame = LONG2FIX(0);
120
+
121
+ #{to_c tree};
122
+
123
+ stack_chunk_set_current_position(stack_chunk, previous_stack_position);
124
+
125
+ if (stack_chunk_instantiated) {
126
+ rb_gc_unregister_address(&rb_stack_chunk);
127
+ frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
128
+ }
129
+
130
+ plocals->active = Qfalse;
131
+ return Qnil;
132
+ }
133
+ "
134
+ }
135
+ end
136
+
137
+ inline_block("
138
+ #{init_code}
139
+
140
+ rb_funcall(tmpklass, #{intern_num :__id__},0);
141
+
142
+ #{fun}(tmpklass);
143
+ return Qnil;
144
+
145
+
146
+ ")
147
+
148
+ end
149
+
150
+ def get_class_name(argument)
151
+ if argument.instance_of? Symbol
152
+ argument.to_s
153
+ elsif argument.instance_of? FastRuby::FastRubySexp
154
+ if argument[0] == :colon3
155
+ get_class_name(argument[1])
156
+ elsif argument[0] == :colon2
157
+ get_class_name(argument[2])
158
+ end
159
+ end
160
+ end
161
+
162
+ def get_container_tree(argument)
163
+ if argument.instance_of? Symbol
164
+ s(:self)
165
+ elsif argument.instance_of? FastRuby::FastRubySexp
166
+ if argument[0] == :colon3
167
+ s(:const, :Object)
168
+ elsif argument[0] == :colon2
169
+ argument[1]
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,96 @@
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 NonLocalTranslator
23
+ register_translator_module self
24
+
25
+ def to_c_return(tree)
26
+ inline_block "
27
+ plocals->return_value = #{to_c(tree[1])};
28
+ plocals->targetted = 1;
29
+ longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
30
+ return Qnil;
31
+ "
32
+ end
33
+
34
+ def to_c_break(tree)
35
+ inline_block(
36
+ "
37
+
38
+ VALUE value = #{tree[1] ? to_c(tree[1]) : "Qnil"};
39
+
40
+ typeof(pframe) target_frame_;
41
+ target_frame_ = (void*)FIX2LONG(plocals->call_frame);
42
+
43
+ if (target_frame_ == 0) {
44
+ #{_raise("rb_eLocalJumpError","illegal break")};
45
+ }
46
+
47
+ plocals->call_frame = LONG2FIX(0);
48
+
49
+ target_frame_->return_value = value;
50
+ target_frame_->targetted = 1;
51
+ pframe->thread_data->exception = Qnil;
52
+ longjmp(pframe->jmp,FASTRUBY_TAG_BREAK);"
53
+ )
54
+ end
55
+
56
+ def to_c_retry(tree)
57
+ inline_block(
58
+ "
59
+ typeof(pframe) target_frame_;
60
+ target_frame_ = (void*)FIX2LONG(plocals->call_frame);
61
+
62
+ if (target_frame_ == 0) {
63
+ #{_raise("rb_eLocalJumpError","illegal retry")};
64
+ }
65
+
66
+ target_frame_->targetted = 1;
67
+ longjmp(pframe->jmp,FASTRUBY_TAG_RETRY);"
68
+ )
69
+ end
70
+
71
+ def to_c_redo(tree)
72
+ if @on_block
73
+ inline_block "
74
+ longjmp(pframe->jmp,FASTRUBY_TAG_REDO);
75
+ return Qnil;
76
+ "
77
+ else
78
+ _raise("rb_eLocalJumpError","illegal redo");
79
+ end
80
+ end
81
+
82
+ def to_c_next(tree)
83
+ if @on_block
84
+ inline_block "
85
+ pframe->thread_data->accumulator = #{tree[1] ? to_c(tree[1]) : "Qnil"};
86
+ longjmp(pframe->jmp,FASTRUBY_TAG_NEXT);
87
+ return Qnil;
88
+ "
89
+ else
90
+ _raise("rb_eLocalJumpError","illegal next");
91
+ end
92
+ end
93
+
94
+
95
+ end
96
+ end
@@ -0,0 +1,190 @@
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 VariabeTranslator
23
+ register_translator_module self
24
+
25
+
26
+ def to_c_cvar(tree)
27
+ "rb_cvar_get(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]})"
28
+ end
29
+
30
+ def to_c_cvasgn(tree)
31
+ "__rb_cvar_set(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]},#{to_c tree[2]},Qfalse)"
32
+ end
33
+
34
+ def to_c_gvar(tree)
35
+ if (tree[1] == :$!)
36
+ "pframe->thread_data->exception"
37
+ else
38
+ "rb_gvar_get((struct global_entry*)#{global_entry(tree[1])})"
39
+ end
40
+ end
41
+
42
+ def to_c_gasgn(tree)
43
+ "_rb_gvar_set((void*)#{global_entry(tree[1])}, #{to_c tree[2]})"
44
+ end
45
+
46
+ def to_c_ivar(tree)
47
+ "rb_ivar_get(#{locals_accessor}self,#{intern_num tree[1]})"
48
+ end
49
+
50
+ def to_c_iasgn(tree)
51
+ "_rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{to_c tree[2]})"
52
+ end
53
+
54
+ def to_c_const(tree)
55
+ "rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
56
+ end
57
+
58
+ def to_c_cdecl(tree)
59
+ if tree[1].instance_of? Symbol
60
+ inline_block "
61
+ // set constant #{tree[1].to_s}
62
+ VALUE val = #{to_c tree[2]};
63
+ rb_const_set(rb_cObject, #{intern_num tree[1]}, val);
64
+ return val;
65
+ "
66
+ elsif tree[1].instance_of? FastRuby::FastRubySexp
67
+
68
+ if tree[1].node_type == :colon2
69
+ inline_block "
70
+ // set constant #{tree[1].to_s}
71
+ VALUE val = #{to_c tree[2]};
72
+ VALUE klass = #{to_c tree[1][1]};
73
+ rb_const_set(klass, #{intern_num tree[1][2]}, val);
74
+ return val;
75
+ "
76
+ elsif tree[1].node_type == :colon3
77
+ inline_block "
78
+ // set constant #{tree[1].to_s}
79
+ VALUE val = #{to_c tree[2]};
80
+ rb_const_set(rb_cObject, #{intern_num tree[1][1]}, val);
81
+ return val;
82
+ "
83
+ end
84
+ end
85
+ end
86
+
87
+ def to_c_colon3(tree)
88
+ "rb_const_get_from(rb_cObject, #{intern_num tree[1]})"
89
+ end
90
+
91
+ def to_c_colon2(tree)
92
+ inline_block "
93
+ VALUE klass = #{to_c tree[1]};
94
+
95
+ if (rb_is_const_id(#{intern_num tree[2]})) {
96
+ switch (TYPE(klass)) {
97
+ case T_CLASS:
98
+ case T_MODULE:
99
+ return rb_const_get_from(klass, #{intern_num tree[2]});
100
+ break;
101
+ default:
102
+ #{_raise("rb_eTypeError","not a class/module")};
103
+ break;
104
+ }
105
+ }
106
+ else {
107
+ return rb_funcall(klass, #{intern_num tree[2]}, 0, 0);
108
+ }
109
+
110
+ return Qnil;
111
+ "
112
+ end
113
+
114
+ def to_c_lasgn(tree)
115
+ if options[:validate_lvar_types]
116
+ klass = @infer_lvar_map[tree[1]]
117
+ if klass
118
+
119
+ verify_type_function = proc { |name| "
120
+ static VALUE #{name}(VALUE arg, void* pframe ) {
121
+ if (CLASS_OF(arg)!=#{literal_value klass}) {
122
+ #{_raise(literal_value(FastRuby::TypeMismatchAssignmentException), "Illegal assignment at runtime (type mismatch)")};
123
+ }
124
+ return arg;
125
+ }
126
+ "
127
+ }
128
+
129
+
130
+ "_lvar_assing(&#{locals_accessor}#{tree[1]}, #{anonymous_function(&verify_type_function)}(#{to_c tree[2]},pframe))"
131
+ else
132
+ "_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
133
+ end
134
+ else
135
+ "_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
136
+ end
137
+ end
138
+
139
+ def to_c_lvar(tree)
140
+ locals_accessor + tree[1].to_s
141
+ end
142
+
143
+
144
+ def to_c_defined(tree)
145
+ nt = tree[1].node_type
146
+
147
+ if nt == :self
148
+ 'rb_str_new2("self")'
149
+ elsif nt == :true
150
+ 'rb_str_new2("true")'
151
+ elsif nt == :false
152
+ 'rb_str_new2("false")'
153
+ elsif nt == :nil
154
+ 'rb_str_new2("nil")'
155
+ elsif nt == :lvar
156
+ 'rb_str_new2("local-variable")'
157
+ elsif nt == :gvar
158
+ "rb_gvar_defined((struct global_entry*)#{global_entry(tree[1][1])}) ? #{literal_value "global-variable"} : Qnil"
159
+ elsif nt == :const
160
+ "rb_const_defined(rb_cObject, #{intern_num tree[1][1]}) ? #{literal_value "constant"} : Qnil"
161
+ elsif nt == :call
162
+ "rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{intern_num tree[1][2]}) ? #{literal_value "method"} : Qnil"
163
+ elsif nt == :yield
164
+ "rb_block_given_p() ? #{literal_value "yield"} : Qnil"
165
+ elsif nt == :ivar
166
+ "rb_ivar_defined(plocals->self,#{intern_num tree[1][1]}) ? #{literal_value "instance-variable"} : Qnil"
167
+ elsif nt == :attrset or
168
+ nt == :op_asgn1 or
169
+ nt == :op_asgn2 or
170
+ nt == :op_asgn_or or
171
+ nt == :op_asgn_and or
172
+ nt == :op_asgn_masgn or
173
+ nt == :masgn or
174
+ nt == :lasgn or
175
+ nt == :dasgn or
176
+ nt == :dasgn_curr or
177
+ nt == :gasgn or
178
+ nt == :iasgn or
179
+ nt == :cdecl or
180
+ nt == :cvdecl or
181
+ nt == :cvasgn
182
+ literal_value "assignment"
183
+ else
184
+ literal_value "expression"
185
+ end
186
+ end
187
+
188
+
189
+ end
190
+ end