sfrp 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.ctags +3 -0
- data/.editorconfig +9 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +629 -0
- data/.travis.yml +12 -0
- data/Gemfile +2 -0
- data/LICENSE +28 -0
- data/README.md +34 -0
- data/Rakefile +1 -0
- data/base-library/Base.sfrp +81 -0
- data/base-library/IO/AVR/ATMEGA8.c +9 -0
- data/base-library/IO/AVR/ATMEGA8.h +6 -0
- data/base-library/IO/AVR/ATMEGA8.sfrp +4 -0
- data/base-library/IO/STDIO.c +40 -0
- data/base-library/IO/STDIO.h +13 -0
- data/base-library/IO/STDIO.sfrp +10 -0
- data/bin/sfrp +7 -0
- data/lib/sfrp.rb +2 -0
- data/lib/sfrp/command.rb +73 -0
- data/lib/sfrp/compiler.rb +94 -0
- data/lib/sfrp/error.rb +4 -0
- data/lib/sfrp/file.rb +18 -0
- data/lib/sfrp/flat/dsl.rb +33 -0
- data/lib/sfrp/flat/elements.rb +90 -0
- data/lib/sfrp/flat/exception.rb +45 -0
- data/lib/sfrp/flat/expression.rb +125 -0
- data/lib/sfrp/flat/set.rb +61 -0
- data/lib/sfrp/input/exception.rb +16 -0
- data/lib/sfrp/input/parser.rb +417 -0
- data/lib/sfrp/input/set.rb +29 -0
- data/lib/sfrp/input/transformer.rb +219 -0
- data/lib/sfrp/low/dsl.rb +126 -0
- data/lib/sfrp/low/element.rb +126 -0
- data/lib/sfrp/low/set.rb +62 -0
- data/lib/sfrp/mono/dsl.rb +120 -0
- data/lib/sfrp/mono/environment.rb +26 -0
- data/lib/sfrp/mono/exception.rb +21 -0
- data/lib/sfrp/mono/expression.rb +124 -0
- data/lib/sfrp/mono/function.rb +86 -0
- data/lib/sfrp/mono/memory.rb +32 -0
- data/lib/sfrp/mono/node.rb +125 -0
- data/lib/sfrp/mono/pattern.rb +69 -0
- data/lib/sfrp/mono/set.rb +151 -0
- data/lib/sfrp/mono/type.rb +210 -0
- data/lib/sfrp/mono/vconst.rb +134 -0
- data/lib/sfrp/output/set.rb +33 -0
- data/lib/sfrp/poly/dsl.rb +171 -0
- data/lib/sfrp/poly/elements.rb +168 -0
- data/lib/sfrp/poly/exception.rb +42 -0
- data/lib/sfrp/poly/expression.rb +170 -0
- data/lib/sfrp/poly/monofier.rb +73 -0
- data/lib/sfrp/poly/set.rb +90 -0
- data/lib/sfrp/poly/typing.rb +197 -0
- data/lib/sfrp/raw/dsl.rb +41 -0
- data/lib/sfrp/raw/elements.rb +164 -0
- data/lib/sfrp/raw/exception.rb +40 -0
- data/lib/sfrp/raw/expression.rb +168 -0
- data/lib/sfrp/raw/namespace.rb +30 -0
- data/lib/sfrp/raw/set.rb +109 -0
- data/lib/sfrp/version.rb +3 -0
- data/sfrp.gemspec +40 -0
- data/spec/sfrp/Test.sfrp +4 -0
- data/spec/sfrp/compiler_spec.rb +17 -0
- data/spec/sfrp/flat/set_spec.rb +40 -0
- data/spec/sfrp/input/parse_test.sfrp +20 -0
- data/spec/sfrp/input/set_spec.rb +18 -0
- data/spec/sfrp/low/set_spec.rb +20 -0
- data/spec/sfrp/mono/expected.yml +295 -0
- data/spec/sfrp/mono/set_spec.rb +152 -0
- data/spec/sfrp/output/set_spec.rb +29 -0
- data/spec/sfrp/poly/set_spec.rb +290 -0
- data/spec/sfrp/raw/set_spec.rb +38 -0
- data/spec/spec_helper.rb +16 -0
- data/test/IntTest/Main.c +5 -0
- data/test/IntTest/Main.h +6 -0
- data/test/IntTest/Main.sfrp +10 -0
- data/test/IntTest/in.txt +3 -0
- data/test/IntTest/out.txt +4 -0
- data/test/MaybeTest/Main.sfrp +8 -0
- data/test/MaybeTest/SubDir/Lib.sfrp +9 -0
- data/test/MaybeTest/in.txt +6 -0
- data/test/MaybeTest/out.txt +6 -0
- data/test/Rakefile +15 -0
- metadata +290 -0
data/lib/sfrp/low/set.rb
ADDED
@@ -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
|