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/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Copyright (c) 2016, Kensuke Sawada
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
12
|
+
documentation and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
3. Neither the name of the copyright holder nor the names of its
|
15
|
+
contributors may be used to endorse or promote products derived from
|
16
|
+
this software without specific prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
19
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
20
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
21
|
+
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
22
|
+
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
24
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
25
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
26
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
28
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
SFRP
|
2
|
+
=====
|
3
|
+
|
4
|
+
Pure Functional Language for microcontrollers.
|
5
|
+
|
6
|
+
[![Build Status](https://travis-ci.org/sfrp/sfrp.svg?branch=master)](https://travis-ci.org/sfrp/sfrp)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/github/sfrp/sfrp/badge.svg?branch=master)](https://coveralls.io/github/sfrp/sfrp?branch=master)
|
8
|
+
|
9
|
+
# Install SFRP
|
10
|
+
```
|
11
|
+
$ git clone https://github.com/sfrp/sfrp.git ~/sfrp
|
12
|
+
$ cd ~/sfrp
|
13
|
+
$ rake install
|
14
|
+
```
|
15
|
+
For updating, `git pull && rake install`.
|
16
|
+
|
17
|
+
# Usage Example
|
18
|
+
Write following simple accumulator program.
|
19
|
+
```
|
20
|
+
-- Main.sfrp
|
21
|
+
import Base
|
22
|
+
import IO.STDIO as IO
|
23
|
+
|
24
|
+
in @x from IO.$getInt()
|
25
|
+
out IO.$putInt(@y)
|
26
|
+
|
27
|
+
@y 0 = @x + @@y
|
28
|
+
```
|
29
|
+
|
30
|
+
Compile and Run the program.
|
31
|
+
```
|
32
|
+
$ sfrp Main --build=cc
|
33
|
+
$ ./Main
|
34
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,81 @@
|
|
1
|
+
ptype Int{int} = /^((0x)?[0-9]+)$/\1/
|
2
|
+
ptype Float{float} = /^([0-9]+\.[0-9]+)$/\1f/
|
3
|
+
ptype Bool{int} = True{1} | False{0}
|
4
|
+
ptype Unit{int} = Unit{0}
|
5
|
+
|
6
|
+
type Maybe[a] = Just(a) | Nothing
|
7
|
+
type Either[a, b] = Left(a) | Right(b)
|
8
|
+
type Tuple2[a, b] = Tuple2(a, b)
|
9
|
+
type Tuple3[a, b, c] = Tuple3(a, b, c)
|
10
|
+
type Tuple4[a, b, c, d] = Tuple4(a, b, c, d)
|
11
|
+
type Tuple5[a, b, c, d, e] = Tuple5(a, b, c, d, e)
|
12
|
+
|
13
|
+
fst(pair : (a, b)) : a = x where (x, _) = pair
|
14
|
+
snd(pair : (a, b)) : b = y where (_, y) = pair
|
15
|
+
|
16
|
+
foreign - as '-(Int) : Int
|
17
|
+
foreign + as '+(Int) : Int
|
18
|
+
foreign ! as '!(Bool) : Bool
|
19
|
+
|
20
|
+
infix || 8
|
21
|
+
foreign || as ||(Bool, Bool) : Bool
|
22
|
+
|
23
|
+
infix && 9
|
24
|
+
foreign && as &&(Bool, Bool) : Bool
|
25
|
+
|
26
|
+
infixl | 10
|
27
|
+
foreign | as |(Int, Int) : Int
|
28
|
+
|
29
|
+
infixl ^ 11
|
30
|
+
foreign ^ as ^(Int, Int) : Int
|
31
|
+
|
32
|
+
infixl & 12
|
33
|
+
foreign & as &(Int, Int) : Int
|
34
|
+
|
35
|
+
infixl == 13
|
36
|
+
infixl != 13
|
37
|
+
infixl \= 13
|
38
|
+
foreign == as ==(Int, Int) : Bool
|
39
|
+
foreign != as !=(Int, Int) : Bool
|
40
|
+
foreign \= as \=(Int, Int) : Bool
|
41
|
+
|
42
|
+
infixl < 14
|
43
|
+
infixl <= 14
|
44
|
+
infixl > 14
|
45
|
+
infixl >= 14
|
46
|
+
infixl <. 14
|
47
|
+
infixl <=. 14
|
48
|
+
infixl >. 14
|
49
|
+
infixl >=. 14
|
50
|
+
foreign < as <(Int, Int) : Bool
|
51
|
+
foreign <= as <=(Int, Int) : Bool
|
52
|
+
foreign > as >(Int, Int) : Bool
|
53
|
+
foreign >= as >=(Int, Int) : Bool
|
54
|
+
foreign < as <.(Float, Float) : Bool
|
55
|
+
foreign <= as <=.(Float, Float) : Bool
|
56
|
+
foreign > as >.(Float, Float) : Bool
|
57
|
+
foreign >= as >=.(Float, Float) : Bool
|
58
|
+
|
59
|
+
infixl << 15
|
60
|
+
infixl >> 15
|
61
|
+
foreign << as <<(Int, Int) : Int
|
62
|
+
foreign >> as >>(Int, Int) : Int
|
63
|
+
|
64
|
+
infixl + 16
|
65
|
+
infixl - 16
|
66
|
+
infixl +. 16
|
67
|
+
foreign + as +(Int, Int) : Int
|
68
|
+
foreign - as -(Int, Int) : Int
|
69
|
+
foreign + as +.(Float, Float) : Float
|
70
|
+
foreign - as -.(Float, Float) : Float
|
71
|
+
|
72
|
+
infixl * 17
|
73
|
+
infixl / 17
|
74
|
+
infixl % 17
|
75
|
+
infixl *. 17
|
76
|
+
infixl /. 17
|
77
|
+
foreign * as *(Int, Int) : Int
|
78
|
+
foreign / as /(Int, Int) : Int
|
79
|
+
foreign % as %(Int, Int) : Int
|
80
|
+
foreign * as *.(Float, Float) : Float
|
81
|
+
foreign / as /.(Float, Float) : Float
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
|
4
|
+
int get_int() {
|
5
|
+
int x;
|
6
|
+
if (scanf("%d", &x) == EOF) {
|
7
|
+
exit(0);
|
8
|
+
}
|
9
|
+
return x;
|
10
|
+
}
|
11
|
+
|
12
|
+
int put_int(int x) {
|
13
|
+
printf("%d\n", x);
|
14
|
+
return 0;
|
15
|
+
}
|
16
|
+
|
17
|
+
float get_float() {
|
18
|
+
float x;
|
19
|
+
if (scanf("%f", &x) == EOF) {
|
20
|
+
exit(0);
|
21
|
+
}
|
22
|
+
return x;
|
23
|
+
}
|
24
|
+
|
25
|
+
int put_float(float x) {
|
26
|
+
printf("%f\n", x);
|
27
|
+
return 0;
|
28
|
+
}
|
29
|
+
|
30
|
+
int get_int_pair(int* a, int* b) {
|
31
|
+
if (scanf("%d %d", a, b) == EOF) {
|
32
|
+
exit(0);
|
33
|
+
}
|
34
|
+
return 0;
|
35
|
+
}
|
36
|
+
|
37
|
+
int put_int_pair(int a, int b) {
|
38
|
+
printf("(%d, %d)\n", a, b);
|
39
|
+
return 0;
|
40
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import Base
|
2
|
+
|
3
|
+
foreign get_int as $getInt() : Int
|
4
|
+
foreign put_int as $putInt(Int) : Unit
|
5
|
+
|
6
|
+
foreign get_float as $getFloat() : Float
|
7
|
+
foreign put_float as $putFloat(Float) : Unit
|
8
|
+
|
9
|
+
foreign get_int_pair as $getIntPair() : (Int, Int)
|
10
|
+
foreign put_int_pair as $putIntPair(Int, Int) : Unit
|
data/bin/sfrp
ADDED
data/lib/sfrp.rb
ADDED
data/lib/sfrp/command.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'sfrp/compiler'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module SFRP
|
5
|
+
class Command < Struct.new(
|
6
|
+
:main_file, :out_dir, :show_files, :include_paths, :error_class, :cc
|
7
|
+
)
|
8
|
+
def self.from_argv(argv, include_path)
|
9
|
+
com = new('Main', './output', false, ['.'], false, nil)
|
10
|
+
extract_argv(com, argv)
|
11
|
+
com[:include_paths] << include_path
|
12
|
+
com
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.extract_argv(com, argv)
|
16
|
+
opt_parser = OptionParser.new do |parse|
|
17
|
+
desc = 'show paths of the .c file'
|
18
|
+
parse.on('--show-files', desc) do
|
19
|
+
com.show_files = true
|
20
|
+
end
|
21
|
+
desc = 'specify output directory (default is ./output)'
|
22
|
+
parse.on('--out=DIR_NAME', desc) do |dir|
|
23
|
+
com.out_dir = './' + dir.gsub(/\/$/, '')
|
24
|
+
end
|
25
|
+
desc = 'add include path (multi specification is allowed)'
|
26
|
+
parse.on('--include=PATH', desc) do |path|
|
27
|
+
com.include_paths << path
|
28
|
+
end
|
29
|
+
desc = 'only print error (do not generate compiled file)'
|
30
|
+
parse.on('--only-print-error', desc) do
|
31
|
+
com.out_dir = nil
|
32
|
+
end
|
33
|
+
desc = 'print error class instead of error message'
|
34
|
+
parse.on('--error-class', desc) do
|
35
|
+
com.error_class = true
|
36
|
+
end
|
37
|
+
desc = 'make binary by given command'
|
38
|
+
parse.on('--build=CC', desc) do |cc|
|
39
|
+
com.cc = cc
|
40
|
+
end
|
41
|
+
end
|
42
|
+
args_without_option = opt_parser.parse(argv)
|
43
|
+
case args_without_option.size
|
44
|
+
when 0
|
45
|
+
nil
|
46
|
+
when 1
|
47
|
+
com.main_file = args_without_option[0].gsub(/\.sfrp$/, '')
|
48
|
+
else
|
49
|
+
STDERR.puts 'invalid target specification'
|
50
|
+
exit(1)
|
51
|
+
end
|
52
|
+
rescue OptionParser::InvalidOption => error
|
53
|
+
puts error.message
|
54
|
+
exit(1)
|
55
|
+
end
|
56
|
+
|
57
|
+
def run
|
58
|
+
outs = Compiler.new(main_file, include_paths).compile(out_dir)
|
59
|
+
out_paths = outs.map { |o| out_dir + '/' + o + '.c' }
|
60
|
+
STDOUT.puts out_paths.join("\n") if show_files
|
61
|
+
STDERR.print `#{cc} -o #{main_file} #{out_paths.join(' ')}` if cc
|
62
|
+
rescue SFRP::CompileError => cerr
|
63
|
+
text = error_class ? cerr.class.to_s : cerr.message
|
64
|
+
if out_dir == nil
|
65
|
+
STDOUT.puts text
|
66
|
+
exit(0)
|
67
|
+
else
|
68
|
+
STDERR.puts text
|
69
|
+
exit(1)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'sfrp/input/set'
|
2
|
+
require 'sfrp/raw/set'
|
3
|
+
require 'sfrp/flat/set'
|
4
|
+
require 'sfrp/poly/set'
|
5
|
+
require 'sfrp/mono/set'
|
6
|
+
require 'sfrp/low/set'
|
7
|
+
require 'sfrp/output/set'
|
8
|
+
require 'sfrp/error'
|
9
|
+
require 'sfrp/file'
|
10
|
+
|
11
|
+
module SFRP
|
12
|
+
class Compiler
|
13
|
+
def initialize(main_fmodule_uri, include_paths)
|
14
|
+
@main_fmodule_uri = main_fmodule_uri
|
15
|
+
@include_paths = include_paths
|
16
|
+
end
|
17
|
+
|
18
|
+
def make_input_set
|
19
|
+
Input::Set.new do |s|
|
20
|
+
collect_fmodule_uris(@main_fmodule_uri).each do |uri|
|
21
|
+
content = File.read(to_full_path(uri))
|
22
|
+
s.append_source_file(uri, content)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_output_set
|
28
|
+
make_input_set
|
29
|
+
.to_raw
|
30
|
+
.to_flat
|
31
|
+
.to_poly
|
32
|
+
.to_mono
|
33
|
+
.to_low(collect_include_strs(@main_fmodule_uri))
|
34
|
+
.to_output
|
35
|
+
end
|
36
|
+
|
37
|
+
def compile(output_dir_path = nil)
|
38
|
+
virtual_files = collect_virtual_files(@main_fmodule_uri)
|
39
|
+
output_set = make_output_set
|
40
|
+
output_set.generate!(output_dir_path, virtual_files) if output_dir_path
|
41
|
+
output_file_names
|
42
|
+
end
|
43
|
+
|
44
|
+
def output_file_names
|
45
|
+
['main'] + collect_virtual_files(@main_fmodule_uri).flat_map do |vf|
|
46
|
+
vf.file_ext == 'c' ? [vf.fmodule_uri.gsub('.', '/')] : []
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def collect_fmodule_uris(fmodule_uri, visited = {})
|
53
|
+
return [] if visited.key?(fmodule_uri)
|
54
|
+
visited[fmodule_uri] = true
|
55
|
+
content = File.read(to_full_path(fmodule_uri))
|
56
|
+
content.each_line.each_with_object([fmodule_uri]) do |line, ary|
|
57
|
+
line.match(/import ([A-Z][a-zA-Z0-9]+(\.[A-Z][a-zA-Z0-9]+)*)/) do |m|
|
58
|
+
ary.concat(collect_fmodule_uris(m[1], visited))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def collect_virtual_files(fmodule_uri)
|
64
|
+
collect_fmodule_uris(fmodule_uri).each_with_object([]) do |uri, ary|
|
65
|
+
path = to_full_path(uri)
|
66
|
+
cpath = path.gsub(/\.sfrp$/, '.c')
|
67
|
+
hpath = path.gsub(/\.sfrp$/, '.h')
|
68
|
+
if File.exist?(cpath)
|
69
|
+
ary << VirtualFile.new(uri, 'c', File.read(cpath))
|
70
|
+
end
|
71
|
+
if File.exist?(hpath)
|
72
|
+
ary << VirtualFile.new(uri, 'h', File.read(hpath))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def collect_include_strs(fmodule_uri)
|
78
|
+
collect_virtual_files(fmodule_uri).each_with_object([]) do |vf, ary|
|
79
|
+
if vf.file_ext == 'h'
|
80
|
+
ary << "#{vf.fmodule_uri.gsub('.', '/')}.#{vf.file_ext}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_full_path(fmodule_uri)
|
86
|
+
relative_path = fmodule_uri.gsub('.', '/')
|
87
|
+
@include_paths.each do |path|
|
88
|
+
full_path = path + '/' + relative_path + '.sfrp'
|
89
|
+
return full_path if File.exist?(full_path)
|
90
|
+
end
|
91
|
+
raise FileResolveError.new(fmodule_uri, @include_paths)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|