rubimc 0.2.1 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4465934e351aae8519533e572a4db1f636230a2d
4
- data.tar.gz: 20b82528892f27d9c7dc428b3c744d973da93dce
3
+ metadata.gz: b52fe6847b85209bb0018b7afd0ebc6fcc92d0cc
4
+ data.tar.gz: 88e2ebaee4e861f2764b21f1458508c63894a443
5
5
  SHA512:
6
- metadata.gz: 6c9694603cc3dcd38c5a82df186c89573f586a0560b414f991771f4f7b638522b382e414b58febe950a210633c90e3a3ac5c43dd2e756997f0cbfc211a746b2a
7
- data.tar.gz: 8bdf46becb20231885f57e47de38d0a8b5c347bb23dc5a1ae4f3788de98116894fb921d6ed89d5faedaaad508b8705e52a61cfba426fde5fb62e4ad8229528ed
6
+ metadata.gz: 3d5e74dc243f0c55e0ea8aa6d876df15336c5027c52df64db64ee03d52a084dc6ea3d46c499b3e6b9a7ffcdf95d9940fd92250d24cca9b93bb9a7cbb600e54e2
7
+ data.tar.gz: 3346556ddb1be68a8da416132fbf137bbacf4db50bb846ac90b77419cec5fd52601db71498fc153628b5b2b2aa0bdb73000897b60ac980068131f994a82ef636
data/README.md CHANGED
@@ -38,22 +38,23 @@ To install *avr-gcc* use this [manual] (http://avr-eclipse.sourceforge.net/wiki/
38
38
 
39
39
 
40
40
  ### ToDo list (main of them):
41
- 0. upload to rubygems
42
- 0. Test core with command "rubimc test"
41
+ 1. Validate code before preprocessing
42
+ 1. Support C-libraries
43
43
  1. Code generator:
44
44
  + define user`s variables as local (now it defined in top-level instance)
45
45
  + support all C types of variables (int ,float, unsigned int, u_int8 e.t.)
46
- + support array, hash, string, range and constants
46
+ + check match types (in assign and operations) and try to cast
47
+ + support array, hash, string, range and constants (as full as possible)
47
48
  + support user`s methods and classes
48
49
  + support threads
49
50
  2. Write libraries for microcontrollers (AVR, PIC, STM, e.t.)
50
51
  3. Fix a lot of possible bugs & features
51
52
 
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
53
+ ### What is done now
54
+ 1. Initialize variables (supported types: bool,int,float,double)
55
+ 2. Support most of ruby operators: arithmetic, unary, comparison, binary (need to realize logical operators: and/or/not)
56
+ 3. Support conditions if/unless (with return values) and it modify version
57
+ 4. Suppotr loops while/until and it modify version (except redo/retry instruction)
57
58
  5. Realize example library for AVR AtTiny13 MCU with DigitalIO and ADC support
58
59
 
59
60
  ### Example for AVR microcontroller:
@@ -124,7 +125,7 @@ ISR(ADC_vect)
124
125
  ### Some rake helpers
125
126
  For create new project RubimC gem support command "generate" (of just "g"). For example:
126
127
  ```sh
127
- rubimc generate mcu "BrainControll.rb" type:attiny13 # create template "BrainControll.rb" for AVR microcontroller 'attiny13'
128
+ rubimc generate mcu BrainControll type:attiny13 # create template "BrainControll.rb" for AVR microcontroller 'attiny13'
128
129
  rubimc g mcu FirstProg # create template "FirstProg.rb" for unknown microcontroller
129
130
  rubimc g clearC Example # create template "Example.rb" for generate clear C code
130
131
  ```
@@ -135,8 +136,7 @@ There is interesting idea for connect few microconrollers (IC) via some firmware
135
136
  ```ruby
136
137
  class BrainController < AVR_atmega16
137
138
  def initialize()
138
- input :button, port: :A, pin: 6
139
- # its a syntax surag of "@button = input name: 'button', port: 'A', pin: 6"
139
+ input :@button, port: :A, pin: 6
140
140
  end
141
141
 
142
142
  def main_loop() # infinit loop, it stop only when IC is reset
@@ -162,7 +162,7 @@ class LeftHandController < AVR_attiny13
162
162
  end
163
163
 
164
164
  def initialize()
165
- output :led, port: :B, pin: 3
165
+ output :@led, port: :B, pin: 3
166
166
  end
167
167
 
168
168
  def main_loop() # infinit loop, it stop only when IC is reset
data/bin/rubimc CHANGED
@@ -114,7 +114,7 @@ elsif exec_type == 'compile'
114
114
  end
115
115
 
116
116
  # === check syntax of user program ===
117
- print "Check syntax..."
117
+ print " Check syntax..."
118
118
  sh "ruby -c '#{input_file}'", verbose: false do |ok, res|
119
119
  exit 1 unless ok # check exit status after command runs
120
120
  end
@@ -134,9 +134,10 @@ elsif exec_type == 'compile'
134
134
  Dir.mkdir("#{release_folder}/") unless Dir.exists?("#{release_folder}/")
135
135
 
136
136
  # === preprocessing user`s program ===
137
- print "preprocessing file \"#{basename}.rb\"..."
137
+ print " preprocessing file \"#{basename}.rb\"..."
138
138
  require 'rubimc/preprocessor'
139
139
  PreProcessor.write_in_file(input_file, dirname, basename, "#{outfile}.rb")
140
+ print "done\n"
140
141
 
141
142
  # === check type: gcc/avr-gcc
142
143
  require "#{outfile}.rb"
@@ -150,7 +151,7 @@ elsif exec_type == 'compile'
150
151
  mcu_type = RubimCode::Printer.mcu_type
151
152
 
152
153
  # === execute preprocessing program, generate C code ===
153
- puts "generate C code"
154
+ puts " generate C code"
154
155
  sh "ruby '#{outfile}.rb' '#{outfile}'.c", verbose: false do |ok, res|
155
156
  exit 1 unless ok # check exit status after command runs
156
157
  end
@@ -159,7 +160,7 @@ elsif exec_type == 'compile'
159
160
  # === compile C code to object-code and link to hex/exe ===
160
161
  # ToDo: add DF_CPU (is it need?)
161
162
  if code_type == "avr-gcc"
162
- print "compile and link..."
163
+ print " compile and link..."
163
164
  sh "avr-gcc -std=c99 -Os -mmcu=#{mcu_type} -c '#{outfile}.c' -o '#{outfile}.o'", verbose: false do |ok, res|
164
165
  exit 1 unless ok # check exit status after command runs
165
166
  end
@@ -170,7 +171,7 @@ elsif exec_type == 'compile'
170
171
  puts "done"
171
172
 
172
173
  elsif code_type == "gcc"
173
- print "compile and link..."
174
+ print " compile and link..."
174
175
  sh "gcc -std=c99 -o '#{outfile}.out' '#{outfile}.c'", verbose: false do |ok, res|
175
176
  exit 1 unless ok # check exit status after command runs
176
177
  end
@@ -183,6 +184,14 @@ elsif exec_type == 'compile'
183
184
  end
184
185
  end
185
186
 
187
+ # Development mode
188
+ elsif exec_type == "dev_compile"
189
+ require "#{gem_dir}/lib/version.rb"
190
+ puts "development mode"
191
+ sh "gem build rubimc.gemspec"
192
+ sh "gem install rubimc-#{RubimCode::VERSION}.gem"
193
+ sh "rubimc compile #{ARGV[1]}"
194
+
186
195
  else
187
196
  puts "ERROR: unknown command for rubimc"
188
197
  puts "Available commands: compile; generate;"
@@ -31,22 +31,41 @@ class RubimCode
31
31
  end
32
32
 
33
33
  def to_i
34
- @name.to_i
34
+ self.name.to_i
35
+ end
36
+
37
+ def to_bool
38
+ return true if self.name == true || self.name =~ (/(true|t|yes|y|1)$/i)
39
+ return false if self.name == false || self.name.blank? || self.name =~ (/(false|f|no|n|0)$/i)
40
+ RubimCode.perror "Can not convert variable #{self} to boolean"
35
41
  end
36
42
 
37
43
  def to_rubim
38
44
  self
39
45
  end
40
46
 
41
- def c_assign=(val)
42
- RubimCode.pout "#{@name} = #{val};"
47
+ def c_assign=(val)
48
+ RubimCode::Isolator.permit!(self)
49
+ RubimCode::Isolator.permit!(val)
50
+
51
+ RubimCode.perror "Undefined variable or method" if val.nil?
52
+ RubimCode.perror "Wrong match types" unless val.is_a? UserVariable
53
+
54
+ RubimCode.pout "#{self.name} = #{val};"
43
55
  end
44
56
 
45
- def common_operator(val, operator_sym)
57
+ def common_operator(val, operator_sym, **options)
46
58
  if not val.class.respond_to? :to_s
47
59
  RubimCode.perror "Conversion of variable #{val} is impossible. Method 'to_s' not found"
48
60
  else
49
- UserVariable.new(self.name + operator_sym.to_s + val.to_s)
61
+ if options[:unary]
62
+ RubimCode::Isolator.permit!(self)
63
+ UserVariable.new(operator_sym.to_s[0] + self.name, 'expression')
64
+ else
65
+ RubimCode::Isolator.permit!(self)
66
+ RubimCode::Isolator.permit!(val)
67
+ UserVariable.new(self.name + operator_sym.to_s + val.to_s, 'expression')
68
+ end
50
69
  end
51
70
  end
52
71
 
@@ -62,18 +81,18 @@ class RubimCode
62
81
  # ToDo: (can not override; use preprocessor)
63
82
 
64
83
  # Unary Operators:
65
- def -@; UserVariable.new("(-" + self.name + ")"); end
66
- def +@; UserVariable.new("(+" + self.name + ")"); end
67
- def !@; UserVariable.new("(+" + self.name + ")"); end
68
- def ~@; UserVariable.new("(+" + self.name + ")"); end
84
+ def -@; common_operator(nil, __method__, unary: true); end
85
+ def +@; common_operator(nil, __method__, unary: true); end
86
+ def !@; common_operator(nil, __method__, unary: true); end
87
+ def ~@; common_operator(nil, __method__, unary: true); end
69
88
 
70
89
  # Comparison Operators:
71
- def ==(val); common_operator(val, __method__); end
72
- def !=(val); common_operator(val, __method__); end
73
- def <(val); common_operator(val, __method__); end
74
- def >(val); common_operator(val, __method__); end
75
- def <=(val); common_operator(val, __method__); end
76
- def >=(val); common_operator(val, __method__); end
90
+ def ==(val); common_operator(val, __method__); end
91
+ def !=(val); common_operator(val, __method__); end
92
+ def <(val); common_operator(val, __method__); end
93
+ def >(val); common_operator(val, __method__); end
94
+ def <=(val); common_operator(val, __method__); end
95
+ def >=(val); common_operator(val, __method__); end
77
96
 
78
97
  # Binary Operators:
79
98
  def &(val); common_operator(val, __method__); end
@@ -88,8 +107,9 @@ class RubimCode
88
107
  # Ternary Operators: (? :)
89
108
  # ToDo...
90
109
 
91
- # Ruby Parallel Assignment:
92
- # a, b, c = 10, 20, 30 # ToDo
110
+ # Ruby Parallel Assignment :
111
+ # a, b, c = 10, 20, 30
112
+ # ToDo: use preprocessor: => [a, b, c].c_assing= 10, 20, 30
93
113
 
94
114
  # ToDo: операторы, которым нет аналогов в Си
95
115
  # def <=>(val); ??? end
@@ -110,7 +130,8 @@ class RubimCode
110
130
  end
111
131
 
112
132
  # ToDo: add mixins Enumerable and Comparable
113
- end
133
+
134
+ end # end UserVariable class
114
135
 
115
136
  # ToDo: в Ruby присваивание значений индексной переменной
116
137
  # не должно влиять на выполнение цикла
@@ -126,7 +147,7 @@ class RubimCode
126
147
  def to_s
127
148
  self.name
128
149
  end
129
- end
150
+ end # end LoopCounter class
130
151
 
131
152
  class UserArray < Array
132
153
  attr_accessor :name, :type
@@ -148,7 +169,7 @@ class RubimCode
148
169
  RubimCode.level -=1
149
170
  RubimCode.pout "}"
150
171
  end
151
- end
172
+ end # end UserArray class
152
173
 
153
174
  # Наследник всех пользовательских классов
154
175
  class UserClass < UserVariable
@@ -194,7 +215,7 @@ class RubimCode
194
215
  end
195
216
  end
196
217
 
197
- end
218
+ end # end UserClass class
198
219
 
199
220
  # Список аппаратных прерываний (содержит Си-код в текстовом виде)
200
221
  class Interrupts
@@ -217,7 +238,37 @@ class RubimCode
217
238
  RubimCode.pout interrupt_code
218
239
  end
219
240
  end
220
- end
241
+ end # end Interrupts class
242
+
243
+ class Isolator
244
+ class << self
245
+ attr_accessor :outside_binding
246
+ attr_accessor :local_variables
247
+ attr_accessor :enabled
248
+ end
249
+
250
+ def self.permit!(var)
251
+ return unless self.enabled
252
+ return unless self.outside_binding
253
+ return unless var.is_a? UserVariable
254
+ return if var.type.in? ["fixed", "expression", "undefined", nil]
255
+ return if var.type === /^tmp/
256
+
257
+ if !local_variables.include?(var.name) and
258
+ outside_binding.local_variable_defined?(var.name.to_sym)
259
+ RubimCode.perror "Undefined variable '#{var.name}'. To pass params in interruprts use instance variables: '@#{var.name}'"
260
+ end
261
+ end
262
+
263
+ def self.run
264
+ self.local_variables = []
265
+ self.enabled = true
266
+ end
267
+
268
+ def self.stop
269
+ self.enabled = false
270
+ end
271
+ end # end Isolator class
221
272
 
222
273
  class CC_ARGS # class for arguments when work with clear C-code
223
274
  def count
@@ -227,7 +278,7 @@ class RubimCode
227
278
  def [](index)
228
279
  RubimCode::UserVariable.new("argv[#{index}]", "int")
229
280
  end
230
- end
281
+ end # end CC_ARGS class
231
282
 
232
283
  end
233
284
  # === END class RubimCode === #
@@ -3,6 +3,7 @@ class << self
3
3
 
4
4
  @@rubim_defined_values = []
5
5
 
6
+ # instructions "if" & "unless"
6
7
  def rubim_cond(cond, type="if", &block)
7
8
  # ToDo: auto-define type of ret_value
8
9
  # use:: __rubim__rval__int, __rubim__rval__float, e.t.
@@ -24,9 +25,10 @@ class << self
24
25
  pout "__rubim__rval#{@level-1} = #{ret_val};" if ret_val!="__rubim__noreturn"
25
26
  pout "}"
26
27
  @level -= 1
27
- return "__rubim__rval#{@level}"
28
+ return RubimCode::UserVariable.new("__rubim__rval#{@level}", 'tmp_int')
28
29
  end
29
30
 
31
+ # instructions "while" & "until"
30
32
  def rubim_cycle(type="while", cond="true", &block)
31
33
  pout "#{type} (#{cond}) {"
32
34
  @level+=1
@@ -35,24 +37,29 @@ class << self
35
37
  @level-=1
36
38
  end
37
39
 
40
+ # flat instructions
38
41
  def rubim_if(cond, &block); rubim_cond(cond, "if", &block); end
39
42
  def rubim_unless(cond, &block); rubim_cond(cond, "unless", &block); end
40
43
  def rubim_while(cond, &block); rubim_cycle("while", cond, &block); end
41
44
  def rubim_until(cond); rubim_cycle("until", cond, &block); end
42
45
  def rubim_loop(&block); rubim_cycle("while", "true", &block); end
43
46
 
47
+ # modify instructions
48
+ def rubim_ifmod(cond); pout "if (#{cond}) {"; @level+=1; true; end
49
+ def rubim_unlessmod(cond); pout "if (!(#{cond})) {"; @level+=1; true; end
44
50
  def rubim_whilemod(cond); pout "} while (#{cond});"; @level-=1; end
45
51
  def rubim_untilmod(cond); pout "} until (#{cond});"; @level-=1; end
46
52
 
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
53
  def rubim_begin(); pout "{"; @level+=1; true; end
50
54
  def rubim_end(); pout "}"; @level-=1; "__rubim__noreturn"; end
51
55
  def rubim_tmpif(tmp); end
52
56
 
53
57
  def rubim_else(); @level-=1; pout "} else {"; @level+=1; end
54
58
  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)
59
+ # ToDo: in 'else' and 'elsif' set return_val, like in rubim_if (need to change preprocessor)
60
+
61
+ def rubim_next; pout "continue;" end
62
+ def rubim_break; pout "break;" end
56
63
 
57
64
  end # class << self
58
65
  end # RubimCode class
@@ -1,4 +1,4 @@
1
- # ToDo: replace Controllers to MCUs
1
+ # ToDo: rename Controllers to MCUs
2
2
  class Controllers
3
3
  def self.all # list of USER`s microcontrolles
4
4
  @@controllers_array
@@ -13,30 +13,6 @@ class Controllers
13
13
  false
14
14
  end
15
15
 
16
- def self.print_cc_layout(position)
17
- if position == :before_main
18
- RubimCode.pout "/**************************************************************"
19
- RubimCode.pout " * This code was generated by RubimC micro-framework"
20
- RubimCode.pout " * RubimC version: #{RubimCode::VERSION}"
21
- RubimCode.pout " * Author: Evgeny Danilov"
22
- RubimCode.pout " * File created at #{Time.now}"
23
- RubimCode.pout " **************************************************************/"
24
- RubimCode.pout
25
- RubimCode.pout "#include <stdbool.h>"
26
- RubimCode.pout "#include <stdio.h>"
27
- RubimCode.pout
28
- yield if block_given?
29
- RubimCode.pout
30
- RubimCode.pout "int main(int argc, char *argv[]) {"
31
- RubimCode.level += 1
32
- else
33
- RubimCode.pout
34
- RubimCode.pout "return 1;"
35
- RubimCode.level -= 1
36
- RubimCode.pout "}"
37
- end
38
- end
39
-
40
16
  def self.find_mcu(name)
41
17
  series_array = Controllers.descendants
42
18
  real_mcu_array = []
@@ -2,75 +2,80 @@
2
2
  # Initialize user`s variables #
3
3
  #####################################################################
4
4
 
5
- class << RubimCode
6
- attr_accessor :binding
7
- end
8
-
9
- def integer(*varies) # varies - набор инициализируемых переменных
10
- str_cc = "int "
11
- ret_var = []
5
+ # type_cc - тип переменной в С-программе
6
+ # variables - набор инициализируемых переменных
7
+ def RubimCode.init_vars(type_cc, *variables)
8
+ vars_cc = ""
9
+ rubim_vars = []
12
10
 
13
- varies.each {|var|
11
+ variables.each {|var|
14
12
  # ToDo - поиск уже объявленных переменных и выдача предупреждений
15
13
 
16
14
  if var.is_a? Hash # ToDo
17
- RubimCode.perror "Ошибка. В бета-версии нельзя назначать переменным значения при объявлении"
15
+ RubimCode.perror "Ошибка. В текущей версии нельзя назначать переменным значения при объявлении"
18
16
  # key = var.keys.first
19
17
  # instance_variable_set("@#{key.to_s}" , UserVariable.new("#{key.to_s}"))
20
- # str_cc += "#{key.to_s}=#{var[key]}, "
21
- else
22
- if var.to_s[0] == '@'
23
- # ToDo:
24
- RubimCode.perror "ToDo:"
25
- elsif var.to_s[0] == '$'
26
- # ToDo or delete
27
- RubimCode.perror "Ошибка. В текущей версии нельзя инициализировать глобальные переменные"
28
- else
29
- str_cc += "#{var}, "
30
- ret_var << RubimCode::UserVariable.new("#{var}", 'int')
31
- end
32
-
33
- # if self.ancestors.include? RubimCode or self == TestController
18
+ # vars_cc += "#{key.to_s}=#{var[key]}, "
34
19
 
35
- # str_cc = "int " if str_cc.nil?
36
- # str_cc += "#{var}, "
20
+ elsif var.is_a? Symbol
21
+ var_str = var.to_s
22
+ var_name = var_str.gsub(/^[@$]/, "")
23
+ new_var = RubimCode::UserVariable.new("#{var_name}", type_cc)
24
+ rubim_vars << new_var
37
25
 
38
- # eval ("
39
- # def #{var}
40
- # @users__var__#{var}
41
- # end
42
- # @users__var__#{var} = RubimCode::UserVariable.new(\"#{var}\", 'int')
43
- # ")
44
-
45
- # # Альтернативная реализация
46
- # var_method = Proc.new {instance_variable_get("@users__var__#{var}")}
47
- # self.class.send(:define_method, var.to_sym, var_method)
48
- # instance_variable_set("@users__var__#{var}" , UserVariable.new("#{var}", 'int'))
49
- # else
50
- # add_var_array(self.name, UserVariable.new("#{var}", 'int'))
51
- # eval ("
52
- # def #{var}=(value)
53
- # pout \"\#{self.name}.#{var} = \#{value};\"
54
- # end
55
- # def #{var}
56
- # UserVariable.new(\"\#{self.name}.#{var}\", 'int')
57
- # end
58
- # ")
59
- # end
26
+ case var_str[0..1]
27
+ when /$./ # define GLOBAL variable
28
+ RubimCode.perror "Ruby-like global variables are not supported yet. Use 'integer :@#{var_name}'"
29
+ when /@@/ # define CLASS variable
30
+ RubimCode.perror "Ruby-like class variables are not supported yet. Use 'integer :@#{var_name}'"
31
+ when /@./ # define INSTANCE variable (in C it defined as global - outside the 'main' function)
32
+ RubimCode::Printer.instance_vars_cc << new_var
33
+ else # define LOCAL variable (in C it defined as local)
34
+ RubimCode::Isolator.local_variables << var_name if RubimCode::Isolator.enabled
35
+ vars_cc += "#{var_name}, "
36
+ end
37
+
38
+ else
39
+ RubimCode.perror "Unknown type of parameters for helper #{__method__}"
60
40
  end
61
41
  }
62
- if ret_var.empty?
63
- RubimCode.perror "no variables to init"
42
+ if rubim_vars.empty?
43
+ RubimCode.perror "No variables for initialize"
44
+ end
45
+ unless vars_cc.empty?
46
+ vars_cc.chomp!(", ")
47
+ RubimCode.pout ("#{type_cc} #{vars_cc};")
64
48
  end
65
- RubimCode.pout ("#{str_cc.chomp(', ')};")
66
49
 
67
- if ret_var.count == 1
68
- return ret_var[0]
50
+ if rubim_vars.count == 1
51
+ return rubim_vars[0]
69
52
  else
70
- return ret_var
53
+ return rubim_vars
71
54
  end
72
55
  end
73
56
 
57
+ def boolean(*variables)
58
+ RubimCode.init_vars("bool", *variables)
59
+ end
60
+ alias :bool :boolean
61
+
62
+ def integer(*variables)
63
+ RubimCode.init_vars("int", *variables)
64
+ end
65
+ alias :int :integer
66
+
67
+ def float(*variables)
68
+ RubimCode.init_vars("float", *variables)
69
+ end
70
+
71
+ def double(*variables)
72
+ RubimCode.init_vars("double", *variables)
73
+ end
74
+ ###############################################################################
75
+ # NOTE! When add NEW TYPES, modify preprocessor: method 'add_binding_to_init' #
76
+ ###############################################################################
77
+
78
+
74
79
  def array_of_integer(var, size: nil)
75
80
  array(var, with: {type: :integer, size: size})
76
81
  end
@@ -85,6 +90,7 @@ def array(var, with: {type: 'UserVariable', size: nil})
85
90
 
86
91
  user_class = with[:type]
87
92
  with[:type] = 'int' if with[:type] == 'integer'
93
+ with[:type] = 'bool' if with[:type] == 'boolean'
88
94
  if (with[:type].in? ['bool','int','float','double','string'])
89
95
  user_class = "UserVariable"
90
96
  end
@@ -1,23 +1,21 @@
1
- def output (var, port: nil, pin: nil, type: "normal")
1
+ def RubimCode.init_io(mcu_class, rb_type, var, port: nil, pin: nil, type: "normal")
2
2
  if port.nil? or pin.nil?
3
3
  RubimCode.perror "Необходимо указать порт и пин для выхода #{var}"
4
- elsif not self.class::PORTS.include? port
5
- RubimCode.perror "У микроконтроллера #{self.class::MCU_NAME} нет порта #{port}"
6
- elsif not self.class::PORTS[port].include? pin.to_i
7
- RubimCode.perror "У микроконтроллера #{self.class::MCU_NAME} нет порта пина #{pin} для порта #{port}"
8
-
9
- elsif type == "normal"
10
- # define_method(var.to_sym) do
11
- # instance_variable_get("@users__var__#{var}")
12
- # end
13
- # instance_variable_set("@users__var__#{var}" , UserOutput.new("#{var}", port: port, pin: pin, type: type))
14
-
15
- eval ("
16
- def #{var}
17
- @users__var__#{var}
18
- end
19
- @users__var__#{var} = RubimCode::UserOutput.new(\"#{var}\", port: port, pin: pin, type: type)
20
- ")
4
+ elsif not mcu_class::PORTS.include? port.to_sym
5
+ RubimCode.perror "У микроконтроллера #{mcu_class::MCU_NAME} нет порта #{port}"
6
+ elsif not mcu_class::PORTS[port.to_sym].include? pin.to_i
7
+ RubimCode.perror "У микроконтроллера #{mcu_class::MCU_NAME} нет порта пина #{pin} для порта #{port}"
8
+ elsif not var.is_a? Symbol
9
+ RubimCode.perror "Unknown type of parameters for helper #{__method__}"
10
+ end
11
+
12
+ if type == "normal"
13
+ var_name = var.to_s.gsub(/^[@$]/, "")
14
+ if rb_type == 'output'
15
+ return RubimCode::UserOutput.new(var_name, port: port, pin: pin, type: type)
16
+ elsif rb_type == 'input'
17
+ return RubimCode::UserInput.new(var_name, port: port, pin: pin, type: type)
18
+ end
21
19
 
22
20
  elsif type == "tri-state"
23
21
  RubimCode.perror "В данный момент тип выхода 'z-state' не реализован"
@@ -27,8 +25,12 @@ def output (var, port: nil, pin: nil, type: "normal")
27
25
  end
28
26
  end
29
27
 
30
- # ToDo: realize this method
28
+ def output(var, port: nil, pin: nil)
29
+ RubimCode.init_io(self.class, 'output', var, port: port, pin: pin)
30
+ end
31
+
31
32
  def input (var, port: nil, pin: nil)
33
+ RubimCode.init_io(self.class, 'input', var, port: port, pin: pin)
32
34
  end
33
35
 
34
36
 
@@ -39,28 +41,55 @@ class RubimCode
39
41
  def rubim_tbit(var, bit); "#{var} ^= 1<<#{bit};"; end
40
42
  end # class << self
41
43
 
42
- class UserOutput
44
+ class UserIO
43
45
  attr_accessor :name, :port, :pin, :type
44
46
 
45
47
  def initialize(name, port: nil, pin: nil, type: "normal")
48
+ # ToDo: check type of params:
49
+ # name, port - only symbol
50
+ # pin - only UserVariable with type 'fixed' (feature: pin can receive also instance vars: @pin_num)
51
+ # type - only 'normal' (feature: realize 'tri-state' type)
46
52
  @name = name.to_s
47
53
  @port = port.to_s
48
- @pin = pin.to_s
54
+ @pin = pin.name.to_s
49
55
  @type = type.to_s
50
- RubimCode.pout (RubimCode.rubim_sbit("DDR#{port}", "#{pin}"))
51
56
  end
57
+ end # end UserIO class
58
+
59
+ class UserOutput < UserIO
60
+ def initialize(name, port: nil, pin: nil, type: "normal")
61
+ super
62
+ RubimCode.pout(RubimCode.rubim_sbit("DDR#{port}", "#{pin}") + " /* #{self.name} configure as output */ ")
63
+ end
64
+
52
65
 
53
66
  def on
54
- RubimCode.pout (RubimCode.rubim_sbit("PORT#{port}", "#{pin}"))
67
+ RubimCode.pout(RubimCode.rubim_sbit("PORT#{port}", "#{pin}") + " /*#{self.name}.#{__method__}*/")
55
68
  end
56
69
 
57
70
  def off
58
- RubimCode.pout (RubimCode.rubim_cbit("PORT#{port}", "#{pin}"))
71
+ RubimCode.pout(RubimCode.rubim_cbit("PORT#{port}", "#{pin}") + " /*#{self.name}.#{__method__}*/")
59
72
  end
60
73
 
61
74
  def toggle
62
- RubimCode.pout (RubimCode.rubim_tbit("PORT#{port}", "#{pin}"))
75
+ RubimCode.pout(RubimCode.rubim_tbit("PORT#{port}", "#{pin}") + " /*#{self.name}.#{__method__}*/")
63
76
  end
64
- end
77
+ end # end UserInput class
78
+
79
+ class UserInput < UserIO
80
+ def initialize(name, port: nil, pin: nil, type: "normal")
81
+ super
82
+ RubimCode.pout(RubimCode.rubim_cbit("DDR#{port}", "#{pin}") + " /* #{self.name} configure as output */ ")
83
+ end
84
+
85
+
86
+ def hi?
87
+ "bit_is_set(PORT#{port}, #{pin})" + " /*#{self.name}.#{__method__}*/"
88
+ end
89
+
90
+ def low?
91
+ "bit_is_clear(PORT#{port}, #{pin})" + " /*#{self.name}.#{__method__}*/"
92
+ end
93
+ end # end UserOutput class
65
94
 
66
- end # RubimCode class
95
+ end # end RubimCode class
@@ -8,7 +8,7 @@ class AVR_attiny13 < AVRController
8
8
  true
9
9
  end
10
10
 
11
- def micro_layout
11
+ def mcu_layout
12
12
  # ToDo: set F_CPU from user programm
13
13
  RubimCode.pout "#define __AVR_ATtiny13__ 1"
14
14
  RubimCode.pout "#define F_CPU 1000000UL" # Microcontroller frequency (Hz)
@@ -56,19 +56,19 @@ class AVR_attiny13 < AVRController
56
56
  refs0 = case options[:ref] # источник опорного напряжения
57
57
  when "vcc" then 0
58
58
  when "internal" then 1
59
- else perror "Undefined value for option :ref in method '#{__method__}'"
59
+ else RubimCode.perror "Undefined value for option :ref in method '#{__method__}'"
60
60
  end
61
61
 
62
62
  adlar = case "right" # options[:result_adjust] # выравнивание результата вычислений всегда по правому краю
63
63
  when "left" then 1
64
64
  when "right" then 0
65
- else perror "Undefined value for option :result_adjust in method '#{__method__}'"
65
+ else RubimCode.perror "Undefined value for option :result_adjust in method '#{__method__}'"
66
66
  end
67
67
 
68
68
  channel = options[:channel]
69
69
  unless channel.in? [ADC0, ADC1, ADC2, ADC3]
70
70
  RubimCode.pout channel
71
- perror "Undefined value for option :channel in method '#{__method__}'"
71
+ RubimCode.perror "Undefined value for option :channel in method '#{__method__}'"
72
72
  end
73
73
 
74
74
  RubimCode.pout("ADMUX = (#{refs0}<<REFS0) | (#{adlar}<<ADLAR) | #{channel};")
@@ -77,7 +77,7 @@ class AVR_attiny13 < AVRController
77
77
  adate = case options[:auto_triggering] # одиночное преобразование или множественное
78
78
  when "enable" then 1
79
79
  when "disable" then 0
80
- else perror "Undefined value for option :auto_triggering in method '#{__method__}'"
80
+ else RubimCode.perror "Undefined value for option :auto_triggering in method '#{__method__}'"
81
81
  end
82
82
 
83
83
  # adif = ? # ToDo: ADC Interrupt Flag
@@ -92,7 +92,7 @@ class AVR_attiny13 < AVRController
92
92
  when 32 then 5
93
93
  when 64 then 6
94
94
  when 128 then 7
95
- else perror "Undefined value for option :prescale in method '#{__method__}'"
95
+ else RubimCode.perror "Undefined value for option :prescale in method '#{__method__}'"
96
96
  end
97
97
 
98
98
  RubimCode.pout ("ADCSRA = (1<<ADEN) | (#{adate}<<ADATE) | (#{adps}<<ADPS0) | (#{adie}<<ADIE);")
@@ -106,7 +106,7 @@ class AVR_attiny13 < AVRController
106
106
  # ToDo: должен возвращать значение, реализовать как С-функцию
107
107
  # ToDo: можно использовать ленивую загрузку Ruby - autoload
108
108
  unless channel.in? [ADC0, ADC1, ADC2, ADC3, nil]
109
- perror "Undefined value for option :channel in method '#{__method__}'"
109
+ RubimCode.perror "Undefined value for option :channel in method '#{__method__}'"
110
110
  end
111
111
 
112
112
  unless channel.nil?
@@ -127,15 +127,16 @@ class AVR_attiny13 < AVRController
127
127
  end
128
128
 
129
129
  def self.interrupt(**options, &block)
130
+
130
131
  options.permit_and_default!(enabled: false)
131
132
  # if is_enabled && block.nil? # ToDo: проверить на наличие блока если прерывание активно
132
133
  # perror "method #{__method__} mast have a block"
133
134
  # end
134
135
 
135
- adie = case options[:enabled] # ADC Interrupt Enable
136
+ adie = case options[:enabled].to_bool # ADC Interrupt Enable
136
137
  when true then 1
137
138
  when false then 0
138
- else perror "Undefined value for option :is_enabled in method '#{__method__}'"
139
+ else RubimCode.perror "Undefined value for option :enabled in method '#{__method__}'"
139
140
  end
140
141
  if adie == 0 # if interrupt disabled
141
142
  RubimCode.pout "Start continuously ADC convert"
@@ -146,10 +147,10 @@ class AVR_attiny13 < AVRController
146
147
  # RubimCode.pout ("sei();") # automatically set (is it?)
147
148
  end
148
149
 
149
- # Genetare Interrupt code
150
+ # Generate Interrupt code
150
151
  if block_given?
151
152
  interrupt_code = "" # Write code in variable "interrupt_code"
152
- RubimCode.pout_destination = interrupt_code
153
+ RubimCode::Printer.pout_destination = interrupt_code
153
154
  old_level = RubimCode.level
154
155
  RubimCode.level = 0
155
156
 
@@ -160,12 +161,15 @@ class AVR_attiny13 < AVRController
160
161
  # ToDo - надо точно разобраться с выравниванием
161
162
  # (see above in convert method)
162
163
  RubimCode.pout "int __rubim__volt = ADCL + ((ADCH&0b11) << 8);"
163
- yield (RubimCode::UserVariable.new("__rubim__volt", "int"))
164
+ RubimCode::Isolator.outside_binding = block.binding
165
+ RubimCode::Isolator.run
166
+ yield(RubimCode::UserVariable.new("__rubim__volt", "tmp_int"))
167
+ RubimCode::Isolator.stop
164
168
  RubimCode.level -= 1
165
169
  RubimCode.pout ("}")
166
170
 
167
171
  RubimCode.level = old_level
168
- RubimCode.pout_destination = :default
172
+ RubimCode::Printer.pout_destination = :default
169
173
  RubimCode::Interrupts.add(interrupt_code)
170
174
  end
171
175
  end # interrupt method
@@ -173,4 +177,5 @@ class AVR_attiny13 < AVRController
173
177
  end # ANALOG_TO_DIGITAL Class
174
178
 
175
179
 
176
- end # RubimCode class
180
+ end # RubimCode class
181
+
@@ -1,16 +1,6 @@
1
1
  class AVRController < Controllers
2
2
  MCU_SERIES = "AVR"
3
-
4
- def self.print_layout(position)
5
- if position == :before_main
6
- print_cc_layout(:before_main) do
7
- micro_layout # prints includes for current microcontroller
8
- end
9
- elsif position == :after_main
10
- print_cc_layout(:after_main)
11
- end
12
- end
13
3
  end
14
4
 
15
- # ToDO: add all folder 'avr'
5
+ # ToDo: add all folder 'avr'
16
6
  require 'rubimc/mcu/avr/attiny13'
@@ -51,7 +51,7 @@ class RubimRipper
51
51
  if (ident.in? [:on_int, :on_float])
52
52
  bug_plus = (symb[0]=="+" ? "+" : "")
53
53
  # Note: space before "UserVariable" is neсessary
54
- source = replace_words(source, symb, "#{bug_plus} RubimCode::UserVariable.new(#{symb})", pos)
54
+ source = replace_words(source, symb, "#{bug_plus} RubimCode::UserVariable.new(#{symb}, 'fixed')", pos)
55
55
  end
56
56
  end
57
57
  return source
@@ -127,18 +127,22 @@ class RubimRipper
127
127
  end
128
128
 
129
129
  def self.replace_boolean_kw(source)
130
- source = replace_keywords(source, "true", "UserVariable.new(true)")
131
- source = replace_keywords(source, "false", "UserVariable.new(false)")
130
+ source = replace_keywords(source, "true", "RubimCode::UserVariable.new(true, 'fixed')")
131
+ source = replace_keywords(source, "false", "RubimCode::UserVariable.new(false, 'fixed')")
132
132
  return source
133
133
  end
134
134
 
135
135
  def self.add_binding_to_init(source) # for initialize variables with methods 'integer', 'float', e.t.
136
+ helpers_array = ["boolean", "bool", "integer", "int", "float", "double"]
137
+ helpers_array += ["string"]
138
+ helpers_array += ["output", "input"]
139
+
136
140
  sexp = Ripper.sexp(source)
137
141
  command_array = find_rec(sexp, :command)
138
142
  command_array.reverse_each do |elem|
139
143
  varies_name = []
140
144
  symb, helper_name, helper_pos = elem[1]
141
- if helper_name.in? ["integer", "float", "string"] # if one of helper methods
145
+ if helper_name.in? helpers_array # if one of helper methods
142
146
  args_add_block = find_rec(elem, :args_add_block)[0][1]
143
147
  args_add_block.each do |arg|
144
148
  if arg[0] == :symbol_literal
@@ -157,6 +161,7 @@ class RubimRipper
157
161
  raise ArgumentError.new("Wrong arguments for helper '#{helper_name}'")
158
162
  end
159
163
  end
164
+ varies_name = [varies_name[0]] if helper_name.in? ['output', 'input']
160
165
  var_str = varies_name.join(', ') # list of vars, defined in helper method
161
166
  source = paste_before_pos(source, "#{var_str} = ", helper_pos) # paste vars before helper method
162
167
  end
@@ -164,6 +169,12 @@ class RubimRipper
164
169
  return source
165
170
  end
166
171
 
172
+ def self.replace_instructions(source)
173
+ source = replace_keywords(source, "next", "RubimCode.rubim_next")
174
+ source = replace_keywords(source, "break", "RubimCode.rubim_break")
175
+ return source
176
+ end
177
+
167
178
  #########################
168
179
  # === PRIVATE SECTION ===
169
180
  #########################
@@ -232,7 +243,7 @@ class RubimRipper
232
243
  raise "can not find near position in array #{array}"
233
244
  end
234
245
 
235
- # Поиск позиции наиболее дальнего идентификатора справа
246
+ # Поиск позиции наиболее дальнего идентификатора справа (рекурсивно)
236
247
  def self.find_far_pos(array)
237
248
  array.reverse_each do |el|
238
249
  if el.is_a? Array # если найден идентификатор, указывающий на позицию
@@ -288,10 +299,10 @@ class PreProcessor
288
299
 
289
300
  def self.execute(str)
290
301
  @@program = str
302
+
303
+ # Последовательность очень важна - не нарушать!
291
304
  @@program = RubimRipper.replace_assing_operators(@@program)
292
305
  @@program = RubimRipper.replace_all_numeric(@@program)
293
-
294
- # Последовательность очень важна - не нарушать!
295
306
  @@program = RubimRipper.replace_then_else_elsif_kw(@@program)
296
307
 
297
308
  @@program = RubimRipper.replace_modify_express(@@program, "if")
@@ -308,47 +319,15 @@ class PreProcessor
308
319
  @@program = RubimRipper.replace_rubim_tmpif(@@program)
309
320
 
310
321
  @@program = RubimRipper.add_binding_to_init(@@program)
311
-
312
- # @@program = RubimRipper.replace_boolean_kw(@@program)
313
-
314
-
315
- # See
316
- # p defined?(x = 1) # => "assignment"
317
- # p defined?(x[5] = 1) # => "method"
318
- # p defined?(x[5] += 1) # => "method"
319
-
320
- # --- OLD VERSION, BASED ON REGEXP ---
321
- # убрать пробелы между всеми односимвольными операторами (кроме оператора ":")
322
- # operators = "\\+\\-\\*\\/\\^\\!\\=\\~\\?\\:\\%\\|\\&"
323
- # @@program.gsub!(/\ *?([#{operators}&&[^\:]])\ ?/, '\1')
324
-
325
- # замена оператора "=" на ".c_assign=" (только перед переменными)
326
- # ch = "a-zA-Z"
327
- # @@program.gsub!(/(^|[^#{ch}\.])([#{ch}\d]+)=([^\=\~])/, '\1\2.c_assign=\3')
328
-
329
- # замена всех цифр(Fixnum), после которых идут операторы, на UserVariable.new()
330
- # @@program.gsub!(/(^|[^\w])([-+]?\d*\.?\d+)([#{operators}&&[^\=]])/, '\1UserVariable.new(\2)\3')
331
- # замена всех цифр(Fixnum), после которых идет указание метода, на UserVariable.new()
332
- # @@program.gsub!(/(^|[^\w])(\d+)(\.[\w&&[^\d]])/, '\1UserVariable.new(\2)\3')
322
+ @@program = RubimRipper.replace_instructions(@@program) # next/break
323
+ @@program = RubimRipper.replace_boolean_kw(@@program) # true/false
333
324
  end
334
325
 
335
326
 
336
327
  # write preprocessing program in file
337
328
  def self.write_in_file(input_file, dirname, basename, outfile)
338
- # basename = File.basename(input_file)
339
- # dirname = File.dirname(input_file)
340
- # outfile = "#{dirname}/release"
341
-
342
- # # clear directory "release"
343
- # Dir.mkdir(outfile) unless Dir.exists?(outfile)
344
- # Dir.foreach(outfile) do |file|
345
- # File.delete("#{outfile}/#{file}") if (file!='.' && file!='..')
346
- # end
347
-
348
329
  PreProcessor.execute( File.read(input_file) )
349
330
  File.write("#{outfile}", PreProcessor.program)
350
-
351
- print "done\n"
352
331
  end
353
332
 
354
333
  end
@@ -16,13 +16,11 @@ end
16
16
 
17
17
  class RubimCode
18
18
  class << self
19
-
20
19
  attr_accessor :level
21
- def level
22
- @level = 0 if @level.nil?
23
- @level
24
- end
20
+ end
21
+ @level = 0
25
22
 
23
+ class << self
26
24
  def perror(error_message)
27
25
  if error_message.nil? or error_message.to_s.nil?
28
26
  raise ArgumentError, "error message is not string"
@@ -32,7 +30,7 @@ class << self
32
30
  code_ptr = caller_locations(2)
33
31
  code_ptr.each do |place|
34
32
  place = place.to_s
35
- place.gsub!(/^release\/pre_/, '')
33
+ place.gsub!(/\/release\//, '/')
36
34
  error_message += "\tfrom #{place}\n"
37
35
  end
38
36
  puts "#ERROR: #{error_message}"
@@ -47,31 +45,22 @@ class << self
47
45
  else
48
46
  @level = 0 if @level.nil?
49
47
  res_str = " "*4*@level + str.to_s
50
- if (($pout_destination == :default) or ($pout_destination.nil?))
48
+ if RubimCode::Printer.pout_destination.in? [:default, nil]
51
49
  puts res_str
52
50
  unless defined? TEST_MODE
53
51
  File.open("#{ARGV[0]}", 'a+') {|file| file.puts(res_str) }
54
52
  end
53
+ elsif RubimCode::Printer.pout_destination == :h_file
54
+ unless defined? TEST_MODE
55
+ h_name = ARGV[0].gsub(/\.c$/, '') + ".h"
56
+ File.open("#{h_name}", 'a+') {|file| file.puts(res_str) }
57
+ end
55
58
  else
56
- $pout_destination.concat(res_str).concat("\n")
59
+ RubimCode::Printer.pout_destination.concat(res_str).concat("\n")
57
60
  end
58
61
  end
59
62
  end
60
63
 
61
- # ToDo: remove to RubimCode::Printer
62
- $pout_destination = :default
63
- def pout_destination=(dest)
64
- if dest.nil?
65
- perror "Wrong parameter for method #{__method__}. Set destination string"
66
- end
67
-
68
- if dest.class.name == "String" or dest == :default # dest.is_a? not work...WTF
69
- $pout_destination = dest
70
- else
71
- perror "Wrong parameter for method #{__method__}. Only string variable or ':default' value is permit as a parameters"
72
- end
73
- end
74
-
75
64
  def clear_c(str)
76
65
  pout "// generate with clear_c function"
77
66
  pout str
@@ -87,6 +76,27 @@ class RubimCode::Printer
87
76
  attr_accessor :sandbox
88
77
  end
89
78
 
79
+ @@instance_vars_cc = []
80
+ def self.instance_vars_cc
81
+ @@instance_vars_cc
82
+ end
83
+
84
+ @@pout_destination = :default
85
+ def self.pout_destination
86
+ @@pout_destination
87
+ end
88
+ def self.pout_destination=(dest)
89
+ if dest.nil?
90
+ perror "Wrong parameter for method #{__method__}. Set destination string"
91
+ end
92
+
93
+ if dest.class.name == "String" or dest.in? [:default, :h_file] # dest.is_a?(String) not work...WTF
94
+ @@pout_destination = dest
95
+ else
96
+ perror "Wrong parameter for method #{__method__}. Only string variable or ':default' value is permit as a parameters"
97
+ end
98
+ end
99
+
90
100
  def self.code_type
91
101
  if not Controllers.all.empty?
92
102
  "avr-gcc"
@@ -101,6 +111,41 @@ class RubimCode::Printer
101
111
  code_type == "avr-gcc" ? Controllers.all.first::MCU_NAME : "undefined"
102
112
  end
103
113
 
114
+ def self.print_layout(position, &mcu_layout)
115
+ return if RubimCode::Printer.sandbox == true # don`t print output in sandbox
116
+ h_name = File.basename(ARGV[0], '.c') + '.h'
117
+ if position == :before_main
118
+ RubimCode::Printer.pout_destination = :h_file
119
+ RubimCode.pout "/**************************************************************"
120
+ RubimCode.pout " * This code was generated by RubimC micro-framework"
121
+ RubimCode.pout " * Include file for \"#{ARGV[0]}\""
122
+ RubimCode.pout " **************************************************************/"
123
+
124
+ RubimCode::Printer.pout_destination = :default
125
+ RubimCode.pout "/**************************************************************"
126
+ RubimCode.pout " * This code was generated by RubimC micro-framework"
127
+ RubimCode.pout " * RubimC version: #{RubimCode::VERSION}"
128
+ RubimCode.pout " * RubimC author: Evgeny Danilov"
129
+ RubimCode.pout " * File created at #{Time.now}"
130
+ RubimCode.pout " **************************************************************/"
131
+ RubimCode.pout
132
+ RubimCode.pout "#include <stdbool.h>"
133
+ RubimCode.pout "#include <stdio.h>"
134
+ RubimCode.pout
135
+ yield if block_given? # print includes for current MCU (see mcu libraries)
136
+ RubimCode.pout
137
+ RubimCode.pout "#include \"#{h_name}\""
138
+ RubimCode.pout
139
+ RubimCode.pout "int main(int argc, char *argv[]) {"
140
+ RubimCode.level += 1
141
+ else
142
+ RubimCode.pout
143
+ RubimCode.pout "return 1;"
144
+ RubimCode.level -= 1
145
+ RubimCode.pout "}"
146
+ end
147
+ end
148
+
104
149
  def self.print_main_loop
105
150
  RubimCode.pout
106
151
  RubimCode.pout "// === Main Infinite Loop === //"
@@ -111,25 +156,38 @@ class RubimCode::Printer
111
156
  RubimCode.pout"} // end main loop"
112
157
  end
113
158
 
159
+ def self.print_instance_vars
160
+ RubimCode::Printer.pout_destination = :h_file
161
+ @@instance_vars_cc.each do |var|
162
+ if var.is_a? RubimCode::UserVariable
163
+ RubimCode.pout "#{var.type} #{var.name};"
164
+ end
165
+ end
166
+ RubimCode::Printer.pout_destination = :default
167
+ end
168
+
114
169
  def self.generate_cc
115
170
  if Controllers.all.count > 1
116
171
  RubimCode.perror "In current version in one file you can define only one Controller Class"
117
172
  end
118
173
 
119
174
  if self.code_type == "avr-gcc" # if compile program for MCU
120
- Controllers.all.each do |controllerClass|
121
- controllerClass.print_layout(:before_main)
122
- controller = controllerClass.new # print initialize section
123
- print_main_loop {controller.main_loop} # print body of main loop
124
- controllerClass.print_layout(:after_main)
125
- RubimCode::Interrupts.print
175
+ Controllers.all.each do |mcu_class|
176
+ print_layout(:before_main) do
177
+ mcu_class.mcu_layout if mcu_class.respond_to? :mcu_layout
178
+ end
179
+ mcu = mcu_class.new # print initialize section
180
+ print_main_loop {mcu.main_loop} # print body of main loop
181
+ print_layout(:after_main)
182
+ RubimCode::Interrupts.print()
183
+ RubimCode::Printer.print_instance_vars()
126
184
  end # each Controllers.all
127
185
 
128
- elsif self.code_type == "gcc" # if compile clear-C program
186
+ elsif self.code_type == "gcc" # if compile clear-C program
129
187
  if Controllers.all.empty? and eval("self.private_methods.include? :main")
130
- Controllers.print_cc_layout(:before_main)
131
- eval("main(RubimCode::CC_ARGS.new)") # execute method :main (CC_ARGS - helper for C agruments argc/argv)
132
- Controllers.print_cc_layout(:after_main)
188
+ print_layout(:before_main)
189
+ eval("main(RubimCode::CC_ARGS.new)") # execute user`s method :main (CC_ARGS - helper for C agruments argc/argv)
190
+ print_layout(:after_main)
133
191
  end
134
192
  end
135
193
  end
@@ -16,7 +16,7 @@ class Object
16
16
  else nil
17
17
  end
18
18
  if type.nil? or self.to_s.nil?
19
- perror "Неизвестный тип переменной"
19
+ RubimCode.perror "Неизвестный тип переменной"
20
20
  end
21
21
  UserVariable.new(self.to_s, type)
22
22
  end
@@ -1,3 +1,3 @@
1
1
  class RubimCode
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubimc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeny Danilov
@@ -53,8 +53,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
53
  version: '0'
54
54
  requirements: []
55
55
  rubyforge_project:
56
- rubygems_version: 2.4.5
56
+ rubygems_version: 2.4.8
57
57
  signing_key:
58
58
  specification_version: 4
59
- summary: 'RubimC: Framework for MCU - 0.2.1'
59
+ summary: 'RubimC: Framework for MCU - 0.2.2'
60
60
  test_files: []