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,62 @@
1
+ require 'sfrp/low/element'
2
+ require 'sfrp/low/dsl'
3
+
4
+ module SFRP
5
+ module Low
6
+ class Set
7
+ attr_reader :meta, :typedefs, :structs, :functions, :macros, :includes
8
+
9
+ def initialize(&block)
10
+ @typedefs = []
11
+ @structs = []
12
+ @functions = []
13
+ @macros = []
14
+ @includes = []
15
+ block.call(self) if block
16
+ end
17
+
18
+ def to_output
19
+ Output::Set.new do |dest_set|
20
+ dest_set.create_file('main', 'c', main_file_content)
21
+ end
22
+ end
23
+
24
+ def <<(element)
25
+ case element
26
+ when Typedef
27
+ @typedefs << element
28
+ when Structure
29
+ @structs << element
30
+ when Function
31
+ @functions << element
32
+ when Macro
33
+ @macros << element
34
+ when Include
35
+ @includes << element
36
+ else
37
+ raise
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def main_file_content
44
+ elements = []
45
+ @includes.each { |x| elements << x.to_s }
46
+ @macros.each { |x| elements << x.to_s }
47
+ @typedefs.each { |x| elements << x.to_s }
48
+ @structs.each { |x| elements << x.to_s }
49
+ @functions.each do |x|
50
+ elements << x.pretty_code_prototype
51
+ end
52
+ @functions.each { |x| elements << x.to_s }
53
+ elements.join("\n")
54
+ end
55
+
56
+ def header_file_content
57
+ elements = []
58
+ elements.join("\n")
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,120 @@
1
+ module SFRP
2
+ module Mono
3
+ module DSL
4
+ extend SFRP::M = self
5
+
6
+ def type(type_str, vconst_strs = nil, static = false, native_str = nil)
7
+ Type.new(type_str, vconst_strs, static, native_str)
8
+ end
9
+
10
+ def vconst(type_str, vconst_str, arg_type_strs, native_str = nil)
11
+ VConst.new(vconst_str, type_str, arg_type_strs, native_str)
12
+ end
13
+
14
+ def node(type_str, node_str, eval_func_str, init_func_str = nil, &block)
15
+ px = NodeDepProxy.new
16
+ block.call(px) if block
17
+ Node.new(node_str, type_str, px.to_a, eval_func_str, init_func_str)
18
+ end
19
+
20
+ def func(type_str, func_str, &block)
21
+ fp = FuncProxy.new
22
+ block.call(fp) if block
23
+ ftype = fp.ftype(type_str)
24
+ Function.new(func_str, fp.param_strs, ftype, fp.exp, fp.ffi_str)
25
+ end
26
+
27
+ def match_e(type_str, left_exp, &block)
28
+ cp = CaseProxy.new
29
+ block.call(cp) if block
30
+ MatchExp.new(type_str, left_exp, cp.to_a)
31
+ end
32
+
33
+ def call_e(type_str, func_str, *arg_exps)
34
+ FuncCallExp.new(type_str, func_str, arg_exps)
35
+ end
36
+
37
+ def vc_call_e(type_str, vconst_str, *arg_exps)
38
+ VConstCallExp.new(type_str, vconst_str, arg_exps)
39
+ end
40
+
41
+ def v_e(type_str, var_str)
42
+ VarRefExp.new(type_str, var_str)
43
+ end
44
+
45
+ def pat(type_str, vconst_str, *arg_patterns)
46
+ Pattern.new(type_str, vconst_str, nil, arg_patterns)
47
+ end
48
+
49
+ def pref(type_str, vconst_str, ref_var_str, *arg_patterns)
50
+ Pattern.new(type_str, vconst_str, ref_var_str, arg_patterns)
51
+ end
52
+
53
+ def pany(type_str, ref_var_str = nil)
54
+ Pattern.new(type_str, nil, ref_var_str, [])
55
+ end
56
+
57
+ class NodeDepProxy
58
+ def initialize
59
+ @node_refs = []
60
+ end
61
+
62
+ def l(node_str)
63
+ @node_refs << Node::NodeRef.new(node_str, true)
64
+ end
65
+
66
+ def c(node_str)
67
+ @node_refs << Node::NodeRef.new(node_str, false)
68
+ end
69
+
70
+ def to_a
71
+ @node_refs
72
+ end
73
+ end
74
+
75
+ class CaseProxy
76
+ def initialize
77
+ @cases = []
78
+ end
79
+
80
+ def case(pattern, &exp_block)
81
+ @cases << MatchExp::Case.new(pattern, exp_block.call)
82
+ end
83
+
84
+ def to_a
85
+ @cases
86
+ end
87
+ end
88
+
89
+ class FuncProxy
90
+ def initialize
91
+ @param_type_strs = []
92
+ @param_strs = []
93
+ end
94
+
95
+ def param(type_str, param_str)
96
+ @param_type_strs << type_str
97
+ @param_strs << param_str
98
+ end
99
+
100
+ def exp(&exp_block)
101
+ @exp = exp_block.call if exp_block
102
+ @exp
103
+ end
104
+
105
+ def ffi_str(str = nil)
106
+ @ffi_str = str if str
107
+ @ffi_str
108
+ end
109
+
110
+ def param_strs
111
+ @param_strs
112
+ end
113
+
114
+ def ftype(return_type_str)
115
+ Function::FType.new(@param_type_strs, return_type_str)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,26 @@
1
+ module SFRP
2
+ module Mono
3
+ class Environment
4
+ def initialize
5
+ @serial_queue = ('_v00'..'_v99').to_a
6
+ @var_str_to_type_str = {}
7
+ end
8
+
9
+ def new_var(type_str)
10
+ var = @serial_queue.shift
11
+ @var_str_to_type_str[var] = type_str
12
+ var
13
+ end
14
+
15
+ def add_var(var_str, type_str)
16
+ @var_str_to_type_str[var_str] = type_str
17
+ end
18
+
19
+ def each_declared_vars(&block)
20
+ @var_str_to_type_str.each do |var_str, type_str|
21
+ block.call(var_str, type_str)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ require 'sfrp/error'
2
+
3
+ module SFRP
4
+ module Mono
5
+ class InvalidTypeOfForeignFunctionError < CompileError
6
+ def initialize(ffi_str)
7
+ @ffi_str = ffi_str
8
+ end
9
+
10
+ def message
11
+ "foreign function '#{@ffi_str}' returns invalid type'"
12
+ end
13
+ end
14
+
15
+ class IncompleteMatchExpError < CompileError
16
+ def message
17
+ "incomplete match-exp"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,124 @@
1
+ module SFRP
2
+ module Mono
3
+ class Exp
4
+ attr_reader :type_str
5
+
6
+ def ==(other)
7
+ comp == other.comp
8
+ end
9
+ end
10
+
11
+ class MatchExp < Exp
12
+ Case = Struct.new(:pattern, :exp)
13
+
14
+ def initialize(type_str, left_exp, cases, id = nil)
15
+ @type_str = type_str
16
+ @left_exp = left_exp
17
+ @cases = cases
18
+ @id = id
19
+ end
20
+
21
+ def comp
22
+ [@type_str, @left_exp, @cases]
23
+ end
24
+
25
+ # Note that the expression this returns is not wrapped by ().
26
+ def to_low(set, env)
27
+ check_completeness(set)
28
+ tmp_var_str = env.new_var(@left_exp.type_str)
29
+ left_let_exp = "#{tmp_var_str} = #{@left_exp.to_low(set, env)}"
30
+ case_exp = L.if_chain_exp do |i|
31
+ @cases.each do |c|
32
+ cond_exps = c.pattern.low_cond_exps(set, tmp_var_str)
33
+ let_exps = c.pattern.low_let_exps(set, tmp_var_str, env)
34
+ exp = (let_exps + [c.exp.to_low(set, env)]).join(', ')
35
+ i.finish(exp) if cond_exps.empty?
36
+ i.append_case(cond_exps.join(' && '), exp)
37
+ end
38
+ end
39
+ "#{left_let_exp}, #{case_exp}"
40
+ end
41
+
42
+ def check_completeness(set)
43
+ set.type(@left_exp.type_str).all_pattern_examples(set).each do |exam|
44
+ unless @cases.any? { |c| c.pattern.accept?(exam) }
45
+ raise IncompleteMatchExpError.new
46
+ end
47
+ end
48
+ end
49
+
50
+ def memory(set)
51
+ m = @cases.map { |c| c.exp.memory(set) }.reduce { |a, b| a.or(b) }
52
+ @left_exp.memory(set).and(m)
53
+ end
54
+ end
55
+
56
+ class FuncCallExp < Exp
57
+ def initialize(type_str, func_str, arg_exps, id = nil)
58
+ @type_str = type_str
59
+ @func_str = func_str
60
+ @arg_exps = arg_exps
61
+ @id = id
62
+ end
63
+
64
+ def comp
65
+ [@type_str, @func_str, @arg_exps]
66
+ end
67
+
68
+ def to_low(set, env)
69
+ low_arg_exps = @arg_exps.map { |e| e.to_low(set, env) }
70
+ set.func(@func_str).low_call_exp_in_exp(set, env, low_arg_exps)
71
+ end
72
+
73
+ def memory(set)
74
+ @arg_exps.reduce(set.func(@func_str).memory(set)) do |m, e|
75
+ m.and(e.memory(set))
76
+ end
77
+ end
78
+ end
79
+
80
+ class VConstCallExp < Exp
81
+ def initialize(type_str, vconst_str, arg_exps, id = nil)
82
+ @type_str = type_str
83
+ @vconst_str = vconst_str
84
+ @arg_exps = arg_exps
85
+ @id = id
86
+ end
87
+
88
+ def comp
89
+ [@type_str, @vconst_strs, @arg_exps]
90
+ end
91
+
92
+ def to_low(set, env)
93
+ low_arg_exps = @arg_exps.map { |e| e.to_low(set, env) }
94
+ set.vconst(@vconst_str).low_constructor_call_exp(low_arg_exps)
95
+ end
96
+
97
+ def memory(set)
98
+ @arg_exps.reduce(Memory.one(@type_str)) do |m, e|
99
+ m.and(e.memory(set))
100
+ end
101
+ end
102
+ end
103
+
104
+ class VarRefExp < Exp
105
+ def initialize(type_str, var_str, id = nil)
106
+ @type_str = type_str
107
+ @var_str = var_str
108
+ @id = id
109
+ end
110
+
111
+ def comp
112
+ [@type_str, @var_str]
113
+ end
114
+
115
+ def to_low(_set, _env)
116
+ @var_str
117
+ end
118
+
119
+ def memory(_set)
120
+ Memory.empty
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,86 @@
1
+ require 'sfrp/mono/exception'
2
+
3
+ module SFRP
4
+ module Mono
5
+ class Function
6
+ FType = Struct.new(:param_type_strs, :return_type_str)
7
+
8
+ attr_reader :str
9
+
10
+ def initialize(str, param_strs, ftype, exp = nil, ffi_str = nil)
11
+ raise ArgumentError if exp.nil? && ffi_str.nil?
12
+ raise ArgumentError unless param_strs.size == ftype.param_type_strs.size
13
+ @str = str
14
+ @param_strs = param_strs
15
+ @ftype = ftype
16
+ @exp = exp
17
+ @ffi_str = ffi_str
18
+ end
19
+
20
+ def comp
21
+ [@str, @param_strs, @ftype, @exp, @ffi_str]
22
+ end
23
+
24
+ def ==(other)
25
+ comp == other.comp
26
+ end
27
+
28
+ # Return max needed memory size to call this function once.
29
+ # If this func is a foreign function, this size is assumed as max needed
30
+ # memory size to hold return-type.
31
+ def memory(set)
32
+ return set.type(@ftype.return_type_str).memory(set) if @ffi_str
33
+ @exp.memory(set)
34
+ end
35
+
36
+ # Return low-expression to call this function.
37
+ def low_call_exp(low_arg_exps)
38
+ return L.call_exp(@ffi_str, low_arg_exps) if @ffi_str
39
+ L.call_exp(@str, low_arg_exps)
40
+ end
41
+
42
+ def low_call_exp_in_exp(set, env, low_arg_exps)
43
+ if @ffi_str
44
+ type = set.type(@ftype.return_type_str)
45
+ if @ffi_str !~ /[a-zA-Z]/
46
+ if low_arg_exps.size == 2
47
+ return "(#{low_arg_exps[0]}) #{@ffi_str} (#{low_arg_exps[1]})"
48
+ end
49
+ if low_arg_exps.size == 1
50
+ return "#{@ffi_str} (#{low_arg_exps[0]})"
51
+ end
52
+ raise InvalidTypeOfForeignFunctionError.new(@ffi_str)
53
+ end
54
+ if type.native?
55
+ return L.call_exp(@ffi_str, low_arg_exps)
56
+ end
57
+ if type.linear?(set)
58
+ var = env.new_var(@ftype.return_type_str)
59
+ pointers = type.low_member_pointers_for_single_vconst(set, var)
60
+ call_exp = L.call_exp(@ffi_str, low_arg_exps + pointers)
61
+ return "(#{var} = #{type.low_allocator_str}(0), #{call_exp}, #{var})"
62
+ end
63
+ raise InvalidTypeOfForeignFunctionError.new(@ffi_str)
64
+ end
65
+ L.call_exp(@str, low_arg_exps)
66
+ end
67
+
68
+ # Generate function in C for this function.
69
+ def gen(src_set, dest_set)
70
+ return if @ffi_str
71
+ env = Environment.new
72
+ type = src_set.type(@ftype.return_type_str)
73
+ dest_set << L.function(@str, type.low_type_str) do |f|
74
+ @param_strs.zip(@ftype.param_type_strs).map do |p_str, t_str|
75
+ f.append_param(src_set.type(t_str).low_type_str, p_str)
76
+ end
77
+ stmt = L.stmt("return #{@exp.to_low(src_set, env)}")
78
+ env.each_declared_vars do |var_str, type_str|
79
+ f << L.stmt("#{src_set.type(type_str).low_type_str} #{var_str}")
80
+ end
81
+ f << stmt
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,32 @@
1
+ module SFRP
2
+ module Mono
3
+ class Memory
4
+ def self.empty
5
+ Memory.new
6
+ end
7
+
8
+ def self.one(type_str)
9
+ Memory.new(type_str => 1)
10
+ end
11
+
12
+ def initialize(hash = {})
13
+ @hash = hash
14
+ end
15
+
16
+ def and(other)
17
+ Memory.new(@hash.merge(other.hash) { |_, v1, v2| v1 + v2 })
18
+ end
19
+
20
+ def or(other)
21
+ Memory.new(@hash.merge(other.hash) { |_, v1, v2| [v1, v2].max })
22
+ end
23
+
24
+ def count(type_str)
25
+ @hash[type_str] || 0
26
+ end
27
+
28
+ protected
29
+ attr_reader :hash
30
+ end
31
+ end
32
+ end