yadriggy 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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