rubimc 0.2.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 +7 -0
- data/LICENSE.md +21 -0
- data/README.md +176 -0
- data/bin/rubimc +190 -0
- data/lib/rubimc/control_structures.rb +58 -0
- data/lib/rubimc/controllers.rb +46 -0
- data/lib/rubimc/init_var.rb +99 -0
- data/lib/rubimc/io_ports.rb +66 -0
- data/lib/rubimc/mcu/avr/attiny13.rb +176 -0
- data/lib/rubimc/mcu/avr/avr_controller.rb +16 -0
- data/lib/rubimc/preprocessor.rb +354 -0
- data/lib/rubimc/printer.rb +143 -0
- data/lib/rubimc/ruby_classes.rb +54 -0
- data/lib/rubimc.rb +234 -0
- data/lib/version.rb +3 -0
- metadata +60 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 4465934e351aae8519533e572a4db1f636230a2d
|
|
4
|
+
data.tar.gz: 20b82528892f27d9c7dc428b3c744d973da93dce
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6c9694603cc3dcd38c5a82df186c89573f586a0560b414f991771f4f7b638522b382e414b58febe950a210633c90e3a3ac5c43dd2e756997f0cbfc211a746b2a
|
|
7
|
+
data.tar.gz: 8bdf46becb20231885f57e47de38d0a8b5c347bb23dc5a1ae4f3788de98116894fb921d6ed89d5faedaaad508b8705e52a61cfba426fde5fb62e4ad8229528ed
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Evgeny Danilov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
### RubimC
|
|
2
|
+
It is a Ruby compiler and framework for microcontrollers. Full name RubimCode in Russian transcription heard as "cut down the code". Current version is working but realizes far not all the features of Ruby. All realized features you can find in folder "examples"
|
|
3
|
+
|
|
4
|
+
### Description:
|
|
5
|
+
RubimC designed to simplify the process of programming microcontrollers, but can also be used as an clear С-code generator. The framework is a syntax-flavored Ruby combines the unique features of the Ruby, adding and expanding the functions required for a specific area. At the input generator takes the program to Ruby, and the output provides a pure C code, based on the user program and libraries that are connected to a select model of the microcontroller. All that is required to generate is installed ruby-interpreter. If it`s nessesary, for compile C-code you need installing compiler *gcc* or *avr-gcc* (for AVR microcontrollers)
|
|
6
|
+
|
|
7
|
+
### Benefits of writing programs in RubymC
|
|
8
|
+
+ increase development speed
|
|
9
|
+
+ code readability and elegance inherent in the Ruby language
|
|
10
|
+
+ an object-oriented approach
|
|
11
|
+
+ the use of an interpreted language does not reduce the performance of the final program because there is **no virtual mashine**
|
|
12
|
+
+ ability of hardware control IC and delivery of messages
|
|
13
|
+
+ ability to get a list of the hardware for a particular version of the device, as well as a list of all methods and help them directly from the generator console, on the basis of libraries.
|
|
14
|
+
|
|
15
|
+
### Why?
|
|
16
|
+
First of all for fan...I want to see at Ruby from other point, not only from famous framework Ruby On Rails. Of course, we have great project [mruby] (http://mruby.org/), that compile Ruby code, realized all common functions of Ruby and standart libraries, and supported by **Matz**. But...mruby generate a big-size code, and, as we know, microcontroller have very small memory. For example, for initialize only one array mruby generate binary file with size 1MB! At the other side RubimC generate code with minimal size, in most cases are not different from the similar size of, written on C. In addition, RubimC generator is clearness. You always can to see on generated C-code and to evaluate its performance and size.
|
|
17
|
+
|
|
18
|
+
### How it`s work
|
|
19
|
+
Code generated in three stage:
|
|
20
|
+
|
|
21
|
+
1. Preprocessing user programm, that replaced some Ruby keywords, operators and identificators
|
|
22
|
+
2. Shell Ruby-code and generate C-code (use metaprograming of Ruby)
|
|
23
|
+
3. Compile C-code (with gcc or avr-gcc).
|
|
24
|
+
|
|
25
|
+
### Install
|
|
26
|
+
All you need to use **RubimC** gem is Ruby interpretator and gcc/avr-gcc compiler.
|
|
27
|
+
|
|
28
|
+
How to [install Ruby] (https://www.ruby-lang.org/en/documentation/installation/). For Ubuntu I recomended to use first chapter of this [manual] (https://gorails.com/setup/ubuntu).
|
|
29
|
+
|
|
30
|
+
Then you can install RubimC gem:
|
|
31
|
+
```sh
|
|
32
|
+
gem install rubimc
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Compiler *gcc* provided by Linux. For others platforms use this [manual] (https://gcc.gnu.org/install/binaries.html).
|
|
36
|
+
|
|
37
|
+
To install *avr-gcc* use this [manual] (http://avr-eclipse.sourceforge.net/wiki/index.php/The_AVR_GCC_Toolchain).
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### ToDo list (main of them):
|
|
41
|
+
0. upload to rubygems
|
|
42
|
+
0. Test core with command "rubimc test"
|
|
43
|
+
1. Code generator:
|
|
44
|
+
+ define user`s variables as local (now it defined in top-level instance)
|
|
45
|
+
+ support all C types of variables (int ,float, unsigned int, u_int8 e.t.)
|
|
46
|
+
+ support array, hash, string, range and constants
|
|
47
|
+
+ support user`s methods and classes
|
|
48
|
+
+ support threads
|
|
49
|
+
2. Write libraries for microcontrollers (AVR, PIC, STM, e.t.)
|
|
50
|
+
3. Fix a lot of possible bugs & features
|
|
51
|
+
|
|
52
|
+
### What is done
|
|
53
|
+
1. Init variables
|
|
54
|
+
2. Support all arithmetic operation except ternary and logical operators (binary operators is done)
|
|
55
|
+
3. Support conditions (if/unless and it`s modify version) and loops (while/until) except next/redo/break/retry keywords
|
|
56
|
+
4. Support arrays init and arithmetic operation with it
|
|
57
|
+
5. Realize example library for AVR AtTiny13 MCU with DigitalIO and ADC support
|
|
58
|
+
|
|
59
|
+
### Example for AVR microcontroller:
|
|
60
|
+
Ruby programm (*"FirstController.rb"*):
|
|
61
|
+
```ruby
|
|
62
|
+
require 'rubimc'
|
|
63
|
+
|
|
64
|
+
class FirstController < AVR_attiny13
|
|
65
|
+
def initialize
|
|
66
|
+
ANALOG_TO_DIGITAL.init(ref: "vcc", channel: ADC0)
|
|
67
|
+
|
|
68
|
+
ANALOG_TO_DIGITAL.interrupt(enabled: true) do |volts|
|
|
69
|
+
output :led, port: :B, pin: 3
|
|
70
|
+
led.off if volts < 30
|
|
71
|
+
led.on if volts >= 220
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def main_loop # infinit loop, it stop only when MCU is reset
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
To compile this code run in console:
|
|
81
|
+
```sh
|
|
82
|
+
rubimc compile FirstController.rb
|
|
83
|
+
```
|
|
84
|
+
or just
|
|
85
|
+
```sh
|
|
86
|
+
rubimc compile --all
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
It generate C-code placed in *"release/FirstController.c"* and hex-file for upload in MCU placed in *"release/FirstController.hex*
|
|
90
|
+
```c
|
|
91
|
+
//=============================
|
|
92
|
+
#include <stdbool.h>
|
|
93
|
+
|
|
94
|
+
#define F_CPU 1000000UL
|
|
95
|
+
#include <avr/io.h>
|
|
96
|
+
#include <avr/iotn13.h>
|
|
97
|
+
#include <avr/interrupt.h>
|
|
98
|
+
|
|
99
|
+
int main()
|
|
100
|
+
{
|
|
101
|
+
// Init ADC
|
|
102
|
+
ADMUX = (0<<REFS0) | (0<<ADLAR) | MUX0;
|
|
103
|
+
ADCSRA = (1<<ADEN) | (0<<ADATE) | (1<<ADPS0) | (0<<ADIE);
|
|
104
|
+
|
|
105
|
+
ADMUX |= 1<<ADIE;
|
|
106
|
+
return 1;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ADC Interrupt
|
|
110
|
+
ISR(ADC_vect)
|
|
111
|
+
{
|
|
112
|
+
int __rubim__volt = ADCL + ((ADCH&0b11) << 8);
|
|
113
|
+
DDRB |= 1<<(3);
|
|
114
|
+
if ((__rubim__volt<=(0))) {
|
|
115
|
+
PORTB &= 255 ^ (1<<(3));
|
|
116
|
+
}
|
|
117
|
+
if (!((__rubim__volt<(15)))) {
|
|
118
|
+
PORTB |= 1<<(3);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
*note: this is a valid C-code, but in real AVR-controllers it may not work, because avr-libraries are still in development*
|
|
123
|
+
|
|
124
|
+
### Some rake helpers
|
|
125
|
+
For create new project RubimC gem support command "generate" (of just "g"). For example:
|
|
126
|
+
```sh
|
|
127
|
+
rubimc generate mcu "BrainControll.rb" type:attiny13 # create template "BrainControll.rb" for AVR microcontroller 'attiny13'
|
|
128
|
+
rubimc g mcu FirstProg # create template "FirstProg.rb" for unknown microcontroller
|
|
129
|
+
rubimc g clearC Example # create template "Example.rb" for generate clear C code
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Some interesting idea
|
|
133
|
+
There is interesting idea for connect few microconrollers (IC) via some firmware interfaces, for example I2C or USB **(at this moment is not realized)**. This example will generate two binary files for each microcontroller.
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
class BrainController < AVR_atmega16
|
|
137
|
+
def initialize()
|
|
138
|
+
input :button, port: :A, pin: 6
|
|
139
|
+
# its a syntax surag of "@button = input name: 'button', port: 'A', pin: 6"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def main_loop() # infinit loop, it stop only when IC is reset
|
|
143
|
+
if want_to_say_hello?
|
|
144
|
+
LeftHandController.move_hand = "up" # transfer data to other controller
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private # define user`s methods and classes
|
|
149
|
+
def want_to_say_hello?
|
|
150
|
+
@button.press?
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
class LeftHandController < AVR_attiny13
|
|
155
|
+
attr_accessor :move_hand, via: "I2C" # I2C - fireware data-transfer bus
|
|
156
|
+
|
|
157
|
+
def move_hand=(message) # execute when command is received
|
|
158
|
+
@led.toggle
|
|
159
|
+
if message=="up"
|
|
160
|
+
# ...run motor...
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def initialize()
|
|
165
|
+
output :led, port: :B, pin: 3
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def main_loop() # infinit loop, it stop only when IC is reset
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Help
|
|
174
|
+
If you interested the project and find some bugs, you may to write the tests and we try to fix it. Examples of tests is placed in folder *test*. To run tests use command *"rspec test/test_all.rb"*. Of course if you try to modify core and libraries it will be wonder.
|
|
175
|
+
|
|
176
|
+
Thank you!
|
data/bin/rubimc
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# Example:
|
|
4
|
+
#
|
|
5
|
+
# rubimc generate mcu "Brain.rb" type:attiny13
|
|
6
|
+
# rubimc g mcu FirstProg
|
|
7
|
+
# rubimc g clearC Example
|
|
8
|
+
#
|
|
9
|
+
# rubimc compile "BrainControll.rb"
|
|
10
|
+
# rubimc compile BrainControll
|
|
11
|
+
# rubimc compile --all
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
require 'rake'
|
|
15
|
+
|
|
16
|
+
gem_dir = File.expand_path("..", File.dirname(__FILE__))
|
|
17
|
+
$LOAD_PATH.unshift gem_dir # Look in gem directory for resources first
|
|
18
|
+
|
|
19
|
+
exec_type = ARGV[0]
|
|
20
|
+
if exec_type == 'generate' or exec_type == 'g'
|
|
21
|
+
gen_type = ARGV[1]
|
|
22
|
+
if gen_type == 'mcu' # generate template for MCU
|
|
23
|
+
name = ARGV[2]
|
|
24
|
+
if name.nil?
|
|
25
|
+
puts "ERROR: you must define mcu name"
|
|
26
|
+
puts "for example: 'rubimc g mcu ExampleProg'"
|
|
27
|
+
exit 1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
parent = "Unknown_MCU"
|
|
31
|
+
type_param = ARGV[3] # ToDo: parse params
|
|
32
|
+
unless type_param.nil?
|
|
33
|
+
require 'rubimc'
|
|
34
|
+
RubimCode::Printer.sandbox = true
|
|
35
|
+
|
|
36
|
+
type_param = type_param.gsub(/type:/, "")
|
|
37
|
+
mcu = Controllers.find_mcu("#{type_param}").first
|
|
38
|
+
if mcu.nil?
|
|
39
|
+
puts "ERROR: mcu type '#{type_param}'' not found in rubimc libraries"
|
|
40
|
+
exit 1
|
|
41
|
+
end
|
|
42
|
+
series, type = mcu::MCU_SERIES, mcu::MCU_NAME
|
|
43
|
+
parent = "#{series}_#{type}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
generated_text = "
|
|
47
|
+
require 'rubimc'
|
|
48
|
+
|
|
49
|
+
class #{name} < #{parent}
|
|
50
|
+
def initialize
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def main_loop # infinit loop, it stop only when IC is reset
|
|
54
|
+
end
|
|
55
|
+
end"
|
|
56
|
+
|
|
57
|
+
elsif gen_type == 'clearC' # generate template for clear C code
|
|
58
|
+
name = ARGV[2]
|
|
59
|
+
if name.nil?
|
|
60
|
+
puts "ERROR: you must define file name"
|
|
61
|
+
puts "for example: 'rubimc g clearC ExampleProg'"
|
|
62
|
+
exit 1
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
generated_text = "
|
|
66
|
+
require 'rubimc'
|
|
67
|
+
|
|
68
|
+
def main(argv)
|
|
69
|
+
end"
|
|
70
|
+
else
|
|
71
|
+
puts "ERROR: unknown param '#{gen_type}'"
|
|
72
|
+
puts "Available params for generator: mcu; clearC"
|
|
73
|
+
exit 1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
generated_text.gsub!(/\t\t\t/, "")
|
|
77
|
+
generated_text = generated_text[1..-1]
|
|
78
|
+
if File.exist?("#{name}.rb")
|
|
79
|
+
puts "WARNING: file '#{name}.rb' already exist. Overrire it (y/n)?"
|
|
80
|
+
answer = STDIN.gets
|
|
81
|
+
exit 1 if ["n\n", "N\n"].include? answer
|
|
82
|
+
end
|
|
83
|
+
File.open("#{name}.rb", 'w') {|file| file.puts(generated_text) }
|
|
84
|
+
# => end generate section
|
|
85
|
+
|
|
86
|
+
elsif exec_type == 'compile'
|
|
87
|
+
|
|
88
|
+
puts "\n === Run RubimC compiler === "
|
|
89
|
+
|
|
90
|
+
input_files = []
|
|
91
|
+
if ARGV[1] == '-all' or ARGV[1] == '--all'
|
|
92
|
+
Dir['*.rb'].each do |file|
|
|
93
|
+
input_files << file
|
|
94
|
+
end
|
|
95
|
+
else
|
|
96
|
+
ARGV[1] += '.rb' if File.extname(ARGV[1]).empty?
|
|
97
|
+
input_files << ARGV[1]
|
|
98
|
+
end
|
|
99
|
+
ARGV.clear
|
|
100
|
+
|
|
101
|
+
unless input_files.any?
|
|
102
|
+
puts 'No files to compile...'
|
|
103
|
+
exit 1
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
need_to_clear_release = true
|
|
107
|
+
input_files.each do |input_file|
|
|
108
|
+
# === check file exist ===
|
|
109
|
+
unless File.exist?(input_file)
|
|
110
|
+
puts "ERROR: File \"#{input_file}\" not found"
|
|
111
|
+
puts "Use 'rubimc compile --all' to compile all files in current directory"
|
|
112
|
+
puts ""
|
|
113
|
+
exit 1
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# === check syntax of user program ===
|
|
117
|
+
print "Check syntax..."
|
|
118
|
+
sh "ruby -c '#{input_file}'", verbose: false do |ok, res|
|
|
119
|
+
exit 1 unless ok # check exit status after command runs
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# === prepare file names ===
|
|
123
|
+
input_file = File.expand_path(input_file)
|
|
124
|
+
basename = File.basename(input_file, ".rb") # extract filename without path and extention
|
|
125
|
+
dirname = File.dirname(input_file)
|
|
126
|
+
release_folder = "#{dirname}/release/"
|
|
127
|
+
outfile = "#{dirname}/release/#{basename}"
|
|
128
|
+
|
|
129
|
+
# === clear directory "release" ===
|
|
130
|
+
if need_to_clear_release
|
|
131
|
+
need_to_clear_release = false
|
|
132
|
+
FileUtils.rm_rf(Dir.glob("#{release_folder}/*"))
|
|
133
|
+
end
|
|
134
|
+
Dir.mkdir("#{release_folder}/") unless Dir.exists?("#{release_folder}/")
|
|
135
|
+
|
|
136
|
+
# === preprocessing user`s program ===
|
|
137
|
+
print "preprocessing file \"#{basename}.rb\"..."
|
|
138
|
+
require 'rubimc/preprocessor'
|
|
139
|
+
PreProcessor.write_in_file(input_file, dirname, basename, "#{outfile}.rb")
|
|
140
|
+
|
|
141
|
+
# === check type: gcc/avr-gcc
|
|
142
|
+
require "#{outfile}.rb"
|
|
143
|
+
unless defined? RubimCode
|
|
144
|
+
puts "ERROR: file '#{outfile}.rb' is not rubimc program"
|
|
145
|
+
exit 1
|
|
146
|
+
end
|
|
147
|
+
RubimCode::Printer.sandbox = true
|
|
148
|
+
RubimCode::Printer.generate_cc
|
|
149
|
+
code_type = RubimCode::Printer.code_type
|
|
150
|
+
mcu_type = RubimCode::Printer.mcu_type
|
|
151
|
+
|
|
152
|
+
# === execute preprocessing program, generate C code ===
|
|
153
|
+
puts "generate C code"
|
|
154
|
+
sh "ruby '#{outfile}.rb' '#{outfile}'.c", verbose: false do |ok, res|
|
|
155
|
+
exit 1 unless ok # check exit status after command runs
|
|
156
|
+
end
|
|
157
|
+
puts "done"
|
|
158
|
+
|
|
159
|
+
# === compile C code to object-code and link to hex/exe ===
|
|
160
|
+
# ToDo: add DF_CPU (is it need?)
|
|
161
|
+
if code_type == "avr-gcc"
|
|
162
|
+
print "compile and link..."
|
|
163
|
+
sh "avr-gcc -std=c99 -Os -mmcu=#{mcu_type} -c '#{outfile}.c' -o '#{outfile}.o'", verbose: false do |ok, res|
|
|
164
|
+
exit 1 unless ok # check exit status after command runs
|
|
165
|
+
end
|
|
166
|
+
# generate hex for upload to MCU
|
|
167
|
+
sh "avr-objcopy -O ihex '#{outfile}.o' '#{outfile}.hex'", verbose: false do |ok, res|
|
|
168
|
+
exit 1 unless ok # check exit status after command runs
|
|
169
|
+
end
|
|
170
|
+
puts "done"
|
|
171
|
+
|
|
172
|
+
elsif code_type == "gcc"
|
|
173
|
+
print "compile and link..."
|
|
174
|
+
sh "gcc -std=c99 -o '#{outfile}.out' '#{outfile}.c'", verbose: false do |ok, res|
|
|
175
|
+
exit 1 unless ok # check exit status after command runs
|
|
176
|
+
end
|
|
177
|
+
puts "done"
|
|
178
|
+
|
|
179
|
+
print "run..."
|
|
180
|
+
sh "'#{outfile}.out'", verbose: false do |ok, res|
|
|
181
|
+
exit 1 unless ok # check exit status after command runs
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
else
|
|
187
|
+
puts "ERROR: unknown command for rubimc"
|
|
188
|
+
puts "Available commands: compile; generate;"
|
|
189
|
+
exit 1
|
|
190
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
class RubimCode
|
|
2
|
+
class << self
|
|
3
|
+
|
|
4
|
+
@@rubim_defined_values = []
|
|
5
|
+
|
|
6
|
+
def rubim_cond(cond, type="if", &block)
|
|
7
|
+
# ToDo: auto-define type of ret_value
|
|
8
|
+
# use:: __rubim__rval__int, __rubim__rval__float, e.t.
|
|
9
|
+
|
|
10
|
+
if @@rubim_defined_values.include? @level
|
|
11
|
+
pout "__rubim__rval#{@level} = 0;"
|
|
12
|
+
else
|
|
13
|
+
pout "int __rubim__rval#{@level} = 0;"
|
|
14
|
+
end
|
|
15
|
+
@@rubim_defined_values << @level
|
|
16
|
+
|
|
17
|
+
if type=="if"
|
|
18
|
+
pout "if (#{cond}) {"
|
|
19
|
+
elsif type=="unless"
|
|
20
|
+
pout "if (!(#{cond})) {"
|
|
21
|
+
end
|
|
22
|
+
@level += 1
|
|
23
|
+
ret_val = yield
|
|
24
|
+
pout "__rubim__rval#{@level-1} = #{ret_val};" if ret_val!="__rubim__noreturn"
|
|
25
|
+
pout "}"
|
|
26
|
+
@level -= 1
|
|
27
|
+
return "__rubim__rval#{@level}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def rubim_cycle(type="while", cond="true", &block)
|
|
31
|
+
pout "#{type} (#{cond}) {"
|
|
32
|
+
@level+=1
|
|
33
|
+
yield
|
|
34
|
+
pout "}"
|
|
35
|
+
@level-=1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def rubim_if(cond, &block); rubim_cond(cond, "if", &block); end
|
|
39
|
+
def rubim_unless(cond, &block); rubim_cond(cond, "unless", &block); end
|
|
40
|
+
def rubim_while(cond, &block); rubim_cycle("while", cond, &block); end
|
|
41
|
+
def rubim_until(cond); rubim_cycle("until", cond, &block); end
|
|
42
|
+
def rubim_loop(&block); rubim_cycle("while", "true", &block); end
|
|
43
|
+
|
|
44
|
+
def rubim_whilemod(cond); pout "} while (#{cond});"; @level-=1; end
|
|
45
|
+
def rubim_untilmod(cond); pout "} until (#{cond});"; @level-=1; end
|
|
46
|
+
|
|
47
|
+
def rubim_ifmod(cond); pout "if (#{cond}) {"; @level+=1; true; end
|
|
48
|
+
def rubim_unlessmod(cond); pout "if (!(#{cond})) {"; @level+=1; true; end
|
|
49
|
+
def rubim_begin(); pout "{"; @level+=1; true; end
|
|
50
|
+
def rubim_end(); pout "}"; @level-=1; "__rubim__noreturn"; end
|
|
51
|
+
def rubim_tmpif(tmp); end
|
|
52
|
+
|
|
53
|
+
def rubim_else(); @level-=1; pout "} else {"; @level+=1; end
|
|
54
|
+
def rubim_elsif(cond); @level-=1; pout "} else if (#{cond}) {"; @level+=1; end
|
|
55
|
+
# ToDo: set return_val, like in rubim_if (need to change preprocessor)
|
|
56
|
+
|
|
57
|
+
end # class << self
|
|
58
|
+
end # RubimCode class
|