rubex 0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/rubex.svg)](https://badge.fury.io/rb/rubex)
|
12
|
+
[![Open Source Helpers](https://www.codetriage.com/v0dro/rubex/badges/users.svg)](https://www.codetriage.com/v0dro/rubex)
|
13
|
+
[![Build Status](https://travis-ci.org/SciRuby/rubex.svg?branch=master)](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
|