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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa363e8e708ddf94ca3406bda52d7603663e9de82a79eec94328082f5310b638
|
|
4
|
+
data.tar.gz: cf1a0911c16fa481bc1680380eb2677329276289c513e8d66d9f4450cad9d762
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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
|
data/lib/kapusta/version.rb
CHANGED
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.
|
|
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
|