sfrp 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,42 @@
1
+ require 'sfrp/error'
2
+
3
+ module SFRP
4
+ module Poly
5
+ class UndeterminableTypeError < CompileError
6
+ def initialize(identifier, typing)
7
+ @identifier = identifier
8
+ @typing = typing
9
+ end
10
+
11
+ def message
12
+ "undeterminable type #{@typing}"
13
+ end
14
+ end
15
+
16
+ class UnifyError < CompileError
17
+ def initialize(typing1, typing2)
18
+ @typing1 = typing1
19
+ @typing2 = typing2
20
+ end
21
+
22
+ def message
23
+ vars = @typing1.variables + @typing2.variables
24
+ "cannot unify #{@typing1.to_s(vars)} and #{@typing2.to_s(vars)}"
25
+ end
26
+ end
27
+
28
+ class RecursiveError < CompileError
29
+ def initialize(node_strs)
30
+ @node_strs = node_strs
31
+ end
32
+
33
+ def chain_str
34
+ [*@node_strs, @node_strs[0]].join(' -> ')
35
+ end
36
+
37
+ def message
38
+ "recursive node/function path: #{chain_str}"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,170 @@
1
+ module SFRP
2
+ module Poly
3
+ class MatchExp
4
+ Case = Struct.new(:pattern, :exp)
5
+
6
+ def initialize(left_exp, cases, id = nil)
7
+ @left_exp = left_exp
8
+ @cases = cases
9
+ @id = id
10
+ end
11
+
12
+ def typing(set, var_env)
13
+ raise if @typing
14
+ left_exp_typing = @left_exp.typing(set, var_env)
15
+ @typing = Typing.new do |t|
16
+ @cases.each do |c|
17
+ new_var_env = var_env.dup
18
+ left_exp_typing.unify(c.pattern.typing(set, new_var_env))
19
+ t.unify(c.exp.typing(set, new_var_env))
20
+ end
21
+ end
22
+ end
23
+
24
+ def clone
25
+ cloned_cases = @cases.map { |c| Case.new(c.pattern.clone, c.exp.clone) }
26
+ MatchExp.new(@left_exp.clone, cloned_cases, @id)
27
+ end
28
+
29
+ def called_func_strs
30
+ [@left_exp, *@cases.map(&:exp)].flat_map(&:called_func_strs)
31
+ end
32
+
33
+ def to_mono(monofier)
34
+ raise UndeterminableTypeError.new(@id, @typing) unless @typing.mono?
35
+ mono_type_str = monofier.use_type(@typing)
36
+ M.match_e(mono_type_str, @left_exp.to_mono(monofier)) do |m|
37
+ @cases.each do |c|
38
+ m.case(c.pattern.to_mono(monofier)) { c.exp.to_mono(monofier) }
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ class FuncCallExp
45
+ def initialize(func_str, arg_exps, id = nil)
46
+ @func_str = func_str
47
+ @arg_exps = arg_exps
48
+ @id = id
49
+ end
50
+
51
+ def typing(set, var_env)
52
+ raise if @typing
53
+ @ftyping = set.func(@func_str).ftyping(set).instance do |ft|
54
+ ft.params.zip(@arg_exps) { |t, e| e.typing(set, var_env).unify(t) }
55
+ end
56
+ @typing = @ftyping.body
57
+ end
58
+
59
+ def clone
60
+ FuncCallExp.new(@func_str, @arg_exps.map(&:clone), @id)
61
+ end
62
+
63
+ def called_func_strs
64
+ [@func_str, *@arg_exps.flat_map(&:called_func_strs)]
65
+ end
66
+
67
+ def to_mono(monofier)
68
+ raise UndeterminableTypeError.new(@id, @typing) unless @typing.mono?
69
+ mono_func_str = monofier.use_func(@func_str, @ftyping)
70
+ args = @arg_exps.map { |e| e.to_mono(monofier) }
71
+ M.call_e(monofier.use_type(@typing), mono_func_str, *args)
72
+ end
73
+ end
74
+
75
+ class VConstCallExp
76
+ def initialize(vconst_str, arg_exps, id = nil)
77
+ @vconst_str = vconst_str
78
+ @arg_exps = arg_exps
79
+ @id = id
80
+ end
81
+
82
+ def typing(set, var_env)
83
+ raise if @typing
84
+ @ftyping = set.vconst(@vconst_str).ftyping.instance do |ft|
85
+ ft.params.zip(@arg_exps) { |t, e| e.typing(set, var_env).unify(t) }
86
+ end
87
+ @typing = @ftyping.body
88
+ end
89
+
90
+ def clone
91
+ VConstCallExp.new(@vconst_str, @arg_exps.map(&:clone), @id)
92
+ end
93
+
94
+ def called_func_strs
95
+ @arg_exps.flat_map(&:called_func_strs)
96
+ end
97
+
98
+ def to_mono(monofier)
99
+ raise UndeterminableTypeError.new(@id, @typing) unless @typing.mono?
100
+ mono_vconst_str = monofier.use_vconst(@vconst_str, @typing)
101
+ args = @arg_exps.map { |e| e.to_mono(monofier) }
102
+ M.vc_call_e(monofier.use_type(@typing), mono_vconst_str, *args)
103
+ end
104
+ end
105
+
106
+ class VarRefExp
107
+ def initialize(var_str, id = nil)
108
+ @var_str = var_str
109
+ @id = id
110
+ end
111
+
112
+ def typing(_set, var_env)
113
+ @typing = var_env[@var_str]
114
+ end
115
+
116
+ def clone
117
+ VarRefExp.new(@var_str, @id)
118
+ end
119
+
120
+ def called_func_strs
121
+ []
122
+ end
123
+
124
+ def to_mono(monofier)
125
+ raise UndeterminableTypeError.new(@id, @typing) unless @typing.mono?
126
+ M.v_e(monofier.use_type(@typing), @var_str)
127
+ end
128
+ end
129
+
130
+ class Pattern
131
+ def initialize(vconst_str, ref_var_str, patterns, id = nil)
132
+ @vconst_str = vconst_str
133
+ @ref_var_str = ref_var_str
134
+ @patterns = patterns
135
+ @id = id
136
+ end
137
+
138
+ def typing(set, var_env)
139
+ raise if @typing
140
+ @typing = Typing.new do |t|
141
+ var_env[@ref_var_str] = t if @ref_var_str
142
+ if @vconst_str
143
+ set.vconst(@vconst_str).ftyping.instance do |ft|
144
+ @patterns.zip(ft.params) do |pat, param_typing|
145
+ pat.typing(set, var_env).unify(param_typing)
146
+ end
147
+ ft.body.unify(t)
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ def clone
154
+ Pattern.new(@vconst_str, @ref_var_str, @patterns.map(&:clone), @id)
155
+ end
156
+
157
+ def to_mono(monofier)
158
+ raise UndeterminableTypeError.new(@id, @typing) unless @typing.mono?
159
+ mono_type_str = monofier.use_type(@typing)
160
+ if @vconst_str
161
+ mono_vconst_str = monofier.use_vconst(@vconst_str, @typing)
162
+ ch = @patterns.map { |pat| pat.to_mono(monofier) }
163
+ M.pref(mono_type_str, mono_vconst_str, @ref_var_str, *ch)
164
+ else
165
+ M.pany(mono_type_str, @ref_var_str)
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,73 @@
1
+ module SFRP
2
+ module Poly
3
+ class Monofier
4
+ def initialize(src_set, dest_set, &block)
5
+ @src_set = src_set
6
+ @dest_set = dest_set
7
+ @type_str = {}
8
+ @func_str = {}
9
+ @vconst_str = {}
10
+ @node_str = {}
11
+ block.call(self) if block
12
+ end
13
+
14
+ def use_type(typing)
15
+ unique_type_str = typing.tconst_str + '/TYPE/' + typing.unique_str
16
+ if @type_str.key?(unique_type_str)
17
+ @type_str[unique_type_str]
18
+ else
19
+ @type_str[unique_type_str] = 'T' + md5(unique_type_str)
20
+ new_tconst = @src_set.tconst(typing.tconst_str).clone
21
+ new_tconst.typing.unify(typing)
22
+ @dest_set << new_tconst.to_mono(self)
23
+ @type_str[unique_type_str]
24
+ end
25
+ end
26
+
27
+ def use_func(func_str, ftyping)
28
+ unique_func_str = func_str + '/FUNC/' + ftyping.unique_str
29
+ if @func_str.key?(unique_func_str)
30
+ @func_str[unique_func_str]
31
+ else
32
+ new_func = @src_set.func(func_str).clone
33
+ mono_func_str = 'F' + md5(unique_func_str)
34
+ new_func.ftyping(@src_set).unify(ftyping)
35
+ @dest_set << new_func.to_mono(self, mono_func_str)
36
+ @func_str[unique_func_str] = mono_func_str
37
+ end
38
+ end
39
+
40
+ def use_vconst(vconst_str, typing)
41
+ unique_vconst_str = vconst_str + '/VCONST/' + typing.unique_str
42
+ if @vconst_str.key?(unique_vconst_str)
43
+ @vconst_str[unique_vconst_str]
44
+ else
45
+ @vconst_str[unique_vconst_str] = 'V' + md5(unique_vconst_str)
46
+ new_vconst = @src_set.vconst(vconst_str).clone
47
+ new_vconst.ftyping.body.unify(typing)
48
+ @dest_set << new_vconst.to_mono(self)
49
+ @vconst_str[unique_vconst_str]
50
+ end
51
+ end
52
+
53
+ def use_node(node_str)
54
+ unique_node_str = node_str + '/NODE/'
55
+ if @node_str.key?(unique_node_str)
56
+ @node_str[unique_node_str]
57
+ else
58
+ @node_str[unique_node_str] = 'N' + md5(unique_node_str)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def md5(str)
65
+ require 'digest/md5'
66
+ @record ||= {}
67
+ hash_val = Digest::MD5.hexdigest(str).to_i(16).to_s(36)[0, 20]
68
+ raise "MD5: #{@record[hash_val]} and #{str}" if @record.key?(hash_val)
69
+ hash_val
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,90 @@
1
+ require 'sfrp/poly/exception'
2
+ require 'sfrp/poly/typing'
3
+ require 'sfrp/poly/elements'
4
+ require 'sfrp/poly/expression'
5
+ require 'sfrp/poly/monofier'
6
+ require 'sfrp/poly/dsl'
7
+
8
+ module SFRP
9
+ module Poly
10
+ class Set
11
+ def initialize(&block)
12
+ @func_h = {}
13
+ @node_h = {}
14
+ @tconst_h = {}
15
+ @vconst_h = {}
16
+ @output_node_strs = []
17
+ @init_func_strs = []
18
+ block.call(self) if block
19
+ end
20
+
21
+ def to_mono
22
+ Mono::Set.new do |dest_set|
23
+ @func_h.values.each do |f|
24
+ f.check_recursion(self)
25
+ f.ftyping(self)
26
+ end
27
+ @node_h.values.each do |n|
28
+ n.check_recursion(self)
29
+ n.typing(self)
30
+ end
31
+ Monofier.new(self, dest_set) do |m|
32
+ @init_func_strs.each do |func_str|
33
+ mono_func_str = m.use_func(func_str, func(func_str).ftyping(self))
34
+ dest_set.append_init_func_str(mono_func_str)
35
+ end
36
+ @node_h.values.each do |node|
37
+ dest_set << node.to_mono(m)
38
+ end
39
+ @output_node_strs.each do |node_str|
40
+ dest_set.append_output_node_str(m.use_node(node_str))
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ def <<(element)
47
+ case element
48
+ when Function
49
+ @func_h[element.str] = element
50
+ when Node
51
+ @node_h[element.str] = element
52
+ when TConst
53
+ @tconst_h[element.str] = element
54
+ when VConst
55
+ @vconst_h[element.str] = element
56
+ else
57
+ raise
58
+ end
59
+ end
60
+
61
+ def append_output_node_str(node_str)
62
+ @output_node_strs << node_str
63
+ end
64
+
65
+ def append_init_func_str(init_func_str)
66
+ @init_func_strs << init_func_str
67
+ end
68
+
69
+ def func(func_str)
70
+ raise func_str unless @func_h.key?(func_str)
71
+ @func_h[func_str]
72
+ end
73
+
74
+ def node(node_str)
75
+ raise node_str unless @node_h.key?(node_str)
76
+ @node_h[node_str]
77
+ end
78
+
79
+ def tconst(tconst_str)
80
+ raise tconst_str unless @tconst_h.key?(tconst_str )
81
+ @tconst_h[tconst_str ]
82
+ end
83
+
84
+ def vconst(vconst_str)
85
+ raise vconst_str unless @vconst_h.key?(vconst_str)
86
+ @vconst_h[vconst_str]
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,197 @@
1
+ module SFRP
2
+ module Poly
3
+ class Typing
4
+ def initialize(tconst_str = nil, arg_typings = [], &block)
5
+ @tconst_str = tconst_str
6
+ @arg_typings = arg_typings
7
+ @parent = nil
8
+ block.call(self) if block
9
+ end
10
+
11
+ def tconst_str
12
+ root == self ? @tconst_str : root.tconst_str
13
+ end
14
+
15
+ def unify(other)
16
+ return self if same?(other)
17
+ return root.unify(other) unless root == self
18
+ if variable? && other.variable?
19
+ @parent = other
20
+ elsif variable? && !other.variable?
21
+ raise UnifyError.new(self, other) if occur?(other)
22
+ @parent = other
23
+ elsif !variable? && other.variable?
24
+ other.unify(self)
25
+ else
26
+ unless tconst_str == other.tconst_str && argc == other.argc
27
+ raise UnifyError.new(self, other)
28
+ end
29
+ arg_typings.zip(other.arg_typings) { |a, b| a.unify(b) }
30
+ @parent = other
31
+ end
32
+ end
33
+
34
+ def unique_str
35
+ raise unless mono?
36
+ "#{tconst_str}[#{arg_typings.map(&:unique_str).join(', ')}]"
37
+ end
38
+
39
+ def mono?
40
+ !variable? && arg_typings.all?(&:mono?)
41
+ end
42
+
43
+ def variables
44
+ return [self] if variable?
45
+ arg_typings.flat_map(&:variables)
46
+ end
47
+
48
+ def to_type_annot(vars)
49
+ if variable?
50
+ idx = vars.index { |v| v.same?(self) }
51
+ raise unless idx
52
+ TypeAnnotationVar.new('a' + idx.to_s)
53
+ else
54
+ args = arg_typings.map { |t| t.to_type_annot(vars) }
55
+ TypeAnnotationType.new(tconst_str, args)
56
+ end
57
+ end
58
+
59
+ def to_s(vars = nil)
60
+ vars ||= variables
61
+ to_type_annot(vars).to_s
62
+ end
63
+
64
+ protected
65
+
66
+ def root
67
+ @parent ? (@parent = @parent.root) : self
68
+ end
69
+
70
+ def argc
71
+ arg_typings.size
72
+ end
73
+
74
+ def arg_typings
75
+ root == self ? @arg_typings : root.arg_typings
76
+ end
77
+
78
+ def variable?
79
+ tconst_str.nil?
80
+ end
81
+
82
+ def same?(other)
83
+ return true if root == other.root
84
+ return false if variable? || other.variable?
85
+ return false unless tconst_str == other.tconst_str && argc == other.argc
86
+ arg_typings.zip(other.arg_typings).all? { |a, b| a.same?(b) }
87
+ end
88
+
89
+ def occur?(other)
90
+ raise unless variable?
91
+ return true if same?(other)
92
+ arg_typings.any? { |t| occur?(t) }
93
+ end
94
+ end
95
+
96
+ class FuncTyping
97
+ attr_reader :params, :body
98
+
99
+ def initialize(param_size, &block)
100
+ @params = Array.new(param_size) { Typing.new }
101
+ @body = Typing.new
102
+ block.call(self) if block
103
+ end
104
+
105
+ def to_ftype_annot
106
+ vars = @body.variables + @params.flat_map(&:variables)
107
+ args = @params.map { |t| t.to_type_annot(vars) }
108
+ FuncTypeAnnotation.new(@body.to_type_annot(vars), args)
109
+ end
110
+
111
+ def unify(other)
112
+ raise unless @params.size == other.params.size
113
+ @params.zip(other.params) { |a, b| a.unify(b) }
114
+ @body.unify(other.body)
115
+ self
116
+ end
117
+
118
+ def instance(&block)
119
+ instance = to_ftype_annot.to_ftyping
120
+ block.call(instance) if block
121
+ instance
122
+ end
123
+
124
+ def unique_str
125
+ args = @params + [@body]
126
+ "Func#{@params.size}[#{args.map(&:unique_str).join(', ')}]"
127
+ end
128
+
129
+ def mono?
130
+ [@body, *@params].all?(&:mono?)
131
+ end
132
+
133
+ def to_s
134
+ to_ftype_annot.to_s
135
+ end
136
+ end
137
+
138
+ class FuncTypeAnnotation
139
+ def initialize(ret_type_annot, arg_type_annots)
140
+ @ret_type_annot = ret_type_annot
141
+ @arg_type_annots = arg_type_annots
142
+ end
143
+
144
+ def to_ftyping(var_strs = nil)
145
+ var_strs ||= [@ret_type_annot, *@arg_type_annots].flat_map(&:var_strs)
146
+ tbl = Hash[var_strs.uniq.map { |s| [s, Typing.new] }]
147
+ FuncTyping.new(@arg_type_annots.size) do |ft|
148
+ ft.params.zip(@arg_type_annots) { |t, at| t.unify(at.to_typing(tbl)) }
149
+ ft.body.unify(@ret_type_annot.to_typing(tbl))
150
+ end
151
+ end
152
+
153
+ def to_s
154
+ "(#{@arg_type_annots.map(&:to_s).join(', ')}) -> #{@ret_type_annot}"
155
+ end
156
+ end
157
+
158
+ class TypeAnnotationType
159
+ def initialize(tconst_str, arg_type_annots)
160
+ @tconst_str = tconst_str
161
+ @arg_type_annots = arg_type_annots
162
+ end
163
+
164
+ def to_typing(tbl)
165
+ Typing.new(@tconst_str, @arg_type_annots.map { |ta| ta.to_typing(tbl) })
166
+ end
167
+
168
+ def var_strs
169
+ @arg_type_annots.flat_map(&:var_strs)
170
+ end
171
+
172
+ def to_s
173
+ return @tconst_str if @arg_type_annots.empty?
174
+ "#{@tconst_str}[#{@arg_type_annots.map(&:to_s).join(', ')}]"
175
+ end
176
+ end
177
+
178
+ class TypeAnnotationVar
179
+ def initialize(var_str)
180
+ @var_str = var_str
181
+ end
182
+
183
+ def to_typing(tbl)
184
+ raise var_str unless tbl.key?(@var_str)
185
+ tbl[@var_str]
186
+ end
187
+
188
+ def var_strs
189
+ [@var_str]
190
+ end
191
+
192
+ def to_s
193
+ @var_str
194
+ end
195
+ end
196
+ end
197
+ end