sfrp 1.1.0

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 (85) hide show
  1. checksums.yaml +7 -0
  2. data/.ctags +3 -0
  3. data/.editorconfig +9 -0
  4. data/.gitignore +14 -0
  5. data/.rubocop.yml +629 -0
  6. data/.travis.yml +12 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE +28 -0
  9. data/README.md +34 -0
  10. data/Rakefile +1 -0
  11. data/base-library/Base.sfrp +81 -0
  12. data/base-library/IO/AVR/ATMEGA8.c +9 -0
  13. data/base-library/IO/AVR/ATMEGA8.h +6 -0
  14. data/base-library/IO/AVR/ATMEGA8.sfrp +4 -0
  15. data/base-library/IO/STDIO.c +40 -0
  16. data/base-library/IO/STDIO.h +13 -0
  17. data/base-library/IO/STDIO.sfrp +10 -0
  18. data/bin/sfrp +7 -0
  19. data/lib/sfrp.rb +2 -0
  20. data/lib/sfrp/command.rb +73 -0
  21. data/lib/sfrp/compiler.rb +94 -0
  22. data/lib/sfrp/error.rb +4 -0
  23. data/lib/sfrp/file.rb +18 -0
  24. data/lib/sfrp/flat/dsl.rb +33 -0
  25. data/lib/sfrp/flat/elements.rb +90 -0
  26. data/lib/sfrp/flat/exception.rb +45 -0
  27. data/lib/sfrp/flat/expression.rb +125 -0
  28. data/lib/sfrp/flat/set.rb +61 -0
  29. data/lib/sfrp/input/exception.rb +16 -0
  30. data/lib/sfrp/input/parser.rb +417 -0
  31. data/lib/sfrp/input/set.rb +29 -0
  32. data/lib/sfrp/input/transformer.rb +219 -0
  33. data/lib/sfrp/low/dsl.rb +126 -0
  34. data/lib/sfrp/low/element.rb +126 -0
  35. data/lib/sfrp/low/set.rb +62 -0
  36. data/lib/sfrp/mono/dsl.rb +120 -0
  37. data/lib/sfrp/mono/environment.rb +26 -0
  38. data/lib/sfrp/mono/exception.rb +21 -0
  39. data/lib/sfrp/mono/expression.rb +124 -0
  40. data/lib/sfrp/mono/function.rb +86 -0
  41. data/lib/sfrp/mono/memory.rb +32 -0
  42. data/lib/sfrp/mono/node.rb +125 -0
  43. data/lib/sfrp/mono/pattern.rb +69 -0
  44. data/lib/sfrp/mono/set.rb +151 -0
  45. data/lib/sfrp/mono/type.rb +210 -0
  46. data/lib/sfrp/mono/vconst.rb +134 -0
  47. data/lib/sfrp/output/set.rb +33 -0
  48. data/lib/sfrp/poly/dsl.rb +171 -0
  49. data/lib/sfrp/poly/elements.rb +168 -0
  50. data/lib/sfrp/poly/exception.rb +42 -0
  51. data/lib/sfrp/poly/expression.rb +170 -0
  52. data/lib/sfrp/poly/monofier.rb +73 -0
  53. data/lib/sfrp/poly/set.rb +90 -0
  54. data/lib/sfrp/poly/typing.rb +197 -0
  55. data/lib/sfrp/raw/dsl.rb +41 -0
  56. data/lib/sfrp/raw/elements.rb +164 -0
  57. data/lib/sfrp/raw/exception.rb +40 -0
  58. data/lib/sfrp/raw/expression.rb +168 -0
  59. data/lib/sfrp/raw/namespace.rb +30 -0
  60. data/lib/sfrp/raw/set.rb +109 -0
  61. data/lib/sfrp/version.rb +3 -0
  62. data/sfrp.gemspec +40 -0
  63. data/spec/sfrp/Test.sfrp +4 -0
  64. data/spec/sfrp/compiler_spec.rb +17 -0
  65. data/spec/sfrp/flat/set_spec.rb +40 -0
  66. data/spec/sfrp/input/parse_test.sfrp +20 -0
  67. data/spec/sfrp/input/set_spec.rb +18 -0
  68. data/spec/sfrp/low/set_spec.rb +20 -0
  69. data/spec/sfrp/mono/expected.yml +295 -0
  70. data/spec/sfrp/mono/set_spec.rb +152 -0
  71. data/spec/sfrp/output/set_spec.rb +29 -0
  72. data/spec/sfrp/poly/set_spec.rb +290 -0
  73. data/spec/sfrp/raw/set_spec.rb +38 -0
  74. data/spec/spec_helper.rb +16 -0
  75. data/test/IntTest/Main.c +5 -0
  76. data/test/IntTest/Main.h +6 -0
  77. data/test/IntTest/Main.sfrp +10 -0
  78. data/test/IntTest/in.txt +3 -0
  79. data/test/IntTest/out.txt +4 -0
  80. data/test/MaybeTest/Main.sfrp +8 -0
  81. data/test/MaybeTest/SubDir/Lib.sfrp +9 -0
  82. data/test/MaybeTest/in.txt +6 -0
  83. data/test/MaybeTest/out.txt +6 -0
  84. data/test/Rakefile +15 -0
  85. metadata +290 -0
@@ -0,0 +1,41 @@
1
+ module SFRP
2
+ module Raw
3
+ extend SFRP::R = self
4
+
5
+ def r(rname, qualifier = nil)
6
+ Ref.new(rname, qualifier)
7
+ end
8
+
9
+ def t(tconst_ref, args, sp = nil)
10
+ TypeAnnotationType.new(tconst_ref, args, sp)
11
+ end
12
+
13
+ def tv(var_str, sp = nil)
14
+ TypeAnnotationVar.new(var_str, sp)
15
+ end
16
+
17
+ def ft(ret_t, arg_ts)
18
+ FuncTypeAnnotation.new(ret_t, arg_ts)
19
+ end
20
+
21
+ def v_e(var_str, sp = nil)
22
+ VarRefExp.new(var_str, sp)
23
+ end
24
+
25
+ def nr_e(node_ref, last, sp = nil)
26
+ NodeRefExp.new(node_ref, last, sp)
27
+ end
28
+
29
+ def call_e(func_ref, args, sp = nil)
30
+ FuncCallExp.new(func_ref, args, sp)
31
+ end
32
+
33
+ def vc_call_e(vconst_ref, args, sp = nil)
34
+ VConstCallExp.new(vconst_ref, args, sp)
35
+ end
36
+
37
+ def seq_e(exps, func_refs, sp = nil)
38
+ SequenceExp.new(exps, func_refs, sp)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,164 @@
1
+ module SFRP
2
+ module Raw
3
+ class Function < Struct.new(:rname, :ns, :ret_ta, :pstrs, :ptas, :exp, :ffi_str, :effect, :sp)
4
+ def absolute_name
5
+ ns.absolute_name(rname)
6
+ end
7
+
8
+ def vconst_refs
9
+ exp ? exp.vconst_refs : []
10
+ end
11
+
12
+ def gen_flat(src_set, dest_set)
13
+ exp.blame_side_effect if exp && !effect
14
+ flat_exp = exp && exp.to_flat(src_set, ns)
15
+ flat_ret_ta = ret_ta && ret_ta.to_flat(src_set, ns)
16
+ flat_ptas = ptas.map { |ta| ta && ta.to_flat(src_set, ns) }
17
+ dest_set << Flat::Function.new(
18
+ absolute_name, flat_ret_ta, pstrs, flat_ptas, flat_exp, ffi_str, sp
19
+ )
20
+ end
21
+ end
22
+
23
+ class TConst < Struct.new(:rname, :ns, :pstrs, :vconsts, :native_str, :static, :sp)
24
+ def absolute_name
25
+ ns.absolute_name(rname)
26
+ end
27
+
28
+ def gen_flat(_src_set, dest_set)
29
+ vconst_strs = vconsts.map(&:absolute_name)
30
+ dest_set << Flat::TConst.new(absolute_name, pstrs, vconst_strs, native_str, static, sp)
31
+ end
32
+ end
33
+
34
+ class VConst < Struct.new(:rname, :tconst_rname, :ns, :native_str, :param_tas, :sp)
35
+ def absolute_name
36
+ ns.absolute_name(rname)
37
+ end
38
+
39
+ def gen_flat(src_set, dest_set)
40
+ tconst_str = src_set.tconst(ns, Ref.new(tconst_rname), sp).absolute_name
41
+ flat_param_tas = param_tas.map { |ta| ta.to_flat(src_set, ns) }
42
+ dest_set << Flat::VConst.new(absolute_name, tconst_str, native_str, flat_param_tas, sp)
43
+ end
44
+ end
45
+
46
+ class PrimTConst < Struct.new(:rname, :ns, :native_str, :pat, :rep, :sp)
47
+ def absolute_name
48
+ ns.absolute_name(rname)
49
+ end
50
+
51
+ def vconst_match?(vconst_str)
52
+ pat.match(vconst_str)
53
+ end
54
+
55
+ def make_vconst(vconst_str)
56
+ raise vconst_str unless vconst_match?(vconst_str)
57
+ VConst.new(vconst_str, rname, ns, vconst_str.gsub(pat, rep), [], sp)
58
+ end
59
+
60
+ def gen_flat(_src_set, dest_set)
61
+ dest_set << Flat::TConst.new(absolute_name, [], nil, native_str, true, sp)
62
+ end
63
+ end
64
+
65
+ class Init < Struct.new(:ns, :func_ref, :arg_exps, :line_number)
66
+ def func_rname
67
+ "%init#{line_number}"
68
+ end
69
+
70
+ def function
71
+ exp = FuncCallExp.new(func_ref, arg_exps, true)
72
+ Function.new(func_rname, ns, nil, [], [], exp, nil, true)
73
+ end
74
+
75
+ def gen_flat(src_set, dest_set)
76
+ function.gen_flat(src_set, dest_set)
77
+ dest_set.append_init_func_str(function.absolute_name)
78
+ end
79
+ end
80
+
81
+ class Node < Struct.new(:rname, :ns, :ta, :exp, :init_exp, :sp)
82
+ def absolute_name
83
+ ns.absolute_name(rname)
84
+ end
85
+
86
+ def vconst_refs
87
+ [exp, init_exp].reject(&:nil?).flat_map(&:vconst_refs)
88
+ end
89
+
90
+ def gen_flat(src_set, dest_set)
91
+ exp.blame_side_effect
92
+ flat_ta = ta && ta.to_flat(src_set, ns)
93
+ flat_init_exp = init_exp && init_exp.to_flat(src_set, ns)
94
+ flat_exp = exp && exp.to_flat(src_set, ns)
95
+ dest_set << Flat::Node.new(absolute_name, flat_ta, flat_exp, flat_init_exp, sp)
96
+ end
97
+ end
98
+
99
+ class Output < Struct.new(:ns, :exps, :func_ref, :line_number, :sp)
100
+ def rname
101
+ "%output_line#{line_number}"
102
+ end
103
+
104
+ def absolute_name
105
+ ns.absolute_name(rname)
106
+ end
107
+
108
+ def convert
109
+ exp = FuncCallExp.new(func_ref, exps, false, sp)
110
+ ta = TypeAnnotationType.new(Ref.new('Unit'), [])
111
+ Node.new(rname, ns, ta, exp, nil, sp)
112
+ end
113
+ end
114
+
115
+ class Input < Struct.new(:rname, :ns, :ta, :arg_exps, :init_exp, :func_ref, :sp)
116
+ def convert
117
+ exp = FuncCallExp.new(func_ref, arg_exps, false, sp)
118
+ Node.new(rname, ns, ta, exp, init_exp, sp)
119
+ end
120
+ end
121
+
122
+ class Infix < Struct.new(:ns, :func_ref, :priority, :direction, :sp)
123
+ LEFT, RIGHT, NONE = :left, :right, :none
124
+
125
+ def absolute_func_name(set)
126
+ func_name = set.func(ns, func_ref, sp).absolute_name
127
+ raise NameError.new(func_ref.to_s, sp) unless func_name
128
+ func_name
129
+ end
130
+
131
+ def absolute_priority(position)
132
+ case direction
133
+ when LEFT
134
+ [priority, 1000 - position]
135
+ when RIGHT
136
+ [priority, position]
137
+ when NONE
138
+ [priority, 0]
139
+ end
140
+ end
141
+ end
142
+
143
+ class FuncTypeAnnotation < Struct.new(:ret_ta, :arg_tas, :sp)
144
+ def to_flat(set, ns)
145
+ flat_arg_tas = arg_tas.map { |ta| ta.to_flat(set, ns) }
146
+ Flat::FuncTypeAnnotation.new(ret_ta.to_flat(set, ns), flat_arg_tas, sp)
147
+ end
148
+ end
149
+
150
+ class TypeAnnotationType < Struct.new(:tconst_ref, :arg_tas, :sp)
151
+ def to_flat(set, ns)
152
+ ab_tc_name = set.tconst(ns, tconst_ref, sp).absolute_name
153
+ flat_arg_tas = arg_tas.map { |ta| ta.to_flat(set, ns) }
154
+ Flat::TypeAnnotationType.new(ab_tc_name, flat_arg_tas, sp)
155
+ end
156
+ end
157
+
158
+ class TypeAnnotationVar < Struct.new(:var_str, :sp)
159
+ def to_flat(_set, _ns)
160
+ Flat::TypeAnnotationVar.new(var_str, sp)
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,40 @@
1
+ require 'sfrp/error'
2
+
3
+ module SFRP
4
+ module Raw
5
+ class NameError < CompileError
6
+ def initialize(target_str, source_position)
7
+ @target_str = target_str
8
+ @source_position = source_position
9
+ end
10
+
11
+ def message
12
+ "Cannot resolve '#{@target_str}'"
13
+ end
14
+ end
15
+
16
+ class AmbiguousNameError < CompileError
17
+ def initialize(target_str, selection_strs, source_position)
18
+ @target_str = target_str
19
+ @selection_strs = selection_strs
20
+ @source_position = source_position
21
+ end
22
+
23
+ def message
24
+ "Ambiguous name '#{@target_str}':\n" +
25
+ @selection_strs.map { |s| ' ' + s }.join("\n")
26
+ end
27
+ end
28
+
29
+ class IllegalSideEffectError < CompileError
30
+ def initialize(target_str, source_position)
31
+ @target_str = target_str
32
+ @source_position = source_position
33
+ end
34
+
35
+ def message
36
+ "Don't call side-effect function '#{@target_str}'"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,168 @@
1
+ module SFRP
2
+ module Raw
3
+ class FuncCallExp < Struct.new(:func_ref, :arg_exps, :effect, :sp)
4
+ def vconst_refs
5
+ arg_exps.flat_map(&:vconst_refs)
6
+ end
7
+
8
+ def blame_side_effect
9
+ raise IllegalSideEffectError.new(func_ref.to_s, sp) if effect
10
+ arg_exps.each(&:blame_side_effect)
11
+ end
12
+
13
+ def to_flat(set, ns)
14
+ ab_func_name = set.func(ns, func_ref, sp).absolute_name
15
+ args = arg_exps.map { |e| e.to_flat(set, ns) }
16
+ Flat::FuncCallExp.new(ab_func_name, args, sp)
17
+ end
18
+ end
19
+
20
+ class VConstCallExp < Struct.new(:vconst_ref, :arg_exps, :sp)
21
+ def vconst_refs
22
+ [vconst_ref, *arg_exps.flat_map(&:vconst_refs)]
23
+ end
24
+
25
+ def blame_side_effect
26
+ arg_exps.each(&:blame_side_effect)
27
+ end
28
+
29
+ def to_flat(set, ns)
30
+ ab_vc_name = set.vconst(ns, vconst_ref, sp).absolute_name
31
+ args = arg_exps.map { |e| e.to_flat(set, ns) }
32
+ Flat::VConstCallExp.new(ab_vc_name, args, sp)
33
+ end
34
+ end
35
+
36
+ class NodeRefExp < Struct.new(:node_ref, :last, :sp)
37
+ def vconst_refs
38
+ []
39
+ end
40
+
41
+ def blame_side_effect
42
+ nil
43
+ end
44
+
45
+ def to_flat(set, ns)
46
+ ab_node_name = set.node(ns, node_ref, sp).absolute_name
47
+ Flat::NodeRefExp.new(ab_node_name, last)
48
+ end
49
+ end
50
+
51
+ class MatchExp < Struct.new(:left_exp, :cases, :sp)
52
+ Case = Struct.new(:pattern, :exp)
53
+
54
+ class Pattern < Struct.new(:vconst_ref, :ref_var_str, :args, :sp)
55
+ def vconst_refs
56
+ (vconst_ref ? [vconst_ref] : []) + args.flat_map(&:vconst_refs)
57
+ end
58
+
59
+ def to_flat(set, ns)
60
+ flat_args = args.map { |a| a.to_flat(set, ns) }
61
+ if vconst_ref
62
+ ab_vc_name = set.vconst(ns, vconst_ref, sp).absolute_name
63
+ Flat::MatchExp::Pattern.new(ab_vc_name, ref_var_str, flat_args, sp)
64
+ else
65
+ Flat::MatchExp::Pattern.new(nil, ref_var_str, flat_args, sp)
66
+ end
67
+ end
68
+ end
69
+
70
+ def vconst_refs
71
+ [left_exp, *cases.map(&:pattern), *cases.map(&:exp)].flat_map(&:vconst_refs)
72
+ end
73
+
74
+ def blame_side_effect
75
+ left_exp.blame_side_effect
76
+ cases.map(&:exp).each(&:blame_side_effect)
77
+ end
78
+
79
+ def to_flat(set, ns)
80
+ flat_cases = cases.map do |c|
81
+ flat_pattern = c.pattern.to_flat(set, ns)
82
+ Flat::MatchExp::Case.new(flat_pattern, c.exp.to_flat(set, ns))
83
+ end
84
+ Flat::MatchExp.new(left_exp.to_flat(set, ns), flat_cases, sp)
85
+ end
86
+ end
87
+
88
+ class VarRefExp < Struct.new(:var_str, :sp)
89
+ def vconst_refs
90
+ []
91
+ end
92
+
93
+ def blame_side_effect
94
+ nil
95
+ end
96
+
97
+ def to_flat(_set, _ns)
98
+ Flat::VarRefExp.new(var_str, sp)
99
+ end
100
+ end
101
+
102
+ class SequenceExp < Struct.new(:exps, :func_refs, :sp)
103
+ def vconst_refs
104
+ exps.flat_map(&:vconst_refs)
105
+ end
106
+
107
+ def blame_side_effect
108
+ exps.each { |e| e.blame_side_effect }
109
+ end
110
+
111
+ def convert(set, ns)
112
+ return exps[0] if exps.size == 1
113
+ pos = set.weakest_op_position(ns, func_refs, sp)
114
+ lseq = SequenceExp.new(exps.take(pos + 1), func_refs.take(pos), sp)
115
+ rseq = SequenceExp.new(exps.drop(pos + 1), func_refs.drop(pos + 1), sp)
116
+ args = [lseq.convert(set, ns), rseq.convert(set, ns)]
117
+ FuncCallExp.new(func_refs[pos], args, false, sp)
118
+ end
119
+
120
+ def to_flat(set, ns)
121
+ convert(set, ns).to_flat(set, ns)
122
+ end
123
+ end
124
+
125
+ module SugarExp
126
+ def vconst_refs
127
+ convert.vconst_refs
128
+ end
129
+
130
+ def blame_side_effect
131
+ convert.blame_side_effect
132
+ end
133
+
134
+ def to_flat(set, ns)
135
+ convert.to_flat(set, ns)
136
+ end
137
+ end
138
+
139
+ class IfExp < Struct.new(:cond_exp, :then_exp, :else_exp, :sp)
140
+ include SugarExp
141
+
142
+ def convert
143
+ cases = [
144
+ MatchExp::Case.new(
145
+ MatchExp::Pattern.new(Ref.new('True'), nil, [], sp), then_exp
146
+ ),
147
+ MatchExp::Case.new(
148
+ MatchExp::Pattern.new(Ref.new('False'), nil, [], sp), else_exp
149
+ )
150
+ ]
151
+ MatchExp.new(cond_exp, cases, sp)
152
+ end
153
+ end
154
+
155
+ class LetExp < Struct.new(:exp, :assignments, :sp)
156
+ include SugarExp
157
+
158
+ Assignment = Struct.new(:pattern, :exp)
159
+
160
+ def convert
161
+ raise if assignments.empty?
162
+ assignments.reverse.reduce(exp) do |e, ass|
163
+ MatchExp.new(ass.exp, [MatchExp::Case.new(ass.pattern, e)], sp)
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,30 @@
1
+ module SFRP
2
+ module Raw
3
+ class Ref < Struct.new(:relative_name, :qualifier_name, :sp)
4
+ def to_s
5
+ return relative_name if qualifier_name.nil?
6
+ qualifier_name + '.' + relative_name
7
+ end
8
+ end
9
+
10
+ class Import < Struct.new(:absolute_namespace_name, :qualifier_name)
11
+
12
+ end
13
+
14
+ class Namespace
15
+ def initialize(absolute_namespace_name, imports)
16
+ @absolute_namespace_name = absolute_namespace_name
17
+ @imports = [Import.new(absolute_namespace_name, nil), *imports]
18
+ end
19
+
20
+ def absolute_name(relative_name)
21
+ @absolute_namespace_name + '.' + relative_name
22
+ end
23
+
24
+ def search_for_absolute_names(ref)
25
+ @imports.select { |i| i.qualifier_name == ref.qualifier_name }
26
+ .map { |i| i.absolute_namespace_name + '.' + ref.relative_name }
27
+ end
28
+ end
29
+ end
30
+ end