yadriggy 1.2.0 → 1.4.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 +5 -5
- data/.gitignore +2 -0
- data/README.md +5 -1
- data/lib/yadriggy/ast.rb +31 -11
- data/lib/yadriggy/checker.rb +8 -3
- data/lib/yadriggy/py/codegen.rb +15 -0
- data/lib/yadriggy/py/py_typechecker.rb +2 -1
- data/lib/yadriggy/py/python.rb +1 -65
- data/lib/yadriggy/py/syntax.rb +75 -0
- data/lib/yadriggy/ruby_typeinfer.rb +5 -1
- data/lib/yadriggy/source_code.rb +21 -4
- data/lib/yadriggy/syntax.rb +2 -2
- data/lib/yadriggy/type.rb +14 -1
- data/lib/yadriggy/typecheck.rb +7 -1
- data/lib/yadriggy/version.rb +1 -1
- data/yadriggy.gemspec +3 -2
- metadata +26 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 965a6bb4be2daef3f40ee7c19460bc96cc991f0a6e438c5dbf60f4b725ab6950
|
4
|
+
data.tar.gz: 10bc72c4deaec889fc53da6f6d0e91acf0c23f77b4dc58af06587d5574720a32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42d1f8b97ec8384892b667921a09bee0a4abbb1d90c2bacd426a1386bb68e986061b950b3ff151065064fbc9230554b564f9ba7a08afd165a19d790670664118
|
7
|
+
data.tar.gz: 6d2aa2b2c56d28da350eaec79535b2c03d843362904d7cdf1da7264d2cd22a411f5f706945414a889eeaed70c1ef8e096364f06b59e9d1c3a845cddd24e09558
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Yadriggy
|
2
2
|
|
3
|
-
Yadriggy (mistletoe in
|
3
|
+
Yadriggy (mistletoe in English) is a library for building a
|
4
4
|
domain-specific language (DSL) embedded in Ruby. It was developed for
|
5
5
|
a particular kind of embedded DSLs.
|
6
6
|
These DSLs borrow the syntax from the host language, Ruby, and the
|
@@ -91,6 +91,10 @@ The idea of `reify` was proposed in the following paper:
|
|
91
91
|
|
92
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.
|
93
93
|
|
94
|
+
Yadriggy-Py was presented in the following paper:
|
95
|
+
|
96
|
+
- Shigeru Chiba, Foreign language interfaces by code migration, Proc. of the 18th ACM SIGPLAN International Conference on Generative Programming: Concepts and Experiences (GPCE 2019), pp. 1-13, ACM, 2019.
|
97
|
+
|
94
98
|
## Installation
|
95
99
|
|
96
100
|
To install, run:
|
data/lib/yadriggy/ast.rb
CHANGED
@@ -257,7 +257,7 @@ module Yadriggy
|
|
257
257
|
attr_reader :column
|
258
258
|
|
259
259
|
def self.tags()
|
260
|
-
[:@int, :@float]
|
260
|
+
[:@int, :@float, :@rational, :@imaginary]
|
261
261
|
end
|
262
262
|
|
263
263
|
def initialize(sexp)
|
@@ -270,8 +270,12 @@ module Yadriggy
|
|
270
270
|
end
|
271
271
|
when :@float
|
272
272
|
sexp[1].to_f
|
273
|
+
when :@rational
|
274
|
+
sexp[1].to_r
|
275
|
+
when :@imaginary
|
276
|
+
Complex(sexp[1])
|
273
277
|
else
|
274
|
-
raise "unknown symbol
|
278
|
+
raise "unknown symbol #{sexp[0]}"
|
275
279
|
end
|
276
280
|
@line_no = sexp[2][0].to_i
|
277
281
|
@column = sexp[2][1].to_i
|
@@ -300,11 +304,11 @@ module Yadriggy
|
|
300
304
|
end
|
301
305
|
|
302
306
|
# @param [Array] s an S-expression.
|
303
|
-
# @param [Symbol]
|
307
|
+
# @param [Array<Symbol>] tags
|
304
308
|
# @return [Array] the S-expression if it starts with the tag.
|
305
309
|
# Otherwise, raise an error.
|
306
|
-
def has_tag?(s,
|
307
|
-
raise "s-exp is not :#{
|
310
|
+
def has_tag?(s, *tags)
|
311
|
+
raise "s-exp is not :#{tags.join(", ")}. #{s}" if !s.nil? && !tags.include?(s[0])
|
308
312
|
s
|
309
313
|
end
|
310
314
|
end
|
@@ -912,16 +916,26 @@ module Yadriggy
|
|
912
916
|
|
913
917
|
def initialize_call(sexp)
|
914
918
|
@receiver = to_node(sexp[1])
|
915
|
-
@op = sexp[2]
|
919
|
+
@op = op_symbol(sexp[2]) # :"." or :"::" or nil.
|
916
920
|
@name = if sexp[3] == :call
|
917
921
|
nil
|
918
922
|
else
|
919
|
-
@name = to_node(has_tag?(sexp[3], :@ident))
|
923
|
+
@name = to_node(has_tag?(sexp[3], :@ident, :@const))
|
920
924
|
end
|
921
925
|
add_child(@receiver)
|
922
926
|
add_child(@name)
|
923
927
|
end
|
924
928
|
|
929
|
+
def op_symbol(op)
|
930
|
+
if op.is_a?(Array)
|
931
|
+
op = has_tag?(op, :@period)
|
932
|
+
op[1].to_sym
|
933
|
+
else
|
934
|
+
# Ruby 2.5 or earlier
|
935
|
+
op
|
936
|
+
end
|
937
|
+
end
|
938
|
+
|
925
939
|
def initialize_args(args_block)
|
926
940
|
args = if args_block[0] == :args_add_block
|
927
941
|
args_block[1]
|
@@ -1380,7 +1394,7 @@ module Yadriggy
|
|
1380
1394
|
if body.is_a?(Array) && body.length > 0 && body[0] == :bodystmt
|
1381
1395
|
bodystmnt = body[1]
|
1382
1396
|
@rescue = Rescue.make(body[2], body[3], body[4])
|
1383
|
-
else # if Ruby 2.
|
1397
|
+
else # if Ruby 2.5 or earlier
|
1384
1398
|
bodystmnt = body
|
1385
1399
|
@rescue = nil
|
1386
1400
|
end
|
@@ -1488,8 +1502,14 @@ module Yadriggy
|
|
1488
1502
|
if else_expr.nil?
|
1489
1503
|
@else = nil
|
1490
1504
|
else
|
1491
|
-
|
1492
|
-
|
1505
|
+
if !else_expr.nil? && else_expr[0].is_a?(Array)
|
1506
|
+
else_body = else_expr
|
1507
|
+
else
|
1508
|
+
# Ruby 2.4 or earlier
|
1509
|
+
elsexpr = has_tag?(else_expr, :else)
|
1510
|
+
else_body = else_expr[1]
|
1511
|
+
end
|
1512
|
+
@else = Exprs.make(else_body)
|
1493
1513
|
add_child(@else)
|
1494
1514
|
end
|
1495
1515
|
|
@@ -1580,7 +1600,7 @@ module Yadriggy
|
|
1580
1600
|
@name = if def_name[0] == :@op
|
1581
1601
|
to_node(def_name)
|
1582
1602
|
else
|
1583
|
-
to_node(has_tag?(def_name, :@ident))
|
1603
|
+
to_node(has_tag?(def_name, :@ident, :@const))
|
1584
1604
|
end
|
1585
1605
|
add_child(@name)
|
1586
1606
|
|
data/lib/yadriggy/checker.rb
CHANGED
@@ -36,6 +36,7 @@ module Yadriggy
|
|
36
36
|
[@rules, @rule_declarators]
|
37
37
|
end
|
38
38
|
|
39
|
+
# @api private
|
39
40
|
private_class_method def self.init_class
|
40
41
|
@rules = {}
|
41
42
|
@rule_declarators = {}
|
@@ -56,6 +57,7 @@ module Yadriggy
|
|
56
57
|
find_rule_entry2(ast.class, ast.usertype)
|
57
58
|
end
|
58
59
|
|
60
|
+
# @api private
|
59
61
|
private_class_method def self.find_rule_entry2(ast_class, utype)
|
60
62
|
unless utype.nil?
|
61
63
|
rule = @rules[utype]
|
@@ -147,7 +149,7 @@ module Yadriggy
|
|
147
149
|
# This is the entry point of the checker. It may also
|
148
150
|
# check the other ASTs invoked in the given AST.
|
149
151
|
#
|
150
|
-
# @param [ASTree|ASTnode] an_ast the AST.
|
152
|
+
# @param [ASTree|ASTnode|nil] an_ast the AST.
|
151
153
|
# @return [Object]
|
152
154
|
def check_all(an_ast)
|
153
155
|
return nil if an_ast.nil?
|
@@ -162,6 +164,9 @@ module Yadriggy
|
|
162
164
|
end
|
163
165
|
|
164
166
|
# Makes a new base environment with the given context class.
|
167
|
+
# It is called by `check_all`. Override this method to customize
|
168
|
+
# `check_all`.
|
169
|
+
#
|
165
170
|
# @param [Module] klass the context class.
|
166
171
|
def make_base_env(klass)
|
167
172
|
klass
|
@@ -191,7 +196,7 @@ module Yadriggy
|
|
191
196
|
# internal use only
|
192
197
|
def apply_typing_rule(rule, an_ast, ast_tenv)
|
193
198
|
if rule.nil?
|
194
|
-
error_found!(an_ast, "no
|
199
|
+
error_found!(an_ast, "no rule for #{an_ast.class}")
|
195
200
|
else
|
196
201
|
old_ast = @current_ast
|
197
202
|
old_tenv = @current_env
|
@@ -210,7 +215,7 @@ module Yadriggy
|
|
210
215
|
# Applies the rule supplied by the superclass.
|
211
216
|
# @param [ASTnode] an_ast an AST.
|
212
217
|
# @param [Object] envi an environment object.
|
213
|
-
# @return [
|
218
|
+
# @return [Object] the result of the application.
|
214
219
|
def proceed(an_ast, envi=nil)
|
215
220
|
rule = if @rule_declarator&.superclass == Object
|
216
221
|
nil
|
data/lib/yadriggy/py/codegen.rb
CHANGED
@@ -333,6 +333,21 @@ module Yadriggy
|
|
333
333
|
print_lambda(ast.block)
|
334
334
|
end
|
335
335
|
|
336
|
+
rule(:with_call) do
|
337
|
+
pairs = ast.args[0].pairs
|
338
|
+
# ast.args[0].pairs[0][1]
|
339
|
+
@printer << 'with '
|
340
|
+
print_each(ast.args[0].pairs, true) do |expr_var|
|
341
|
+
print(expr_var[0])
|
342
|
+
@printer << ' as '
|
343
|
+
print(expr_var[1])
|
344
|
+
end
|
345
|
+
@printer << ':'
|
346
|
+
@printer.down
|
347
|
+
print(ast.block.body)
|
348
|
+
@printer.up
|
349
|
+
end
|
350
|
+
|
336
351
|
rule(Conditional) do
|
337
352
|
if ast.op == :if
|
338
353
|
@printer << ast.op << ' '
|
data/lib/yadriggy/py/python.rb
CHANGED
@@ -2,77 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'pycall'
|
4
4
|
require 'yadriggy'
|
5
|
+
require 'yadriggy/py/syntax'
|
5
6
|
require 'yadriggy/py/codegen'
|
6
7
|
require 'yadriggy/py/py_typechecker'
|
7
8
|
require 'yadriggy/py/import'
|
8
9
|
|
9
10
|
module Yadriggy
|
10
11
|
module Py
|
11
|
-
|
12
|
-
Syntax = Yadriggy.define_syntax do
|
13
|
-
expr = Name | Number | Super | Binary | Unary | ternary |
|
14
|
-
StringLiteral | Lambda |
|
15
|
-
ArrayLiteral | Paren | lambda_call | fun_call | ArrayRef | HashLiteral
|
16
|
-
stmnt = Return | ForLoop | Loop | if_stmnt | Break |
|
17
|
-
BeginEnd | Def | ModuleDef
|
18
|
-
exprs = Exprs | stmnt | expr
|
19
|
-
|
20
|
-
Name = { name: String }
|
21
|
-
Number = { value: Numeric }
|
22
|
-
VariableCall = Name
|
23
|
-
InstanceVariable = nil
|
24
|
-
GlobalVariable = nil
|
25
|
-
Reserved = Name
|
26
|
-
Const = Name
|
27
|
-
Binary = { left: expr, op: Symbol, right: expr }
|
28
|
-
ArrayRef = { array: expr, indexes: expr }
|
29
|
-
ArrayRefField = ArrayRef
|
30
|
-
Assign = { left: [expr] | expr, op: Symbol,
|
31
|
-
right: [expr] | expr }
|
32
|
-
Dots = Binary
|
33
|
-
Unary = { op: Symbol, operand: expr }
|
34
|
-
StringLiteral = { value: String }
|
35
|
-
ArrayLiteral = { elements: ForLoop | [ expr ] }
|
36
|
-
Paren = { expression: expr }
|
37
|
-
HashLiteral = { pairs: [ (expr|Label|SymbolLiteral) * expr ] }
|
38
|
-
Return = { values: [ expr ] }
|
39
|
-
ForLoop = {vars: [ Identifier ], set: expr, body: exprs }
|
40
|
-
Loop = { op: :while, cond: expr, body: exprs }
|
41
|
-
Break = { values: nil }
|
42
|
-
if_stmnt = Conditional + { op: :if, cond: expr, then: exprs,
|
43
|
-
all_elsif: [expr * exprs], else: (exprs) }
|
44
|
-
ternary = Conditional + { op: :ifop, cond: expr, then: expr,
|
45
|
-
all_elsif: nil, else: expr }
|
46
|
-
Parameters = { params: [ Identifier ],
|
47
|
-
optionals: [ Identifier * expr ],
|
48
|
-
rest_of_params: (Identifier),
|
49
|
-
params_after_rest: [ Identifier ],
|
50
|
-
keywords: [ Label * expr ],
|
51
|
-
rest_of_keywords: (Identifier),
|
52
|
-
block_param: (Identifier) }
|
53
|
-
Block = Parameters + { body: exprs }
|
54
|
-
Lambda = Block + { body: expr } # -> (x) { x + 1 }
|
55
|
-
lambda_name = { name: "lambda" }
|
56
|
-
lambda_call = Call + { receiver: nil, op: nil, name: lambda_name,
|
57
|
-
args: nil, block_arg: nil, block: Block }
|
58
|
-
fun_call = Call + { receiver: (expr), op: (Symbol), name: Identifier,
|
59
|
-
args: [ expr ], block_arg: nil, block: nil }
|
60
|
-
Command = fun_call
|
61
|
-
Exprs = { expressions: [ exprs ] }
|
62
|
-
Rescue = { types: [ Const | ConstPathRef ],
|
63
|
-
parameter: (Identifier),
|
64
|
-
body: (exprs), nested_rescue: (Rescue),
|
65
|
-
else: (exprs), ensure: (exprs) }
|
66
|
-
BeginEnd = { body: exprs, rescue: (Rescue) }
|
67
|
-
Def = Parameters +
|
68
|
-
{ singular: (expr), name: Identifier, body: exprs,
|
69
|
-
rescue: (Rescue) }
|
70
|
-
ModuleDef = { name: Const | ConstPathRef, body: exprs,
|
71
|
-
rescue: (Rescue) }
|
72
|
-
ClassDef = ModuleDef +
|
73
|
-
{ superclass: (Const | ConstPathRef) }
|
74
|
-
end
|
75
|
-
|
76
12
|
def self.run(&blk)
|
77
13
|
ast = Yadriggy::reify(blk)
|
78
14
|
Syntax.raise_error unless Syntax.check(ast.tree)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright (C) 2018- Shigeru Chiba. All rights reserved.
|
2
|
+
|
3
|
+
require 'yadriggy'
|
4
|
+
|
5
|
+
module Yadriggy
|
6
|
+
module Py
|
7
|
+
Syntax = Yadriggy.define_syntax do
|
8
|
+
expr = Name | Number | Super | Binary | Unary | ternary |
|
9
|
+
StringLiteral | Lambda |
|
10
|
+
ArrayLiteral | Paren | lambda_call | with_call | fun_call |
|
11
|
+
ArrayRef | HashLiteral
|
12
|
+
stmnt = Return | ForLoop | Loop | if_stmnt | Break |
|
13
|
+
BeginEnd | Def | ModuleDef
|
14
|
+
exprs = Exprs | stmnt | expr
|
15
|
+
|
16
|
+
Name = { name: String }
|
17
|
+
Number = { value: Numeric }
|
18
|
+
VariableCall = Name
|
19
|
+
InstanceVariable = nil
|
20
|
+
GlobalVariable = nil
|
21
|
+
Reserved = Name
|
22
|
+
Const = Name
|
23
|
+
Binary = { left: expr, op: Symbol, right: expr }
|
24
|
+
ArrayRef = { array: expr, indexes: expr }
|
25
|
+
ArrayRefField = ArrayRef
|
26
|
+
Assign = { left: [expr] | expr, op: Symbol,
|
27
|
+
right: [expr] | expr }
|
28
|
+
Dots = Binary
|
29
|
+
Unary = { op: Symbol, operand: expr }
|
30
|
+
StringLiteral = { value: String }
|
31
|
+
ArrayLiteral = { elements: ForLoop | [ expr ] }
|
32
|
+
Paren = { expression: expr }
|
33
|
+
HashLiteral = { pairs: [ (expr|Label|SymbolLiteral) * expr ] }
|
34
|
+
Return = { values: [ expr ] }
|
35
|
+
ForLoop = {vars: [ Identifier ], set: expr, body: exprs }
|
36
|
+
Loop = { op: :while, cond: expr, body: exprs }
|
37
|
+
Break = { values: nil }
|
38
|
+
if_stmnt = Conditional + { op: :if, cond: expr, then: exprs,
|
39
|
+
all_elsif: [expr * exprs], else: (exprs) }
|
40
|
+
ternary = Conditional + { op: :ifop, cond: expr, then: expr,
|
41
|
+
all_elsif: nil, else: expr }
|
42
|
+
Parameters = { params: [ Identifier ],
|
43
|
+
optionals: [ Identifier * expr ],
|
44
|
+
rest_of_params: (Identifier),
|
45
|
+
params_after_rest: [ Identifier ],
|
46
|
+
keywords: [ Label * expr ],
|
47
|
+
rest_of_keywords: (Identifier),
|
48
|
+
block_param: (Identifier) }
|
49
|
+
Block = Parameters + { body: exprs }
|
50
|
+
Lambda = Block + { body: expr } # -> (x) { x + 1 }
|
51
|
+
lambda_name = { name: "lambda" }
|
52
|
+
lambda_call = Call + { receiver: nil, op: nil, name: lambda_name,
|
53
|
+
args: nil, block_arg: nil, block: Block }
|
54
|
+
with_name = { name: "with" }
|
55
|
+
with_call = Call + { receiver: nil, op: nil, name: with_name,
|
56
|
+
args: HashLiteral, block_arg: nil, block: Block }
|
57
|
+
fun_call = Call + { receiver: (expr), op: (Symbol), name: Identifier,
|
58
|
+
args: [ expr ], block_arg: nil, block: nil }
|
59
|
+
Command = fun_call
|
60
|
+
Exprs = { expressions: [ exprs ] }
|
61
|
+
Rescue = { types: [ Const | ConstPathRef ],
|
62
|
+
parameter: (Identifier),
|
63
|
+
body: (exprs), nested_rescue: (Rescue),
|
64
|
+
else: (exprs), ensure: (exprs) }
|
65
|
+
BeginEnd = { body: exprs, rescue: (Rescue) }
|
66
|
+
Def = Parameters +
|
67
|
+
{ singular: (expr), name: Identifier, body: exprs,
|
68
|
+
rescue: (Rescue) }
|
69
|
+
ModuleDef = { name: Const | ConstPathRef, body: exprs,
|
70
|
+
rescue: (Rescue) }
|
71
|
+
ClassDef = ModuleDef +
|
72
|
+
{ superclass: (Const | ConstPathRef) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -238,8 +238,12 @@ module Yadriggy
|
|
238
238
|
end
|
239
239
|
when :**, :*, :/, :%, :+, :-
|
240
240
|
if left_t <= RubyClass::Numeric
|
241
|
-
if left_t <= RubyClass::
|
241
|
+
if left_t <= RubyClass::Complex || right_t <= RubyClass::Complex
|
242
|
+
return RubyClass::Complex
|
243
|
+
elsif left_t <= RubyClass::Float || right_t <= RubyClass::Float
|
242
244
|
return RubyClass::Float
|
245
|
+
elsif left_t <= RubyClass::Rational || right_t <= RubyClass::Rational
|
246
|
+
return RubyClass::Rational
|
243
247
|
else
|
244
248
|
return RubyClass::Integer
|
245
249
|
end
|
data/lib/yadriggy/source_code.rb
CHANGED
@@ -3,10 +3,13 @@
|
|
3
3
|
require 'ripper'
|
4
4
|
require 'pry'
|
5
5
|
|
6
|
+
# Interactive shell.
|
6
7
|
class Pry
|
8
|
+
# Log.
|
7
9
|
class History
|
8
|
-
#
|
9
|
-
# We modify Pry::History::push to record a duplicated line as well.
|
10
|
+
# Records a line.
|
11
|
+
# We modify the original `Pry::History::push` to record a duplicated line as well.
|
12
|
+
# @param [String] line an input.
|
10
13
|
def push(line)
|
11
14
|
unless line.empty? || line.include?("\0")
|
12
15
|
@pusher.call(line)
|
@@ -22,6 +25,14 @@ class Pry
|
|
22
25
|
end
|
23
26
|
|
24
27
|
module Yadriggy
|
28
|
+
# Discards all the code given to Pry before.
|
29
|
+
# This should be called when the code given before includes
|
30
|
+
# a syntax error and hence {reify} cannot obtain an
|
31
|
+
# abstract syntax tree.
|
32
|
+
def self.reset_pry
|
33
|
+
SourceCode.reset_pry
|
34
|
+
end
|
35
|
+
|
25
36
|
# @api private
|
26
37
|
# Retrieves source code in the S-expression style.
|
27
38
|
class SourceCode
|
@@ -40,11 +51,17 @@ module Yadriggy
|
|
40
51
|
prog && [file_name, find_sexp(prog, line)]
|
41
52
|
end
|
42
53
|
|
54
|
+
@pry_offset = 0
|
55
|
+
|
56
|
+
def self.reset_pry
|
57
|
+
@pry_offset = Pry.history.history_line_count - Pry.history.original_lines
|
58
|
+
end
|
59
|
+
|
43
60
|
def self.read_pry_history
|
44
61
|
cmds = Pry.commands
|
45
|
-
his = Pry.history.to_a[Pry.history.original_lines ...
|
62
|
+
his = Pry.history.to_a[Pry.history.original_lines + @pry_offset ...
|
46
63
|
Pry.history.history_line_count]
|
47
|
-
his.reduce(
|
64
|
+
his.reduce("\n" * @pry_offset) do |source, line|
|
48
65
|
if cmds.select {|k,v| v.matches?(line) }.empty?
|
49
66
|
source << line << "\n"
|
50
67
|
else
|
data/lib/yadriggy/syntax.rb
CHANGED
@@ -514,7 +514,7 @@ module Yadriggy
|
|
514
514
|
block_param: (Identifier) }
|
515
515
|
Block <= Parameters + { body: exprs }
|
516
516
|
Lambda <= Block
|
517
|
-
Call <= { receiver: (expr), op: (Symbol), name: (Identifier),
|
517
|
+
Call <= { receiver: (expr), op: (Symbol), name: (Identifier | Const),
|
518
518
|
args: [ expr ], block_arg: (expr), block: (Block) }
|
519
519
|
Command <= Call
|
520
520
|
Exprs <= { expressions: [ expr ] }
|
@@ -524,7 +524,7 @@ module Yadriggy
|
|
524
524
|
else: (exprs), ensure: (exprs) }
|
525
525
|
BeginEnd <= { body: exprs, rescue: (Rescue) }
|
526
526
|
Def <= Parameters +
|
527
|
-
{ singular: (expr), name: Identifier, body: exprs,
|
527
|
+
{ singular: (expr), name: (Identifier | Const), body: exprs,
|
528
528
|
rescue: (Rescue) }
|
529
529
|
ModuleDef <= { name: Const | ConstPathRef, body: exprs,
|
530
530
|
rescue: (Rescue) }
|
data/lib/yadriggy/type.rb
CHANGED
@@ -381,6 +381,8 @@ module Yadriggy
|
|
381
381
|
RubyClass::String = RubyClass.make(String)
|
382
382
|
RubyClass::Integer = RubyClass.make(Integer)
|
383
383
|
RubyClass::Float = RubyClass.make(Float)
|
384
|
+
RubyClass::Rational = RubyClass.make(Rational)
|
385
|
+
RubyClass::Complex = RubyClass.make(Complex)
|
384
386
|
RubyClass::Range = RubyClass.make(Range)
|
385
387
|
RubyClass::Hash = RubyClass.make(Hash)
|
386
388
|
RubyClass::Array = RubyClass.make(Array)
|
@@ -621,10 +623,21 @@ module Yadriggy
|
|
621
623
|
# Obtains the name of this type.
|
622
624
|
# @return [String] the type name.
|
623
625
|
def name
|
624
|
-
name = @ruby_class.name
|
626
|
+
name = @ruby_class.name.dup
|
625
627
|
name << '<' << @args.map{|e| e.name }.join(',') << '>'
|
626
628
|
name
|
627
629
|
end
|
630
|
+
|
631
|
+
# @api private
|
632
|
+
# Gets a method with the given name declared in this type.
|
633
|
+
# `nil` is returned when the method is not exactly determined.
|
634
|
+
#
|
635
|
+
# @return [Method|nil]
|
636
|
+
def get_method_object(method_name)
|
637
|
+
exact_type.instance_method(method_name)
|
638
|
+
rescue NameError
|
639
|
+
Type.error_found!("no such method: #{@ruby_class}\##{method_name}")
|
640
|
+
end
|
628
641
|
end
|
629
642
|
|
630
643
|
# A role that can be attached to a {Type} object.
|
data/lib/yadriggy/typecheck.rb
CHANGED
@@ -160,6 +160,7 @@ module Yadriggy
|
|
160
160
|
end
|
161
161
|
|
162
162
|
# Gets the current type environment.
|
163
|
+
# @return [TypeEnv] the type enviornment.
|
163
164
|
#
|
164
165
|
def type_env
|
165
166
|
@current_env
|
@@ -204,12 +205,17 @@ module Yadriggy
|
|
204
205
|
#
|
205
206
|
# This is an alias of check_all() but it memoizes the results.
|
206
207
|
#
|
208
|
+
# @param [ASTnode|ASTree|nil] an_ast an AST or nil.
|
209
|
+
# @return [Type] the type of the given AST. It memoizes the results.
|
210
|
+
#
|
207
211
|
def typecheck(an_ast)
|
208
212
|
check_all(an_ast)
|
209
213
|
end
|
210
214
|
|
211
215
|
# Makes a new base type environment with the given context class.
|
212
216
|
#
|
217
|
+
# @return [TypeEnv] the type enviornment.
|
218
|
+
#
|
213
219
|
def make_base_env(klass)
|
214
220
|
TypeEnv::BaseTypeEnv.new(klass)
|
215
221
|
end
|
@@ -248,7 +254,7 @@ module Yadriggy
|
|
248
254
|
#
|
249
255
|
# @param [ASTnode|nil] an_ast an AST.
|
250
256
|
# @param [Type] a_type a type.
|
251
|
-
# @return [Type|
|
257
|
+
# @return [Type|DynType] the given type `a_type`.
|
252
258
|
def type_as(an_ast, a_type)
|
253
259
|
if an_ast.nil?
|
254
260
|
DynType
|
data/lib/yadriggy/version.rb
CHANGED
data/yadriggy.gemspec
CHANGED
@@ -23,11 +23,12 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ["lib"]
|
25
25
|
|
26
|
+
spec.add_dependency "pycall"
|
26
27
|
spec.add_dependency "ffi"
|
27
28
|
spec.add_dependency "pry"
|
28
29
|
|
29
|
-
spec.add_development_dependency "bundler"
|
30
|
-
spec.add_development_dependency "rake", "
|
30
|
+
spec.add_development_dependency "bundler"
|
31
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
31
32
|
spec.add_development_dependency "yard"
|
32
33
|
# spec.add_development_dependency "minitest", "~> 5.0"
|
33
34
|
spec.add_development_dependency "test-unit", "~> 3.2.5"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yadriggy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shigeru Chiba
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pycall
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: ffi
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -42,30 +56,30 @@ dependencies:
|
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - "
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - "
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - "
|
73
|
+
- - ">="
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
75
|
+
version: 12.3.3
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - "
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
82
|
+
version: 12.3.3
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: yard
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,6 +148,7 @@ files:
|
|
134
148
|
- lib/yadriggy/py/import.rb
|
135
149
|
- lib/yadriggy/py/py_typechecker.rb
|
136
150
|
- lib/yadriggy/py/python.rb
|
151
|
+
- lib/yadriggy/py/syntax.rb
|
137
152
|
- lib/yadriggy/ruby_typecheck.rb
|
138
153
|
- lib/yadriggy/ruby_typeinfer.rb
|
139
154
|
- lib/yadriggy/source_code.rb
|
@@ -161,8 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
176
|
- !ruby/object:Gem::Version
|
162
177
|
version: '0'
|
163
178
|
requirements: []
|
164
|
-
|
165
|
-
rubygems_version: 2.6.14
|
179
|
+
rubygems_version: 3.3.11
|
166
180
|
signing_key:
|
167
181
|
specification_version: 4
|
168
182
|
summary: library for building a DSL embedded in Ruby.
|