Class: Emfrp::Interpreter

Inherits:
Object
  • Object
show all
Defined in:
lib/emfrp/interpreter/evaluater.rb,
lib/emfrp/interpreter/interpreter.rb,
lib/emfrp/interpreter/command_manager.rb

Defined Under Namespace

Modules: Evaluater Classes: CommandManager, InterpreterError

Instance Method Summary collapse

Constructor Details

#initialize(include_dirs, output_io, main_path) ⇒ Interpreter

Returns a new instance of Interpreter.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/emfrp/interpreter/interpreter.rb', line 18

def initialize(include_dirs, output_io, main_path)
  @file_loader = FileLoader.new(include_dirs)
  @main_path = main_path
  @output_io = output_io
  @readline_nums = (1..1000).to_a
  @command_manager = CommandManager.make(self)
  @top = Parser.parse_input(main_path, @file_loader, Parser.module_or_material_file)
  @infix_parser = Parser.from_infixes_to_parser(@top[:infixes])
  @top = Parser.infix_convert(@top, @infix_parser)
  PreConvert.convert(@top)
  Typing.typing(@top)
rescue Parser::ParsingError => err
  err.print_error(@output_io)
  raise InterpreterError.new(err.code)
rescue CompileError => err
  err.print_error(@output_io, @file_loader)
  raise InterpreterError.new(err.code)
end

Instance Method Details

#append_def(uniq_id, def_str) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/emfrp/interpreter/interpreter.rb', line 65

def append_def(uniq_id, def_str)
  file_name = "command-line-#{uniq_id}"
  @file_loader.add_to_loaded(file_name, def_str)
  ds = Parser.parse(def_str, file_name, Parser.oneline_file)
  ds.map!{|d| Parser.infix_convert(d, @infix_parser)}
  ds.each do |d|
    PreConvert.additional_convert(@top, d)
    Typing.additional_typing(@top, d)
    @top.add(d)
  end
  return nil
rescue Parser::ParsingError => err
  err.print_error(@output_io)
  return err.code
rescue CompileError => err
  err.print_error(@output_io, @file_loader)
  ds.each do |d|
    PreConvert.cancel(@top, d)
  end
  return err.code
end

#closeObject



163
164
165
# File 'lib/emfrp/interpreter/interpreter.rb', line 163

def close
  puts ""
end

#command_exec(command_name, arg, readline_id) ⇒ Object



146
147
148
149
150
151
152
153
# File 'lib/emfrp/interpreter/interpreter.rb', line 146

def command_exec(command_name, arg, readline_id)
  res = @command_manager.exec(command_name, arg, readline_id)
  if res == :command_format_error
    puts "Error: command_format_error"
    @command_manager.print_usage(command_name, @output_io)
  end
  return res
end

#compile(c_output_io, h_output_io, main_output_io, name, print_log = false) ⇒ Object



37
38
39
# File 'lib/emfrp/interpreter/interpreter.rb', line 37

def compile(c_output_io, h_output_io, main_output_io, name, print_log=false)
  Emfrp::Codegen.codegen(@top, c_output_io, h_output_io, main_output_io, name)
end

#compile_default(gen_cpp = false, gen_main = true) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/emfrp/interpreter/interpreter.rb', line 41

def compile_default(gen_cpp = false, gen_main = true)
  filename = @top[:module_name][:desc]
  c_output_file = filename + (gen_cpp ? ".cpp" : ".c")
  h_output_file = filename + ".h"
  main_output_file = filename + "Main" + ".c"
  File.open(c_output_file, 'w') do |c_file|
    File.open(h_output_file, 'w') do |h_file|
      main_output_file += ".gen" if File.exist?(main_output_file)
      if gen_main
        File.open(main_output_file, 'w') do |main_file|
          compile(c_file, h_file, main_file, filename)
        end
      else
        require "stringio"
        compile(c_file, h_file, StringIO.new, filename)
      end
      return nil
    end
  end
rescue SystemCallError => err
  puts err.inspect
  return :file_write_error
end

#completion_procObject



175
176
177
178
179
180
181
182
# File 'lib/emfrp/interpreter/interpreter.rb', line 175

def completion_proc
  command_comp = @command_manager.completion_proc
  proc do |s|
    token_candidates = lexical_tokens.select{|x| x.index(s) == 0}
    command_candidates = command_comp.call(s)
    token_candidates + command_candidates
  end
end

#current_readline_idObject



171
172
173
# File 'lib/emfrp/interpreter/interpreter.rb', line 171

def current_readline_id
  "%03d" % @readline_nums.first
end

#disable_io(&block) ⇒ Object



155
156
157
158
159
160
161
# File 'lib/emfrp/interpreter/interpreter.rb', line 155

def disable_io(&block)
  output_io = @output_io
  @output_io = StringIO.new
  block.call
ensure
  @output_io = output_io
end

#exec_embedded_commands(only_on_main_path = false) ⇒ Object

-> true-like(abnormal-term) / false-like(normal-term)



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/emfrp/interpreter/interpreter.rb', line 100

def exec_embedded_commands(only_on_main_path=false) #
  @top[:commands].any? do |com|
    if !only_on_main_path || com[:file_name] == @file_loader.loaded_full_path(@main_path)
      unless process_repl_line(com[:command_str])
        nil
      else
        puts "Embedded command on #{com[:file_name]}:#{com[:line_number]}\n"
        true
      end
    else
      nil
    end
  end
end

#lexical_tokensObject



184
185
186
187
188
189
190
# File 'lib/emfrp/interpreter/interpreter.rb', line 184

def lexical_tokens
  res = []
  res += @top[:dict][:const_space].keys
  res += @top[:dict][:data_space].keys
  res += @top[:dict][:func_space].keys
  return res
end

#pp(obj) ⇒ Object



192
193
194
# File 'lib/emfrp/interpreter/interpreter.rb', line 192

def pp(obj)
  PP.pp(obj, @output_io)
end

#proceed_readline_idObject



167
168
169
# File 'lib/emfrp/interpreter/interpreter.rb', line 167

def proceed_readline_id
  "%03d" % @readline_nums.shift
end

#process_repl_line(line) ⇒ Object

-> true-like(abnormal-term) / false-like(normal-term)



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/emfrp/interpreter/interpreter.rb', line 116

def process_repl_line(line)
  readline_id = proceed_readline_id()
  @last_status = case line
  when /^\s*(data|func|type)\s(.*)$/
    append_def(readline_id, line)
  when /^[a-z][a-zA-Z0-9]*\s*=(.*)$/
    append_def(readline_id, "data #{line}")
  when /^\s*\:([a-z\-]+)\s*(.*)$/
    @last_command = $1
    command_exec($1, $2, readline_id)
  when /^\s*\:\s+(.*)$/
    if @last_command
      command_exec(@last_command, $1, readline_id)
    else
      puts "Error: there isn't a last-executed command"
      :recall_last_executed_error
    end
  when ""
    nil
  else
    if exp = str_to_exp(line)
      val = Evaluater.eval_exp(@top, exp)
      puts "#{Evaluater.value_to_s(val)} : #{exp[:typing].inspect.colorize(:green)}"
      nil
    else
      :eval_error
    end
  end
end

#puts(str) ⇒ Object



196
197
198
# File 'lib/emfrp/interpreter/interpreter.rb', line 196

def puts(str)
  @output_io.puts(str)
end

#str_to_exp(exp_str, type = nil) ⇒ Object

-> parsed-expression or nil(fail)



88
89
90
91
92
93
94
95
96
97
# File 'lib/emfrp/interpreter/interpreter.rb', line 88

def str_to_exp(exp_str, type=nil)
  @eval_serial ||= (0..1000).to_a
  uname = "tmp%03d" % @eval_serial.shift
  type_ano = type ? " : #{type}" : ""
  unless append_def(uname, "data #{uname}#{type_ano} = #{exp_str}")
    @top[:datas].last[:exp]
  else
    nil
  end
end