yadriggy 1.2.1 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d83c607a05a798affb11bc37c66957e52fea134
4
- data.tar.gz: b09072545e519f69744cde7b7a16c0b0fc605a7d
3
+ metadata.gz: 5af1fba63b8de51cbdd01aec66b557292134c43f
4
+ data.tar.gz: f797ce20c6a020eac1cd3ecc7de7cdc6567ccd13
5
5
  SHA512:
6
- metadata.gz: 1941aeddac242432dfe7f24b99c84e2563abc94ca7b280a51761dab718ed5c43a20763ddb11a410d60d0cb95848b94c7d15c458945773866fa33e415eaf2363e
7
- data.tar.gz: 73fa0d7468e8384589865f5f7535a97580f045909969e0df8fe82cee5fddfc181e8f8f5f97a5a6cd57534df950d4dab2ee2a0e65b95ff32379dc7a5ef8c8a9f6
6
+ metadata.gz: e91097275404a17c9c6e98c1ee0b4ae58c4c21a13562baae2fdad877d0d9905dc53878a99d754ba729465d2e8716d925ef1191ce836419307ea85c2c91f25605
7
+ data.tar.gz: 8a6e29162f1f420ec5598ffed5de0a179cc45f3cf9639570d08d281566bff2bf21d176730b5767bb19f0d4a10012825eda4e6044dc86626da47e5f95cef0e857
data/.gitignore CHANGED
@@ -11,3 +11,5 @@
11
11
  /spec/reports/
12
12
  /testbin/
13
13
  /tmp/
14
+ /lib/yadriggy/oops/yadriggy_oops.bundle
15
+ /lib/yadriggy/oops/gc.hpp
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Yadriggy
2
2
 
3
- Yadriggy (mistletoe in Japanese) is a library for building a
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:
@@ -912,7 +912,7 @@ module Yadriggy
912
912
 
913
913
  def initialize_call(sexp)
914
914
  @receiver = to_node(sexp[1])
915
- @op = sexp[2] # :"." or :"::" or nil.
915
+ @op = op_symbol(sexp[2]) # :"." or :"::" or nil.
916
916
  @name = if sexp[3] == :call
917
917
  nil
918
918
  else
@@ -922,6 +922,16 @@ module Yadriggy
922
922
  add_child(@name)
923
923
  end
924
924
 
925
+ def op_symbol(op)
926
+ if op.is_a?(Array)
927
+ op = has_tag?(op, :@period)
928
+ op[1].to_sym
929
+ else
930
+ # Ruby 2.5 or earlier
931
+ op
932
+ end
933
+ end
934
+
925
935
  def initialize_args(args_block)
926
936
  args = if args_block[0] == :args_add_block
927
937
  args_block[1]
@@ -1380,7 +1390,7 @@ module Yadriggy
1380
1390
  if body.is_a?(Array) && body.length > 0 && body[0] == :bodystmt
1381
1391
  bodystmnt = body[1]
1382
1392
  @rescue = Rescue.make(body[2], body[3], body[4])
1383
- else # if Ruby 2.4 or earlier
1393
+ else # if Ruby 2.5 or earlier
1384
1394
  bodystmnt = body
1385
1395
  @rescue = nil
1386
1396
  end
@@ -1488,8 +1498,14 @@ module Yadriggy
1488
1498
  if else_expr.nil?
1489
1499
  @else = nil
1490
1500
  else
1491
- elsexpr = has_tag?(else_expr, :else)
1492
- @else = Exprs.make(elsexpr[1])
1501
+ if !else_expr.nil? && else_expr[0].is_a?(Array)
1502
+ else_body = else_expr
1503
+ else
1504
+ # Ruby 2.4 or earlier
1505
+ elsexpr = has_tag?(else_expr, :else)
1506
+ else_body = else_expr[1]
1507
+ end
1508
+ @else = Exprs.make(else_body)
1493
1509
  add_child(@else)
1494
1510
  end
1495
1511
 
@@ -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 typing rule for #{an_ast.class}")
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 [Type] the type of the given AST.
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
@@ -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 << ' '
@@ -1,6 +1,7 @@
1
1
  # Copyright (C) 2018- Shigeru Chiba. All rights reserved.
2
2
 
3
- require 'yadriggy/py/python'
3
+ require 'yadriggy'
4
+ require 'yadriggy/py/syntax'
4
5
 
5
6
  module Yadriggy
6
7
  module Py
@@ -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
@@ -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
- # @api private
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('') do |source, line|
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
@@ -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|nil] the given type `a_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
@@ -1,5 +1,5 @@
1
1
  # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
2
 
3
3
  module Yadriggy
4
- VERSION = "1.2.1"
4
+ VERSION = "1.3.0"
5
5
  end
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency "ffi"
28
28
  spec.add_dependency "pry"
29
29
 
30
- spec.add_development_dependency "bundler", "~> 1.13"
30
+ spec.add_development_dependency "bundler"
31
31
  spec.add_development_dependency "rake", "~> 10.0"
32
32
  spec.add_development_dependency "yard"
33
33
  # spec.add_development_dependency "minitest", "~> 5.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yadriggy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.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: 2018-12-10 00:00:00.000000000 Z
11
+ date: 2019-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pycall
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.13'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.13'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -148,6 +148,7 @@ files:
148
148
  - lib/yadriggy/py/import.rb
149
149
  - lib/yadriggy/py/py_typechecker.rb
150
150
  - lib/yadriggy/py/python.rb
151
+ - lib/yadriggy/py/syntax.rb
151
152
  - lib/yadriggy/ruby_typecheck.rb
152
153
  - lib/yadriggy/ruby_typeinfer.rb
153
154
  - lib/yadriggy/source_code.rb