yadriggy 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/.yardopts +3 -0
- data/README.md +12 -9
- data/Rakefile +5 -0
- data/lib/yadriggy.rb +1 -1
- data/lib/yadriggy/algebra.rb +31 -3
- data/lib/yadriggy/assert.rb +8 -8
- data/lib/yadriggy/ast.rb +71 -15
- data/lib/yadriggy/ast_location.rb +1 -1
- data/lib/yadriggy/c/c.rb +5 -5
- data/lib/yadriggy/c/codegen.rb +12 -27
- data/lib/yadriggy/c/config.rb +1 -1
- data/lib/yadriggy/c/ctype.rb +5 -5
- data/lib/yadriggy/c/ctypecheck.rb +6 -6
- data/lib/yadriggy/c/ffi.rb +8 -8
- data/lib/yadriggy/checker.rb +60 -26
- data/lib/yadriggy/eval.rb +5 -1
- data/lib/yadriggy/eval_all.rb +13 -0
- data/lib/yadriggy/pretty_print.rb +14 -6
- data/lib/yadriggy/py.rb +11 -0
- data/lib/yadriggy/py/codegen.rb +457 -0
- data/lib/yadriggy/py/import.rb +90 -0
- data/lib/yadriggy/py/py_typechecker.rb +62 -0
- data/lib/yadriggy/py/python.rb +130 -0
- data/lib/yadriggy/ruby_typecheck.rb +96 -45
- data/lib/yadriggy/ruby_typeinfer.rb +60 -25
- data/lib/yadriggy/source_code.rb +27 -17
- data/lib/yadriggy/syntax.rb +23 -8
- data/lib/yadriggy/type.rb +38 -38
- data/lib/yadriggy/typecheck.rb +18 -5
- data/lib/yadriggy/version.rb +1 -1
- data/yadriggy.gemspec +2 -1
- metadata +24 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f73ad8ceb3807a109ddbd4c11ddafee6f1854c32
|
4
|
+
data.tar.gz: 307556c77ee0760ddde8e55cece63d6975505ace
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0922e73e77795a2d351887d3e9a11760b4e4ec5f8fb8535a440ef6cca8c707f0ad402805aec919a8f52f58fa1ae17c7c877549a6ee44119b0b0bf73cfce8ee0
|
7
|
+
data.tar.gz: 66d4ad0cdef21663929443687fb5d3e3f3b1f57a86c00fd35f38cd1b70f691a98f9a44515da17fb222c116072ea36152a7827f042695599c66e47e9fd2f74a5f
|
data/.yardopts
ADDED
data/README.md
CHANGED
@@ -2,22 +2,23 @@
|
|
2
2
|
|
3
3
|
Yadriggy (mistletoe in Japanese) is a library for building a
|
4
4
|
domain-specific language (DSL) embedded in Ruby. It was developed for
|
5
|
-
a particular kind of embedded DSLs
|
5
|
+
a particular kind of embedded DSLs.
|
6
6
|
These DSLs borrow the syntax from the host language, Ruby, and the
|
7
7
|
code written in the DSLs is embedded in normal Ruby code. However,
|
8
8
|
the execution of the DSL code is independent of Ruby. Its semantics
|
9
9
|
can be totally different from Ruby and the code can be run out of the
|
10
|
-
Ruby VM.
|
10
|
+
Ruby VM. These DSLs look like Ruby but they are different
|
11
11
|
languages except their syntax.
|
12
|
-
They
|
13
|
-
|
12
|
+
They are embedded in Ruby by borrowing the syntax but their embedding is
|
13
|
+
outward; their execution engines are their own.
|
14
14
|
|
15
15
|
For details, the documentation is available from [Wiki](https://github.com/csg-tokyo/yadriggy/wiki).
|
16
16
|
|
17
|
-
##
|
17
|
+
## An example
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
Computation offloading from Ruby is a typical example of the DSLs
|
20
|
+
implemented by Yadriggy.
|
21
|
+
For example, Yadriggy provides a simple DSL to offload
|
21
22
|
from Ruby to native C language.
|
22
23
|
|
23
24
|
```ruby
|
@@ -30,7 +31,7 @@ def fib(n) ! Integer
|
|
30
31
|
if n > 1
|
31
32
|
return fib(n - 1) + fib(n - 2)
|
32
33
|
else
|
33
|
-
return
|
34
|
+
return n
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
@@ -59,7 +60,7 @@ The variable `n` in the Ruby code keeps the old value.
|
|
59
60
|
|
60
61
|
Note that the definition of `fib` contains type declarations
|
61
62
|
since this DSL is not Ruby.
|
62
|
-
|
63
|
+
This DSL looks like Ruby but it is a different language.
|
63
64
|
`! Integer` following `def fib(n)` specifies the return type.
|
64
65
|
`typedecl` specifies the types of the parameters (and local variables
|
65
66
|
if any). In this DSL, most types have to be statically given
|
@@ -84,6 +85,8 @@ ast = Yadriggy.reify {|a| a + 1 }
|
|
84
85
|
`reify` returns the AST of the given block `{|a| a + 1 }`.
|
85
86
|
It takes not only a block but also a `Method` or `Proc` object.
|
86
87
|
|
88
|
+
Yadriggy works with Pry and IRuby unless a syntax error occurs.
|
89
|
+
|
87
90
|
The idea of `reify` was proposed in the following paper:
|
88
91
|
|
89
92
|
- Shigeru Chiba, YungYu Zhuang, Maximilian Scherr, "Deeply Reifying Running Code for Constructing a Domain-Specific Language", PPPJ'16, Article No. 1, ACM, August 2016.
|
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
|
+
require "yard"
|
3
4
|
|
4
5
|
Rake::TestTask.new(:test) do |t|
|
5
6
|
t.libs << "test"
|
@@ -7,4 +8,8 @@ Rake::TestTask.new(:test) do |t|
|
|
7
8
|
t.test_files = FileList['test/**/*_test.rb']
|
8
9
|
end
|
9
10
|
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
12
|
+
t.options = ['-m markdown', '--no-private']
|
13
|
+
end
|
14
|
+
|
10
15
|
task :default => :test
|
data/lib/yadriggy.rb
CHANGED
data/lib/yadriggy/algebra.rb
CHANGED
@@ -113,8 +113,15 @@ module Yadriggy
|
|
113
113
|
binary(left, op, right)
|
114
114
|
end
|
115
115
|
|
116
|
+
# @param [Object|Array] left the left value.
|
117
|
+
# @param [Symbol] op the operator.
|
118
|
+
# @param [Object|Array] right the right value.
|
116
119
|
def assign(left, op, right)
|
117
|
-
|
120
|
+
if left.is_a?(Array) || right.is_a?(Array)
|
121
|
+
raise NotImplementedError.new('multiple assignment')
|
122
|
+
else
|
123
|
+
binary(left, op, right)
|
124
|
+
end
|
118
125
|
end
|
119
126
|
|
120
127
|
def array_ref(array, index)
|
@@ -259,13 +266,24 @@ module Yadriggy
|
|
259
266
|
end
|
260
267
|
end
|
261
268
|
|
262
|
-
#
|
269
|
+
# Evaluator for Algebra
|
263
270
|
#
|
264
271
|
class EvalAlgebra < Eval
|
272
|
+
# Initializes.
|
273
|
+
#
|
274
|
+
# @param [Algebra] algebra
|
265
275
|
def initialize(algebra)
|
266
276
|
@algebra = algebra
|
267
277
|
end
|
268
278
|
|
279
|
+
def evaluate(expr)
|
280
|
+
if expr.nil?
|
281
|
+
nil_value(nil)
|
282
|
+
else
|
283
|
+
expr.accept(self)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
269
287
|
def nil_value(expr)
|
270
288
|
@algebra.nil_value
|
271
289
|
end
|
@@ -355,7 +373,17 @@ module Yadriggy
|
|
355
373
|
end
|
356
374
|
|
357
375
|
def assign(expr)
|
358
|
-
|
376
|
+
right = if expr.right.is_a?(Array)
|
377
|
+
expr.right.map {|e| evaluate(e) }
|
378
|
+
else
|
379
|
+
evaluate(expr.right)
|
380
|
+
end
|
381
|
+
left = if expr.left.is_a?(Array)
|
382
|
+
expr.left.map {|e| evaluate(e) }
|
383
|
+
else
|
384
|
+
evaluate(expr.left)
|
385
|
+
end
|
386
|
+
@algebra.assign(left, expr.op, right)
|
359
387
|
end
|
360
388
|
|
361
389
|
def array_ref(expr)
|
data/lib/yadriggy/assert.rb
CHANGED
@@ -22,7 +22,7 @@ module Yadriggy
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
# @private
|
25
|
+
# @api private
|
26
26
|
def self.puts_reason(reason, evar=nil)
|
27
27
|
puts '--- Yadriggy::Assert ---'
|
28
28
|
print evar.cause.class.name, ': ' if evar&.cause
|
@@ -52,13 +52,13 @@ module Yadriggy
|
|
52
52
|
|
53
53
|
# Reason that an assertion fails.
|
54
54
|
class Reason
|
55
|
-
# @private
|
55
|
+
# @api private
|
56
56
|
def setup(ast, results)
|
57
57
|
@ast = ast
|
58
58
|
@results = results
|
59
59
|
end
|
60
60
|
|
61
|
-
# Gets the AST of the block given to {
|
61
|
+
# Gets the AST of the block given to {Yadriggy::Assert::assertion}.
|
62
62
|
# @return [ASTnode] an abstract syntax tree.
|
63
63
|
def ast() @ast end
|
64
64
|
|
@@ -85,7 +85,7 @@ module Yadriggy
|
|
85
85
|
output.reverse!
|
86
86
|
end
|
87
87
|
|
88
|
-
# @private
|
88
|
+
# @api private
|
89
89
|
# @return [String] the new header.
|
90
90
|
def show2(ast, header, output)
|
91
91
|
if ast.is_a?(Paren)
|
@@ -136,7 +136,7 @@ module Yadriggy
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
# @private
|
139
|
+
# @api private
|
140
140
|
# Obtains the text representation of the given value.
|
141
141
|
def str_rep(v)
|
142
142
|
max = 70
|
@@ -149,7 +149,7 @@ module Yadriggy
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
|
-
# Exception thrown by {#assertion}.
|
152
|
+
# Exception thrown by {Yadriggy::Assert#assertion}.
|
153
153
|
#
|
154
154
|
class AssertFailure < StandardError
|
155
155
|
def initialize(reason, msg=nil, cause=nil)
|
@@ -167,7 +167,7 @@ module Yadriggy
|
|
167
167
|
def reason() @reason end
|
168
168
|
end
|
169
169
|
|
170
|
-
# @private
|
170
|
+
# @api private
|
171
171
|
# Executes the given AST and records the result.
|
172
172
|
# @param [ASTnode] ast the given AST.
|
173
173
|
# @param [Binding] blk_binding the binding for executing the AST.
|
@@ -210,7 +210,7 @@ module Yadriggy
|
|
210
210
|
end
|
211
211
|
end
|
212
212
|
|
213
|
-
# @private
|
213
|
+
# @api private
|
214
214
|
# Eval the AST by the RubyVM
|
215
215
|
# @return [Pair<String,Object>] an array. The first element is the source code
|
216
216
|
# and the second element is the resulting value.
|
data/lib/yadriggy/ast.rb
CHANGED
@@ -16,11 +16,13 @@ module Yadriggy
|
|
16
16
|
# the recorded ASTs are shared among {ASTree} objects.
|
17
17
|
# Every call to {Yadriggy#reify} on {Yadriggy} makes a new table. Hence,
|
18
18
|
#
|
19
|
-
#
|
19
|
+
# ```
|
20
|
+
# ast1 = Yadriggy.reify(proc1)
|
20
21
|
# ast2 = ast.reify(proc2)
|
21
|
-
# a1 = Yadriggy.reify(proc1)
|
22
|
+
# a1 = Yadriggy.reify(proc1) # a1 != ast1
|
22
23
|
# a2 = a1.reify(proc2) # a2 != ast2
|
23
|
-
# b2 = a1.reify(proc2) # b2 == a2
|
24
|
+
# b2 = a1.reify(proc2) # b2 == a2
|
25
|
+
# ```
|
24
26
|
#
|
25
27
|
# Although `ast1` and `a1`, and `ast2` and `a2` are different copies
|
26
28
|
# of the AST of the same proc, `a2` and `b2` refer to the same AST.
|
@@ -136,7 +138,7 @@ module Yadriggy
|
|
136
138
|
end
|
137
139
|
end
|
138
140
|
|
139
|
-
# Reserved words such self, true, and false.
|
141
|
+
# Reserved words such as self, nil, true, and false.
|
140
142
|
#
|
141
143
|
class Reserved < Name
|
142
144
|
def self.tag() :@kw end
|
@@ -324,7 +326,12 @@ module Yadriggy
|
|
324
326
|
|
325
327
|
def initialize(sexp)
|
326
328
|
if sexp[0] == :dyna_symbol
|
327
|
-
|
329
|
+
sexp2 = if sexp[1][0] == :string_content
|
330
|
+
sexp[1][1]
|
331
|
+
else
|
332
|
+
sexp[1][0]
|
333
|
+
end
|
334
|
+
init(has_tag?(sexp2, :@tstring_content))
|
328
335
|
elsif sexp[0] == :symbol_literal
|
329
336
|
init(has_tag?(sexp[1], :symbol)[1])
|
330
337
|
else
|
@@ -399,7 +406,8 @@ module Yadriggy
|
|
399
406
|
def self.tag() :paren end
|
400
407
|
|
401
408
|
def initialize(sexp)
|
402
|
-
|
409
|
+
e = if sexp[1][0].is_a?(Array) then sexp[1][0] else sexp[1] end
|
410
|
+
@expression = to_node(e)
|
403
411
|
add_child(@expression)
|
404
412
|
end
|
405
413
|
|
@@ -424,6 +432,10 @@ module Yadriggy
|
|
424
432
|
def initialize(sexp)
|
425
433
|
if sexp[1].nil?
|
426
434
|
@elements = []
|
435
|
+
elsif is_percent_literal(sexp[1])
|
436
|
+
@elements = sexp[1].map do |e|
|
437
|
+
StringInterpolation.new([:string_literal, [:string_content] + e])
|
438
|
+
end
|
427
439
|
else
|
428
440
|
@elements = to_nodes(sexp[1])
|
429
441
|
end
|
@@ -436,6 +448,15 @@ module Yadriggy
|
|
436
448
|
def accept(evaluator)
|
437
449
|
evaluator.array(self)
|
438
450
|
end
|
451
|
+
|
452
|
+
private
|
453
|
+
|
454
|
+
def is_percent_literal(sexp)
|
455
|
+
sexp.is_a?(Array) && sexp.size > 0 &&
|
456
|
+
sexp.all? do |e|
|
457
|
+
e.is_a?(Array) && e.all? {|ee| ee.is_a?(Array) }
|
458
|
+
end
|
459
|
+
end
|
439
460
|
end
|
440
461
|
|
441
462
|
# String interpolation.
|
@@ -673,25 +694,33 @@ module Yadriggy
|
|
673
694
|
end
|
674
695
|
|
675
696
|
# Assignment such as `=` and `+=`.
|
697
|
+
# `Assign#left` and `Assign#right` return an `ASTnode`,
|
698
|
+
# or an array of `ASTnode` if the node represents multiple
|
699
|
+
# assignment.
|
676
700
|
#
|
677
701
|
class Assign < Binary
|
678
|
-
def self.tags() [:assign, :opassign] end
|
702
|
+
def self.tags() [:assign, :opassign, :massign] end
|
679
703
|
|
680
704
|
def initialize(sexp)
|
681
705
|
case sexp[0]
|
682
706
|
when :assign
|
683
707
|
@left = to_node(sexp[1])
|
708
|
+
add_child(@left)
|
684
709
|
@op = :'='
|
685
|
-
|
710
|
+
init_right(sexp[2])
|
686
711
|
when :opassign
|
687
712
|
@left = to_node(sexp[1])
|
713
|
+
add_child(@left)
|
688
714
|
@op = has_tag?(sexp[2], :@op)[1].to_sym
|
689
|
-
|
715
|
+
init_right(sexp[3])
|
716
|
+
when :massign
|
717
|
+
@left = to_nodes(sexp[1])
|
718
|
+
add_children(@left)
|
719
|
+
@op = :'='
|
720
|
+
init_right(sexp[2])
|
690
721
|
else
|
691
722
|
raise "unknown assignment " + sexp[0].to_s
|
692
723
|
end
|
693
|
-
add_child(@left)
|
694
|
-
add_child(@right)
|
695
724
|
end
|
696
725
|
|
697
726
|
# A method for Visitor pattern.
|
@@ -700,6 +729,19 @@ module Yadriggy
|
|
700
729
|
def accept(evaluator)
|
701
730
|
evaluator.assign(self)
|
702
731
|
end
|
732
|
+
|
733
|
+
private
|
734
|
+
|
735
|
+
# @api private
|
736
|
+
def init_right(right_operand)
|
737
|
+
if right_operand[0] == :mrhs_new_from_args
|
738
|
+
@right = to_nodes(right_operand[1]) + [to_node(right_operand[2])]
|
739
|
+
add_children(@right)
|
740
|
+
else
|
741
|
+
@right = to_node(right_operand)
|
742
|
+
add_child(@right)
|
743
|
+
end
|
744
|
+
end
|
703
745
|
end
|
704
746
|
|
705
747
|
# Hash table.
|
@@ -792,7 +834,7 @@ module Yadriggy
|
|
792
834
|
parent, link_from_children)
|
793
835
|
end
|
794
836
|
|
795
|
-
# @private
|
837
|
+
# @api private
|
796
838
|
def initialize2(recv, op, name, args, barg, blk,
|
797
839
|
parent, link_from_children)
|
798
840
|
@receiver = recv
|
@@ -826,6 +868,12 @@ module Yadriggy
|
|
826
868
|
marg = sexp[1]
|
827
869
|
if marg[0] == :method_add_arg
|
828
870
|
initialize_method_arg(marg[1], marg[2])
|
871
|
+
elsif marg[0] == :command
|
872
|
+
initialize_call([:call, nil, nil, marg[1]])
|
873
|
+
initialize_args(marg[2]) if marg.length > 2
|
874
|
+
elsif marg[0] == :command_call
|
875
|
+
initialize_call([:call, marg[1], marg[2], marg[3]])
|
876
|
+
initialize_args(marg[4]) if marg.length > 4
|
829
877
|
else
|
830
878
|
initialize_method_arg(marg, [])
|
831
879
|
end
|
@@ -865,13 +913,21 @@ module Yadriggy
|
|
865
913
|
def initialize_call(sexp)
|
866
914
|
@receiver = to_node(sexp[1])
|
867
915
|
@op = sexp[2] # :"." or :"::" or nil.
|
868
|
-
@name =
|
916
|
+
@name = if sexp[3] == :call
|
917
|
+
nil
|
918
|
+
else
|
919
|
+
@name = to_node(has_tag?(sexp[3], :@ident))
|
920
|
+
end
|
869
921
|
add_child(@receiver)
|
870
922
|
add_child(@name)
|
871
923
|
end
|
872
924
|
|
873
925
|
def initialize_args(args_block)
|
874
|
-
args =
|
926
|
+
args = if args_block[0] == :args_add_block
|
927
|
+
args_block[1]
|
928
|
+
else
|
929
|
+
args_block
|
930
|
+
end
|
875
931
|
args2 = initialize_star_arg(args)
|
876
932
|
@args = to_nodes(args2)
|
877
933
|
@block_arg = if args_block[2]
|
@@ -1652,7 +1708,7 @@ module Yadriggy
|
|
1652
1708
|
end
|
1653
1709
|
end
|
1654
1710
|
|
1655
|
-
# @private
|
1711
|
+
# @api private
|
1656
1712
|
# A table of reified abstract syntax trees.
|
1657
1713
|
# It is used for guaranteeing the uniqueness
|
1658
1714
|
# of ASTree objects.
|
data/lib/yadriggy/c/c.rb
CHANGED
@@ -95,7 +95,7 @@ module Yadriggy
|
|
95
95
|
mod
|
96
96
|
end
|
97
97
|
|
98
|
-
# @private
|
98
|
+
# @api private
|
99
99
|
# @return [Pair<Module,Array<String>>]
|
100
100
|
def self.compile0(obj, lib_name, dir, module_name,
|
101
101
|
typechecker_class, gen_class)
|
@@ -109,7 +109,7 @@ module Yadriggy
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
# @private
|
112
|
+
# @api private
|
113
113
|
# @return [Pair<Module,Array<String>>]
|
114
114
|
def self.compile1(obj, lib_name, dir, module_name,
|
115
115
|
typechecker_class, gen_class)
|
@@ -141,7 +141,7 @@ module Yadriggy
|
|
141
141
|
attach_funcs(pub_methods, checker, gen, module_name, lib_name, dir)
|
142
142
|
end
|
143
143
|
|
144
|
-
# @private
|
144
|
+
# @api private
|
145
145
|
# @return [Array<ASTree>] the ASTs of compiled methods.
|
146
146
|
def self.compiled_methods(checker, method_objs)
|
147
147
|
ast = nil
|
@@ -165,7 +165,7 @@ module Yadriggy
|
|
165
165
|
return pub_methods
|
166
166
|
end
|
167
167
|
|
168
|
-
# @private
|
168
|
+
# @api private
|
169
169
|
def self.generate_funcs(ast, gen, printer)
|
170
170
|
gen.name_global_variables
|
171
171
|
gen.headers
|
@@ -185,7 +185,7 @@ module Yadriggy
|
|
185
185
|
raise BuildError.new(gen.error_messages) if gen.errors?
|
186
186
|
end
|
187
187
|
|
188
|
-
# @private
|
188
|
+
# @api private
|
189
189
|
# @return [Pair<Module,Array<String>>] the module where the methods
|
190
190
|
# are attached. The second element is method names.
|
191
191
|
def self.attach_funcs(pub_methods, checker, gen, module_name,
|