class RubimCode

RubimCode CORE #

#

Author: Evgeny Danilov # Created at 2016 March-14 #

Constants

VERSION

Attributes

level[RW]

Public Class Methods

clear_c(str) click to toggle source
# File lib/rubimc/printer.rb, line 64
def clear_c(str)
        pout "// generate with clear_c function"
        pout str
        pout "// end clear_c function"
end
init_io(mcu_class, rb_type, var, port: nil, pin: nil, type: "normal") click to toggle source
# File lib/rubimc/io_ports.rb, line 1
def RubimCode.init_io(mcu_class, rb_type, var, port: nil, pin: nil, type: "normal")
        if port.nil? or pin.nil?
                RubimCode.perror "Необходимо указать порт и пин для выхода #{var}"
        elsif not mcu_class::PORTS.include? port.to_sym
                RubimCode.perror "У микроконтроллера #{mcu_class::MCU_NAME} нет порта #{port}"
        elsif not mcu_class::PORTS[port.to_sym].include? pin.to_i
                RubimCode.perror "У микроконтроллера #{mcu_class::MCU_NAME} нет порта пина #{pin} для порта #{port}"
        elsif not var.is_a? Symbol
                RubimCode.perror "Unknown type of parameters for helper #{__method__}"
        end

        if type == "normal"
                var_name = var.to_s.gsub(/^[@$]/, "")
                if rb_type == 'output'
                        return RubimCode::UserOutput.new(var_name, port: port, pin: pin, type: type)
                elsif rb_type == 'input'
                        return RubimCode::UserInput.new(var_name, port: port, pin: pin, type: type)
                end

        elsif type == "tri-state"
                RubimCode.perror "В данный момент тип выхода 'z-state' не реализован"

        else
                RubimCode.perror "Неизвестный тип выхода '#{type}'"
        end
end
init_vars(type_cc, *variables) click to toggle source

type_cc - тип переменной в С-программе variables - набор инициализируемых переменных

# File lib/rubimc/init_var.rb, line 7
def RubimCode.init_vars(type_cc, *variables) 
        vars_cc = ""
        rubim_vars = []

        variables.each {|var|
                # ToDo - поиск уже объявленных переменных и выдача предупреждений

                if var.is_a? Hash # ToDo
                        RubimCode.perror "Ошибка. В текущей версии нельзя назначать переменным значения при объявлении"
                        # key = var.keys.first
                        # instance_variable_set("@#{key.to_s}" , UserVariable.new("#{key.to_s}"))
                        # vars_cc += "#{key.to_s}=#{var[key]}, "

                elsif var.is_a? Symbol
                        var_str = var.to_s
                        var_name = var_str.gsub(/^[@$]/, "")
                        new_var = RubimCode::UserVariable.new("#{var_name}", type_cc)
                        rubim_vars << new_var

                        case var_str[0..1]
                                when /$./ # define GLOBAL variable
                                        RubimCode.perror "Ruby-like global variables are not supported yet. Use 'integer :@#{var_name}'"
                                when /@@/ # define CLASS variable
                                        RubimCode.perror "Ruby-like class variables are not supported yet. Use 'integer :@#{var_name}'"
                                when /@./ # define INSTANCE variable (in C it defined as global - outside the 'main' function)
                                        RubimCode::Printer.instance_vars_cc << new_var
                                else          # define LOCAL variable (in C it defined as local)
                                        RubimCode::Isolator.local_variables << var_name if RubimCode::Isolator.enabled
                                        vars_cc += "#{var_name}, "
                        end
                        
                else
                        RubimCode.perror "Unknown type of parameters for helper #{__method__}"
                end
        }
        if rubim_vars.empty?
                RubimCode.perror "No variables for initialize"
        end
        unless vars_cc.empty?
                vars_cc.chomp!(", ")
                RubimCode.pout ("#{type_cc} #{vars_cc};")
        end

        if rubim_vars.count == 1
                return rubim_vars[0]
        else
                return rubim_vars
        end
end
perror(error_message) click to toggle source
# File lib/rubimc/printer.rb, line 24
def perror(error_message)
        if error_message.nil? or error_message.to_s.nil? 
                raise ArgumentError, "error message is not string" 
        end

        error_message += "\n"
        code_ptr = caller_locations(2)
        code_ptr.each do |place| 
                place = place.to_s
                place.gsub!(/\/release\//, '/')
                error_message += "\tfrom #{place}\n"
        end
        puts "#ERROR: #{error_message}"
        exit 1
end
pout(str = "") click to toggle source
# File lib/rubimc/printer.rb, line 40
def pout(str = "")
        return if RubimCode::Printer.sandbox == true # don`t print output in sandbox

        if str.nil? or str.to_s.nil?
                raise ArgumentError, "str is nil"
        else
                @level = 0 if @level.nil?
                res_str = " "*4*@level + str.to_s 
                if RubimCode::Printer.pout_destination.in? [:default, nil]
                        puts res_str
                        unless defined? TEST_MODE
                                File.open("#{ARGV[0]}", 'a+') {|file| file.puts(res_str) }
                        end
                elsif RubimCode::Printer.pout_destination == :h_file
                        unless defined? TEST_MODE
                                h_name = ARGV[0].gsub(/\.c$/, '') + ".h"
                                File.open("#{h_name}", 'a+') {|file| file.puts(res_str) }
                        end
                else
                        RubimCode::Printer.pout_destination.concat(res_str).concat("\n")
                end
        end
end
rubim_begin() click to toggle source
# File lib/rubimc/control_structures.rb, line 53
def rubim_begin(); pout "{"; @level+=1; true; end
rubim_break() click to toggle source
# File lib/rubimc/control_structures.rb, line 62
def rubim_break; pout "break;" end
rubim_cbit(var, bit) click to toggle source
# File lib/rubimc/io_ports.rb, line 40
def rubim_cbit(var, bit); "#{var} &= ~(1<<#{bit});"; end
rubim_cond(cond, type="if") { || ... } click to toggle source

instructions “if” & “unless”

# File lib/rubimc/control_structures.rb, line 7
def rubim_cond(cond, type="if", &block)
        # ToDo: auto-define type of ret_value
        # use::  __rubim__rval__int, __rubim__rval__float, e.t.

        if @@rubim_defined_values.include? @level
                pout "__rubim__rval#{@level} = 0;"
        else
                pout "int __rubim__rval#{@level} = 0;"
        end
        @@rubim_defined_values << @level

        if type=="if"
                pout "if (#{cond}) {"
        elsif type=="unless"
                pout "if (!(#{cond})) {"
        end
        @level += 1 
        ret_val = yield
        pout "__rubim__rval#{@level-1} = #{ret_val};" if ret_val!="__rubim__noreturn"
        pout "}"
        @level -= 1
        return RubimCode::UserVariable.new("__rubim__rval#{@level}", 'tmp_int')
end
rubim_cycle(type="while", cond="true") { || ... } click to toggle source

instructions “while” & “until”

# File lib/rubimc/control_structures.rb, line 32
def rubim_cycle(type="while", cond="true", &block)
        pout "#{type} (#{cond}) {"
        @level+=1
                yield
                pout "}"
        @level-=1
end
rubim_else() click to toggle source
# File lib/rubimc/control_structures.rb, line 57
def rubim_else(); @level-=1; pout "} else {"; @level+=1; end
rubim_elsif(cond) click to toggle source
# File lib/rubimc/control_structures.rb, line 58
def rubim_elsif(cond); @level-=1; pout "} else if (#{cond}) {"; @level+=1; end
rubim_end() click to toggle source
# File lib/rubimc/control_structures.rb, line 54
def rubim_end(); pout "}"; @level-=1; "__rubim__noreturn"; end
rubim_if(cond, &block) click to toggle source

flat instructions

# File lib/rubimc/control_structures.rb, line 41
def rubim_if(cond, &block); rubim_cond(cond, "if", &block); end
rubim_ifmod(cond) click to toggle source

modify instructions

# File lib/rubimc/control_structures.rb, line 48
def rubim_ifmod(cond); pout "if (#{cond}) {"; @level+=1; true; end
rubim_loop(&block) click to toggle source
# File lib/rubimc/control_structures.rb, line 45
def rubim_loop(&block); rubim_cycle("while", "true", &block); end
rubim_next() click to toggle source

ToDo: in ‘else’ and ‘elsif’ set return_val, like in rubim_if (need to change preprocessor)

# File lib/rubimc/control_structures.rb, line 61
def rubim_next; pout "continue;" end
rubim_sbit(var, bit) click to toggle source
# File lib/rubimc/io_ports.rb, line 39
def rubim_sbit(var, bit); "#{var} |= 1<<#{bit};"; end
rubim_tbit(var, bit) click to toggle source
# File lib/rubimc/io_ports.rb, line 41
def rubim_tbit(var, bit); "#{var} ^= 1<<#{bit};"; end
rubim_tmpif(tmp) click to toggle source
# File lib/rubimc/control_structures.rb, line 55
def rubim_tmpif(tmp); end
rubim_unless(cond, &block) click to toggle source
# File lib/rubimc/control_structures.rb, line 42
def rubim_unless(cond, &block); rubim_cond(cond, "unless", &block); end
rubim_unlessmod(cond) click to toggle source
# File lib/rubimc/control_structures.rb, line 49
def rubim_unlessmod(cond); pout "if (!(#{cond})) {"; @level+=1; true; end
rubim_until(cond) click to toggle source
# File lib/rubimc/control_structures.rb, line 44
def rubim_until(cond); rubim_cycle("until", cond, &block); end
rubim_untilmod(cond) click to toggle source
# File lib/rubimc/control_structures.rb, line 51
def rubim_untilmod(cond); pout "} until (#{cond});"; @level-=1; end
rubim_while(cond, &block) click to toggle source
# File lib/rubimc/control_structures.rb, line 43
def rubim_while(cond, &block); rubim_cycle("while", cond, &block); end
rubim_whilemod(cond) click to toggle source
# File lib/rubimc/control_structures.rb, line 50
def rubim_whilemod(cond); pout "} while (#{cond});"; @level-=1; end