emfrp 0.1.2 → 0.1.3

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -12
  3. data/bin/emfrp +4 -1
  4. data/examples/LCDClock/LCDClock.mfrp +93 -93
  5. data/examples/LCDClock/LCDClock_LPC1768.bin +0 -0
  6. data/examples/LCDClock/README.md +24 -24
  7. data/examples/LCDPositioner/LCDPositioner.mfrp +30 -30
  8. data/examples/LCDPositioner/LCDPositionerMain.c +15 -15
  9. data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -25
  10. data/examples/MostDistantPoint/MostDistantPointMain.c +14 -14
  11. data/lib/emfrp/compile/c/alloc.rb +200 -200
  12. data/lib/emfrp/compile/c/codegen.rb +18 -18
  13. data/lib/emfrp/compile/c/codegen_context.rb +218 -218
  14. data/lib/emfrp/compile/c/monofy.rb +185 -185
  15. data/lib/emfrp/compile/c/syntax_codegen.rb +364 -364
  16. data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -119
  17. data/lib/emfrp/compile/graphviz/graphviz.rb +53 -53
  18. data/lib/emfrp/compile_error.rb +95 -95
  19. data/lib/emfrp/interpreter/command_manager.rb +367 -367
  20. data/lib/emfrp/interpreter/evaluater.rb +146 -146
  21. data/lib/emfrp/interpreter/file_loader.rb +52 -52
  22. data/lib/emfrp/interpreter/interpreter.rb +200 -195
  23. data/lib/emfrp/parser/expression.rb +386 -386
  24. data/lib/emfrp/parser/misc.rb +184 -184
  25. data/lib/emfrp/parser/newnode_convert.rb +72 -72
  26. data/lib/emfrp/parser/operator.rb +25 -25
  27. data/lib/emfrp/parser/parser.rb +150 -150
  28. data/lib/emfrp/parser/parsing_error.rb +49 -49
  29. data/lib/emfrp/parser/toplevel.rb +555 -555
  30. data/lib/emfrp/pre_convert/pre_convert.rb +32 -32
  31. data/lib/emfrp/syntax.rb +171 -171
  32. data/lib/emfrp/typing/typing_error.rb +47 -47
  33. data/lib/emfrp/typing/union_type.rb +197 -197
  34. data/lib/emfrp/version.rb +1 -1
  35. data/mfrp_include/Std.mfrp +122 -122
  36. data/tests/Rakefile +8 -8
  37. data/tests/Rakefile.common +27 -27
  38. data/tests/command/Rakefile +2 -2
  39. data/tests/command/ReplaceNode.mfrp +39 -39
  40. data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -14
  41. data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -15
  42. data/tests/compiler/ComplexDataType/Rakefile +2 -2
  43. data/tests/compiler/ComplexDataType/expected_out.txt +0 -0
  44. data/tests/compiler/ComplexDataType/in.txt +5 -5
  45. data/tests/compiler/LCDClock/LCDClock.mfrp +90 -90
  46. data/tests/compiler/LCDClock/LCDClockMain.c +0 -0
  47. data/tests/compiler/LCDClock/Rakefile +2 -2
  48. data/tests/compiler/LCDClock/expected_out.txt +0 -0
  49. data/tests/compiler/LCDClock/in.txt +0 -0
  50. data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -30
  51. data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -15
  52. data/tests/compiler/LCDPositioner/Rakefile +2 -2
  53. data/tests/compiler/LCDPositioner/graph.dot +0 -0
  54. data/tests/compiler/LCDPositioner/graph.png +0 -0
  55. data/tests/compiler/Rakefile +8 -8
  56. data/tests/compiler/Rakefile.common +23 -23
  57. data/tests/compiler/UseData/Rakefile +2 -2
  58. data/tests/compiler/UseData/UseData.mfrp +8 -8
  59. data/tests/compiler/UseSubModule/Rakefile +2 -2
  60. data/tests/compiler/UseSubModule/SubModule.mfrp +8 -8
  61. data/tests/compiler/UseSubModule/SubModule2.mfrp +5 -5
  62. data/tests/compiler/UseSubModule/UseSubModule.mfrp +11 -11
  63. data/tests/core/FromAnnotation.mfrp +18 -18
  64. data/tests/core/Last.mfrp +10 -10
  65. data/tests/core/Rakefile +2 -2
  66. data/tests/core/TypingTest.mfrp +11 -11
  67. data/tests/core/WithoutInputs.mfrp +19 -19
  68. data/tests/load_time_error/Rakefile +32 -32
  69. data/tests/load_time_error/TypeMismatch.mfrp +4 -4
  70. metadata +3 -3
@@ -1,195 +1,200 @@
1
- require 'pp'
2
- require 'stringio'
3
-
4
- require 'emfrp'
5
- require 'emfrp/interpreter/file_loader'
6
- require 'emfrp/interpreter/evaluater'
7
- require 'emfrp/interpreter/command_manager'
8
-
9
- module Emfrp
10
- class Interpreter
11
- class InterpreterError < StandardError
12
- attr_reader :code
13
- def initialize(code)
14
- @code = code
15
- end
16
- end
17
-
18
- def initialize(include_dirs, output_io, main_path)
19
- @file_loader = FileLoader.new(include_dirs)
20
- @main_path = main_path
21
- @output_io = output_io
22
- @readline_nums = (1..1000).to_a
23
- @command_manager = CommandManager.make(self)
24
- @top = Parser.parse_input(main_path, @file_loader, Parser.module_or_material_file)
25
- @infix_parser = Parser.from_infixes_to_parser(@top[:infixes])
26
- @top = Parser.infix_convert(@top, @infix_parser)
27
- PreConvert.convert(@top)
28
- Typing.typing(@top)
29
- rescue Parser::ParsingError => err
30
- err.print_error(@output_io)
31
- raise InterpreterError.new(err.code)
32
- rescue CompileError => err
33
- err.print_error(@output_io, @file_loader)
34
- raise InterpreterError.new(err.code)
35
- end
36
-
37
- def compile(c_output_io, h_output_io, main_output_io, name, print_log=false)
38
- Emfrp::Codegen.codegen(@top, c_output_io, h_output_io, main_output_io, name)
39
- end
40
-
41
- def compile_default
42
- filename = @top[:module_name][:desc]
43
- c_output_file = filename + ".c"
44
- h_output_file = filename + ".h"
45
- main_output_file = filename + "Main" + ".c"
46
- File.open(c_output_file, 'w') do |c_file|
47
- File.open(h_output_file, 'w') do |h_file|
48
- main_output_file += ".gen" if File.exist?(main_output_file)
49
- File.open(main_output_file, 'w') do |main_file|
50
- compile(c_file, h_file, main_file, filename)
51
- end
52
- return nil
53
- end
54
- end
55
- rescue SystemCallError => err
56
- puts err.inspect
57
- return :file_write_error
58
- end
59
-
60
- def append_def(uniq_id, def_str)
61
- file_name = "command-line-#{uniq_id}"
62
- @file_loader.add_to_loaded(file_name, def_str)
63
- ds = Parser.parse(def_str, file_name, Parser.oneline_file)
64
- ds.map!{|d| Parser.infix_convert(d, @infix_parser)}
65
- ds.each do |d|
66
- PreConvert.additional_convert(@top, d)
67
- Typing.additional_typing(@top, d)
68
- @top.add(d)
69
- end
70
- return nil
71
- rescue Parser::ParsingError => err
72
- err.print_error(@output_io)
73
- return err.code
74
- rescue CompileError => err
75
- err.print_error(@output_io, @file_loader)
76
- ds.each do |d|
77
- PreConvert.cancel(@top, d)
78
- end
79
- return err.code
80
- end
81
-
82
- #-> parsed-expression or nil(fail)
83
- def str_to_exp(exp_str, type=nil)
84
- @eval_serial ||= (0..1000).to_a
85
- uname = "tmp%03d" % @eval_serial.shift
86
- type_ano = type ? " : #{type}" : ""
87
- unless append_def(uname, "data #{uname}#{type_ano} = #{exp_str}")
88
- @top[:datas].last[:exp]
89
- else
90
- nil
91
- end
92
- end
93
-
94
- #-> true-like(abnormal-term) / false-like(normal-term)
95
- def exec_embedded_commands(only_on_main_path=false) #
96
- @top[:commands].any? do |com|
97
- if !only_on_main_path || com[:file_name] == @file_loader.loaded_full_path(@main_path)
98
- unless process_repl_line(com[:command_str])
99
- nil
100
- else
101
- puts "Embedded command on #{com[:file_name]}:#{com[:line_number]}\n"
102
- true
103
- end
104
- else
105
- nil
106
- end
107
- end
108
- end
109
-
110
- #-> true-like(abnormal-term) / false-like(normal-term)
111
- def process_repl_line(line)
112
- readline_id = proceed_readline_id()
113
- @last_status = case line
114
- when /^\s*(data|func|type)\s(.*)$/
115
- append_def(readline_id, line)
116
- when /^[a-z][a-zA-Z0-9]*\s*=(.*)$/
117
- append_def(readline_id, "data #{line}")
118
- when /^\s*\:([a-z\-]+)\s*(.*)$/
119
- @last_command = $1
120
- command_exec($1, $2, readline_id)
121
- when /^\s*\:\s+(.*)$/
122
- if @last_command
123
- command_exec(@last_command, $1, readline_id)
124
- else
125
- puts "Error: there isn't a last-executed command"
126
- :recall_last_executed_error
127
- end
128
- when ""
129
- nil
130
- else
131
- if exp = str_to_exp(line)
132
- val = Evaluater.eval_exp(@top, exp)
133
- puts "#{Evaluater.value_to_s(val)} : #{exp[:typing].inspect.colorize(:green)}"
134
- nil
135
- else
136
- :eval_error
137
- end
138
- end
139
- end
140
-
141
- def command_exec(command_name, arg, readline_id)
142
- res = @command_manager.exec(command_name, arg, readline_id)
143
- if res == :command_format_error
144
- puts "Error: command_format_error"
145
- @command_manager.print_usage(command_name, @output_io)
146
- end
147
- return res
148
- end
149
-
150
- def disable_io(&block)
151
- output_io = @output_io
152
- @output_io = StringIO.new
153
- block.call
154
- ensure
155
- @output_io = output_io
156
- end
157
-
158
- def close
159
- puts ""
160
- end
161
-
162
- def proceed_readline_id
163
- "%03d" % @readline_nums.shift
164
- end
165
-
166
- def current_readline_id
167
- "%03d" % @readline_nums.first
168
- end
169
-
170
- def completion_proc
171
- command_comp = @command_manager.completion_proc
172
- proc do |s|
173
- token_candidates = lexical_tokens.select{|x| x.index(s) == 0}
174
- command_candidates = command_comp.call(s)
175
- token_candidates + command_candidates
176
- end
177
- end
178
-
179
- def lexical_tokens
180
- res = []
181
- res += @top[:dict][:const_space].keys
182
- res += @top[:dict][:data_space].keys
183
- res += @top[:dict][:func_space].keys
184
- return res
185
- end
186
-
187
- def pp(obj)
188
- PP.pp(obj, @output_io)
189
- end
190
-
191
- def puts(str)
192
- @output_io.puts(str)
193
- end
194
- end
195
- end
1
+ require 'pp'
2
+ require 'stringio'
3
+
4
+ require 'emfrp'
5
+ require 'emfrp/interpreter/file_loader'
6
+ require 'emfrp/interpreter/evaluater'
7
+ require 'emfrp/interpreter/command_manager'
8
+
9
+ module Emfrp
10
+ class Interpreter
11
+ class InterpreterError < StandardError
12
+ attr_reader :code
13
+ def initialize(code)
14
+ @code = code
15
+ end
16
+ end
17
+
18
+ def initialize(include_dirs, output_io, main_path)
19
+ @file_loader = FileLoader.new(include_dirs)
20
+ @main_path = main_path
21
+ @output_io = output_io
22
+ @readline_nums = (1..1000).to_a
23
+ @command_manager = CommandManager.make(self)
24
+ @top = Parser.parse_input(main_path, @file_loader, Parser.module_or_material_file)
25
+ @infix_parser = Parser.from_infixes_to_parser(@top[:infixes])
26
+ @top = Parser.infix_convert(@top, @infix_parser)
27
+ PreConvert.convert(@top)
28
+ Typing.typing(@top)
29
+ rescue Parser::ParsingError => err
30
+ err.print_error(@output_io)
31
+ raise InterpreterError.new(err.code)
32
+ rescue CompileError => err
33
+ err.print_error(@output_io, @file_loader)
34
+ raise InterpreterError.new(err.code)
35
+ end
36
+
37
+ def compile(c_output_io, h_output_io, main_output_io, name, print_log=false)
38
+ Emfrp::Codegen.codegen(@top, c_output_io, h_output_io, main_output_io, name)
39
+ end
40
+
41
+ def compile_default(gen_cpp = false, gen_main = true)
42
+ filename = @top[:module_name][:desc]
43
+ c_output_file = filename + (gen_cpp ? ".cpp" : ".c")
44
+ h_output_file = filename + ".h"
45
+ main_output_file = filename + "Main" + ".c"
46
+ File.open(c_output_file, 'w') do |c_file|
47
+ File.open(h_output_file, 'w') do |h_file|
48
+ main_output_file += ".gen" if File.exist?(main_output_file)
49
+ if gen_main
50
+ File.open(main_output_file, 'w') do |main_file|
51
+ compile(c_file, h_file, main_file, filename)
52
+ end
53
+ else
54
+ require "stringio"
55
+ compile(c_file, h_file, StringIO.new, filename)
56
+ end
57
+ return nil
58
+ end
59
+ end
60
+ rescue SystemCallError => err
61
+ puts err.inspect
62
+ return :file_write_error
63
+ end
64
+
65
+ def append_def(uniq_id, def_str)
66
+ file_name = "command-line-#{uniq_id}"
67
+ @file_loader.add_to_loaded(file_name, def_str)
68
+ ds = Parser.parse(def_str, file_name, Parser.oneline_file)
69
+ ds.map!{|d| Parser.infix_convert(d, @infix_parser)}
70
+ ds.each do |d|
71
+ PreConvert.additional_convert(@top, d)
72
+ Typing.additional_typing(@top, d)
73
+ @top.add(d)
74
+ end
75
+ return nil
76
+ rescue Parser::ParsingError => err
77
+ err.print_error(@output_io)
78
+ return err.code
79
+ rescue CompileError => err
80
+ err.print_error(@output_io, @file_loader)
81
+ ds.each do |d|
82
+ PreConvert.cancel(@top, d)
83
+ end
84
+ return err.code
85
+ end
86
+
87
+ #-> parsed-expression or nil(fail)
88
+ def str_to_exp(exp_str, type=nil)
89
+ @eval_serial ||= (0..1000).to_a
90
+ uname = "tmp%03d" % @eval_serial.shift
91
+ type_ano = type ? " : #{type}" : ""
92
+ unless append_def(uname, "data #{uname}#{type_ano} = #{exp_str}")
93
+ @top[:datas].last[:exp]
94
+ else
95
+ nil
96
+ end
97
+ end
98
+
99
+ #-> true-like(abnormal-term) / false-like(normal-term)
100
+ def exec_embedded_commands(only_on_main_path=false) #
101
+ @top[:commands].any? do |com|
102
+ if !only_on_main_path || com[:file_name] == @file_loader.loaded_full_path(@main_path)
103
+ unless process_repl_line(com[:command_str])
104
+ nil
105
+ else
106
+ puts "Embedded command on #{com[:file_name]}:#{com[:line_number]}\n"
107
+ true
108
+ end
109
+ else
110
+ nil
111
+ end
112
+ end
113
+ end
114
+
115
+ #-> true-like(abnormal-term) / false-like(normal-term)
116
+ def process_repl_line(line)
117
+ readline_id = proceed_readline_id()
118
+ @last_status = case line
119
+ when /^\s*(data|func|type)\s(.*)$/
120
+ append_def(readline_id, line)
121
+ when /^[a-z][a-zA-Z0-9]*\s*=(.*)$/
122
+ append_def(readline_id, "data #{line}")
123
+ when /^\s*\:([a-z\-]+)\s*(.*)$/
124
+ @last_command = $1
125
+ command_exec($1, $2, readline_id)
126
+ when /^\s*\:\s+(.*)$/
127
+ if @last_command
128
+ command_exec(@last_command, $1, readline_id)
129
+ else
130
+ puts "Error: there isn't a last-executed command"
131
+ :recall_last_executed_error
132
+ end
133
+ when ""
134
+ nil
135
+ else
136
+ if exp = str_to_exp(line)
137
+ val = Evaluater.eval_exp(@top, exp)
138
+ puts "#{Evaluater.value_to_s(val)} : #{exp[:typing].inspect.colorize(:green)}"
139
+ nil
140
+ else
141
+ :eval_error
142
+ end
143
+ end
144
+ end
145
+
146
+ def command_exec(command_name, arg, readline_id)
147
+ res = @command_manager.exec(command_name, arg, readline_id)
148
+ if res == :command_format_error
149
+ puts "Error: command_format_error"
150
+ @command_manager.print_usage(command_name, @output_io)
151
+ end
152
+ return res
153
+ end
154
+
155
+ def disable_io(&block)
156
+ output_io = @output_io
157
+ @output_io = StringIO.new
158
+ block.call
159
+ ensure
160
+ @output_io = output_io
161
+ end
162
+
163
+ def close
164
+ puts ""
165
+ end
166
+
167
+ def proceed_readline_id
168
+ "%03d" % @readline_nums.shift
169
+ end
170
+
171
+ def current_readline_id
172
+ "%03d" % @readline_nums.first
173
+ end
174
+
175
+ def completion_proc
176
+ command_comp = @command_manager.completion_proc
177
+ proc do |s|
178
+ token_candidates = lexical_tokens.select{|x| x.index(s) == 0}
179
+ command_candidates = command_comp.call(s)
180
+ token_candidates + command_candidates
181
+ end
182
+ end
183
+
184
+ def lexical_tokens
185
+ res = []
186
+ res += @top[:dict][:const_space].keys
187
+ res += @top[:dict][:data_space].keys
188
+ res += @top[:dict][:func_space].keys
189
+ return res
190
+ end
191
+
192
+ def pp(obj)
193
+ PP.pp(obj, @output_io)
194
+ end
195
+
196
+ def puts(str)
197
+ @output_io.puts(str)
198
+ end
199
+ end
200
+ end