Class: RubimCode

Inherits:
Object show all
Defined in:
lib/rubimc.rb,
lib/rubimc.rb,
lib/version.rb,
lib/rubimc/printer.rb,
lib/rubimc/io_ports.rb,
lib/rubimc/control_structures.rb

Overview

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

Defined Under Namespace

Classes: CC_ARGS, Interrupts, Isolator, LoopCounter, Printer, UserArray, UserClass, UserIO, UserInput, UserOutput, UserVariable

Constant Summary collapse

VERSION =
"0.2.2"
@@rubim_defined_values =
[]

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.levelObject

Returns the value of attribute level.



19
20
21
# File 'lib/rubimc/printer.rb', line 19

def level
  @level
end

Class Method Details

.clear_c(str) ⇒ Object



64
65
66
67
68
# 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") ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 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) ⇒ Object

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



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 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) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 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 = "") ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 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_beginObject



53
# File 'lib/rubimc/control_structures.rb', line 53

def rubim_begin(); pout "{"; @level+=1; true; end

.rubim_breakObject



62
# File 'lib/rubimc/control_structures.rb', line 62

def rubim_break; pout "break;" end

.rubim_cbit(var, bit) ⇒ Object



40
# File 'lib/rubimc/io_ports.rb', line 40

def rubim_cbit(var, bit); "#{var} &= ~(1<<#{bit});"; end

.rubim_cond(cond, type = "if", &block) ⇒ Object

instructions “if” & “unless”



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 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", &block) ⇒ Object

instructions “while” & “until”



32
33
34
35
36
37
38
# 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_elseObject



57
# File 'lib/rubimc/control_structures.rb', line 57

def rubim_else(); @level-=1; pout "} else {"; @level+=1; end

.rubim_elsif(cond) ⇒ Object



58
# File 'lib/rubimc/control_structures.rb', line 58

def rubim_elsif(cond); @level-=1; pout "} else if (#{cond}) {"; @level+=1; end

.rubim_endObject



54
# File 'lib/rubimc/control_structures.rb', line 54

def rubim_end(); pout "}"; @level-=1; "__rubim__noreturn"; end

.rubim_if(cond, &block) ⇒ Object

flat instructions



41
# File 'lib/rubimc/control_structures.rb', line 41

def rubim_if(cond, &block); rubim_cond(cond, "if", &block); end

.rubim_ifmod(cond) ⇒ Object

modify instructions



48
# File 'lib/rubimc/control_structures.rb', line 48

def rubim_ifmod(cond); pout "if (#{cond}) {"; @level+=1; true; end

.rubim_loop(&block) ⇒ Object



45
# File 'lib/rubimc/control_structures.rb', line 45

def rubim_loop(&block); rubim_cycle("while", "true", &block); end

.rubim_nextObject

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



61
# File 'lib/rubimc/control_structures.rb', line 61

def rubim_next; pout "continue;" end

.rubim_sbit(var, bit) ⇒ Object



39
# File 'lib/rubimc/io_ports.rb', line 39

def rubim_sbit(var, bit); "#{var} |= 1<<#{bit};"; end

.rubim_tbit(var, bit) ⇒ Object



41
# File 'lib/rubimc/io_ports.rb', line 41

def rubim_tbit(var, bit); "#{var} ^= 1<<#{bit};"; end

.rubim_tmpif(tmp) ⇒ Object



55
# File 'lib/rubimc/control_structures.rb', line 55

def rubim_tmpif(tmp); end

.rubim_unless(cond, &block) ⇒ Object



42
# File 'lib/rubimc/control_structures.rb', line 42

def rubim_unless(cond, &block); rubim_cond(cond, "unless", &block); end

.rubim_unlessmod(cond) ⇒ Object



49
# File 'lib/rubimc/control_structures.rb', line 49

def rubim_unlessmod(cond); pout "if (!(#{cond})) {"; @level+=1; true; end

.rubim_until(cond) ⇒ Object



44
# File 'lib/rubimc/control_structures.rb', line 44

def rubim_until(cond); rubim_cycle("until", cond, &block); end

.rubim_untilmod(cond) ⇒ Object



51
# File 'lib/rubimc/control_structures.rb', line 51

def rubim_untilmod(cond); pout "} until (#{cond});"; @level-=1; end

.rubim_while(cond, &block) ⇒ Object



43
# File 'lib/rubimc/control_structures.rb', line 43

def rubim_while(cond, &block); rubim_cycle("while", cond, &block); end

.rubim_whilemod(cond) ⇒ Object



50
# File 'lib/rubimc/control_structures.rb', line 50

def rubim_whilemod(cond); pout "} while (#{cond});"; @level-=1; end