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,150 +1,150 @@
1
- require 'parser_combinator/string_parser'
2
-
3
- require 'emfrp/syntax'
4
- require 'emfrp/parser/toplevel'
5
- require 'emfrp/parser/expression'
6
- require 'emfrp/parser/misc'
7
- require 'emfrp/parser/operator'
8
- require 'emfrp/parser/parsing_error'
9
- require 'emfrp/parser/newnode_convert'
10
-
11
- module Emfrp
12
- class Parser < ParserCombinator::StringParser
13
- def self.parse_input(path, file_loader, file_type=module_file)
14
- if file_loader.loaded?(path)
15
- return Top.new
16
- end
17
- src_str, file_name = file_loader.load(path)
18
- parse_src(src_str, file_name, file_loader, file_type)
19
- end
20
-
21
- def self.parse_src(src_str, file_name, file_loader, file_type=module_file)
22
- case res = file_type.parse_from_string(convert_case_group(src_str), file_name)
23
- when Fail
24
- raise ParsingError.new(src_str, file_name, res.status)
25
- when Ok
26
- newnode_tops = res.parsed[:newnodes].map do |newnode|
27
- NewNodeConvert.parse_module(res.parsed[:module_name][:desc], newnode, file_loader)
28
- end
29
- res.parsed[:newnodes] = []
30
- tops = res.parsed[:uses].map do |use_path|
31
- parse_input(use_path.map{|x| x[:desc]}, file_loader, material_file)
32
- end
33
- return Top.new(*tops, res.parsed, *newnode_tops)
34
- else
35
- raise "unexpected return of parser (bug)"
36
- end
37
- end
38
-
39
- def self.parse(src_str, file_name, parser)
40
- case res = parser.parse_from_string(convert_case_group(src_str), file_name)
41
- when Fail
42
- raise ParsingError.new(src_str, file_name, res.status)
43
- when Ok
44
- return res.parsed
45
- else
46
- raise "unexpected return of parser (bug)"
47
- end
48
- end
49
-
50
- def self.convert_case_group(src_str)
51
- raise ParsingError.new("TAB is not allowed to use in sources.") if src_str.chars.include?("\t")
52
- lines = src_str.each_line.to_a.map(&:chomp)
53
- len = lines.length
54
- len.times do |ln|
55
- if lines[ln].strip.chars.last == ":"
56
- width = lines[ln].chars.take_while{|c| c == "\s"}.size
57
- ((ln+1)..(len-1)).each do |ln2|
58
- width2 = lines[ln2].chars.take_while{|c| c == "\s"}.size
59
- if lines[ln2].strip == ""
60
- next
61
- elsif width2 <= width
62
- lines[ln2 - 1] << " :endcase"
63
- break
64
- elsif ln2 == len - 1
65
- lines[ln2] << " :endcase"
66
- break
67
- end
68
- end
69
- end
70
- end
71
- lines.map{|l| l + "\n"}.join
72
- end
73
-
74
- def self.from_infixes_to_parser(infixes)
75
- priority_listl = [[], [], [], [], [], [], [], [], [], []]
76
- priority_listr = [[], [], [], [], [], [], [], [], [], []]
77
- priority_listn = [[], [], [], [], [], [], [], [], [], []]
78
- defined_op = {}
79
- infixes.reverse.each do |id|
80
- if defined_op[id[:op][:desc]]
81
- next
82
- else
83
- defined_op[id[:op][:desc]] = true
84
- end
85
- if id[:priority] == nil || ("0" <= id[:priority][:desc] && id[:priority][:desc] <= "9")
86
- priority = id[:priority] == nil ? 9 : id[:priority][:desc].to_i
87
- opp = sat{|i| i.is_a?(SSymbol) && i[:desc] == id[:op][:desc]}.map(&:item)
88
- if id[:type][:desc] == "infix"
89
- priority_listn[priority] << opp
90
- elsif id[:type][:desc] == "infixl"
91
- priority_listl[priority] << opp
92
- elsif id[:type][:desc] == "infixr"
93
- priority_listr[priority] << opp
94
- else
95
- raise "invalid infix type"
96
- end
97
- else
98
- raise "invalid prirority"
99
- end
100
- end
101
- priority_list = [{:op => sat{|i| i.is_a?(SSymbol)}.map(&:item), :dir => "left"}]
102
- 10.times do |i|
103
- if priority_listl[i].length > 0
104
- priority_list << {:op => priority_listl[i].inject(&:|), :dir => "left"}
105
- end
106
- if priority_listr[i].length > 0
107
- priority_list << {:op => priority_listr[i].inject(&:|), :dir => "right"}
108
- end
109
- if priority_listn[i].length > 0
110
- priority_list << {:op => priority_listn[i].inject(&:|), :dir => "left"}
111
- end
112
- end
113
- return OpParser.make_op_parser(priority_list)
114
- end
115
-
116
- def self.infix_rearrange(top)
117
- infix_parser = from_infixes_to_parser(top[:infixes])
118
- return infix_convert(top, infix_parser)
119
- end
120
-
121
- def self.infix_convert(s, parser)
122
- case s
123
- when Syntax
124
- new_s = s.class[s.map{|k, v| [k, infix_convert(v, parser)]}]
125
- if s.is_a?(OperatorSeq)
126
- items = Items.new(new_s[:seq].map{|c| Item.new(c, nil)})
127
- res = parser.parse(items)
128
- if res.is_a?(Fail)
129
- raise "operator parsing fail!!"
130
- end
131
- res.parsed
132
- else
133
- new_s
134
- end
135
- when Array
136
- s.map{|c| infix_convert(c, parser)}
137
- else
138
- s
139
- end
140
- end
141
-
142
- def err(place, required, code=nil)
143
- self.onfail(:place => place, :required => required, :code => code)
144
- end
145
-
146
- def to_nil
147
- self.map{|x| x[0]}
148
- end
149
- end
150
- end
1
+ require 'parser_combinator/string_parser'
2
+
3
+ require 'emfrp/syntax'
4
+ require 'emfrp/parser/toplevel'
5
+ require 'emfrp/parser/expression'
6
+ require 'emfrp/parser/misc'
7
+ require 'emfrp/parser/operator'
8
+ require 'emfrp/parser/parsing_error'
9
+ require 'emfrp/parser/newnode_convert'
10
+
11
+ module Emfrp
12
+ class Parser < ParserCombinator::StringParser
13
+ def self.parse_input(path, file_loader, file_type=module_file)
14
+ if file_loader.loaded?(path)
15
+ return Top.new
16
+ end
17
+ src_str, file_name = file_loader.load(path)
18
+ parse_src(src_str, file_name, file_loader, file_type)
19
+ end
20
+
21
+ def self.parse_src(src_str, file_name, file_loader, file_type=module_file)
22
+ case res = file_type.parse_from_string(convert_case_group(src_str), file_name)
23
+ when Fail
24
+ raise ParsingError.new(src_str, file_name, res.status)
25
+ when Ok
26
+ newnode_tops = res.parsed[:newnodes].map do |newnode|
27
+ NewNodeConvert.parse_module(res.parsed[:module_name][:desc], newnode, file_loader)
28
+ end
29
+ res.parsed[:newnodes] = []
30
+ tops = res.parsed[:uses].map do |use_path|
31
+ parse_input(use_path.map{|x| x[:desc]}, file_loader, material_file)
32
+ end
33
+ return Top.new(*tops, res.parsed, *newnode_tops)
34
+ else
35
+ raise "unexpected return of parser (bug)"
36
+ end
37
+ end
38
+
39
+ def self.parse(src_str, file_name, parser)
40
+ case res = parser.parse_from_string(convert_case_group(src_str), file_name)
41
+ when Fail
42
+ raise ParsingError.new(src_str, file_name, res.status)
43
+ when Ok
44
+ return res.parsed
45
+ else
46
+ raise "unexpected return of parser (bug)"
47
+ end
48
+ end
49
+
50
+ def self.convert_case_group(src_str)
51
+ raise ParsingError.new("TAB is not allowed to use in sources.") if src_str.chars.include?("\t")
52
+ lines = src_str.each_line.to_a.map(&:chomp)
53
+ len = lines.length
54
+ len.times do |ln|
55
+ if lines[ln].strip.chars.last == ":"
56
+ width = lines[ln].chars.take_while{|c| c == "\s"}.size
57
+ ((ln+1)..(len-1)).each do |ln2|
58
+ width2 = lines[ln2].chars.take_while{|c| c == "\s"}.size
59
+ if lines[ln2].strip == ""
60
+ next
61
+ elsif width2 <= width
62
+ lines[ln2 - 1] << " :endcase"
63
+ break
64
+ elsif ln2 == len - 1
65
+ lines[ln2] << " :endcase"
66
+ break
67
+ end
68
+ end
69
+ end
70
+ end
71
+ lines.map{|l| l + "\n"}.join
72
+ end
73
+
74
+ def self.from_infixes_to_parser(infixes)
75
+ priority_listl = [[], [], [], [], [], [], [], [], [], []]
76
+ priority_listr = [[], [], [], [], [], [], [], [], [], []]
77
+ priority_listn = [[], [], [], [], [], [], [], [], [], []]
78
+ defined_op = {}
79
+ infixes.reverse.each do |id|
80
+ if defined_op[id[:op][:desc]]
81
+ next
82
+ else
83
+ defined_op[id[:op][:desc]] = true
84
+ end
85
+ if id[:priority] == nil || ("0" <= id[:priority][:desc] && id[:priority][:desc] <= "9")
86
+ priority = id[:priority] == nil ? 9 : id[:priority][:desc].to_i
87
+ opp = sat{|i| i.is_a?(SSymbol) && i[:desc] == id[:op][:desc]}.map(&:item)
88
+ if id[:type][:desc] == "infix"
89
+ priority_listn[priority] << opp
90
+ elsif id[:type][:desc] == "infixl"
91
+ priority_listl[priority] << opp
92
+ elsif id[:type][:desc] == "infixr"
93
+ priority_listr[priority] << opp
94
+ else
95
+ raise "invalid infix type"
96
+ end
97
+ else
98
+ raise "invalid prirority"
99
+ end
100
+ end
101
+ priority_list = [{:op => sat{|i| i.is_a?(SSymbol)}.map(&:item), :dir => "left"}]
102
+ 10.times do |i|
103
+ if priority_listl[i].length > 0
104
+ priority_list << {:op => priority_listl[i].inject(&:|), :dir => "left"}
105
+ end
106
+ if priority_listr[i].length > 0
107
+ priority_list << {:op => priority_listr[i].inject(&:|), :dir => "right"}
108
+ end
109
+ if priority_listn[i].length > 0
110
+ priority_list << {:op => priority_listn[i].inject(&:|), :dir => "left"}
111
+ end
112
+ end
113
+ return OpParser.make_op_parser(priority_list)
114
+ end
115
+
116
+ def self.infix_rearrange(top)
117
+ infix_parser = from_infixes_to_parser(top[:infixes])
118
+ return infix_convert(top, infix_parser)
119
+ end
120
+
121
+ def self.infix_convert(s, parser)
122
+ case s
123
+ when Syntax
124
+ new_s = s.class[s.map{|k, v| [k, infix_convert(v, parser)]}]
125
+ if s.is_a?(OperatorSeq)
126
+ items = Items.new(new_s[:seq].map{|c| Item.new(c, nil)})
127
+ res = parser.parse(items)
128
+ if res.is_a?(Fail)
129
+ raise "operator parsing fail!!"
130
+ end
131
+ res.parsed
132
+ else
133
+ new_s
134
+ end
135
+ when Array
136
+ s.map{|c| infix_convert(c, parser)}
137
+ else
138
+ s
139
+ end
140
+ end
141
+
142
+ def err(place, required, code=nil)
143
+ self.onfail(:place => place, :required => required, :code => code)
144
+ end
145
+
146
+ def to_nil
147
+ self.map{|x| x[0]}
148
+ end
149
+ end
150
+ end
@@ -1,49 +1,49 @@
1
- require 'colorize'
2
-
3
- module Emfrp
4
- class Parser
5
- class ParsingError < StandardError
6
- def initialize(src_str, file_name, status)
7
- @src_str = src_str
8
- @file_name = file_name
9
- @status = status
10
- end
11
-
12
- def code
13
- @status.message[:code] || :noname
14
- end
15
-
16
- def line_number
17
- if @status.rest.length > 0
18
- @status.rest[0].tag[:line_number]
19
- else
20
- @src_str.each_line.count
21
- end
22
- end
23
-
24
- def column_number
25
- if @status.rest.length > 0
26
- @status.rest[0].tag[:column_number]
27
- else
28
- @src_str.each_line.last.length
29
- end
30
- end
31
-
32
- def line
33
- @src_str.each_line.to_a[line_number - 1]
34
- end
35
-
36
- def print_error(output_io)
37
- output_io << "#{@file_name}:#{line_number}: "
38
- output_io << "SyntaxError, in `#{@status.message[:place]}`: "
39
- output_io << "#{@status.message[:required]} is expected"
40
- if @status.rest.length == 0
41
- output_io << ", but parser reached end-of-file\n"
42
- else
43
- output_io << "\n#{line.chomp}\n"
44
- output_io << "#{" " * (column_number - 1)}#{"^".colorize(:green)}\n"
45
- end
46
- end
47
- end
48
- end
49
- end
1
+ require 'colorize'
2
+
3
+ module Emfrp
4
+ class Parser
5
+ class ParsingError < StandardError
6
+ def initialize(src_str, file_name, status)
7
+ @src_str = src_str
8
+ @file_name = file_name
9
+ @status = status
10
+ end
11
+
12
+ def code
13
+ @status.message[:code] || :noname
14
+ end
15
+
16
+ def line_number
17
+ if @status.rest.length > 0
18
+ @status.rest[0].tag[:line_number]
19
+ else
20
+ @src_str.each_line.count
21
+ end
22
+ end
23
+
24
+ def column_number
25
+ if @status.rest.length > 0
26
+ @status.rest[0].tag[:column_number]
27
+ else
28
+ @src_str.each_line.last.length
29
+ end
30
+ end
31
+
32
+ def line
33
+ @src_str.each_line.to_a[line_number - 1]
34
+ end
35
+
36
+ def print_error(output_io)
37
+ output_io << "#{@file_name}:#{line_number}: "
38
+ output_io << "SyntaxError, in `#{@status.message[:place]}`: "
39
+ output_io << "#{@status.message[:required]} is expected"
40
+ if @status.rest.length == 0
41
+ output_io << ", but parser reached end-of-file\n"
42
+ else
43
+ output_io << "\n#{line.chomp}\n"
44
+ output_io << "#{" " * (column_number - 1)}#{"^".colorize(:green)}\n"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end