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,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