kapusta 0.13.1 → 0.13.2

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
  SHA256:
3
- metadata.gz: 9324827934a0647689027ecf5fc6bf83708fe536cd904dc04d1f9c0594c37581
4
- data.tar.gz: 736a8f7d8158fc4502415168f5791d7af8b98f392800255576c1d0182ef920c6
3
+ metadata.gz: fa363e8e708ddf94ca3406bda52d7603663e9de82a79eec94328082f5310b638
4
+ data.tar.gz: cf1a0911c16fa481bc1680380eb2677329276289c513e8d66d9f4450cad9d762
5
5
  SHA512:
6
- metadata.gz: 62e4118362c7fbe7ae034470a01ddf37a0bb826fb142e2611d72b09ded1777e52bf2b078cf48c0283dda6f0a8c5989ec31f60d0913cf16ec3ac9ccabf2c40626
7
- data.tar.gz: 5fbd5b3a7809eff626c43203b1c36761efac10cb5663ca345ace26fbea731da63402909be6a04f22aedaca80945e1db3456209a6ac335b8fc4a2152bcc198395
6
+ metadata.gz: d2e4405abbab87cc70e8b00ab05840f50b6050c965d63351e6db3a2e5ab2f97219bb517d837ef8f8166df27ae4d53d0bd9a595de6bbed3d5e0319de0c13b2a88
7
+ data.tar.gz: 8e88867b98adba5e17d0eaf6a506518bdb0a7f7b2628d5ce3937fad5f29e73766dba4767340716f06ec7ff3e9b68df6924b7cadf936a71cb18bf47e88a26ca4b
@@ -496,37 +496,8 @@ module Kapusta
496
496
  Kapusta.kebab_to_snake(name).gsub(/[^a-zA-Z0-9_]/, '_')
497
497
  end
498
498
 
499
- SIMPLE_EXPRESSION_PATTERNS = [
500
- /\A[a-z_]\w*\z/, # local
501
- /\A@@?[a-z_]\w*\z/, # @ivar / @@cvar
502
- /\A\$[a-zA-Z_]\w*\z/, # $gvar
503
- /\A[A-Z]\w*(?:::[A-Z]\w*)*\z/, # Constant / A::B::C
504
- /\A[a-z_]\w*[!?=]?\([^()\n]*\)\z/, # bare call foo(...)
505
- /\A-?\d+(?:\.\d+)?\z/, # number
506
- /\A[a-z_]\w*(?:\.[a-z_]\w*[!?=]?(?:\([^()\n]*\))?|\[[^\[\]]*\])+\z/, # local + .m/[k] chain
507
- /\A[A-Z]\w*(?:::[A-Z]\w*)*(?:\.[a-z_]\w*[!?=]?(?:\([^()\n]*\))?|\[[^\[\]]*\])+\z/, # const + chain
508
- /\A\([^()\n]*\)(?:\.[a-zA-Z_]\w*[!?=]?(?:\([^()\n]*\))?|\[[^\[\]]*\])+\z/, # (expr).chain
509
- /\A:[a-zA-Z_]\w*[!?=]?\z/, # :symbol
510
- /\A"(?:[^"\\]|\\.)*"\z/, # "string"
511
- /\A'(?:[^'\\]|\\.)*'\z/, # 'string'
512
- /\A\[[^\[\]\n]*\]\z/ # [flat, array]
513
- ].freeze
514
- private_constant :SIMPLE_EXPRESSION_PATTERNS
515
-
516
- SIMPLE_EXPRESSION_KEYWORDS = %w[nil true false self].freeze
517
- private_constant :SIMPLE_EXPRESSION_KEYWORDS
518
-
519
499
  def simple_expression?(code)
520
- SIMPLE_EXPRESSION_PATTERNS.any? { |re| code.match?(re) } ||
521
- SIMPLE_EXPRESSION_KEYWORDS.include?(code) ||
522
- negation_simple?(code)
523
- end
524
-
525
- def negation_simple?(code)
526
- return false unless code.start_with?('!') && code.length > 1
527
-
528
- rest = code[1..]
529
- simple_expression?(rest) || (rest.start_with?('(') && rest.end_with?(')'))
500
+ SimpleExpression.match?(code)
530
501
  end
531
502
  end
532
503
  end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kapusta
4
+ module Compiler
5
+ module EmitterModules
6
+ module SimpleExpression
7
+ module_function
8
+
9
+ KEYWORDS = %w[nil true false self].freeze
10
+
11
+ OPENERS = { '(' => ')', '[' => ']', '{' => '}' }.freeze
12
+ CLOSERS = OPENERS.values.freeze
13
+
14
+ # `{...}` is intentionally excluded — a top-level hash or block literal
15
+ # shouldn't be treated as a bare primary even though balanced.
16
+ PRIMARY_OPENERS = { '(' => ')', '[' => ']' }.freeze
17
+
18
+ PRIMARY_PATTERNS = [
19
+ /\A-?\d+(?:\.\d+)?/, # number (incl. negative literal)
20
+ /\A:[a-zA-Z_]\w*[!?=]?/, # :symbol
21
+ /\A"(?:[^"\\]|\\.)*"/, # "string"
22
+ /\A'(?:[^'\\]|\\.)*'/, # 'string'
23
+ /\A@@?[a-z_]\w*/, # @ivar / @@cvar
24
+ /\A\$[a-zA-Z_]\w*/, # $gvar
25
+ /\A[A-Z]\w*(?:::[A-Z]\w*)*/, # Constant / A::B::C
26
+ /\A[a-z_]\w*[!?=]?/ # local or bare call head
27
+ ].freeze
28
+
29
+ CHAIN_METHOD = /\A\.[a-zA-Z_]\w*[!?=]?/
30
+
31
+ def match?(code)
32
+ return false if code.empty? || code.include?("\n")
33
+ return true if KEYWORDS.include?(code)
34
+ return negation?(code) if code.start_with?('!')
35
+
36
+ consume(code, 0) == code.length
37
+ end
38
+
39
+ def negation?(code)
40
+ return false if code.length < 2
41
+
42
+ rest = code[1..]
43
+ match?(rest) || (rest.start_with?('(') && rest.end_with?(')'))
44
+ end
45
+
46
+ def consume(code, pos)
47
+ pos = consume_primary(code, pos)
48
+ while pos && pos < code.length
49
+ advanced = consume_segment(code, pos)
50
+ break unless advanced
51
+
52
+ pos = advanced
53
+ end
54
+ pos
55
+ end
56
+
57
+ def consume_primary(code, pos)
58
+ return consume_group(code, pos) if PRIMARY_OPENERS.key?(code[pos])
59
+
60
+ regex = PRIMARY_PATTERNS.find { |re| code[pos..].match?(re) }
61
+ return unless regex
62
+
63
+ after = pos + regex.match(code[pos..]).end(0)
64
+ code[after] == '(' ? consume_group(code, after) : after
65
+ end
66
+
67
+ def consume_segment(code, pos)
68
+ return consume_group(code, pos) if code[pos] == '['
69
+ return unless code[pos] == '.'
70
+
71
+ match = CHAIN_METHOD.match(code[pos..])
72
+ return unless match
73
+
74
+ after = pos + match.end(0)
75
+ code[after] == '(' ? consume_group(code, after) : after
76
+ end
77
+
78
+ def consume_group(code, pos)
79
+ return unless OPENERS.key?(code[pos])
80
+
81
+ stack = [OPENERS[code[pos]]]
82
+ pos += 1
83
+ quote = nil
84
+ while pos < code.length
85
+ ch = code[pos]
86
+ if quote
87
+ if ch == '\\' && pos + 1 < code.length
88
+ pos += 2
89
+ else
90
+ quote = nil if ch == quote
91
+ pos += 1
92
+ end
93
+ elsif ['"', "'"].include?(ch)
94
+ quote = ch
95
+ pos += 1
96
+ elsif OPENERS.key?(ch)
97
+ stack.push(OPENERS[ch])
98
+ pos += 1
99
+ elsif CLOSERS.include?(ch)
100
+ return unless stack.last == ch
101
+
102
+ stack.pop
103
+ pos += 1
104
+ return pos if stack.empty?
105
+ else
106
+ pos += 1
107
+ end
108
+ end
109
+ nil
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'emitter/simple_expression'
3
4
  require_relative 'emitter/support'
4
5
  require_relative 'emitter/expressions'
5
6
  require_relative 'emitter/bindings'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kapusta
4
- VERSION = '0.13.1'
4
+ VERSION = '0.13.2'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kapusta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.13.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgenii Morozov
@@ -153,6 +153,7 @@ files:
153
153
  - lib/kapusta/compiler/emitter/expressions.rb
154
154
  - lib/kapusta/compiler/emitter/interop.rb
155
155
  - lib/kapusta/compiler/emitter/patterns.rb
156
+ - lib/kapusta/compiler/emitter/simple_expression.rb
156
157
  - lib/kapusta/compiler/emitter/support.rb
157
158
  - lib/kapusta/compiler/lua_compat.rb
158
159
  - lib/kapusta/compiler/macro_expander.rb