rubex 0.1 → 0.1.1
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.
- checksums.yaml +5 -5
- data/.gitignore +3 -2
- data/.travis.yml +9 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +4 -1
- data/Rakefile +2 -2
- data/bin/rubex +4 -5
- data/lib/rubex.rb +4 -4
- data/lib/rubex/ast.rb +4 -1
- data/lib/rubex/ast/expression.rb +22 -1191
- data/lib/rubex/ast/expression/actual_arg_list.rb +40 -0
- data/lib/rubex/ast/expression/analysed_element_ref.rb +26 -0
- data/lib/rubex/ast/expression/analysed_element_ref/c_var_element_ref.rb +30 -0
- data/lib/rubex/ast/expression/analysed_element_ref/ruby_object_element_ref.rb +42 -0
- data/lib/rubex/ast/expression/arg_declaration.rb +43 -0
- data/lib/rubex/ast/expression/binary.rb +57 -0
- data/lib/rubex/ast/expression/binary/binary_boolean.rb +23 -0
- data/lib/rubex/ast/expression/binary/binary_boolean_special_op.rb +20 -0
- data/lib/rubex/ast/expression/binary/empty_classes.rb +62 -0
- data/lib/rubex/ast/expression/block_given.rb +15 -0
- data/lib/rubex/ast/expression/coerce_object.rb +15 -0
- data/lib/rubex/ast/expression/command_call.rb +74 -0
- data/lib/rubex/ast/expression/command_call/struct_or_union_member_call.rb +38 -0
- data/lib/rubex/ast/expression/element_ref.rb +64 -0
- data/lib/rubex/ast/expression/empty.rb +13 -0
- data/lib/rubex/ast/expression/from_ruby_object.rb +20 -0
- data/lib/rubex/ast/expression/func_ptr_arg_declaration.rb +21 -0
- data/lib/rubex/ast/expression/func_ptr_internal_arg_declaration.rb +13 -0
- data/lib/rubex/ast/expression/literal.rb +30 -0
- data/lib/rubex/ast/expression/literal/array_lit.rb +51 -0
- data/lib/rubex/ast/expression/literal/c_null.rb +15 -0
- data/lib/rubex/ast/expression/literal/char.rb +36 -0
- data/lib/rubex/ast/expression/literal/double.rb +14 -0
- data/lib/rubex/ast/expression/literal/false.rb +33 -0
- data/lib/rubex/ast/expression/literal/hash_lit.rb +45 -0
- data/lib/rubex/ast/expression/literal/int.rb +14 -0
- data/lib/rubex/ast/expression/literal/nil.rb +14 -0
- data/lib/rubex/ast/expression/literal/ruby_symbol.rb +22 -0
- data/lib/rubex/ast/expression/literal/string_lit.rb +45 -0
- data/lib/rubex/ast/expression/literal/true.rb +29 -0
- data/lib/rubex/ast/expression/method_call.rb +52 -0
- data/lib/rubex/ast/expression/method_call/c_function_call.rb +40 -0
- data/lib/rubex/ast/expression/method_call/ruby_method_call.rb +83 -0
- data/lib/rubex/ast/expression/name.rb +127 -0
- data/lib/rubex/ast/expression/ruby_constant.rb +25 -0
- data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_array_element_ref.rb +20 -0
- data/lib/rubex/ast/expression/ruby_object_element_ref/ruby_hash_element_ref.rb +22 -0
- data/lib/rubex/ast/expression/self.rb +15 -0
- data/lib/rubex/ast/expression/size_of.rb +22 -0
- data/lib/rubex/ast/expression/struct_or_union_member_call/element_ref_member_call.rb +23 -0
- data/lib/rubex/ast/expression/to_ruby_object.rb +21 -0
- data/lib/rubex/ast/expression/typecast.rb +20 -0
- data/lib/rubex/ast/expression/typecast_to.rb +10 -0
- data/lib/rubex/ast/expression/unary.rb +37 -0
- data/lib/rubex/ast/expression/unary_base.rb +24 -0
- data/lib/rubex/ast/expression/unary_base/ampersand.rb +16 -0
- data/lib/rubex/ast/expression/unary_base/unary_bit_not.rb +18 -0
- data/lib/rubex/ast/expression/unary_base/unary_not.rb +18 -0
- data/lib/rubex/ast/expression/unary_base/unary_sub.rb +18 -0
- data/lib/rubex/ast/node.rb +111 -111
- data/lib/rubex/ast/statement.rb +9 -1160
- data/lib/rubex/ast/statement/alias.rb +43 -0
- data/lib/rubex/ast/statement/argument_list.rb +59 -0
- data/lib/rubex/ast/statement/assign.rb +35 -0
- data/lib/rubex/ast/statement/begin_block.rb +14 -0
- data/lib/rubex/ast/statement/begin_block/begin.rb +202 -0
- data/lib/rubex/ast/statement/begin_block/else.rb +21 -0
- data/lib/rubex/ast/statement/begin_block/ensure.rb +21 -0
- data/lib/rubex/ast/statement/begin_block/rescue.rb +34 -0
- data/lib/rubex/ast/statement/break.rb +18 -0
- data/lib/rubex/ast/statement/c_array_decl.rb +49 -0
- data/lib/rubex/ast/statement/c_base_type.rb +26 -0
- data/lib/rubex/ast/statement/c_function_decl.rb +30 -0
- data/lib/rubex/ast/statement/c_ptr_decl.rb +52 -0
- data/lib/rubex/ast/statement/c_ptr_decl/c_ptr_func_decl.rb +25 -0
- data/lib/rubex/ast/statement/c_struct_or_union_def.rb +49 -0
- data/lib/rubex/ast/statement/expression.rb +26 -0
- data/lib/rubex/ast/statement/for.rb +73 -0
- data/lib/rubex/ast/statement/forward_decl.rb +31 -0
- data/lib/rubex/ast/statement/if_block.rb +64 -0
- data/lib/rubex/ast/statement/if_block/else.rb +30 -0
- data/lib/rubex/ast/statement/if_block/elsif.rb +22 -0
- data/lib/rubex/ast/statement/if_block/helper.rb +38 -0
- data/lib/rubex/ast/statement/print.rb +49 -0
- data/lib/rubex/ast/statement/raise.rb +66 -0
- data/lib/rubex/ast/statement/return.rb +45 -0
- data/lib/rubex/ast/statement/var_decl.rb +49 -0
- data/lib/rubex/ast/statement/while.rb +34 -0
- data/lib/rubex/ast/statement/yield.rb +41 -0
- data/lib/rubex/ast/top_statement.rb +1 -815
- data/lib/rubex/ast/top_statement/c_bindings.rb +145 -0
- data/lib/rubex/ast/top_statement/klass.rb +125 -0
- data/lib/rubex/ast/top_statement/klass/attached_klass.rb +417 -0
- data/lib/rubex/ast/top_statement/method_def.rb +110 -0
- data/lib/rubex/ast/top_statement/method_def/c_function_def.rb +26 -0
- data/lib/rubex/ast/top_statement/method_def/ruby_method_def.rb +33 -0
- data/lib/rubex/cli.rb +26 -0
- data/lib/rubex/code_writer.rb +1 -1
- data/lib/rubex/compiler.rb +49 -28
- data/lib/rubex/compiler_config.rb +4 -2
- data/lib/rubex/constants.rb +71 -71
- data/lib/rubex/data_type.rb +9 -675
- data/lib/rubex/data_type/c_array.rb +33 -0
- data/lib/rubex/data_type/c_function.rb +23 -0
- data/lib/rubex/data_type/c_ptr.rb +71 -0
- data/lib/rubex/data_type/c_str.rb +23 -0
- data/lib/rubex/data_type/c_struct_or_union.rb +23 -0
- data/lib/rubex/data_type/char.rb +30 -0
- data/lib/rubex/data_type/f_32.rb +38 -0
- data/lib/rubex/data_type/f_64.rb +38 -0
- data/lib/rubex/data_type/int.rb +32 -0
- data/lib/rubex/data_type/int/c_boolean.rb +13 -0
- data/lib/rubex/data_type/int_16.rb +32 -0
- data/lib/rubex/data_type/int_32.rb +32 -0
- data/lib/rubex/data_type/int_64.rb +36 -0
- data/lib/rubex/data_type/int_8.rb +33 -0
- data/lib/rubex/data_type/l_int.rb +38 -0
- data/lib/rubex/data_type/l_l_int.rb +26 -0
- data/lib/rubex/data_type/ruby_method.rb +22 -0
- data/lib/rubex/data_type/ruby_object.rb +19 -0
- data/lib/rubex/data_type/ruby_object/boolean.rb +11 -0
- data/lib/rubex/data_type/ruby_object/boolean/false_type.rb +5 -0
- data/lib/rubex/data_type/ruby_object/boolean/true_type.rb +5 -0
- data/lib/rubex/data_type/ruby_object/nil_type.rb +9 -0
- data/lib/rubex/data_type/ruby_object/ruby_array.rb +10 -0
- data/lib/rubex/data_type/ruby_object/ruby_constant.rb +18 -0
- data/lib/rubex/data_type/ruby_object/ruby_constant/ruby_class.rb +18 -0
- data/lib/rubex/data_type/ruby_object/ruby_hash.rb +9 -0
- data/lib/rubex/data_type/ruby_object/ruby_string.rb +10 -0
- data/lib/rubex/data_type/ruby_object/ruby_symbol.rb +10 -0
- data/lib/rubex/data_type/type_def.rb +34 -0
- data/lib/rubex/data_type/u_char.rb +27 -0
- data/lib/rubex/data_type/u_int.rb +32 -0
- data/lib/rubex/data_type/u_int_16.rb +22 -0
- data/lib/rubex/data_type/u_int_32.rb +22 -0
- data/lib/rubex/data_type/u_int_64.rb +26 -0
- data/lib/rubex/data_type/u_int_8.rb +22 -0
- data/lib/rubex/data_type/u_l_int.rb +36 -0
- data/lib/rubex/data_type/u_l_int/size_t.rb +10 -0
- data/lib/rubex/data_type/u_l_l_int.rb +26 -0
- data/lib/rubex/data_type/void.rb +15 -0
- data/lib/rubex/data_type_helpers/float_helpers.rb +8 -0
- data/lib/rubex/data_type_helpers/helpers.rb +48 -0
- data/lib/rubex/data_type_helpers/int_helpers.rb +10 -0
- data/lib/rubex/data_type_helpers/u_int_helpers.rb +11 -0
- data/lib/rubex/helpers.rb +35 -118
- data/lib/rubex/helpers/node_type_methods.rb +9 -0
- data/lib/rubex/helpers/writers.rb +79 -0
- data/lib/rubex/parser.racc +83 -34
- data/lib/rubex/parser.racc.rb +233 -184
- data/lib/rubex/version.rb +2 -2
- data/rubex.gemspec +2 -0
- data/spec/basic_ruby_method_spec.rb +1 -1
- data/spec/binding_ptr_args_spec.rb +2 -2
- data/spec/bitwise_operators_spec.rb +1 -1
- data/spec/blocks_spec.rb +2 -2
- data/spec/c_bindings_spec.rb +1 -1
- data/spec/c_constants_spec.rb +1 -1
- data/spec/c_function_ptrs_spec.rb +1 -1
- data/spec/c_functions_spec.rb +2 -2
- data/spec/c_struct_interface_spec.rb +1 -1
- data/spec/call_by_reference_spec.rb +2 -2
- data/spec/class_methods_spec.rb +2 -2
- data/spec/class_spec.rb +4 -4
- data/spec/cli_spec.rb +43 -0
- data/spec/comments_spec.rb +2 -2
- data/spec/default_args_spec.rb +21 -23
- data/spec/error_handling_spec.rb +1 -1
- data/spec/examples_spec.rb +4 -4
- data/spec/expressions_spec.rb +1 -1
- data/spec/fixtures/cli/cli.rubex +3 -0
- data/spec/fixtures/examples/array_to_hash.rubex +1 -1
- data/spec/fixtures/examples/rcsv.rubex +10 -6
- data/spec/fixtures/loops/loops.rubex +1 -1
- data/spec/fixtures/ruby_strings/string_blank_bm.rb +7 -5
- data/spec/fixtures/struct/struct.rubex +7 -2
- data/spec/fixtures/temp_allocation/temp_allocation.rubex +8 -0
- data/spec/if_else_spec.rb +3 -7
- data/spec/implicit_lib_include_spec.rb +1 -1
- data/spec/init_ruby_objects_with_literal_syntax_spec.rb +1 -1
- data/spec/loops_spec.rb +1 -1
- data/spec/recursion_spec.rb +18 -21
- data/spec/ruby_constant_method_calls_spec.rb +4 -4
- data/spec/ruby_operators_spec.rb +1 -1
- data/spec/ruby_raise_spec.rb +1 -1
- data/spec/ruby_strings_spec.rb +3 -3
- data/spec/ruby_symbols_spec.rb +1 -1
- data/spec/ruby_types_spec.rb +2 -2
- data/spec/spec_helper.rb +42 -10
- data/spec/statement_expression_spec.rb +3 -3
- data/spec/static_array_spec.rb +3 -3
- data/spec/string_literals_spec.rb +2 -2
- data/spec/struct_spec.rb +4 -4
- data/spec/temp_allocation_spec.rb +35 -0
- data/spec/typecasting_spec.rb +2 -2
- data/spec/var_declarions_spec.rb +2 -2
- metadata +168 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 742568f609bbfd393f0262b1f8b79089a3e22007053e72714bbb8cc256fd5066
|
4
|
+
data.tar.gz: 7bd08df3a97cdf480bdb4fa5b34ef37553678f97cbd19f53027296148724c66a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32b17fb06897cf4ca018dd61ba27ee58b6f21d885b715c7ab13effd726175465379912c168c21ba0a7ba48ee69f244996fbb680ae5a33a78021cd07745b6473f
|
7
|
+
data.tar.gz: febfc14a8dabb0ab050d592f9d50cfeaaf068007cb0635104876cfa679710fd311e4e71d38f4f8cf3019a6ef78e231fa4638381803899e3f4ee499f19312d41c
|
data/.gitignore
CHANGED
@@ -43,8 +43,8 @@ build-iPhoneSimulator/
|
|
43
43
|
# for a library or gem, you might want to ignore these files since the code is
|
44
44
|
# intended to run in multiple environments; otherwise, check them in:
|
45
45
|
Gemfile.lock
|
46
|
-
|
47
|
-
|
46
|
+
.ruby-version
|
47
|
+
.ruby-gemset
|
48
48
|
|
49
49
|
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
50
|
.rvmrc
|
@@ -52,3 +52,4 @@ Gemfile.lock
|
|
52
52
|
lib/rubex/parser.output
|
53
53
|
lib/rubex/parser.tab.rb
|
54
54
|
/.idea/
|
55
|
+
TAGS
|
data/.travis.yml
CHANGED
@@ -2,13 +2,21 @@ language:
|
|
2
2
|
ruby
|
3
3
|
|
4
4
|
rvm:
|
5
|
-
- '2.2'
|
6
5
|
- '2.3.0'
|
7
6
|
- '2.4.0'
|
7
|
+
- '2.5.0'
|
8
8
|
|
9
9
|
script:
|
10
10
|
- bundle exec rake spec
|
11
11
|
|
12
|
+
before_install:
|
13
|
+
- sudo apt-get -qq update
|
14
|
+
- sudo apt-get install -y libcsv3
|
15
|
+
|
12
16
|
install:
|
13
17
|
- gem install bundler
|
14
18
|
- bundle install
|
19
|
+
|
20
|
+
os:
|
21
|
+
- linux
|
22
|
+
|
data/CONTRIBUTING.md
CHANGED
@@ -46,7 +46,7 @@ When writing the `<=>` operator under Rubex::DataType classes, I have been force
|
|
46
46
|
|
47
47
|
This consists of a hash that looks like this:
|
48
48
|
```
|
49
|
-
{
|
49
|
+
{
|
50
50
|
dtype: ,
|
51
51
|
variables: [{}]
|
52
52
|
}
|
@@ -67,7 +67,7 @@ The `:variables` key maps to a value that is an Array of Hashes that contains a
|
|
67
67
|
|
68
68
|
If Hash, it will look like this:
|
69
69
|
```
|
70
|
-
{
|
70
|
+
{
|
71
71
|
name:,
|
72
72
|
return_ptr_level:,
|
73
73
|
arg_list:
|
data/README.md
CHANGED
@@ -9,6 +9,8 @@ Rubex keeps you happy even when writing C extensions.
|
|
9
9
|
# Status
|
10
10
|
|
11
11
|
[](https://badge.fury.io/rb/rubex)
|
12
|
+
[](https://www.codetriage.com/v0dro/rubex)
|
13
|
+
[](https://travis-ci.org/SciRuby/rubex)
|
12
14
|
|
13
15
|
# Table of Contents
|
14
16
|
|
@@ -116,6 +118,7 @@ Notice the only difference between the above Rubex code and Ruby is the specific
|
|
116
118
|
Rubex also takes care of the initial setup and compilation of the C files, so all you need to do is execute a bunch of commands and your extension is up and running!
|
117
119
|
|
118
120
|
# Installation
|
121
|
+
To build, requires Ruby version >= 2.3.0
|
119
122
|
|
120
123
|
The gem as of now has not reached v0.1. However, you can try it out with:
|
121
124
|
```
|
@@ -155,4 +158,4 @@ See the [CONTRIBUTING](CONTRIBUTING.md) and the GitHub issue tracker for future
|
|
155
158
|
|
156
159
|
* The Ruby Association (Japan) for providing the initial funding for this project through the Ruby Association Grant 2016.
|
157
160
|
* Koichi Sasada (@ko1) and Kenta Murata (@mrkn) for their support and mentorship throughout this project.
|
158
|
-
* Fukuoka Ruby Award 2017.
|
161
|
+
* Fukuoka Ruby Award 2017.
|
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rspec/core/rake_task'
|
2
2
|
require 'bundler/gem_tasks'
|
3
|
+
require 'oedipus_lex'
|
3
4
|
|
4
5
|
$:.unshift File.expand_path("../lib", __FILE__)
|
5
6
|
|
@@ -15,7 +16,6 @@ end
|
|
15
16
|
|
16
17
|
# -v -> verbose
|
17
18
|
# -t -> with debugging output
|
18
|
-
|
19
|
+
task :default => :spec
|
19
20
|
RSpec::Core::RakeTask.new(:spec)
|
20
|
-
|
21
21
|
task :spec => :parser
|
data/bin/rubex
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'rubex'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
if Rubex::Cli.all_tasks.keys.include?(ARGV[0]) || ARGV.empty?
|
5
|
+
Rubex::Cli.start
|
6
|
+
else
|
7
|
+
Rubex::Cli.start(["generate"] + ARGV)
|
8
8
|
end
|
9
9
|
|
10
|
-
Rubex::Compiler.compile file_name
|
data/lib/rubex.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'forwardable'
|
2
|
-
|
3
|
-
require 'rubex/error'
|
4
|
-
require 'rubex/helpers'
|
5
|
-
require 'rubex/code_writer'
|
6
2
|
require 'rubex/data_type'
|
7
3
|
require 'rubex/constants'
|
4
|
+
require 'rubex/error'
|
8
5
|
require 'rubex/ast'
|
6
|
+
require 'rubex/helpers'
|
7
|
+
require 'rubex/code_writer'
|
9
8
|
require 'rubex/symbol_table'
|
10
9
|
require 'rubex/parser.racc.rb'
|
11
10
|
require 'rubex/compiler_config'
|
12
11
|
require 'rubex/compiler'
|
12
|
+
require 'rubex/cli'
|
data/lib/rubex/ast.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
require 'rubex/
|
1
|
+
require 'rubex/helpers'
|
2
2
|
require 'rubex/ast/statement'
|
3
|
+
Dir['./lib/rubex/ast/statement/**/*.rb'].sort.each { |f| require f }
|
3
4
|
require 'rubex/ast/expression'
|
5
|
+
Dir['./lib/rubex/ast/expression/**/*.rb'].sort.each { |f| require f }
|
4
6
|
require 'rubex/ast/top_statement'
|
7
|
+
require 'rubex/ast/node'
|
data/lib/rubex/ast/expression.rb
CHANGED
@@ -2,26 +2,31 @@ module Rubex
|
|
2
2
|
module AST
|
3
3
|
module Expression
|
4
4
|
class Base
|
5
|
+
attr_reader :type, :entry
|
5
6
|
attr_accessor :typecast
|
6
7
|
|
7
8
|
# In case an expr has to be of a certain type, like a string literal
|
8
9
|
# assigned to a char*, this method will analyse the literal in context
|
9
10
|
# to the target dtype.
|
10
11
|
def analyse_for_target_type target_type, local_scope
|
11
|
-
|
12
|
+
analyse_types local_scope
|
12
13
|
end
|
13
14
|
|
14
15
|
# If the typecast exists, the typecast is made the overall type of
|
15
16
|
# the expression.
|
16
|
-
def
|
17
|
+
def analyse_types local_scope
|
17
18
|
if @typecast
|
18
|
-
@typecast.
|
19
|
+
@typecast.analyse_types(local_scope)
|
19
20
|
@type = @typecast.type
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
24
|
def expression?; true; end
|
24
25
|
|
26
|
+
def has_temp
|
27
|
+
@has_temp
|
28
|
+
end
|
29
|
+
|
25
30
|
def c_code local_scope
|
26
31
|
@typecast ? @typecast.c_code(local_scope) : ""
|
27
32
|
end
|
@@ -50,1213 +55,39 @@ module Rubex
|
|
50
55
|
|
51
56
|
def allocate_temps local_scope
|
52
57
|
if @subexprs
|
53
|
-
@subexprs.each { |expr| expr.
|
58
|
+
@subexprs.each { |expr| expr.allocate_temps(local_scope) }
|
54
59
|
end
|
60
|
+
allocate_temp local_scope, @type
|
55
61
|
end
|
56
62
|
|
57
63
|
def release_temps local_scope
|
58
64
|
if @subexprs
|
59
|
-
@subexprs.each { |expr| expr.
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def generate_evaluation_code code, local_scope
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
def generate_disposal_code code
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
def generate_assignment_code rhs, code, local_scope
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
class Typecast < Base
|
77
|
-
attr_reader :type
|
78
|
-
|
79
|
-
def initialize dtype, ptr_level
|
80
|
-
@dtype, @ptr_level = dtype, ptr_level
|
81
|
-
end
|
82
|
-
|
83
|
-
def analyse_statement local_scope
|
84
|
-
@type = Rubex::Helpers.determine_dtype @dtype, @ptr_level
|
85
|
-
end
|
86
|
-
|
87
|
-
def c_code local_scope
|
88
|
-
"(#{@type.to_s})"
|
89
|
-
end
|
90
|
-
end # class Typecast
|
91
|
-
|
92
|
-
class SizeOf < Base
|
93
|
-
attr_reader :type
|
94
|
-
|
95
|
-
def initialize type, ptr_level
|
96
|
-
@size_of_type = Helpers.determine_dtype type, ptr_level
|
97
|
-
end
|
98
|
-
|
99
|
-
def analyse_statement local_scope
|
100
|
-
@type = DataType::ULInt.new
|
101
|
-
super
|
102
|
-
end
|
103
|
-
|
104
|
-
def c_code local_scope
|
105
|
-
"sizeof(#{@size_of_type})"
|
106
|
-
end
|
107
|
-
end # class SizeOf
|
108
|
-
|
109
|
-
class Binary < Base
|
110
|
-
include Rubex::Helpers::NodeTypeMethods
|
111
|
-
|
112
|
-
attr_reader :operator
|
113
|
-
attr_accessor :left, :right
|
114
|
-
# Final return type of expression
|
115
|
-
attr_accessor :type, :subexprs
|
116
|
-
|
117
|
-
def initialize left, operator, right
|
118
|
-
@left, @operator, @right = left, operator, right
|
119
|
-
@@analyse_visited = []
|
120
|
-
@subexprs = []
|
121
|
-
end
|
122
|
-
|
123
|
-
def analyse_statement local_scope
|
124
|
-
analyse_left_and_right_nodes local_scope, self
|
125
|
-
analyse_return_type local_scope, self
|
126
|
-
super
|
127
|
-
end
|
128
|
-
|
129
|
-
def allocate_temps local_scope
|
130
|
-
@subexprs.each do |expr|
|
131
|
-
if expr.is_a?(Binary)
|
132
|
-
expr.allocate_temps local_scope
|
133
|
-
else
|
134
|
-
expr.allocate_temp local_scope, expr.type
|
135
|
-
end
|
65
|
+
@subexprs.each { |expr| expr.release_temps(local_scope) }
|
136
66
|
end
|
67
|
+
release_temp local_scope
|
137
68
|
end
|
138
69
|
|
139
|
-
def generate_evaluation_code
|
140
|
-
@left.generate_evaluation_code code, local_scope
|
141
|
-
@right.generate_evaluation_code code, local_scope
|
142
|
-
end
|
143
|
-
|
144
|
-
def generate_disposal_code code
|
145
|
-
@left.generate_disposal_code code
|
146
|
-
@right.generate_disposal_code code
|
147
|
-
end
|
148
|
-
|
149
|
-
def c_code local_scope
|
150
|
-
code = super
|
151
|
-
code << "( "
|
152
|
-
left_code = @left.c_code(local_scope)
|
153
|
-
right_code = @right.c_code(local_scope)
|
154
|
-
if type_of(@left).object? || type_of(@right).object?
|
155
|
-
left_ruby_code = @left.type.to_ruby_object(left_code)
|
156
|
-
right_ruby_code = @right.type.to_ruby_object(right_code)
|
157
|
-
|
158
|
-
if ["&&", "||"].include?(@operator)
|
159
|
-
code << Rubex::C_MACRO_INT2BOOL +
|
160
|
-
"(RTEST(#{left_ruby_code}) #{@operator} RTEST(#{right_ruby_code}))"
|
161
|
-
else
|
162
|
-
code << "rb_funcall(#{left_ruby_code}, rb_intern(\"#{@operator}\") "
|
163
|
-
code << ", 1, #{right_ruby_code})"
|
164
|
-
end
|
165
|
-
else
|
166
|
-
code << "#{left_code} #{@operator} #{right_code}"
|
167
|
-
end
|
168
|
-
code << " )"
|
169
|
-
|
170
|
-
code
|
171
|
-
end
|
172
|
-
|
173
|
-
def == other
|
174
|
-
self.class == other.class && @type == other.type &&
|
175
|
-
@left == other.left && @right == other.right &&
|
176
|
-
@operator == other.operator
|
177
|
-
end
|
178
|
-
|
179
|
-
private
|
70
|
+
def generate_evaluation_code(code, local_scope); end
|
180
71
|
|
181
|
-
def
|
182
|
-
|
183
|
-
return (t.c_function? ? t.type : t)
|
184
|
-
end
|
185
|
-
|
186
|
-
def analyse_left_and_right_nodes local_scope, tree
|
187
|
-
if tree.respond_to?(:left)
|
188
|
-
analyse_left_and_right_nodes local_scope, tree.left
|
189
|
-
|
190
|
-
if !@@analyse_visited.include?(tree.left.object_id)
|
191
|
-
if tree.right.type
|
192
|
-
tree.left.analyse_for_target_type(tree.right.type, local_scope)
|
193
|
-
else
|
194
|
-
tree.left.analyse_statement(local_scope)
|
195
|
-
end
|
196
|
-
@subexprs << tree.left
|
197
|
-
@@analyse_visited << tree.left.object_id
|
198
|
-
end
|
199
|
-
|
200
|
-
if !@@analyse_visited.include?(tree.right.object_id)
|
201
|
-
if tree.left.type
|
202
|
-
tree.right.analyse_for_target_type(tree.left.type, local_scope)
|
203
|
-
else
|
204
|
-
tree.right.analyse_statement(local_scope)
|
205
|
-
end
|
206
|
-
@subexprs << tree.right
|
207
|
-
@@analyse_visited << tree.right.object_id
|
208
|
-
end
|
209
|
-
|
210
|
-
@@analyse_visited << tree.object_id
|
211
|
-
|
212
|
-
analyse_left_and_right_nodes local_scope, tree.right
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def analyse_return_type local_scope, tree
|
217
|
-
if tree.respond_to? :left
|
218
|
-
analyse_return_type local_scope, tree.left
|
219
|
-
analyse_return_type local_scope, tree.right
|
220
|
-
|
221
|
-
if ['==', '<', '>', '<=', '>=', '||', '&&', '!='].include? tree.operator
|
222
|
-
if type_of(tree.left).object? || type_of(tree.right).object?
|
223
|
-
tree.type = Rubex::DataType::Boolean.new
|
224
|
-
else
|
225
|
-
tree.type = Rubex::DataType::CBoolean.new
|
226
|
-
end
|
227
|
-
else
|
228
|
-
if tree.left.type.bool? || tree.right.type.bool?
|
229
|
-
raise Rubex::TypeMismatchError, "Operation #{tree.operator} cannot"\
|
230
|
-
"be performed between #{tree.left} and #{tree.right}"
|
231
|
-
end
|
232
|
-
tree.type = Rubex::Helpers.result_type_for(
|
233
|
-
type_of(tree.left), type_of(tree.right))
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end # class Binary
|
238
|
-
|
239
|
-
class UnaryBase < Base
|
240
|
-
def initialize expr
|
241
|
-
@expr = expr
|
242
|
-
end
|
243
|
-
|
244
|
-
def analyse_statement local_scope
|
245
|
-
@expr.analyse_statement local_scope
|
246
|
-
@type = @expr.type
|
247
|
-
@expr.allocate_temps local_scope
|
248
|
-
@expr.allocate_temp local_scope, @type
|
249
|
-
@expr.release_temps local_scope
|
250
|
-
@expr.release_temp local_scope
|
251
|
-
@expr = @expr.to_ruby_object if @type.object?
|
252
|
-
end
|
253
|
-
|
254
|
-
def generate_evaluation_code code, local_scope
|
255
|
-
@expr.generate_evaluation_code code, local_scope
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
class UnaryNot < UnaryBase
|
260
|
-
attr_reader :type
|
261
|
-
|
262
|
-
def c_code local_scope
|
263
|
-
code = @expr.c_code(local_scope)
|
264
|
-
if @type.object?
|
265
|
-
"rb_funcall(#{code}, rb_intern(\"!\"), 0)"
|
266
|
-
else
|
267
|
-
"!#{code}"
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
class UnarySub < UnaryBase
|
273
|
-
attr_reader :type
|
274
|
-
|
275
|
-
def c_code local_scope
|
276
|
-
code = @expr.c_code(local_scope)
|
277
|
-
if @type.object?
|
278
|
-
"rb_funcall(#{code}, rb_intern(\"-\"), 0)"
|
279
|
-
else
|
280
|
-
"-#{code}"
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
class Ampersand < UnaryBase
|
286
|
-
attr_reader :type
|
287
|
-
|
288
|
-
def analyse_statement local_scope
|
289
|
-
@expr.analyse_statement local_scope
|
290
|
-
@type = DataType::CPtr.new @expr.type
|
291
|
-
end
|
292
|
-
|
293
|
-
def c_code local_scope
|
294
|
-
"&#{@expr.c_code(local_scope)}"
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
class UnaryBitNot < UnaryBase
|
299
|
-
attr_reader :type
|
300
|
-
|
301
|
-
def c_code local_scope
|
302
|
-
code = @expr.c_code(local_scope)
|
303
|
-
if @type.object?
|
304
|
-
"rb_funcall(#{code}, rb_intern(\"~\"), 0)"
|
305
|
-
else
|
306
|
-
"~#{code}"
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
class Unary < Base
|
312
|
-
attr_reader :operator, :expr, :type
|
313
|
-
|
314
|
-
OP_CLASS_MAP = {
|
315
|
-
'&' => Ampersand,
|
316
|
-
'-' => UnarySub,
|
317
|
-
'!' => UnaryNot,
|
318
|
-
'~' => UnaryBitNot
|
319
|
-
}
|
320
|
-
|
321
|
-
def initialize operator, expr
|
322
|
-
@operator, @expr = operator, expr
|
323
|
-
end
|
324
|
-
|
325
|
-
def analyse_statement local_scope
|
326
|
-
@expr = OP_CLASS_MAP[@operator].new(@expr)
|
327
|
-
@expr.analyse_statement local_scope
|
328
|
-
@type = @expr.type
|
329
|
-
super
|
330
|
-
end
|
331
|
-
|
332
|
-
def generate_evaluation_code code, local_scope
|
333
|
-
@expr.generate_evaluation_code code, local_scope
|
334
|
-
end
|
335
|
-
|
336
|
-
def c_code local_scope
|
337
|
-
code = super
|
338
|
-
code << @expr.c_code(local_scope)
|
339
|
-
end
|
340
|
-
end # class Unary
|
341
|
-
|
342
|
-
class ElementRef < Base
|
343
|
-
attr_reader :entry, :pos, :type, :name, :object_ptr
|
344
|
-
|
345
|
-
def initialize name, pos
|
346
|
-
@name, @pos = name, pos
|
347
|
-
@subexprs = []
|
348
|
-
end
|
349
|
-
|
350
|
-
# FIXME: This method needs to be implemented for all exprs that are
|
351
|
-
# possible LHS candidates.
|
352
|
-
# def analyse_declaration rhs, local_scope
|
353
|
-
# analyse_statement local_scope
|
354
|
-
# @has_temp = false
|
355
|
-
# end
|
356
|
-
|
357
|
-
def analyse_statement local_scope, struct_scope=nil
|
358
|
-
if struct_scope.nil?
|
359
|
-
@entry = local_scope.find @name
|
360
|
-
else
|
361
|
-
@entry = struct_scope[@name]
|
362
|
-
end
|
363
|
-
|
364
|
-
@object_ptr = true if @entry.type.cptr? && @entry.type.type.object?
|
365
|
-
@type = @entry.type.object? ? @entry.type : @entry.type.type
|
366
|
-
|
367
|
-
if @type.object? && !@object_ptr
|
368
|
-
@has_temp = true
|
369
|
-
@pos.analyse_statement local_scope
|
370
|
-
if !(@type.ruby_array?)
|
371
|
-
@pos = @pos.to_ruby_object
|
372
|
-
end
|
373
|
-
@subexprs << @pos
|
374
|
-
else
|
375
|
-
@pos.analyse_statement local_scope
|
376
|
-
end
|
377
|
-
super(local_scope)
|
378
|
-
end
|
379
|
-
|
380
|
-
# This method will be called when [] ruby method or C array element
|
381
|
-
# reference is called.
|
382
|
-
# TODO: refactor this by creating separate classes for ruby object, object
|
383
|
-
# ptr, c type.
|
384
|
-
def generate_evaluation_code code, local_scope
|
385
|
-
if @type.object? && !@object_ptr
|
386
|
-
if @type.ruby_array?
|
387
|
-
code << "#{@c_code} = RARRAY_AREF(#{@entry.c_name}, #{@pos.c_code(local_scope)});"
|
388
|
-
elsif @type.ruby_hash?
|
389
|
-
@pos.generate_evaluation_code code, local_scope
|
390
|
-
code << "#{@c_code} = rb_hash_aref(#{@entry.c_name}, #{@pos.c_code(local_scope)});"
|
391
|
-
else
|
392
|
-
@pos.generate_evaluation_code code, local_scope
|
393
|
-
code << "#{@c_code} = rb_funcall(#{@entry.c_name}, rb_intern(\"[]\"), 1, "
|
394
|
-
code << "#{@pos.c_code(local_scope)});"
|
395
|
-
end
|
396
|
-
code.nl
|
397
|
-
@pos.generate_disposal_code code
|
398
|
-
else
|
399
|
-
@pos.generate_evaluation_code code, local_scope
|
400
|
-
@c_code = "#{@entry.c_name}[#{@pos.c_code(local_scope)}]"
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
def generate_disposal_code code
|
405
|
-
if @type.object? && !@object_ptr
|
72
|
+
def generate_disposal_code(code)
|
73
|
+
if @has_temp
|
406
74
|
code << "#{@c_code} = 0;"
|
407
75
|
code.nl
|
408
76
|
end
|
409
77
|
end
|
410
78
|
|
411
|
-
|
412
|
-
# takes place.
|
413
|
-
def generate_assignment_code rhs, code, local_scope
|
414
|
-
if @type.object? && !@object_ptr
|
415
|
-
@pos.generate_evaluation_code code, local_scope
|
416
|
-
if @type.ruby_hash?
|
417
|
-
code << "rb_hash_aset(#{@entry.c_name}, #{@pos.c_code(local_scope)}, #{rhs.c_code(local_scope)});"
|
418
|
-
else
|
419
|
-
code << "rb_funcall(#{@entry.c_name}, rb_intern(\"[]=\"), 2, "
|
420
|
-
code << "#{@pos.c_code(local_scope)}, #{rhs.c_code(local_scope)});"
|
421
|
-
end
|
422
|
-
@pos.generate_disposal_code code
|
423
|
-
else
|
424
|
-
code << "#{@entry.c_name}[#{@pos.c_code(local_scope)}] = "
|
425
|
-
code << "#{rhs.c_code(local_scope)};"
|
426
|
-
end
|
427
|
-
code.nl
|
428
|
-
end
|
429
|
-
|
430
|
-
# FIXME: This is jugaad. Change.
|
431
|
-
def generate_element_ref_code expr, code, local_scope
|
432
|
-
if !@object_ptr
|
433
|
-
@pos.generate_evaluation_code code, local_scope
|
434
|
-
str = "#{@c_code} = rb_funcall(#{expr.c_code(local_scope)}."
|
435
|
-
str << "#{@entry.c_name}, rb_intern(\"[]\"), 1, "
|
436
|
-
str << "#{@pos.c_code(local_scope)});"
|
437
|
-
code << str
|
438
|
-
code.nl
|
439
|
-
@pos.generate_disposal_code code
|
440
|
-
else
|
441
|
-
generate_evaluation_code code, local_scope
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
def c_code local_scope
|
446
|
-
code = super
|
447
|
-
code << @c_code
|
448
|
-
code
|
449
|
-
end
|
450
|
-
end # class ElementRef
|
451
|
-
|
452
|
-
class Self < Base
|
453
|
-
def c_code local_scope
|
454
|
-
local_scope.self_name
|
455
|
-
end
|
456
|
-
|
457
|
-
def type
|
458
|
-
Rubex::DataType::RubyObject.new
|
459
|
-
end
|
460
|
-
end # class Self
|
461
|
-
|
462
|
-
class RubyConstant < Base
|
463
|
-
include Rubex::AST::Expression
|
464
|
-
attr_reader :name, :entry, :type
|
465
|
-
|
466
|
-
def initialize name
|
467
|
-
@name = name
|
468
|
-
end
|
469
|
-
|
470
|
-
def analyse_statement local_scope
|
471
|
-
@type = Rubex::DataType::RubyConstant.new @name
|
472
|
-
c_name = Rubex::DEFAULT_CLASS_MAPPINGS[@name]
|
473
|
-
@entry = Rubex::SymbolTable::Entry.new name, c_name, @type, nil
|
474
|
-
end
|
475
|
-
|
476
|
-
def c_code local_scope
|
477
|
-
if @entry.c_name # built-in constant.
|
478
|
-
@entry.c_name
|
479
|
-
else
|
480
|
-
"rb_const_get(CLASS_OF(#{local_scope.self_name}), rb_intern(\"#{@entry.name}\"))"
|
481
|
-
end
|
482
|
-
end
|
483
|
-
end # class RubyConstant
|
484
|
-
|
485
|
-
# Singular name node with no sub expressions.
|
486
|
-
class Name < Base
|
487
|
-
attr_reader :name, :entry, :type
|
488
|
-
|
489
|
-
def initialize name
|
490
|
-
@name = name
|
491
|
-
end
|
492
|
-
|
493
|
-
# Used when the node is a LHS of an assign statement.
|
494
|
-
def analyse_declaration rhs, local_scope
|
495
|
-
@entry = local_scope.find @name
|
496
|
-
unless @entry
|
497
|
-
local_scope.add_ruby_obj(name: @name,
|
498
|
-
c_name: Rubex::VAR_PREFIX + @name, value: @rhs)
|
499
|
-
@entry = local_scope[@name]
|
500
|
-
end
|
501
|
-
@type = @entry.type
|
502
|
-
end
|
503
|
-
|
504
|
-
def analyse_for_target_type target_type, local_scope
|
505
|
-
@entry = local_scope.find @name
|
506
|
-
|
507
|
-
if @entry && @entry.type.c_function? && target_type.c_function_ptr?
|
508
|
-
@type = @entry.type
|
509
|
-
else
|
510
|
-
analyse_statement local_scope
|
511
|
-
end
|
512
|
-
end
|
513
|
-
|
514
|
-
# Analyse a Name node. This can either be a variable name or a method call
|
515
|
-
# without parenthesis. Code in this method that creates a CommandCall
|
516
|
-
# node primarily exists because in Ruby methods without arguments can
|
517
|
-
# be called without parentheses. These names can potentially be Ruby
|
518
|
-
# methods that are not visible to Rubex, but are present in the Ruby
|
519
|
-
# run time.
|
520
|
-
def analyse_statement local_scope
|
521
|
-
@entry = local_scope.find @name
|
522
|
-
# FIXME: Figure out a way to perform compile time checking of expressions
|
523
|
-
# to see if the said Ruby methods are actually present in the Ruby
|
524
|
-
# runtime. Maybe read symbols in the Ruby interpreter and load them
|
525
|
-
# as a pre-compilation step?
|
526
|
-
|
527
|
-
# If entry is not present, assume its a Ruby method call to some method
|
528
|
-
# outside of the current Rubex scope or a Ruby constant.
|
529
|
-
if !@entry
|
530
|
-
# Check if first letter is a capital to check for Ruby constant.
|
531
|
-
if @name[0].match /[A-Z]/
|
532
|
-
@name = Expression::RubyConstant.new @name
|
533
|
-
@name.analyse_statement local_scope
|
534
|
-
@entry = @name.entry
|
535
|
-
else # extern Ruby method
|
536
|
-
@entry = local_scope.add_ruby_method(
|
537
|
-
name: @name,
|
538
|
-
c_name: @name,
|
539
|
-
extern: true,
|
540
|
-
scope: nil,
|
541
|
-
arg_list: [])
|
542
|
-
end
|
543
|
-
end
|
544
|
-
# If the entry is a RubyMethod, it should be interpreted as a command
|
545
|
-
# call. So, make the @name a CommandCall Node.
|
546
|
-
if @entry.type.ruby_method? #|| @entry.type.c_function?
|
547
|
-
@name = Rubex::AST::Expression::CommandCall.new(
|
548
|
-
Expression::Self.new, @name, [])
|
549
|
-
@name.analyse_statement local_scope
|
550
|
-
end
|
551
|
-
|
552
|
-
if @entry.type.alias_type? || @entry.type.ruby_method? ||
|
553
|
-
@entry.type.c_function?
|
554
|
-
@type = @entry.type.type
|
555
|
-
else
|
556
|
-
@type = @entry.type
|
557
|
-
end
|
558
|
-
super
|
559
|
-
end
|
560
|
-
|
561
|
-
def generate_evaluation_code code, local_scope
|
562
|
-
if @name.respond_to? :generate_evaluation_code
|
563
|
-
@name.generate_evaluation_code code, local_scope
|
564
|
-
end
|
565
|
-
end
|
566
|
-
|
567
|
-
def generate_disposal_code code
|
568
|
-
if @name.respond_to? :generate_disposal_code
|
569
|
-
@name.generate_disposal_code code
|
570
|
-
end
|
571
|
-
end
|
572
|
-
|
573
|
-
def generate_assignment_code rhs, code, local_scope
|
574
|
-
code << "#{self.c_code(local_scope)} = #{rhs.c_code(local_scope)};"
|
575
|
-
code.nl
|
576
|
-
rhs.generate_disposal_code code
|
577
|
-
end
|
578
|
-
|
579
|
-
def c_code local_scope
|
580
|
-
code = super
|
581
|
-
if @name.is_a?(Rubex::AST::Expression::Base)
|
582
|
-
code << @name.c_code(local_scope)
|
583
|
-
else
|
584
|
-
code << @entry.c_name
|
585
|
-
end
|
586
|
-
|
587
|
-
code
|
588
|
-
end
|
589
|
-
end # class Name
|
590
|
-
|
591
|
-
class MethodCall < Base
|
592
|
-
attr_reader :method_name, :type
|
593
|
-
|
594
|
-
def initialize method_name, invoker, arg_list
|
595
|
-
@method_name, @invoker, @arg_list = method_name, invoker, arg_list
|
596
|
-
end
|
597
|
-
|
598
|
-
# Analyse a method call. If the method that is being called is defined
|
599
|
-
# in a class in a Rubex file, it can easily be interpreted as a Ruby
|
600
|
-
# method. However, in case it is not, a new symtab entry will be created
|
601
|
-
# which will mark the method as 'extern' so that future calls to that
|
602
|
-
# same method can be simply pulled from the symtab.
|
603
|
-
# local_scope is the local method scope.
|
604
|
-
def analyse_statement local_scope
|
605
|
-
entry = local_scope.find(@method_name)
|
606
|
-
if !entry
|
607
|
-
entry = local_scope.add_ruby_method(
|
608
|
-
name: @method_name,
|
609
|
-
c_name: @method_name,
|
610
|
-
extern: true,
|
611
|
-
arg_list: @arg_list,
|
612
|
-
scope: nil)
|
613
|
-
end
|
614
|
-
|
615
|
-
if method_not_within_scope? local_scope
|
616
|
-
raise Rubex::NoMethodError, "Cannot call #{@name} from this method."
|
617
|
-
end
|
618
|
-
|
619
|
-
# FIXME: Print a warning during compilation if a symbol is being
|
620
|
-
# interpreted as a Ruby method call due it not being found in the
|
621
|
-
# symbol table.
|
622
|
-
|
623
|
-
# A symtab entry for a predeclared extern C func.
|
624
|
-
if entry && entry.type.base_type.c_function?
|
625
|
-
@type = entry.type.base_type
|
626
|
-
# All C functions have compulsory last arg as self. This does not
|
627
|
-
# apply to extern functions as they are usually not made for accepting
|
628
|
-
# a VALUE last arg.
|
629
|
-
@arg_list << Expression::Self.new if !entry.extern?
|
630
|
-
type_check_arg_types entry
|
631
|
-
else
|
632
|
-
@type = Rubex::DataType::RubyObject.new
|
633
|
-
end
|
634
|
-
|
635
|
-
if entry.type.ruby_method? && !entry.extern? && @arg_list.size > 0
|
636
|
-
@arg_list_var = entry.c_name + Rubex::ACTUAL_ARGS_SUFFIX
|
637
|
-
|
638
|
-
args_size = entry.type.arg_list&.size || 0
|
639
|
-
local_scope.add_carray(name: @arg_list_var, c_name: @arg_list_var,
|
640
|
-
dimension: Literal::Int.new("#{args_size}"),
|
641
|
-
type: Rubex::DataType::RubyObject.new)
|
642
|
-
end
|
643
|
-
super
|
644
|
-
end
|
645
|
-
|
646
|
-
def generate_evaluation_code code, local_scope
|
647
|
-
end
|
648
|
-
|
649
|
-
def generate_disposal_code code
|
650
|
-
end
|
651
|
-
|
652
|
-
def c_code local_scope
|
653
|
-
code = super
|
654
|
-
entry = local_scope.find(@method_name)
|
655
|
-
if entry.type.ruby_method?
|
656
|
-
code << code_for_ruby_method_call(local_scope)
|
657
|
-
else
|
658
|
-
code << code_for_c_method_call(local_scope, entry)
|
659
|
-
end
|
660
|
-
|
661
|
-
code
|
662
|
-
end
|
663
|
-
|
664
|
-
private
|
665
|
-
|
666
|
-
def type_check_arg_types entry
|
667
|
-
@arg_list.map!.with_index do |arg, idx|
|
668
|
-
Helpers.to_lhs_type(entry.type.base_type.arg_list[idx], arg)
|
669
|
-
end
|
670
|
-
end
|
671
|
-
|
672
|
-
# Checks if method being called is of the same type of the caller. For
|
673
|
-
# example, only instance methods can call instance methods and only
|
674
|
-
# class methods can call class methods. C functions are accessible from
|
675
|
-
# both instance methods and class methods.
|
676
|
-
#
|
677
|
-
# Since there is no way to determine whether methods outside the scope
|
678
|
-
# of the compiled Rubex file are singletons or not, Rubex will assume
|
679
|
-
# that they belong to the correct scope and will compile a call to those
|
680
|
-
# methods anyway. Error, if any, will be caught only at runtime.
|
681
|
-
def method_not_within_scope? local_scope
|
682
|
-
entry = local_scope.find @method_name
|
683
|
-
caller_entry = local_scope.find local_scope.name
|
684
|
-
if ( caller_entry.singleton? && entry.singleton?) ||
|
685
|
-
(!caller_entry.singleton? && !entry.singleton?) ||
|
686
|
-
entry.c_function?
|
687
|
-
false
|
688
|
-
else
|
689
|
-
true
|
690
|
-
end
|
691
|
-
end
|
692
|
-
|
693
|
-
def code_for_c_method_call local_scope, entry
|
694
|
-
str = "#{entry.c_name}("
|
695
|
-
str << @arg_list.map { |a| a.c_code(local_scope) }.join(",")
|
696
|
-
str << ")"
|
697
|
-
str
|
698
|
-
end
|
699
|
-
|
700
|
-
def code_for_ruby_method_call local_scope
|
701
|
-
entry = local_scope.find @method_name
|
702
|
-
str = ""
|
703
|
-
if entry.extern?
|
704
|
-
str << "rb_funcall(#{@invoker.c_code(local_scope)}, "
|
705
|
-
str << "rb_intern(\"#{@method_name}\"), "
|
706
|
-
str << "#{@arg_list.size}"
|
707
|
-
@arg_list.each do |arg|
|
708
|
-
str << " ,#{arg.type.to_ruby_object(arg.c_code(local_scope))}"
|
709
|
-
end
|
710
|
-
str << ", NULL" if @arg_list.empty?
|
711
|
-
str << ")"
|
712
|
-
else
|
713
|
-
str << populate_method_args_into_value_array(local_scope)
|
714
|
-
str << actual_ruby_method_call(local_scope, entry)
|
715
|
-
end
|
716
|
-
str
|
717
|
-
end
|
718
|
-
|
719
|
-
def actual_ruby_method_call local_scope, entry
|
720
|
-
str = "#{entry.c_name}(#{@arg_list.size}, #{@arg_list_var || "NULL"},"
|
721
|
-
str << "#{local_scope.self_name})"
|
722
|
-
end
|
723
|
-
|
724
|
-
def populate_method_args_into_value_array local_scope
|
725
|
-
str = ""
|
726
|
-
@arg_list.each_with_index do |arg, idx|
|
727
|
-
str = "#{@arg_list_var}[#{idx}] = "
|
728
|
-
str << "#{arg.type.to_ruby_object(arg.c_code(local_scope))}"
|
729
|
-
str << ";\n"
|
730
|
-
end
|
731
|
-
|
732
|
-
str
|
733
|
-
end
|
734
|
-
end # class MethodCall
|
735
|
-
|
736
|
-
class CommandCall < Base
|
737
|
-
attr_reader :expr, :command, :arg_list, :type
|
738
|
-
|
739
|
-
def initialize expr, command, arg_list
|
740
|
-
@expr, @command, @arg_list = expr, command, arg_list
|
741
|
-
@subexprs = []
|
742
|
-
end
|
743
|
-
|
744
|
-
# Analyse the command call. If the @command is found in the symbol table,
|
745
|
-
# it is either a struct member or a method call. If not found, it is
|
746
|
-
# assumed to be a Ruby method call and passed on the MethodCall node
|
747
|
-
# where it is interpreted likewise. The upside is that Rubex can call
|
748
|
-
# arbitrary Ruby methods that are defined in external Ruby scripts and
|
749
|
-
# not visible to Rubex at compile time. The downside is that errors with
|
750
|
-
# such methods will be visible to the programmer only during runtime.
|
751
|
-
def analyse_statement local_scope
|
752
|
-
@arg_list.each do |arg|
|
753
|
-
arg.analyse_statement local_scope
|
754
|
-
@subexprs << arg
|
755
|
-
end
|
756
|
-
# Case for implicit 'self' when a method in the class itself is being called.
|
757
|
-
if @expr.nil?
|
758
|
-
entry = local_scope.find(@command)
|
759
|
-
@expr = Expression::Self.new if entry && !entry.extern?
|
760
|
-
else
|
761
|
-
@expr.analyse_statement(local_scope)
|
762
|
-
@expr.allocate_temps local_scope
|
763
|
-
@expr.allocate_temp local_scope, @expr.type
|
764
|
-
end
|
765
|
-
analyse_command_type local_scope
|
766
|
-
super
|
767
|
-
end
|
768
|
-
|
769
|
-
# FIXME: refactor this method (or class). Too many ifs. Too much jagaad.
|
770
|
-
def generate_evaluation_code code, local_scope
|
771
|
-
@c_code = ""
|
772
|
-
@arg_list.each do |arg|
|
773
|
-
arg.generate_evaluation_code code, local_scope
|
774
|
-
end
|
775
|
-
@expr.generate_evaluation_code(code, local_scope) if @expr
|
776
|
-
|
777
|
-
if @expr && @type.object? && @command.is_a?(Rubex::AST::Expression::ElementRef) &&
|
778
|
-
!@command.object_ptr
|
779
|
-
@command.generate_element_ref_code @expr, code, local_scope
|
780
|
-
@c_code << "#{@command.c_code(local_scope)}"
|
781
|
-
else
|
782
|
-
@command.generate_evaluation_code code, local_scope
|
783
|
-
# Interpreted as a method call
|
784
|
-
if @command.is_a? Rubex::AST::Expression::MethodCall
|
785
|
-
@c_code << @command.c_code(local_scope)
|
786
|
-
else # interpreted as referencing the contents of a struct
|
787
|
-
op = @expr.type.cptr? ? "->" : "."
|
788
|
-
|
789
|
-
@c_code << "#{@expr.c_code(local_scope)}#{op}#{@command.c_code(local_scope)}"
|
790
|
-
end
|
791
|
-
end
|
792
|
-
end
|
79
|
+
def generate_assignment_code(rhs, code, local_scope); end
|
793
80
|
|
794
|
-
def
|
795
|
-
@
|
796
|
-
|
797
|
-
@arg_list.each do |arg|
|
798
|
-
arg.generate_disposal_code code
|
81
|
+
def generate_and_dispose_subexprs(code, local_scope, &block)
|
82
|
+
@subexprs.each do |s|
|
83
|
+
s.generate_evaluation_code code, local_scope
|
799
84
|
end
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
generate_evaluation_code code, local_scope
|
804
|
-
code << "#{self.c_code(local_scope)} = #{rhs.c_code(local_scope)};"
|
805
|
-
code.nl
|
806
|
-
end
|
807
|
-
|
808
|
-
def c_code local_scope
|
809
|
-
code = super
|
810
|
-
code << @c_code
|
811
|
-
code
|
812
|
-
end
|
813
|
-
|
814
|
-
private
|
815
|
-
|
816
|
-
def analyse_command_type local_scope
|
817
|
-
if @expr && ((@expr.type.cptr? && @expr.type.type.struct_or_union?) ||
|
818
|
-
(@expr.type.struct_or_union?))
|
819
|
-
scope = @expr.type.base_type.scope
|
820
|
-
if @command.is_a? String
|
821
|
-
@command = Expression::Name.new @command
|
822
|
-
@command.analyse_statement scope
|
823
|
-
end
|
824
|
-
|
825
|
-
if !scope.has_entry?(@command.name)
|
826
|
-
raise "Entry #{@command.name} does not exist in #{@expr}."
|
827
|
-
end
|
828
|
-
|
829
|
-
if @command.is_a? Rubex::AST::Expression::ElementRef
|
830
|
-
@command.analyse_statement local_scope, scope
|
831
|
-
end
|
832
|
-
else
|
833
|
-
@command = Expression::MethodCall.new @command, @expr, @arg_list
|
834
|
-
@command.analyse_statement local_scope
|
85
|
+
block.call if block_given?
|
86
|
+
@subexprs.each do |s|
|
87
|
+
s.generate_disposal_code code
|
835
88
|
end
|
836
|
-
@type = @command.type
|
837
|
-
@command.allocate_temps local_scope
|
838
|
-
@command.allocate_temp local_scope, @type
|
839
|
-
@command.release_temps local_scope
|
840
|
-
@command.release_temp local_scope
|
841
89
|
end
|
842
|
-
end # class CommandCall
|
843
|
-
|
844
|
-
|
845
|
-
class ArgDeclaration < Base
|
846
|
-
attr_reader :entry, :type
|
847
|
-
|
848
|
-
# data_hash - a Hash containing data about the variable.
|
849
|
-
def initialize data_hash
|
850
|
-
@data_hash = data_hash
|
851
|
-
end
|
852
|
-
|
853
|
-
def analyse_statement local_scope, inside_func_ptr: false, extern: false
|
854
|
-
# FIXME: Support array of function pointers and array in arguments.
|
855
|
-
var = @data_hash[:variables][0]
|
856
|
-
dtype = @data_hash[:dtype]
|
857
|
-
ident = var[:ident]
|
858
|
-
ptr_level = var[:ptr_level]
|
859
|
-
value = var[:value]
|
860
|
-
|
861
|
-
if ident.is_a?(Hash) # function pointer
|
862
|
-
cfunc_return_type = Helpers.determine_dtype(dtype,
|
863
|
-
ident[:return_ptr_level])
|
864
|
-
arg_list = ident[:arg_list].analyse_statement(local_scope,
|
865
|
-
inside_func_ptr: true)
|
866
|
-
ptr_level = "*" if ptr_level.empty?
|
867
|
-
|
868
|
-
if inside_func_ptr
|
869
|
-
name, c_name = nil, nil
|
870
|
-
else
|
871
|
-
name = ident[:name]
|
872
|
-
c_name = Rubex::ARG_PREFIX + name
|
873
|
-
end
|
874
|
-
|
875
|
-
@type = Helpers.determine_dtype(
|
876
|
-
DataType::CFunction.new(name, c_name, arg_list, cfunc_return_type, nil),
|
877
|
-
ptr_level)
|
878
|
-
else
|
879
|
-
if !inside_func_ptr
|
880
|
-
name, c_name = ident, Rubex::ARG_PREFIX + ident
|
881
|
-
end
|
882
|
-
@type = Helpers.determine_dtype(dtype, ptr_level)
|
883
|
-
end
|
884
|
-
|
885
|
-
value.analyse_statement(local_scope) if value
|
886
|
-
|
887
|
-
if !extern && !inside_func_ptr
|
888
|
-
@entry = local_scope.add_arg(name: name, c_name: c_name, type: @type,
|
889
|
-
value: value)
|
890
|
-
end
|
891
|
-
end # def analyse_statement
|
892
|
-
end # class ArgDeclaration
|
893
|
-
|
894
|
-
class CoerceObject < Base
|
895
|
-
attr_reader :expr
|
896
|
-
|
897
|
-
extend Forwardable
|
898
|
-
|
899
|
-
def_delegators :@expr, :generate_evaluation_code, :generate_disposal_code,
|
900
|
-
:generate_assignment_code, :allocate_temp, :allocate_temps,
|
901
|
-
:release_temp, :release_temps, :type
|
902
90
|
end
|
903
|
-
|
904
|
-
# Internal class to typecast from a C type to another C type.
|
905
|
-
class TypecastTo < CoerceObject
|
906
|
-
def initialize dtype
|
907
|
-
|
908
|
-
end
|
909
|
-
# TODO
|
910
|
-
end
|
911
|
-
|
912
|
-
# internal node for converting to ruby object.
|
913
|
-
class ToRubyObject < CoerceObject
|
914
|
-
attr_reader :type
|
915
|
-
|
916
|
-
def initialize expr
|
917
|
-
@expr = expr
|
918
|
-
@type = Rubex::DataType::RubyObject.new
|
919
|
-
end
|
920
|
-
|
921
|
-
def c_code local_scope
|
922
|
-
t = @expr.type
|
923
|
-
t = (t.c_function? || t.alias_type?) ? t.type : t
|
924
|
-
"#{t.to_ruby_object(@expr.c_code(local_scope))}"
|
925
|
-
end
|
926
|
-
end
|
927
|
-
|
928
|
-
# internal node for converting from ruby object.
|
929
|
-
class FromRubyObject < CoerceObject
|
930
|
-
# expr - Expression to convert
|
931
|
-
# from_node - LHS expression. Of type Rubex::AST::Expression
|
932
|
-
def initialize expr, from_node
|
933
|
-
@expr = expr
|
934
|
-
@type = @expr.type
|
935
|
-
@from_node = from_node
|
936
|
-
end
|
937
|
-
|
938
|
-
def c_code local_scope
|
939
|
-
"#{@from_node.type.from_ruby_object(@expr.c_code(local_scope))}"
|
940
|
-
end
|
941
|
-
end
|
942
|
-
|
943
|
-
class BlockGiven < Base
|
944
|
-
attr_reader :type
|
945
|
-
|
946
|
-
def analyse_statement local_scope
|
947
|
-
@type = DataType::CBoolean.new
|
948
|
-
end
|
949
|
-
|
950
|
-
def c_code local_scope
|
951
|
-
"rb_block_given_p()"
|
952
|
-
end
|
953
|
-
end
|
954
|
-
|
955
|
-
# Internal node that denotes empty expression for a statement for example
|
956
|
-
# the `return` for a C function with return type `void`.
|
957
|
-
class Empty < Base
|
958
|
-
attr_reader :type
|
959
|
-
|
960
|
-
def analyse_statement local_scope
|
961
|
-
@type = DataType::Void.new
|
962
|
-
end
|
963
|
-
end
|
964
|
-
|
965
|
-
module Literal
|
966
|
-
class Base < Rubex::AST::Expression::Base
|
967
|
-
attr_reader :name, :type
|
968
|
-
|
969
|
-
def initialize name
|
970
|
-
@name = name
|
971
|
-
end
|
972
|
-
|
973
|
-
def c_code local_scope
|
974
|
-
code = super
|
975
|
-
code << @name
|
976
|
-
end
|
977
|
-
|
978
|
-
def c_name
|
979
|
-
@name
|
980
|
-
end
|
981
|
-
|
982
|
-
def literal?; true; end
|
983
|
-
|
984
|
-
def == other
|
985
|
-
self.class == other.class && @name == other.name
|
986
|
-
end
|
987
|
-
end # class Base
|
988
|
-
|
989
|
-
class ArrayLit < Literal::Base
|
990
|
-
include Enumerable
|
991
|
-
|
992
|
-
attr_accessor :c_array
|
993
|
-
|
994
|
-
def each &block
|
995
|
-
@array_list.each(&block)
|
996
|
-
end
|
997
|
-
|
998
|
-
def initialize array_list
|
999
|
-
@array_list = array_list
|
1000
|
-
@subexprs = []
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
def analyse_statement local_scope
|
1004
|
-
@has_temp = true
|
1005
|
-
@type = DataType::RubyObject.new
|
1006
|
-
@array_list.map! do |e|
|
1007
|
-
e.analyse_statement local_scope
|
1008
|
-
e = e.to_ruby_object
|
1009
|
-
@subexprs << e
|
1010
|
-
e
|
1011
|
-
end
|
1012
|
-
end
|
1013
|
-
|
1014
|
-
def generate_evaluation_code code, local_scope
|
1015
|
-
code << "#{@c_code} = rb_ary_new2(#{@array_list.size});"
|
1016
|
-
code.nl
|
1017
|
-
@array_list.each do |e|
|
1018
|
-
code << "rb_ary_push(#{@c_code}, #{e.c_code(local_scope)});"
|
1019
|
-
code.nl
|
1020
|
-
end
|
1021
|
-
end
|
1022
|
-
|
1023
|
-
def generate_disposal_code code
|
1024
|
-
code << "#{@c_code} = 0;"
|
1025
|
-
code.nl
|
1026
|
-
end
|
1027
|
-
|
1028
|
-
def c_code local_scope
|
1029
|
-
@c_code
|
1030
|
-
end
|
1031
|
-
end # class ArrayLit
|
1032
|
-
|
1033
|
-
class HashLit < Literal::Base
|
1034
|
-
def initialize key_val_pairs
|
1035
|
-
@key_val_pairs = key_val_pairs
|
1036
|
-
end
|
1037
|
-
|
1038
|
-
def analyse_statement local_scope
|
1039
|
-
@has_temp = true
|
1040
|
-
@type = Rubex::DataType::RubyObject.new
|
1041
|
-
@key_val_pairs.map! do |k, v|
|
1042
|
-
k.analyse_for_target_type(@type, local_scope)
|
1043
|
-
v.analyse_for_target_type(@type, local_scope)
|
1044
|
-
[k.to_ruby_object, v.to_ruby_object]
|
1045
|
-
end
|
1046
|
-
end
|
1047
|
-
|
1048
|
-
def generate_evaluation_code code, local_scope
|
1049
|
-
code << "#{@c_code} = rb_hash_new();"
|
1050
|
-
code.nl
|
1051
|
-
@key_val_pairs.each do |k, v|
|
1052
|
-
k.generate_evaluation_code(code, local_scope)
|
1053
|
-
v.generate_evaluation_code(code, local_scope)
|
1054
|
-
|
1055
|
-
code << "rb_hash_aset(#{@c_code}, #{k.c_code(local_scope)}, "
|
1056
|
-
code << "#{v.c_code(local_scope)});"
|
1057
|
-
code.nl
|
1058
|
-
|
1059
|
-
k.generate_disposal_code code
|
1060
|
-
v.generate_disposal_code code
|
1061
|
-
code.nl
|
1062
|
-
end
|
1063
|
-
end
|
1064
|
-
|
1065
|
-
def allocate_temps local_scope
|
1066
|
-
@key_val_pairs.each do |k,v|
|
1067
|
-
k.allocate_temp local_scope, k.type
|
1068
|
-
v.allocate_temp local_scope, v.type
|
1069
|
-
end
|
1070
|
-
end
|
1071
|
-
|
1072
|
-
def release_temps local_scope
|
1073
|
-
@key_val_pairs.each do |k,v|
|
1074
|
-
k.release_temp local_scope
|
1075
|
-
v.release_temp local_scope
|
1076
|
-
end
|
1077
|
-
end
|
1078
|
-
|
1079
|
-
def generate_disposal_code code
|
1080
|
-
code << "#{@c_code} = 0;"
|
1081
|
-
code.nl
|
1082
|
-
end
|
1083
|
-
|
1084
|
-
def c_code local_scope
|
1085
|
-
@c_code
|
1086
|
-
end
|
1087
|
-
end
|
1088
|
-
|
1089
|
-
class RubySymbol < Literal::Base
|
1090
|
-
def initialize name
|
1091
|
-
super(name[1..-1])
|
1092
|
-
@type = Rubex::DataType::RubySymbol.new
|
1093
|
-
end
|
1094
|
-
|
1095
|
-
def generate_evaluation_code code, local_scope
|
1096
|
-
@c_code = "ID2SYM(rb_intern(\"#{@name}\"))"
|
1097
|
-
end
|
1098
|
-
|
1099
|
-
def c_code local_scope
|
1100
|
-
@c_code
|
1101
|
-
end
|
1102
|
-
end
|
1103
|
-
|
1104
|
-
class Double < Literal::Base
|
1105
|
-
def initialize name
|
1106
|
-
super
|
1107
|
-
@type = Rubex::DataType::F64.new
|
1108
|
-
end
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
class Int < Literal::Base
|
1112
|
-
def initialize name
|
1113
|
-
super
|
1114
|
-
@type = Rubex::DataType::Int.new
|
1115
|
-
end
|
1116
|
-
end
|
1117
|
-
|
1118
|
-
class StringLit < Literal::Base
|
1119
|
-
def initialize name
|
1120
|
-
super
|
1121
|
-
end
|
1122
|
-
|
1123
|
-
def analyse_for_target_type target_type, local_scope
|
1124
|
-
if target_type.char_ptr?
|
1125
|
-
@type = Rubex::DataType::CStr.new
|
1126
|
-
elsif target_type.object?
|
1127
|
-
@type = Rubex::DataType::RubyString.new
|
1128
|
-
analyse_statement local_scope
|
1129
|
-
else
|
1130
|
-
raise Rubex::TypeError, "Cannot assign #{target_type} to string."
|
1131
|
-
end
|
1132
|
-
end
|
1133
|
-
|
1134
|
-
def analyse_statement local_scope
|
1135
|
-
@type = Rubex::DataType::RubyString.new unless @type
|
1136
|
-
@has_temp = 1
|
1137
|
-
end
|
1138
|
-
|
1139
|
-
def generate_evaluation_code code, local_scope
|
1140
|
-
if @type.cstr?
|
1141
|
-
@c_code = "\"#{@name}\""
|
1142
|
-
else
|
1143
|
-
code << "#{@c_code} = rb_str_new2(\"#{@name}\");"
|
1144
|
-
code.nl
|
1145
|
-
end
|
1146
|
-
end
|
1147
|
-
|
1148
|
-
def generate_disposal_code code
|
1149
|
-
if @type.object?
|
1150
|
-
code << "#{@c_code} = 0;"
|
1151
|
-
code.nl
|
1152
|
-
end
|
1153
|
-
end
|
1154
|
-
|
1155
|
-
def c_code local_scope
|
1156
|
-
@c_code
|
1157
|
-
end
|
1158
|
-
end # class StringLit
|
1159
|
-
|
1160
|
-
class Char < Literal::Base
|
1161
|
-
def initialize name
|
1162
|
-
super
|
1163
|
-
end
|
1164
|
-
|
1165
|
-
def analyse_for_target_type target_type, local_scope
|
1166
|
-
if target_type.char?
|
1167
|
-
@type = Rubex::DataType::Char.new
|
1168
|
-
elsif target_type.object?
|
1169
|
-
@type = Rubex::DataType::RubyString.new
|
1170
|
-
analyse_statement local_scope
|
1171
|
-
else
|
1172
|
-
raise Rubex::TypeError, "Cannot assign #{target_type} to string."
|
1173
|
-
end
|
1174
|
-
end
|
1175
|
-
|
1176
|
-
def analyse_statement local_scope
|
1177
|
-
@type = Rubex::DataType::RubyString.new unless @type
|
1178
|
-
end
|
1179
|
-
|
1180
|
-
def generate_evaluation_code code, local_scope
|
1181
|
-
if @type.char?
|
1182
|
-
@c_code = @name
|
1183
|
-
else
|
1184
|
-
@c_code = "rb_str_new2(\"#{@name[1]}\")"
|
1185
|
-
end
|
1186
|
-
end
|
1187
|
-
|
1188
|
-
def c_code local_scope
|
1189
|
-
@c_code
|
1190
|
-
end
|
1191
|
-
end # class Char
|
1192
|
-
|
1193
|
-
class True < Literal::Base
|
1194
|
-
def initialize name
|
1195
|
-
super
|
1196
|
-
end
|
1197
|
-
|
1198
|
-
def analyse_for_target_type target_type, local_scope
|
1199
|
-
if target_type.object?
|
1200
|
-
@type = Rubex::DataType::TrueType.new
|
1201
|
-
else
|
1202
|
-
@type = Rubex::DataType::CBoolean.new
|
1203
|
-
end
|
1204
|
-
end
|
1205
|
-
|
1206
|
-
def analyse_statement local_scope
|
1207
|
-
@type = Rubex::DataType::TrueType.new
|
1208
|
-
end
|
1209
|
-
|
1210
|
-
def c_code local_scope
|
1211
|
-
if @type.object?
|
1212
|
-
@name
|
1213
|
-
else
|
1214
|
-
"1"
|
1215
|
-
end
|
1216
|
-
end
|
1217
|
-
end # class True
|
1218
|
-
|
1219
|
-
class False < Literal::Base
|
1220
|
-
def initialize name
|
1221
|
-
super
|
1222
|
-
end
|
1223
|
-
|
1224
|
-
def analyse_for_target_type target_type, local_scope
|
1225
|
-
if target_type.object?
|
1226
|
-
@type = Rubex::DataType::FalseType.new
|
1227
|
-
else
|
1228
|
-
@type = Rubex::DataType::CBoolean.new
|
1229
|
-
end
|
1230
|
-
end
|
1231
|
-
|
1232
|
-
def analyse_statement local_scope
|
1233
|
-
@type = Rubex::DataType::FalseType.new
|
1234
|
-
end
|
1235
|
-
|
1236
|
-
def c_code local_scope
|
1237
|
-
if @type.object?
|
1238
|
-
@name
|
1239
|
-
else
|
1240
|
-
"0"
|
1241
|
-
end
|
1242
|
-
end
|
1243
|
-
end # class False
|
1244
|
-
|
1245
|
-
class Nil < Literal::Base
|
1246
|
-
def initialize name
|
1247
|
-
super
|
1248
|
-
@type = Rubex::DataType::NilType.new
|
1249
|
-
end
|
1250
|
-
end # class Nil
|
1251
|
-
|
1252
|
-
class CNull < Literal::Base
|
1253
|
-
def initialize name
|
1254
|
-
# Rubex treats NULL's dtype as void*
|
1255
|
-
super
|
1256
|
-
@type = Rubex::DataType::CPtr.new(Rubex::DataType::Void.new)
|
1257
|
-
end
|
1258
|
-
end # class CNull
|
1259
|
-
end # module Literal
|
1260
91
|
end # module Expression
|
1261
92
|
end # module AST
|
1262
93
|
end # module Rubex
|