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.
@@ -0,0 +1,143 @@
1
+ def print_comment(comment)
2
+ comment.lines.each do |line|
3
+ RubimCode.pout "// #{line}"
4
+ end
5
+ end
6
+
7
+ def printf(str, *args)
8
+ if args.empty?
9
+ RubimCode.pout("printf(#{str.dump});")
10
+ else
11
+ args_str = args.join(', ')
12
+ RubimCode.pout("printf(#{str.dump}, #{args_str});")
13
+ end
14
+ end
15
+
16
+
17
+ class RubimCode
18
+ class << self
19
+
20
+ attr_accessor :level
21
+ def level
22
+ @level = 0 if @level.nil?
23
+ @level
24
+ end
25
+
26
+ def perror(error_message)
27
+ if error_message.nil? or error_message.to_s.nil?
28
+ raise ArgumentError, "error message is not string"
29
+ end
30
+
31
+ error_message += "\n"
32
+ code_ptr = caller_locations(2)
33
+ code_ptr.each do |place|
34
+ place = place.to_s
35
+ place.gsub!(/^release\/pre_/, '')
36
+ error_message += "\tfrom #{place}\n"
37
+ end
38
+ puts "#ERROR: #{error_message}"
39
+ exit 1
40
+ end
41
+
42
+ def pout(str = "")
43
+ return if RubimCode::Printer.sandbox == true # don`t print output in sandbox
44
+
45
+ if str.nil? or str.to_s.nil?
46
+ raise ArgumentError, "str is nil"
47
+ else
48
+ @level = 0 if @level.nil?
49
+ res_str = " "*4*@level + str.to_s
50
+ if (($pout_destination == :default) or ($pout_destination.nil?))
51
+ puts res_str
52
+ unless defined? TEST_MODE
53
+ File.open("#{ARGV[0]}", 'a+') {|file| file.puts(res_str) }
54
+ end
55
+ else
56
+ $pout_destination.concat(res_str).concat("\n")
57
+ end
58
+ end
59
+ end
60
+
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
+ def clear_c(str)
76
+ pout "// generate with clear_c function"
77
+ pout str
78
+ pout "// end clear_c function"
79
+ end
80
+
81
+
82
+ end # class << self
83
+ end # RubimCode class
84
+
85
+ class RubimCode::Printer
86
+ class << self
87
+ attr_accessor :sandbox
88
+ end
89
+
90
+ def self.code_type
91
+ if not Controllers.all.empty?
92
+ "avr-gcc"
93
+ elsif Controllers.all.empty? and eval("self.private_methods.include? :main")
94
+ "gcc"
95
+ else
96
+ RubimCode.perror "Can not to define type of code"
97
+ end
98
+ end
99
+
100
+ def self.mcu_type
101
+ code_type == "avr-gcc" ? Controllers.all.first::MCU_NAME : "undefined"
102
+ end
103
+
104
+ def self.print_main_loop
105
+ RubimCode.pout
106
+ RubimCode.pout "// === Main Infinite Loop === //"
107
+ RubimCode.pout "while (true) {"
108
+ RubimCode.level += 1
109
+ yield # print body of main loop
110
+ RubimCode.level -= 1
111
+ RubimCode.pout"} // end main loop"
112
+ end
113
+
114
+ def self.generate_cc
115
+ if Controllers.all.count > 1
116
+ RubimCode.perror "In current version in one file you can define only one Controller Class"
117
+ end
118
+
119
+ 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
126
+ end # each Controllers.all
127
+
128
+ elsif self.code_type == "gcc" # if compile clear-C program
129
+ 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)
133
+ end
134
+ end
135
+ end
136
+
137
+ END { # execute when user`s program is end
138
+ exit 0 if defined? TEST_MODE
139
+ exit 0 if sandbox == true
140
+ self.generate_cc
141
+ exit 0
142
+ }
143
+ end
@@ -0,0 +1,54 @@
1
+ class Object
2
+ def not_nil?
3
+ !self.nil?
4
+ end
5
+
6
+ def has_parent?(name)
7
+ return false unless self.respond_to? :ancestors
8
+ self!=name and self.ancestors.include?(name)
9
+ end
10
+
11
+ def to_rubim
12
+ type = case self.class.name
13
+ when "Fixnum" then 'int'
14
+ when "Float" then 'float'
15
+ when "String" then 'string'
16
+ else nil
17
+ end
18
+ if type.nil? or self.to_s.nil?
19
+ perror "Неизвестный тип переменной"
20
+ end
21
+ UserVariable.new(self.to_s, type)
22
+ end
23
+
24
+ def in?(array)
25
+ array.each {|el| return true if el == self}
26
+ return false
27
+ end
28
+
29
+ end
30
+
31
+ class Class
32
+ # get list of all childs inhereted from self class
33
+ def descendants
34
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
35
+ end # see alternative realization: http://apidock.com/rails/Class/descendants
36
+ end
37
+
38
+ class Hash
39
+ def permit_and_default! (**args)
40
+ self.keys.each do |param|
41
+ if not args.keys.include? param
42
+ mname = caller_locations(1)[2].label
43
+ perror "Method '#{mname}' have no param: #{param}}"
44
+ end
45
+ end
46
+
47
+ args.keys.each do |param|
48
+ self[param] = args[param] if self[param].nil?
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+
data/lib/rubimc.rb ADDED
@@ -0,0 +1,234 @@
1
+ #####################################################################
2
+ # RubimCode CORE #
3
+ # #
4
+ # Author: Evgeny Danilov #
5
+ # Created at 2016 March-14 #
6
+ #####################################################################
7
+ class RubimCode; end
8
+
9
+ require "version"
10
+ require "rubimc/ruby_classes"
11
+
12
+ require "rubimc/io_ports"
13
+ require "rubimc/controllers"
14
+ require "rubimc/mcu/avr/avr_controller"
15
+
16
+ require "rubimc/printer"
17
+ require "rubimc/init_var"
18
+ require "rubimc/control_structures"
19
+
20
+ class RubimCode
21
+
22
+ class UserVariable
23
+ attr_accessor :name, :type
24
+ # attr_accessor :level # ToDo: для указания области видимости
25
+ def initialize(name, type = "undefined")
26
+ @name, @type = name.to_s, type.to_s
27
+ end
28
+
29
+ def to_s
30
+ "(" + self.name + ")"
31
+ end
32
+
33
+ def to_i
34
+ @name.to_i
35
+ end
36
+
37
+ def to_rubim
38
+ self
39
+ end
40
+
41
+ def c_assign=(val)
42
+ RubimCode.pout "#{@name} = #{val};"
43
+ end
44
+
45
+ def common_operator(val, operator_sym)
46
+ if not val.class.respond_to? :to_s
47
+ RubimCode.perror "Conversion of variable #{val} is impossible. Method 'to_s' not found"
48
+ else
49
+ UserVariable.new(self.name + operator_sym.to_s + val.to_s)
50
+ end
51
+ end
52
+
53
+ # Arithmetic Operators:
54
+ def +(val); common_operator(val, __method__); end
55
+ def -(val); common_operator(val, __method__); end
56
+ def *(val); common_operator(val, __method__); end
57
+ def /(val); common_operator(val, __method__); end
58
+ def %(val); common_operator(val, __method__); end
59
+ def **(val);common_operator(val, __method__); end
60
+
61
+ # Operators +=, -=, e.t.
62
+ # ToDo: (can not override; use preprocessor)
63
+
64
+ # 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
69
+
70
+ # 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
77
+
78
+ # Binary Operators:
79
+ def &(val); common_operator(val, __method__); end
80
+ def |(val); common_operator(val, __method__); end
81
+ def ^(val); common_operator(val, __method__); end
82
+ def <<(val); common_operator(val, __method__); end
83
+ def >>(val); common_operator(val, __method__); end
84
+
85
+ # Logical Operators: (and, or, not, &&, ||)
86
+ # can not override, use preprocessor
87
+
88
+ # Ternary Operators: (? :)
89
+ # ToDo...
90
+
91
+ # Ruby Parallel Assignment:
92
+ # a, b, c = 10, 20, 30 # ToDo
93
+
94
+ # ToDo: операторы, которым нет аналогов в Си
95
+ # def <=>(val); ??? end
96
+ # def ===(val); ??? end
97
+ # def =~(val); ??? end
98
+ # def !~(val); ??? end
99
+
100
+ # Range-operators ".." and "..."
101
+ # ToDo: is it need? or use Enumerator?
102
+
103
+ def times
104
+ n = LoopCounter.new
105
+ RubimCode.pout ("for (int #{n}=0; #{n}<#{self}; #{n}++) {")
106
+ RubimCode.level += 1
107
+ yield(n)
108
+ RubimCode.pout ("}")
109
+ RubimCode.level -= 1
110
+ end
111
+
112
+ # ToDo: add mixins Enumerable and Comparable
113
+ end
114
+
115
+ # ToDo: в Ruby присваивание значений индексной переменной
116
+ # не должно влиять на выполнение цикла
117
+ # например следующий цикл будет выполнен ровно 10 раз
118
+ # for var in 1..10; var = var+2; end
119
+ class LoopCounter < UserVariable
120
+ def initialize
121
+ name = "i" + RubimCode.level.to_s
122
+ # ToDo - вместо "i" - __rubim__i
123
+ super(name)
124
+ end
125
+
126
+ def to_s
127
+ self.name
128
+ end
129
+ end
130
+
131
+ class UserArray < Array
132
+ attr_accessor :name, :type
133
+
134
+ def []=(index, val)
135
+ RubimCode.pout "#{@name}[#{index.to_i}] = #{val.to_s};"
136
+ end
137
+
138
+ def [](index)
139
+ super index.to_i
140
+ end
141
+
142
+ def each
143
+ n = LoopCounter.new
144
+ RubimCode.pout "for (int #{n}=0; #{n}<#{self.size}; #{n}++) {"
145
+ RubimCode.level +=1
146
+ joy_name = self.name + "[#{n}]"
147
+ yield(self[0].class.new("#{joy_name}"))
148
+ RubimCode.level -=1
149
+ RubimCode.pout "}"
150
+ end
151
+ end
152
+
153
+ # Наследник всех пользовательских классов
154
+ class UserClass < UserVariable
155
+
156
+ # список всех пользовательских "свойств" класса
157
+ @@var_array = {}
158
+ def self.add_var_array(user_class_name, value)
159
+ @@var_array[user_class_name.to_sym] ||= []
160
+ @@var_array[user_class_name.to_sym] << value
161
+ end
162
+
163
+ # генерация класса (typedef struct + методы)
164
+ def self.generate_struct
165
+ RubimCode.pout "typedef struct {"
166
+ RubimCode.level +=1
167
+ @@var_array[self.to_s.to_sym].each do |var|
168
+ RubimCode.pout "#{var.type} #{var.name};"
169
+ end
170
+ RubimCode.pout "} #{self.to_s};"
171
+ RubimCode.level -=1
172
+
173
+ public_instance_methods(false).each do |method_name|
174
+ tmp_str = ""
175
+ pout_destination = tmp_str
176
+ return_var = self.new("(*params)").send(method_name).to_rubim
177
+ pout_destination = :default
178
+ return_var.type = "void" if return_var.type.nil? # if type is not set
179
+
180
+ RubimCode.pout "#{return_var.type} #{method_name.to_s} (#{self.to_s} *params) {"
181
+ RubimCode.level += 1
182
+ self.new("(*params)").send(method_name)
183
+ RubimCode.pout "return #{return_var};"
184
+ RubimCode.pout "}"
185
+ RubimCode.level -= 1
186
+ end
187
+ end
188
+
189
+ def self.redefine_users_methods
190
+ public_instance_methods(false).each do |method_name|
191
+ define_method(method_name) do
192
+ "#{__method__}(&#{self.name})"
193
+ end
194
+ end
195
+ end
196
+
197
+ end
198
+
199
+ # Список аппаратных прерываний (содержит Си-код в текстовом виде)
200
+ class Interrupts
201
+ @@interrupt_array = []
202
+
203
+ def self.array
204
+ @@interrupt_array
205
+ end
206
+
207
+ def self.add(val)
208
+ if val.class.name == "String"
209
+ @@interrupt_array << val
210
+ else
211
+ RubimCode.perror "wrong params in method #{__method__}"
212
+ end
213
+ end
214
+
215
+ def self.print
216
+ @@interrupt_array.each do |interrupt_code|
217
+ RubimCode.pout interrupt_code
218
+ end
219
+ end
220
+ end
221
+
222
+ class CC_ARGS # class for arguments when work with clear C-code
223
+ def count
224
+ RubimCode::UserVariable.new("argc", "int")
225
+ end
226
+
227
+ def [](index)
228
+ RubimCode::UserVariable.new("argv[#{index}]", "int")
229
+ end
230
+ end
231
+
232
+ end
233
+ # === END class RubimCode === #
234
+
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ class RubimCode
2
+ VERSION = "0.2.1"
3
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubimc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Evgeny Danilov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-27 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby compiler and framework for microcontrollers like AVR, PIC & STM.
14
+ It was designed to simplify the process of programming microcontrollers, but can
15
+ also be used as an clear С-code generator that can be compiled with gcc
16
+ email: jmelkor@rambler.ru
17
+ executables:
18
+ - rubimc
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - LICENSE.md
23
+ - README.md
24
+ - bin/rubimc
25
+ - lib/rubimc.rb
26
+ - lib/rubimc/control_structures.rb
27
+ - lib/rubimc/controllers.rb
28
+ - lib/rubimc/init_var.rb
29
+ - lib/rubimc/io_ports.rb
30
+ - lib/rubimc/mcu/avr/attiny13.rb
31
+ - lib/rubimc/mcu/avr/avr_controller.rb
32
+ - lib/rubimc/preprocessor.rb
33
+ - lib/rubimc/printer.rb
34
+ - lib/rubimc/ruby_classes.rb
35
+ - lib/version.rb
36
+ homepage: https://github.com/jmelkor/RubimC
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 2.4.5
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: 'RubimC: Framework for MCU - 0.2.1'
60
+ test_files: []