summaryrefslogtreecommitdiff
path: root/prism
diff options
context:
space:
mode:
Diffstat (limited to 'prism')
-rw-r--r--prism/config.yml343
-rw-r--r--prism/encoding.c239
-rw-r--r--prism/extension.c22
-rw-r--r--prism/extension.h2
-rw-r--r--prism/options.c24
-rw-r--r--prism/options.h52
-rw-r--r--prism/parser.h3
-rw-r--r--prism/prism.c3526
-rw-r--r--prism/prism.h55
-rw-r--r--prism/regexp.h4
-rw-r--r--prism/srcs.mk150
-rw-r--r--prism/srcs.mk.in48
-rw-r--r--prism/templates/include/prism/ast.h.erb46
-rw-r--r--prism/templates/lib/prism/compiler.rb.erb6
-rw-r--r--prism/templates/lib/prism/node.rb.erb42
-rw-r--r--prism/templates/lib/prism/serialize.rb.erb2
-rw-r--r--prism/templates/lib/prism/visitor.rb.erb8
-rw-r--r--prism/templates/src/diagnostic.c.erb5
-rw-r--r--prism/templates/src/serialize.c.erb2
-rwxr-xr-xprism/templates/template.rb7
-rw-r--r--prism/util/pm_buffer.h8
-rw-r--r--prism/util/pm_constant_pool.c2
-rw-r--r--prism/util/pm_integer.h4
-rw-r--r--prism/util/pm_list.h6
-rw-r--r--prism/util/pm_string.c14
-rw-r--r--prism/util/pm_string.h14
-rw-r--r--prism/version.h4
27 files changed, 2423 insertions, 2215 deletions
diff --git a/prism/config.yml b/prism/config.yml
index 3d5eee190f..4e5b077a35 100644
--- a/prism/config.yml
+++ b/prism/config.yml
@@ -60,6 +60,7 @@ errors:
- CONDITIONAL_WHILE_PREDICATE
- CONSTANT_PATH_COLON_COLON_CONSTANT
- DEF_ENDLESS
+ - DEF_ENDLESS_PARAMETERS
- DEF_ENDLESS_SETTER
- DEF_NAME
- DEF_PARAMS_TERM
@@ -101,6 +102,8 @@ errors:
- EXPECT_FOR_DELIMITER
- EXPECT_IDENT_REQ_PARAMETER
- EXPECT_IN_DELIMITER
+ - EXPECT_LPAREN_AFTER_NOT_LPAREN
+ - EXPECT_LPAREN_AFTER_NOT_OTHER
- EXPECT_LPAREN_REQ_PARAMETER
- EXPECT_MESSAGE
- EXPECT_RBRACKET
@@ -216,6 +219,7 @@ errors:
- PARAMETER_WILD_LOOSE_COMMA
- PATTERN_ARRAY_MULTIPLE_RESTS
- PATTERN_CAPTURE_DUPLICATE
+ - PATTERN_CAPTURE_IN_ALTERNATIVE
- PATTERN_EXPRESSION_AFTER_BRACKET
- PATTERN_EXPRESSION_AFTER_COMMA
- PATTERN_EXPRESSION_AFTER_HROCKET
@@ -277,6 +281,7 @@ errors:
- UNEXPECTED_INDEX_KEYWORDS
- UNEXPECTED_LABEL
- UNEXPECTED_MULTI_WRITE
+ - UNEXPECTED_PARAMETER_DEFAULT_VALUE
- UNEXPECTED_RANGE_OPERATOR
- UNEXPECTED_SAFE_NAVIGATION
- UNEXPECTED_TOKEN_CLOSE_CONTEXT
@@ -320,13 +325,44 @@ warnings:
- UNUSED_LOCAL_VARIABLE
- VOID_STATEMENT
tokens:
+ # The order of the tokens at the beginning is important, because we use them
+ # for a lookup table.
- name: EOF
value: 1
comment: final token in the file
- - name: MISSING
- comment: "a token that was expected but not found"
- - name: NOT_PROVIDED
- comment: "a token that was not present but it is okay"
+ - name: BRACE_RIGHT
+ comment: "}"
+ - name: COMMA
+ comment: ","
+ - name: EMBEXPR_END
+ comment: "}"
+ - name: KEYWORD_DO
+ comment: "do"
+ - name: KEYWORD_ELSE
+ comment: "else"
+ - name: KEYWORD_ELSIF
+ comment: "elsif"
+ - name: KEYWORD_END
+ comment: "end"
+ - name: KEYWORD_ENSURE
+ comment: "ensure"
+ - name: KEYWORD_IN
+ comment: "in"
+ - name: KEYWORD_RESCUE
+ comment: "rescue"
+ - name: KEYWORD_THEN
+ comment: "then"
+ - name: KEYWORD_WHEN
+ comment: "when"
+ - name: NEWLINE
+ comment: "a newline character outside of other tokens"
+ - name: PARENTHESIS_RIGHT
+ comment: ")"
+ - name: PIPE
+ comment: "|"
+ - name: SEMICOLON
+ comment: ";"
+ # Tokens from here on are not used for lookup, and can be in any order.
- name: AMPERSAND
comment: "&"
- name: AMPERSAND_AMPERSAND
@@ -349,8 +385,6 @@ tokens:
comment: "!~"
- name: BRACE_LEFT
comment: "{"
- - name: BRACE_RIGHT
- comment: "}"
- name: BRACKET_LEFT
comment: "["
- name: BRACKET_LEFT_ARRAY
@@ -373,8 +407,6 @@ tokens:
comment: ":"
- name: COLON_COLON
comment: "::"
- - name: COMMA
- comment: ","
- name: COMMENT
comment: "a comment"
- name: CONSTANT
@@ -393,8 +425,6 @@ tokens:
comment: "a line inside of embedded documentation"
- name: EMBEXPR_BEGIN
comment: "#{"
- - name: EMBEXPR_END
- comment: "}"
- name: EMBVAR
comment: "#"
- name: EQUAL
@@ -461,20 +491,10 @@ tokens:
comment: "def"
- name: KEYWORD_DEFINED
comment: "defined?"
- - name: KEYWORD_DO
- comment: "do"
- name: KEYWORD_DO_LOOP
comment: "do keyword for a predicate in a while, until, or for loop"
- - name: KEYWORD_ELSE
- comment: "else"
- - name: KEYWORD_ELSIF
- comment: "elsif"
- - name: KEYWORD_END
- comment: "end"
- name: KEYWORD_END_UPCASE
comment: "END"
- - name: KEYWORD_ENSURE
- comment: "ensure"
- name: KEYWORD_FALSE
comment: "false"
- name: KEYWORD_FOR
@@ -483,8 +503,6 @@ tokens:
comment: "if"
- name: KEYWORD_IF_MODIFIER
comment: "if in the modifier form"
- - name: KEYWORD_IN
- comment: "in"
- name: KEYWORD_MODULE
comment: "module"
- name: KEYWORD_NEXT
@@ -497,8 +515,6 @@ tokens:
comment: "or"
- name: KEYWORD_REDO
comment: "redo"
- - name: KEYWORD_RESCUE
- comment: "rescue"
- name: KEYWORD_RESCUE_MODIFIER
comment: "rescue in the modifier form"
- name: KEYWORD_RETRY
@@ -509,8 +525,6 @@ tokens:
comment: "self"
- name: KEYWORD_SUPER
comment: "super"
- - name: KEYWORD_THEN
- comment: "then"
- name: KEYWORD_TRUE
comment: "true"
- name: KEYWORD_UNDEF
@@ -523,8 +537,6 @@ tokens:
comment: "until"
- name: KEYWORD_UNTIL_MODIFIER
comment: "until in the modifier form"
- - name: KEYWORD_WHEN
- comment: "when"
- name: KEYWORD_WHILE
comment: "while"
- name: KEYWORD_WHILE_MODIFIER
@@ -561,16 +573,12 @@ tokens:
comment: "-="
- name: MINUS_GREATER
comment: "->"
- - name: NEWLINE
- comment: "a newline character outside of other tokens"
- name: NUMBERED_REFERENCE
comment: "a numbered reference to a capture group in the previous regular expression match"
- name: PARENTHESIS_LEFT
comment: "("
- name: PARENTHESIS_LEFT_PARENTHESES
comment: "( for a parentheses node"
- - name: PARENTHESIS_RIGHT
- comment: ")"
- name: PERCENT
comment: "%"
- name: PERCENT_EQUAL
@@ -585,8 +593,6 @@ tokens:
comment: "%I"
- name: PERCENT_UPPER_W
comment: "%W"
- - name: PIPE
- comment: "|"
- name: PIPE_EQUAL
comment: "|="
- name: PIPE_PIPE
@@ -603,8 +609,6 @@ tokens:
comment: "the beginning of a regular expression"
- name: REGEXP_END
comment: "the end of a regular expression"
- - name: SEMICOLON
- comment: ";"
- name: SLASH
comment: "/"
- name: SLASH_EQUAL
@@ -649,6 +653,10 @@ tokens:
comment: "a separator between words in a list"
- name: __END__
comment: "marker for the point in the file at which the parser should stop"
+ - name: MISSING
+ comment: "a token that was expected but not found"
+ - name: NOT_PROVIDED
+ comment: "a token that was not present but it is okay"
flags:
- name: ArgumentsNodeFlags
values:
@@ -987,8 +995,19 @@ nodes:
- name: constant
type: node?
kind:
- - ConstantReadNode
- ConstantPathNode
+ - ConstantReadNode
+ comment: |
+ Represents the optional constant preceding the Array
+
+ foo in Bar[]
+ ^^^
+
+ foo in Bar[1, 2, 3]
+ ^^^
+
+ foo in Bar::Baz[1, 2, 3]
+ ^^^^^^^^
- name: requireds
type: node[]
kind: pattern expression
@@ -1250,17 +1269,17 @@ nodes:
- name: opening_loc
type: location
comment: |
- Represents the location of the opening `|`.
+ Represents the location of the opening `{` or `do`.
[1, 2, 3].each { |i| puts x }
- ^
+ ^
- name: closing_loc
type: location
comment: |
- Represents the location of the closing `|`.
+ Represents the location of the closing `}` or `end`.
[1, 2, 3].each { |i| puts x }
- ^
+ ^
comment: |
Represents a block of ruby code.
@@ -1498,6 +1517,16 @@ nodes:
foo(bar)
^
+ - name: equal_loc
+ type: location?
+ comment: |
+ Represents the location of the equal sign, in the case that this is an attribute write.
+
+ foo.bar = value
+ ^
+
+ foo[bar] = value
+ ^
- name: block
type: node?
kind:
@@ -1784,7 +1813,7 @@ nodes:
Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
case true; when false; end
- ^^^^
+ ^^^^
- name: conditions
type: node[]
kind: WhenNode
@@ -1828,6 +1857,11 @@ nodes:
type: constant[]
- name: class_keyword_loc
type: location
+ comment: |
+ Represents the location of the `class` keyword.
+
+ class Foo end
+ ^^^^^
- name: constant_path
type: node
kind:
@@ -1836,18 +1870,43 @@ nodes:
- on error: CallNode # class 0.X end
- name: inheritance_operator_loc
type: location?
+ comment: |
+ Represents the location of the `<` operator.
+
+ class Foo < Bar
+ ^
- name: superclass
type: node?
kind: non-void expression
+ comment: |
+ Represents the superclass of the class.
+
+ class Foo < Bar
+ ^^^
- name: body
type: node?
kind:
- StatementsNode
- BeginNode
+ comment: |
+ Represents the body of the class.
+
+ class Foo
+ foo
+ ^^^
- name: end_keyword_loc
type: location
+ comment: |
+ Represents the location of the `end` keyword.
+
+ class Foo end
+ ^^^
- name: name
type: constant
+ comment: |
+ The name of the class.
+
+ class Foo end # name `:Foo`
comment: |
Represents a class declaration involving the `class` keyword.
@@ -2374,23 +2433,68 @@ nodes:
- name: constant
type: node?
kind:
- - ConstantReadNode
- ConstantPathNode
+ - ConstantReadNode
+ comment: |
+ Represents the optional constant preceding the pattern
+
+ foo in Foo(*bar, baz, *qux)
+ ^^^
- name: left
type: node
kind: SplatNode
+ comment: |
+ Represents the first wildcard node in the pattern.
+
+ foo in *bar, baz, *qux
+ ^^^^
+
+ foo in Foo(*bar, baz, *qux)
+ ^^^^
- name: requireds
type: node[]
kind: pattern expression
+ comment: |
+ Represents the nodes in between the wildcards.
+
+ foo in *bar, baz, *qux
+ ^^^
+
+ foo in Foo(*bar, baz, 1, *qux)
+ ^^^^^^
- name: right
type: node
kind:
- SplatNode
- on error: MissingNode
+ comment: |
+ Represents the second wildcard node in the pattern.
+
+ foo in *bar, baz, *qux
+ ^^^^
+
+ foo in Foo(*bar, baz, *qux)
+ ^^^^
- name: opening_loc
type: location?
+ comment: |
+ The location of the opening brace.
+
+ foo in [*bar, baz, *qux]
+ ^
+
+ foo in Foo(*bar, baz, *qux)
+ ^
- name: closing_loc
type: location?
+ comment: |
+ The location of the closing brace.
+
+ foo in [*bar, baz, *qux]
+ ^
+
+ foo in Foo(*bar, baz, *qux)
+ ^
comment: |
Represents a find pattern in pattern matching.
@@ -2402,6 +2506,9 @@ nodes:
foo in Foo(*bar, baz, *qux)
^^^^^^^^^^^^^^^^^^^^
+
+ foo => *bar, baz, *qux
+ ^^^^^^^^^^^^^^^
- name: FlipFlopNode
flags: RangeFlags
fields:
@@ -2521,11 +2628,18 @@ nodes:
- name: block
type: node?
kind: BlockNode
+ comment: |
+ All other arguments are forwarded as normal, except the original block is replaced with the new block.
comment: |
- Represents the use of the `super` keyword without parentheses or arguments.
+ Represents the use of the `super` keyword without parentheses or arguments, but which might have a block.
super
^^^^^
+
+ super { 123 }
+ ^^^^^^^^^^^^^
+
+ If it has any other arguments, it would be a `SuperNode` instead.
- name: GlobalVariableAndWriteNode
fields:
- name: name
@@ -2679,20 +2793,60 @@ nodes:
- name: constant
type: node?
kind:
- - ConstantReadNode
- ConstantPathNode
+ - ConstantReadNode
+ comment: |
+ Represents the optional constant preceding the Hash.
+
+ foo => Bar[a: 1, b: 2]
+ ^^^
+
+ foo => Bar::Baz[a: 1, b: 2]
+ ^^^^^^^^
- name: elements
type: node[]
kind: AssocNode
+ comment: |
+ Represents the explicit named hash keys and values.
+
+ foo => { a: 1, b:, ** }
+ ^^^^^^^^
- name: rest
type: node?
kind:
- AssocSplatNode
- NoKeywordsParameterNode
+ comment: |
+ Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`.
+
+ foo => { a: 1, b:, **c }
+ ^^^
+
+ foo => { a: 1, b:, ** }
+ ^^
+
+ foo => { a: 1, b:, **nil }
+ ^^^^^
- name: opening_loc
type: location?
+ comment: |
+ The location of the opening brace.
+
+ foo => { a: 1 }
+ ^
+
+ foo => Bar[a: 1]
+ ^
- name: closing_loc
type: location?
+ comment: |
+ The location of the closing brace.
+
+ foo => { a: 1 }
+ ^
+
+ foo => Bar[a: 1]
+ ^
comment: |
Represents a hash pattern in pattern matching.
@@ -2701,6 +2855,12 @@ nodes:
foo => { a: 1, b: 2, **c }
^^^^^^^^^^^^^^^^^^^
+
+ foo => Bar[a: 1, b: 2]
+ ^^^^^^^^^^^^^^^
+
+ foo in { a: 1, b: 2 }
+ ^^^^^^^^^^^^^^
- name: IfNode
fields:
- name: if_keyword_loc
@@ -3146,6 +3306,9 @@ nodes:
- EmbeddedVariableNode
- InterpolatedStringNode # `"a" "#{b}"`
- on error: XStringNode # `<<`FOO` "bar"
+ - on error: InterpolatedXStringNode
+ - on error: SymbolNode
+ - on error: InterpolatedSymbolNode
- name: closing_loc
type: location?
newline: parts
@@ -3353,6 +3516,9 @@ nodes:
foo, bar = baz
^^^ ^^^
+
+ foo => baz
+ ^^^
- name: LocalVariableWriteNode
fields:
- name: name
@@ -3443,11 +3609,65 @@ nodes:
- name: value
type: node
kind: non-void expression
+ comment: |
+ Represents the left-hand side of the operator.
+
+ foo => bar
+ ^^^
- name: pattern
type: node
kind: pattern expression
+ comment: |
+ Represents the right-hand side of the operator. The type of the node depends on the expression.
+
+ Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`.
+
+ foo => a # This is equivalent to writing `a = foo`
+ ^
+
+ Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant.
+
+ foo => [a]
+ ^^^
+
+ foo => a, b
+ ^^^^
+
+ foo => Bar[a, b]
+ ^^^^^^^^^
+
+ If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead.
+
+ foo => *, 1, *a
+ ^^^^^
+
+ Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`.
+
+ foo => { a: 1, b: }
+
+ foo => Bar[a: 1, b:]
+
+ foo => Bar[**]
+
+ To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode`
+
+ foo => ^a
+ ^^
+
+ Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`.
+
+ foo => ^(a + 1)
+
+ Anything else will result in the regular node for that expression, for example a `ConstantReadNode`.
+
+ foo => CONST
- name: operator_loc
type: location
+ comment: |
+ The location of the operator.
+
+ foo => bar
+ ^^
comment: |
Represents the use of the `=>` operator.
@@ -3877,12 +4097,32 @@ nodes:
- name: expression
type: node
kind: non-void expression
+ comment: |
+ The expression used in the pinned expression
+
+ foo in ^(bar)
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ The location of the `^` operator
+
+ foo in ^(bar)
+ ^
- name: lparen_loc
type: location
+ comment: |
+ The location of the opening parenthesis.
+
+ foo in ^(bar)
+ ^
- name: rparen_loc
type: location
+ comment: |
+ The location of the closing parenthesis.
+
+ foo in ^(bar)
+ ^
comment: |
Represents the use of the `^` operator for pinning an expression in a pattern matching expression.
@@ -3901,8 +4141,18 @@ nodes:
- NumberedReferenceReadNode # foo in ^$1
- ItLocalVariableReadNode # proc { 1 in ^it }
- on error: MissingNode # foo in ^Bar
+ comment: |
+ The variable used in the pinned expression
+
+ foo in ^bar
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ The location of the `^` operator
+
+ foo in ^bar
+ ^
comment: |
Represents the use of the `^` operator for pinning a variable in a pattern matching expression.
@@ -4268,6 +4518,7 @@ nodes:
- name: arguments
type: node?
kind: ArgumentsNode
+ comment: "Can be only `nil` when there are empty parentheses, like `super()`."
- name: rparen_loc
type: location?
- name: block
@@ -4283,6 +4534,8 @@ nodes:
super foo, bar
^^^^^^^^^^^^^^
+
+ If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead.
- name: SymbolNode
flags: SymbolFlags
fields:
diff --git a/prism/encoding.c b/prism/encoding.c
index a4aeed104f..d7e5616840 100644
--- a/prism/encoding.c
+++ b/prism/encoding.c
@@ -2,7 +2,7 @@
typedef uint32_t pm_unicode_codepoint_t;
-#define UNICODE_ALPHA_CODEPOINTS_LENGTH 1450
+#define UNICODE_ALPHA_CODEPOINTS_LENGTH 1508
static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEPOINTS_LENGTH] = {
0x100, 0x2C1,
0x2C6, 0x2D1,
@@ -10,7 +10,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x2EC, 0x2EC,
0x2EE, 0x2EE,
0x345, 0x345,
- 0x370, 0x374,
+ 0x363, 0x374,
0x376, 0x377,
0x37A, 0x37D,
0x37F, 0x37F,
@@ -50,7 +50,8 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x840, 0x858,
0x860, 0x86A,
0x870, 0x887,
- 0x889, 0x88E,
+ 0x889, 0x88F,
+ 0x897, 0x897,
0x8A0, 0x8C9,
0x8D4, 0x8DF,
0x8E3, 0x8E9,
@@ -140,7 +141,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0xC4A, 0xC4C,
0xC55, 0xC56,
0xC58, 0xC5A,
- 0xC5D, 0xC5D,
+ 0xC5C, 0xC5D,
0xC60, 0xC63,
0xC80, 0xC83,
0xC85, 0xC8C,
@@ -152,7 +153,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0xCC6, 0xCC8,
0xCCA, 0xCCC,
0xCD5, 0xCD6,
- 0xCDD, 0xCDE,
+ 0xCDC, 0xCDE,
0xCE0, 0xCE3,
0xCF1, 0xCF3,
0xD00, 0xD0C,
@@ -264,7 +265,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1C00, 0x1C36,
0x1C4D, 0x1C4F,
0x1C5A, 0x1C7D,
- 0x1C80, 0x1C88,
+ 0x1C80, 0x1C8A,
0x1C90, 0x1CBA,
0x1CBD, 0x1CBF,
0x1CE9, 0x1CEC,
@@ -272,7 +273,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1CF5, 0x1CF6,
0x1CFA, 0x1CFA,
0x1D00, 0x1DBF,
- 0x1DE7, 0x1DF4,
+ 0x1DD3, 0x1DF4,
0x1E00, 0x1F15,
0x1F18, 0x1F1D,
0x1F20, 0x1F45,
@@ -352,11 +353,8 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0xA67F, 0xA6EF,
0xA717, 0xA71F,
0xA722, 0xA788,
- 0xA78B, 0xA7CA,
- 0xA7D0, 0xA7D1,
- 0xA7D3, 0xA7D3,
- 0xA7D5, 0xA7D9,
- 0xA7F2, 0xA805,
+ 0xA78B, 0xA7DC,
+ 0xA7F1, 0xA805,
0xA807, 0xA827,
0xA840, 0xA873,
0xA880, 0xA8C3,
@@ -446,6 +444,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x105A3, 0x105B1,
0x105B3, 0x105B9,
0x105BB, 0x105BC,
+ 0x105C0, 0x105F3,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
@@ -464,6 +463,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x108F4, 0x108F5,
0x10900, 0x10915,
0x10920, 0x10939,
+ 0x10940, 0x10959,
0x10980, 0x109B7,
0x109BE, 0x109BF,
0x10A00, 0x10A03,
@@ -483,9 +483,14 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x10C80, 0x10CB2,
0x10CC0, 0x10CF2,
0x10D00, 0x10D27,
+ 0x10D4A, 0x10D65,
+ 0x10D69, 0x10D69,
+ 0x10D6F, 0x10D85,
0x10E80, 0x10EA9,
0x10EAB, 0x10EAC,
0x10EB0, 0x10EB1,
+ 0x10EC2, 0x10EC7,
+ 0x10EFA, 0x10EFC,
0x10F00, 0x10F1C,
0x10F27, 0x10F27,
0x10F30, 0x10F45,
@@ -529,6 +534,17 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x11350, 0x11350,
0x11357, 0x11357,
0x1135D, 0x11363,
+ 0x11380, 0x11389,
+ 0x1138B, 0x1138B,
+ 0x1138E, 0x1138E,
+ 0x11390, 0x113B5,
+ 0x113B7, 0x113C0,
+ 0x113C2, 0x113C2,
+ 0x113C5, 0x113C5,
+ 0x113C7, 0x113CA,
+ 0x113CC, 0x113CD,
+ 0x113D1, 0x113D1,
+ 0x113D3, 0x113D3,
0x11400, 0x11441,
0x11443, 0x11445,
0x11447, 0x1144A,
@@ -567,6 +583,8 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x11A50, 0x11A97,
0x11A9D, 0x11A9D,
0x11AB0, 0x11AF8,
+ 0x11B60, 0x11B67,
+ 0x11BC0, 0x11BE0,
0x11C00, 0x11C08,
0x11C0A, 0x11C36,
0x11C38, 0x11C3E,
@@ -588,6 +606,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x11D90, 0x11D91,
0x11D93, 0x11D96,
0x11D98, 0x11D98,
+ 0x11DB0, 0x11DDB,
0x11EE0, 0x11EF6,
0x11F00, 0x11F10,
0x11F12, 0x11F3A,
@@ -599,7 +618,9 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x12F90, 0x12FF0,
0x13000, 0x1342F,
0x13441, 0x13446,
+ 0x13460, 0x143FA,
0x14400, 0x14646,
+ 0x16100, 0x1612E,
0x16800, 0x16A38,
0x16A40, 0x16A5E,
0x16A70, 0x16ABE,
@@ -608,16 +629,19 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x16B40, 0x16B43,
0x16B63, 0x16B77,
0x16B7D, 0x16B8F,
+ 0x16D40, 0x16D6C,
0x16E40, 0x16E7F,
+ 0x16EA0, 0x16EB8,
+ 0x16EBB, 0x16ED3,
0x16F00, 0x16F4A,
0x16F4F, 0x16F87,
0x16F8F, 0x16F9F,
0x16FE0, 0x16FE1,
0x16FE3, 0x16FE3,
- 0x16FF0, 0x16FF1,
- 0x17000, 0x187F7,
- 0x18800, 0x18CD5,
- 0x18D00, 0x18D08,
+ 0x16FF0, 0x16FF6,
+ 0x17000, 0x18CD5,
+ 0x18CFF, 0x18D1E,
+ 0x18D80, 0x18DF2,
0x1AFF0, 0x1AFF3,
0x1AFF5, 0x1AFFB,
0x1AFFD, 0x1AFFE,
@@ -677,6 +701,11 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1E290, 0x1E2AD,
0x1E2C0, 0x1E2EB,
0x1E4D0, 0x1E4EB,
+ 0x1E5D0, 0x1E5ED,
+ 0x1E5F0, 0x1E5F0,
+ 0x1E6C0, 0x1E6DE,
+ 0x1E6E0, 0x1E6F5,
+ 0x1E6FE, 0x1E6FF,
0x1E7E0, 0x1E7E6,
0x1E7E8, 0x1E7EB,
0x1E7ED, 0x1E7EE,
@@ -722,16 +751,16 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1F150, 0x1F169,
0x1F170, 0x1F189,
0x20000, 0x2A6DF,
- 0x2A700, 0x2B739,
- 0x2B740, 0x2B81D,
- 0x2B820, 0x2CEA1,
+ 0x2A700, 0x2B81D,
+ 0x2B820, 0x2CEAD,
0x2CEB0, 0x2EBE0,
+ 0x2EBF0, 0x2EE5D,
0x2F800, 0x2FA1D,
0x30000, 0x3134A,
- 0x31350, 0x323AF,
+ 0x31350, 0x33479,
};
-#define UNICODE_ALNUM_CODEPOINTS_LENGTH 1528
+#define UNICODE_ALNUM_CODEPOINTS_LENGTH 1598
static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEPOINTS_LENGTH] = {
0x100, 0x2C1,
0x2C6, 0x2D1,
@@ -739,7 +768,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x2EC, 0x2EC,
0x2EE, 0x2EE,
0x345, 0x345,
- 0x370, 0x374,
+ 0x363, 0x374,
0x376, 0x377,
0x37A, 0x37D,
0x37F, 0x37F,
@@ -778,7 +807,8 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x840, 0x858,
0x860, 0x86A,
0x870, 0x887,
- 0x889, 0x88E,
+ 0x889, 0x88F,
+ 0x897, 0x897,
0x8A0, 0x8C9,
0x8D4, 0x8DF,
0x8E3, 0x8E9,
@@ -872,7 +902,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0xC4A, 0xC4C,
0xC55, 0xC56,
0xC58, 0xC5A,
- 0xC5D, 0xC5D,
+ 0xC5C, 0xC5D,
0xC60, 0xC63,
0xC66, 0xC6F,
0xC80, 0xC83,
@@ -885,7 +915,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0xCC6, 0xCC8,
0xCCA, 0xCCC,
0xCD5, 0xCD6,
- 0xCDD, 0xCDE,
+ 0xCDC, 0xCDE,
0xCE0, 0xCE3,
0xCE6, 0xCEF,
0xCF1, 0xCF3,
@@ -1007,7 +1037,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1C00, 0x1C36,
0x1C40, 0x1C49,
0x1C4D, 0x1C7D,
- 0x1C80, 0x1C88,
+ 0x1C80, 0x1C8A,
0x1C90, 0x1CBA,
0x1CBD, 0x1CBF,
0x1CE9, 0x1CEC,
@@ -1015,7 +1045,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1CF5, 0x1CF6,
0x1CFA, 0x1CFA,
0x1D00, 0x1DBF,
- 0x1DE7, 0x1DF4,
+ 0x1DD3, 0x1DF4,
0x1E00, 0x1F15,
0x1F18, 0x1F1D,
0x1F20, 0x1F45,
@@ -1094,11 +1124,8 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0xA67F, 0xA6EF,
0xA717, 0xA71F,
0xA722, 0xA788,
- 0xA78B, 0xA7CA,
- 0xA7D0, 0xA7D1,
- 0xA7D3, 0xA7D3,
- 0xA7D5, 0xA7D9,
- 0xA7F2, 0xA805,
+ 0xA78B, 0xA7DC,
+ 0xA7F1, 0xA805,
0xA807, 0xA827,
0xA840, 0xA873,
0xA880, 0xA8C3,
@@ -1191,6 +1218,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x105A3, 0x105B1,
0x105B3, 0x105B9,
0x105BB, 0x105BC,
+ 0x105C0, 0x105F3,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
@@ -1209,6 +1237,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x108F4, 0x108F5,
0x10900, 0x10915,
0x10920, 0x10939,
+ 0x10940, 0x10959,
0x10980, 0x109B7,
0x109BE, 0x109BF,
0x10A00, 0x10A03,
@@ -1229,9 +1258,14 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x10CC0, 0x10CF2,
0x10D00, 0x10D27,
0x10D30, 0x10D39,
+ 0x10D40, 0x10D65,
+ 0x10D69, 0x10D69,
+ 0x10D6F, 0x10D85,
0x10E80, 0x10EA9,
0x10EAB, 0x10EAC,
0x10EB0, 0x10EB1,
+ 0x10EC2, 0x10EC7,
+ 0x10EFA, 0x10EFC,
0x10F00, 0x10F1C,
0x10F27, 0x10F27,
0x10F30, 0x10F45,
@@ -1278,6 +1312,17 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11350, 0x11350,
0x11357, 0x11357,
0x1135D, 0x11363,
+ 0x11380, 0x11389,
+ 0x1138B, 0x1138B,
+ 0x1138E, 0x1138E,
+ 0x11390, 0x113B5,
+ 0x113B7, 0x113C0,
+ 0x113C2, 0x113C2,
+ 0x113C5, 0x113C5,
+ 0x113C7, 0x113CA,
+ 0x113CC, 0x113CD,
+ 0x113D1, 0x113D1,
+ 0x113D3, 0x113D3,
0x11400, 0x11441,
0x11443, 0x11445,
0x11447, 0x1144A,
@@ -1297,6 +1342,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11680, 0x116B5,
0x116B8, 0x116B8,
0x116C0, 0x116C9,
+ 0x116D0, 0x116E3,
0x11700, 0x1171A,
0x1171D, 0x1172A,
0x11730, 0x11739,
@@ -1322,6 +1368,9 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11A50, 0x11A97,
0x11A9D, 0x11A9D,
0x11AB0, 0x11AF8,
+ 0x11B60, 0x11B67,
+ 0x11BC0, 0x11BE0,
+ 0x11BF0, 0x11BF9,
0x11C00, 0x11C08,
0x11C0A, 0x11C36,
0x11C38, 0x11C3E,
@@ -1346,6 +1395,8 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11D93, 0x11D96,
0x11D98, 0x11D98,
0x11DA0, 0x11DA9,
+ 0x11DB0, 0x11DDB,
+ 0x11DE0, 0x11DE9,
0x11EE0, 0x11EF6,
0x11F00, 0x11F10,
0x11F12, 0x11F3A,
@@ -1358,7 +1409,10 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x12F90, 0x12FF0,
0x13000, 0x1342F,
0x13441, 0x13446,
+ 0x13460, 0x143FA,
0x14400, 0x14646,
+ 0x16100, 0x1612E,
+ 0x16130, 0x16139,
0x16800, 0x16A38,
0x16A40, 0x16A5E,
0x16A60, 0x16A69,
@@ -1370,16 +1424,20 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x16B50, 0x16B59,
0x16B63, 0x16B77,
0x16B7D, 0x16B8F,
+ 0x16D40, 0x16D6C,
+ 0x16D70, 0x16D79,
0x16E40, 0x16E7F,
+ 0x16EA0, 0x16EB8,
+ 0x16EBB, 0x16ED3,
0x16F00, 0x16F4A,
0x16F4F, 0x16F87,
0x16F8F, 0x16F9F,
0x16FE0, 0x16FE1,
0x16FE3, 0x16FE3,
- 0x16FF0, 0x16FF1,
- 0x17000, 0x187F7,
- 0x18800, 0x18CD5,
- 0x18D00, 0x18D08,
+ 0x16FF0, 0x16FF6,
+ 0x17000, 0x18CD5,
+ 0x18CFF, 0x18D1E,
+ 0x18D80, 0x18DF2,
0x1AFF0, 0x1AFF3,
0x1AFF5, 0x1AFFB,
0x1AFFD, 0x1AFFE,
@@ -1394,6 +1452,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1BC80, 0x1BC88,
0x1BC90, 0x1BC99,
0x1BC9E, 0x1BC9E,
+ 0x1CCF0, 0x1CCF9,
0x1D400, 0x1D454,
0x1D456, 0x1D49C,
0x1D49E, 0x1D49F,
@@ -1443,6 +1502,11 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1E2F0, 0x1E2F9,
0x1E4D0, 0x1E4EB,
0x1E4F0, 0x1E4F9,
+ 0x1E5D0, 0x1E5ED,
+ 0x1E5F0, 0x1E5FA,
+ 0x1E6C0, 0x1E6DE,
+ 0x1E6E0, 0x1E6F5,
+ 0x1E6FE, 0x1E6FF,
0x1E7E0, 0x1E7E6,
0x1E7E8, 0x1E7EB,
0x1E7ED, 0x1E7EE,
@@ -1490,16 +1554,16 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1F170, 0x1F189,
0x1FBF0, 0x1FBF9,
0x20000, 0x2A6DF,
- 0x2A700, 0x2B739,
- 0x2B740, 0x2B81D,
- 0x2B820, 0x2CEA1,
+ 0x2A700, 0x2B81D,
+ 0x2B820, 0x2CEAD,
0x2CEB0, 0x2EBE0,
+ 0x2EBF0, 0x2EE5D,
0x2F800, 0x2FA1D,
0x30000, 0x3134A,
- 0x31350, 0x323AF,
+ 0x31350, 0x33479,
};
-#define UNICODE_ISUPPER_CODEPOINTS_LENGTH 1302
+#define UNICODE_ISUPPER_CODEPOINTS_LENGTH 1320
static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_CODEPOINTS_LENGTH] = {
0x100, 0x100,
0x102, 0x102,
@@ -1774,6 +1838,7 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C
0x10C7, 0x10C7,
0x10CD, 0x10CD,
0x13A0, 0x13F5,
+ 0x1C89, 0x1C89,
0x1C90, 0x1CBA,
0x1CBD, 0x1CBF,
0x1E00, 0x1E00,
@@ -2103,9 +2168,15 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C
0xA7C2, 0xA7C2,
0xA7C4, 0xA7C7,
0xA7C9, 0xA7C9,
+ 0xA7CB, 0xA7CC,
+ 0xA7CE, 0xA7CE,
0xA7D0, 0xA7D0,
+ 0xA7D2, 0xA7D2,
+ 0xA7D4, 0xA7D4,
0xA7D6, 0xA7D6,
0xA7D8, 0xA7D8,
+ 0xA7DA, 0xA7DA,
+ 0xA7DC, 0xA7DC,
0xA7F5, 0xA7F5,
0xFF21, 0xFF3A,
0x10400, 0x10427,
@@ -2115,8 +2186,10 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C
0x1058C, 0x10592,
0x10594, 0x10595,
0x10C80, 0x10CB2,
+ 0x10D50, 0x10D65,
0x118A0, 0x118BF,
0x16E40, 0x16E5F,
+ 0x16EA0, 0x16EB8,
0x1D400, 0x1D419,
0x1D434, 0x1D44D,
0x1D468, 0x1D481,
@@ -2304,6 +2377,10 @@ pm_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n) {
*/
size_t
pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT) ? 1 : 0;
}
@@ -2324,6 +2401,10 @@ pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
*/
size_t
pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & (PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0;
}
@@ -2344,6 +2425,10 @@ pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
*/
bool
pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_UPPERCASE_BIT) ? true : false;
}
@@ -2362,7 +2447,8 @@ pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n) {
static pm_unicode_codepoint_t
pm_cesu_8_codepoint(const uint8_t *b, ptrdiff_t n, size_t *width) {
- if (b[0] < 0x80) {
+
+ if ((n > 0) && (b[0] < 0x80)) {
*width = 1;
return (pm_unicode_codepoint_t) b[0];
}
@@ -2401,6 +2487,10 @@ pm_cesu_8_codepoint(const uint8_t *b, ptrdiff_t n, size_t *width) {
static size_t
pm_encoding_cesu_8_char_width(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
size_t width;
pm_cesu_8_codepoint(b, n, &width);
return width;
@@ -2408,6 +2498,10 @@ pm_encoding_cesu_8_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_cesu_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT) ? 1 : 0;
}
@@ -2424,6 +2518,10 @@ pm_encoding_cesu_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_cesu_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & (PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0;
}
@@ -2440,6 +2538,10 @@ pm_encoding_cesu_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
static bool
pm_encoding_cesu_8_isupper_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_UPPERCASE_BIT) ? true : false;
}
@@ -3855,14 +3957,14 @@ static const uint8_t pm_encoding_windows_874_table[256] = {
};
#define PRISM_ENCODING_TABLE(name) \
- static size_t pm_encoding_ ##name ## _alpha_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) { \
- return (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHABETIC_BIT); \
+ static size_t pm_encoding_ ##name ## _alpha_char(const uint8_t *b, ptrdiff_t n) { \
+ return ((n > 0) && (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHABETIC_BIT)); \
} \
- static size_t pm_encoding_ ##name ## _alnum_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) { \
- return (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; \
+ static size_t pm_encoding_ ##name ## _alnum_char(const uint8_t *b, ptrdiff_t n) { \
+ return ((n > 0) && (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0; \
} \
- static bool pm_encoding_ ##name ## _isupper_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) { \
- return (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_UPPERCASE_BIT); \
+ static bool pm_encoding_ ##name ## _isupper_char(const uint8_t *b, ptrdiff_t n) { \
+ return ((n > 0) && (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_UPPERCASE_BIT)); \
}
PRISM_ENCODING_TABLE(cp850)
@@ -3931,8 +4033,8 @@ PRISM_ENCODING_TABLE(windows_874)
* means that if the top bit is not set, the character is 1 byte long.
*/
static size_t
-pm_encoding_ascii_char_width(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return *b < 0x80 ? 1 : 0;
+pm_encoding_ascii_char_width(const uint8_t *b, ptrdiff_t n) {
+ return ((n > 0) && (*b < 0x80)) ? 1 : 0;
}
/**
@@ -3940,8 +4042,8 @@ pm_encoding_ascii_char_width(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t
* alphabetical character.
*/
static size_t
-pm_encoding_ascii_alpha_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT);
+pm_encoding_ascii_alpha_char(const uint8_t *b, ptrdiff_t n) {
+ return (n > 0) ? (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT) : 0;
}
/**
@@ -3951,7 +4053,7 @@ pm_encoding_ascii_alpha_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t
*/
static size_t
pm_encoding_ascii_alpha_char_7bit(const uint8_t *b, ptrdiff_t n) {
- return (*b < 0x80) ? pm_encoding_ascii_alpha_char(b, n) : 0;
+ return ((n > 0) && (*b < 0x80)) ? pm_encoding_ascii_alpha_char(b, n) : 0;
}
/**
@@ -3959,8 +4061,8 @@ pm_encoding_ascii_alpha_char_7bit(const uint8_t *b, ptrdiff_t n) {
* alphanumeric character.
*/
static size_t
-pm_encoding_ascii_alnum_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0;
+pm_encoding_ascii_alnum_char(const uint8_t *b, ptrdiff_t n) {
+ return ((n > 0) && (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0;
}
/**
@@ -3970,7 +4072,7 @@ pm_encoding_ascii_alnum_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t
*/
static size_t
pm_encoding_ascii_alnum_char_7bit(const uint8_t *b, ptrdiff_t n) {
- return (*b < 0x80) ? pm_encoding_ascii_alnum_char(b, n) : 0;
+ return ((n > 0) && (*b < 0x80)) ? pm_encoding_ascii_alnum_char(b, n) : 0;
}
/**
@@ -3978,8 +4080,8 @@ pm_encoding_ascii_alnum_char_7bit(const uint8_t *b, ptrdiff_t n) {
* character.
*/
static bool
-pm_encoding_ascii_isupper_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return (pm_encoding_ascii_table[*b] & PRISM_ENCODING_UPPERCASE_BIT);
+pm_encoding_ascii_isupper_char(const uint8_t *b, ptrdiff_t n) {
+ return (n > 0) && (pm_encoding_ascii_table[*b] & PRISM_ENCODING_UPPERCASE_BIT);
}
/**
@@ -3998,7 +4100,7 @@ pm_encoding_single_char_width(PRISM_ATTRIBUTE_UNUSED const uint8_t *b, PRISM_ATT
static size_t
pm_encoding_euc_jp_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4042,6 +4144,9 @@ pm_encoding_euc_jp_isupper_char(const uint8_t *b, ptrdiff_t n) {
*/
static size_t
pm_encoding_shift_jis_char_width(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
// These are the single byte characters.
if (b[0] < 0x80 || (b[0] >= 0xA1 && b[0] <= 0xDF)) {
return 1;
@@ -4105,7 +4210,7 @@ pm_encoding_shift_jis_isupper_char(const uint8_t *b, ptrdiff_t n) {
*/
static bool
pm_encoding_ascii_isupper_char_7bit(const uint8_t *b, ptrdiff_t n) {
- return (*b < 0x80) && pm_encoding_ascii_isupper_char(b, n);
+ return (n > 0) && (*b < 0x80) && pm_encoding_ascii_isupper_char(b, n);
}
/**
@@ -4115,7 +4220,7 @@ pm_encoding_ascii_isupper_char_7bit(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_big5_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4134,7 +4239,7 @@ pm_encoding_big5_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_cp949_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters
- if (*b <= 0x80) {
+ if ((n > 0) && (*b <= 0x80)) {
return 1;
}
@@ -4153,7 +4258,7 @@ pm_encoding_cp949_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_emacs_mule_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the 1 byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4196,7 +4301,7 @@ pm_encoding_emacs_mule_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_euc_kr_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4215,7 +4320,7 @@ pm_encoding_euc_kr_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_euc_tw_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4239,7 +4344,7 @@ pm_encoding_euc_tw_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_gb18030_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the 1 byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4263,7 +4368,7 @@ pm_encoding_gb18030_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_gbk_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b <= 0x80) {
+ if ((n > 0) && (*b <= 0x80)) {
return 1;
}
diff --git a/prism/extension.c b/prism/extension.c
index 1533ca7bb3..71c2d91b98 100644
--- a/prism/extension.c
+++ b/prism/extension.c
@@ -25,6 +25,7 @@ VALUE rb_cPrismLexResult;
VALUE rb_cPrismParseLexResult;
VALUE rb_cPrismStringQuery;
VALUE rb_cPrismScope;
+VALUE rb_cPrismCurrentVersionError;
VALUE rb_cPrismDebugEncoding;
@@ -199,7 +200,12 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
if (!NIL_P(value)) {
const char *version = check_string(value);
- if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
+ if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
+ const char *current_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
+ if (!pm_options_version_set(options, current_version, 3)) {
+ rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, current_version));
+ }
+ } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
}
}
@@ -888,7 +894,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
* version of Ruby syntax (which you can trigger with `nil` or
* `"latest"`). You may also restrict the syntax to a specific version of
* Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
- * the current Ruby is running use `version: RUBY_VERSION`. Raises
+ * the current Ruby is running use `version: "current"`. Raises
* ArgumentError if the version is not currently supported by Prism.
*/
static VALUE
@@ -994,6 +1000,14 @@ profile_file(int argc, VALUE *argv, VALUE self) {
return Qnil;
}
+static int
+parse_stream_eof(void *stream) {
+ if (rb_funcall((VALUE) stream, rb_intern("eof?"), 0)) {
+ return 1;
+ }
+ return 0;
+}
+
/**
* An implementation of fgets that is suitable for use with Ruby IO objects.
*/
@@ -1034,7 +1048,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
pm_parser_t parser;
pm_buffer_t buffer;
- pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options);
+ pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options);
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
VALUE source = pm_source_new(&parser, encoding, options.freeze);
@@ -1356,6 +1370,8 @@ Init_prism(void) {
rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
rb_cPrismScope = rb_define_class_under(rb_cPrism, "Scope", rb_cObject);
+ rb_cPrismCurrentVersionError = rb_const_get(rb_cPrism, rb_intern("CurrentVersionError"));
+
// Intern all of the IDs eagerly that we support so that we don't have to do
// it every time we parse.
rb_id_option_command_line = rb_intern_const("command_line");
diff --git a/prism/extension.h b/prism/extension.h
index 506da2fd6f..510faa48e8 100644
--- a/prism/extension.h
+++ b/prism/extension.h
@@ -1,7 +1,7 @@
#ifndef PRISM_EXT_NODE_H
#define PRISM_EXT_NODE_H
-#define EXPECTED_PRISM_VERSION "1.4.0"
+#define EXPECTED_PRISM_VERSION "1.8.0"
#include <ruby.h>
#include <ruby/encoding.h>
diff --git a/prism/options.c b/prism/options.c
index a457178ce8..09d2a65a6c 100644
--- a/prism/options.c
+++ b/prism/options.c
@@ -88,27 +88,37 @@ pm_options_version_set(pm_options_t *options, const char *version, size_t length
return true;
}
- if (strncmp(version, "3.5", 3) == 0) {
- options->version = PM_OPTIONS_VERSION_LATEST;
+ if (strncmp(version, "3.5", 3) == 0 || strncmp(version, "4.0", 3) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_0;
+ return true;
+ }
+
+ if (strncmp(version, "4.1", 3) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_1;
return true;
}
return false;
}
- if (length >= 4) {
- if (strncmp(version, "3.3.", 4) == 0 && is_number(version + 4, length - 4)) {
+ if (length >= 4 && is_number(version + 4, length - 4)) {
+ if (strncmp(version, "3.3.", 4) == 0) {
options->version = PM_OPTIONS_VERSION_CRUBY_3_3;
return true;
}
- if (strncmp(version, "3.4.", 4) == 0 && is_number(version + 4, length - 4)) {
+ if (strncmp(version, "3.4.", 4) == 0) {
options->version = PM_OPTIONS_VERSION_CRUBY_3_4;
return true;
}
- if (strncmp(version, "3.5.", 4) == 0 && is_number(version + 4, length - 4)) {
- options->version = PM_OPTIONS_VERSION_LATEST;
+ if (strncmp(version, "3.5.", 4) == 0 || strncmp(version, "4.0.", 4) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_0;
+ return true;
+ }
+
+ if (strncmp(version, "4.1.", 4) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_1;
return true;
}
}
diff --git a/prism/options.h b/prism/options.h
index 2f64701b0c..c00c7bf755 100644
--- a/prism/options.h
+++ b/prism/options.h
@@ -82,14 +82,26 @@ typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const
* parse in the same way as a specific version of CRuby would have.
*/
typedef enum {
- /** The current version of prism. */
- PM_OPTIONS_VERSION_LATEST = 0,
+ /** If an explicit version is not provided, the current version of prism will be used. */
+ PM_OPTIONS_VERSION_UNSET = 0,
/** The vendored version of prism in CRuby 3.3.x. */
PM_OPTIONS_VERSION_CRUBY_3_3 = 1,
/** The vendored version of prism in CRuby 3.4.x. */
- PM_OPTIONS_VERSION_CRUBY_3_4 = 2
+ PM_OPTIONS_VERSION_CRUBY_3_4 = 2,
+
+ /** The vendored version of prism in CRuby 4.0.x. */
+ PM_OPTIONS_VERSION_CRUBY_3_5 = 3,
+
+ /** The vendored version of prism in CRuby 4.0.x. */
+ PM_OPTIONS_VERSION_CRUBY_4_0 = 3,
+
+ /** The vendored version of prism in CRuby 4.1.x. */
+ PM_OPTIONS_VERSION_CRUBY_4_1 = 4,
+
+ /** The current version of prism. */
+ PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_4_1
} pm_options_version_t;
/**
@@ -231,6 +243,8 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20;
* @param shebang_callback The shebang callback to set.
* @param shebang_callback_data Any additional data that should be passed along
* to the callback.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data);
@@ -239,6 +253,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *optio
*
* @param options The options struct to set the filepath on.
* @param filepath The filepath to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath);
@@ -247,6 +263,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, cons
*
* @param options The options struct to set the line on.
* @param line The line to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t line);
@@ -255,6 +273,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t
*
* @param options The options struct to set the encoding on.
* @param encoding The encoding to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding);
@@ -263,6 +283,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, cons
*
* @param options The options struct to set the encoding_locked value on.
* @param encoding_locked The encoding_locked value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked);
@@ -271,6 +293,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *option
*
* @param options The options struct to set the frozen string literal value on.
* @param frozen_string_literal The frozen string literal value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal);
@@ -279,6 +303,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *
*
* @param options The options struct to set the command line option on.
* @param command_line The command_line value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line);
@@ -291,6 +317,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options,
* @param version The version to set.
* @param length The length of the version string.
* @return Whether or not the version was parsed successfully.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length);
@@ -299,6 +327,8 @@ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const
*
* @param options The options struct to set the main script value on.
* @param main_script The main script value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, bool main_script);
@@ -307,6 +337,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, b
*
* @param options The options struct to set the partial script value on.
* @param partial_script The partial script value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script);
@@ -315,6 +347,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options
*
* @param options The options struct to set the freeze value on.
* @param freeze The freeze value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool freeze);
@@ -324,6 +358,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool f
* @param options The options struct to initialize the scopes array on.
* @param scopes_count The number of scopes to allocate.
* @return Whether or not the scopes array was initialized successfully.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count);
@@ -333,6 +369,8 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_
* @param options The options struct to get the scope from.
* @param index The index of the scope to get.
* @return A pointer to the scope at the given index.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index);
@@ -343,6 +381,8 @@ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm
* @param scope The scope struct to initialize.
* @param locals_count The number of locals to allocate.
* @return Whether or not the scope was initialized successfully.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count);
@@ -352,6 +392,8 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, si
* @param scope The scope struct to get the local from.
* @param index The index of the local to get.
* @return A pointer to the local at the given index.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index);
@@ -360,6 +402,8 @@ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_
*
* @param scope The scope struct to set the forwarding on.
* @param forwarding The forwarding value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding);
@@ -367,6 +411,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t
* Free the internal memory associated with the options.
*
* @param options The options struct whose internal memory should be freed.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
diff --git a/prism/parser.h b/prism/parser.h
index 992729d655..95d7aac710 100644
--- a/prism/parser.h
+++ b/prism/parser.h
@@ -299,6 +299,9 @@ typedef enum {
/** a rescue else statement within a do..end block */
PM_CONTEXT_BLOCK_ELSE,
+ /** expressions in block parameters `foo do |...| end ` */
+ PM_CONTEXT_BLOCK_PARAMETERS,
+
/** a rescue statement within a do..end block */
PM_CONTEXT_BLOCK_RESCUE,
diff --git a/prism/prism.c b/prism/prism.c
index cc634b59e3..b158e505b2 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -19,6 +19,24 @@ pm_version(void) {
#define MAX(a,b) (((a)>(b))?(a):(b))
/******************************************************************************/
+/* Helpful AST-related macros */
+/******************************************************************************/
+
+#define FL PM_NODE_FLAGS
+#define UP PM_NODE_UPCAST
+
+#define PM_TOKEN_START(token_) ((token_)->start)
+#define PM_TOKEN_END(token_) ((token_)->end)
+
+#define PM_NODE_START(node_) (UP(node_)->location.start)
+#define PM_NODE_END(node_) (UP(node_)->location.end)
+
+#define PM_LOCATION_NULL_VALUE(parser_) ((pm_location_t) { .start = (parser_)->start, .end = (parser_)->start })
+#define PM_LOCATION_TOKEN_VALUE(token_) ((pm_location_t) { .start = PM_TOKEN_START(token_), .end = PM_TOKEN_END(token_) })
+#define PM_LOCATION_NODE_VALUE(node_) ((pm_location_t) { .start = PM_NODE_START(node_), .end = PM_NODE_END(node_) })
+#define PM_OPTIONAL_LOCATION_TOKEN_VALUE(token) ((token)->type == PM_TOKEN_NOT_PROVIDED ? ((pm_location_t) { 0 }) : PM_LOCATION_TOKEN_VALUE(token))
+
+/******************************************************************************/
/* Lex mode manipulations */
/******************************************************************************/
@@ -1049,25 +1067,25 @@ pm_check_value_expression(pm_parser_t *parser, pm_node_t *node) {
if (cast->ensure_clause != NULL) {
if (cast->rescue_clause != NULL) {
- pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->rescue_clause);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->rescue_clause));
if (vn != NULL) return vn;
}
if (cast->statements != NULL) {
- pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
if (vn != NULL) return vn;
}
- node = (pm_node_t *) cast->ensure_clause;
+ node = UP(cast->ensure_clause);
} else if (cast->rescue_clause != NULL) {
if (cast->statements == NULL) return NULL;
- pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
if (vn == NULL) return NULL;
if (void_node == NULL) void_node = vn;
for (pm_rescue_node_t *rescue_clause = cast->rescue_clause; rescue_clause != NULL; rescue_clause = rescue_clause->subsequent) {
- pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) rescue_clause->statements);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(rescue_clause->statements));
if (vn == NULL) {
void_node = NULL;
break;
@@ -1078,24 +1096,24 @@ pm_check_value_expression(pm_parser_t *parser, pm_node_t *node) {
}
if (cast->else_clause != NULL) {
- node = (pm_node_t *) cast->else_clause;
+ node = UP(cast->else_clause);
} else {
return void_node;
}
} else {
- node = (pm_node_t *) cast->statements;
+ node = UP(cast->statements);
}
break;
}
case PM_ENSURE_NODE: {
pm_ensure_node_t *cast = (pm_ensure_node_t *) node;
- node = (pm_node_t *) cast->statements;
+ node = UP(cast->statements);
break;
}
case PM_PARENTHESES_NODE: {
pm_parentheses_node_t *cast = (pm_parentheses_node_t *) node;
- node = (pm_node_t *) cast->body;
+ node = UP(cast->body);
break;
}
case PM_STATEMENTS_NODE: {
@@ -1108,7 +1126,7 @@ pm_check_value_expression(pm_parser_t *parser, pm_node_t *node) {
if (cast->statements == NULL || cast->subsequent == NULL) {
return NULL;
}
- pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
if (vn == NULL) {
return NULL;
}
@@ -1123,19 +1141,19 @@ pm_check_value_expression(pm_parser_t *parser, pm_node_t *node) {
if (cast->statements == NULL || cast->else_clause == NULL) {
return NULL;
}
- pm_node_t *vn = pm_check_value_expression(parser, (pm_node_t *) cast->statements);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
if (vn == NULL) {
return NULL;
}
if (void_node == NULL) {
void_node = vn;
}
- node = (pm_node_t *) cast->else_clause;
+ node = UP(cast->else_clause);
break;
}
case PM_ELSE_NODE: {
pm_else_node_t *cast = (pm_else_node_t *) node;
- node = (pm_node_t *) cast->statements;
+ node = UP(cast->statements);
break;
}
case PM_AND_NODE: {
@@ -1409,7 +1427,7 @@ pm_conditional_predicate_warn_write_literal_p(const pm_node_t *node) {
static inline void
pm_conditional_predicate_warn_write_literal(pm_parser_t *parser, const pm_node_t *node) {
if (pm_conditional_predicate_warn_write_literal_p(node)) {
- pm_parser_warn_node(parser, node, parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_WARN_EQUAL_IN_CONDITIONAL_3_3 : PM_WARN_EQUAL_IN_CONDITIONAL);
+ pm_parser_warn_node(parser, node, parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_WARN_EQUAL_IN_CONDITIONAL_3_3 : PM_WARN_EQUAL_IN_CONDITIONAL);
}
}
@@ -1559,13 +1577,6 @@ not_provided(pm_parser_t *parser) {
return (pm_token_t) { .type = PM_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start };
}
-#define PM_LOCATION_NULL_VALUE(parser) ((pm_location_t) { .start = (parser)->start, .end = (parser)->start })
-#define PM_LOCATION_TOKEN_VALUE(token) ((pm_location_t) { .start = (token)->start, .end = (token)->end })
-#define PM_LOCATION_NODE_VALUE(node) ((pm_location_t) { .start = (node)->location.start, .end = (node)->location.end })
-#define PM_LOCATION_NODE_BASE_VALUE(node) ((pm_location_t) { .start = (node)->base.location.start, .end = (node)->base.location.end })
-#define PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE ((pm_location_t) { .start = NULL, .end = NULL })
-#define PM_OPTIONAL_LOCATION_TOKEN_VALUE(token) ((token)->type == PM_TOKEN_NOT_PROVIDED ? PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE : PM_LOCATION_TOKEN_VALUE(token))
-
/**
* This is a special out parameter to the parse_arguments_list function that
* includes opening and closing parentheses in addition to the arguments since
@@ -1635,7 +1646,7 @@ pm_arguments_validate_block(pm_parser_t *parser, pm_arguments_t *arguments, pm_b
// If we didn't hit a case before this check, then at this point we need to
// add a syntax error.
- pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_UNEXPECTED_BLOCK);
+ pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_UNEXPECTED_BLOCK);
}
/******************************************************************************/
@@ -1928,8 +1939,23 @@ pm_node_alloc(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) {
return memory;
}
-#define PM_NODE_ALLOC(parser, type) (type *) pm_node_alloc(parser, sizeof(type))
-#define PM_NODE_IDENTIFY(parser) (++parser->node_id)
+#define PM_NODE_ALLOC(parser_, type_) (type_ *) pm_node_alloc(parser_, sizeof(type_))
+#define PM_NODE_INIT(parser_, type_, flags_, start_, end_) (pm_node_t) { \
+ .type = (type_), \
+ .flags = (flags_), \
+ .node_id = ++(parser_)->node_id, \
+ .location = { .start = (start_), .end = (end_) } \
+}
+
+#define PM_NODE_INIT_UNSET(parser_, type_, flags_) PM_NODE_INIT(parser_, type_, flags_, NULL, NULL)
+#define PM_NODE_INIT_BASE(parser_, type_, flags_) PM_NODE_INIT(parser_, type_, flags_, (parser_)->start, (parser_)->start)
+#define PM_NODE_INIT_TOKEN(parser_, type_, flags_, token_) PM_NODE_INIT(parser_, type_, flags_, PM_TOKEN_START(token_), PM_TOKEN_END(token_))
+#define PM_NODE_INIT_NODE(parser_, type_, flags_, node_) PM_NODE_INIT(parser_, type_, flags_, PM_NODE_START(node_), PM_NODE_END(node_))
+
+#define PM_NODE_INIT_TOKENS(parser_, type_, flags_, left_, right_) PM_NODE_INIT(parser_, type_, flags_, PM_TOKEN_START(left_), PM_TOKEN_END(right_))
+#define PM_NODE_INIT_NODES(parser_, type_, flags_, left_, right_) PM_NODE_INIT(parser_, type_, flags_, PM_NODE_START(left_), PM_NODE_END(right_))
+#define PM_NODE_INIT_TOKEN_NODE(parser_, type_, flags_, token_, node_) PM_NODE_INIT(parser_, type_, flags_, PM_TOKEN_START(token_), PM_NODE_END(node_))
+#define PM_NODE_INIT_NODE_TOKEN(parser_, type_, flags_, node_, token_) PM_NODE_INIT(parser_, type_, flags_, PM_NODE_START(node_), PM_TOKEN_END(token_))
/**
* Allocate a new MissingNode node.
@@ -1938,11 +1964,9 @@ static pm_missing_node_t *
pm_missing_node_create(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
pm_missing_node_t *node = PM_NODE_ALLOC(parser, pm_missing_node_t);
- *node = (pm_missing_node_t) {{
- .type = PM_MISSING_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = { .start = start, .end = end }
- }};
+ *node = (pm_missing_node_t) {
+ .base = PM_NODE_INIT(parser, PM_MISSING_NODE, 0, start, end)
+ };
return node;
}
@@ -1956,14 +1980,7 @@ pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyw
pm_alias_global_variable_node_t *node = PM_NODE_ALLOC(parser, pm_alias_global_variable_node_t);
*node = (pm_alias_global_variable_node_t) {
- {
- .type = PM_ALIAS_GLOBAL_VARIABLE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = old_name->location.end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_ALIAS_GLOBAL_VARIABLE_NODE, 0, keyword, old_name),
.new_name = new_name,
.old_name = old_name,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
@@ -1981,14 +1998,7 @@ pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_n
pm_alias_method_node_t *node = PM_NODE_ALLOC(parser, pm_alias_method_node_t);
*node = (pm_alias_method_node_t) {
- {
- .type = PM_ALIAS_METHOD_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = old_name->location.end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_ALIAS_METHOD_NODE, 0, keyword, old_name),
.new_name = new_name,
.old_name = old_name,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
@@ -2005,14 +2015,7 @@ pm_alternation_pattern_node_create(pm_parser_t *parser, pm_node_t *left, pm_node
pm_alternation_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_alternation_pattern_node_t);
*node = (pm_alternation_pattern_node_t) {
- {
- .type = PM_ALTERNATION_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = left->location.start,
- .end = right->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_ALTERNATION_PATTERN_NODE, 0, left, right),
.left = left,
.right = right,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -2031,14 +2034,7 @@ pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *opera
pm_and_node_t *node = PM_NODE_ALLOC(parser, pm_and_node_t);
*node = (pm_and_node_t) {
- {
- .type = PM_AND_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = left->location.start,
- .end = right->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_AND_NODE, 0, left, right),
.left = left,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.right = right
@@ -2055,11 +2051,7 @@ pm_arguments_node_create(pm_parser_t *parser) {
pm_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_arguments_node_t);
*node = (pm_arguments_node_t) {
- {
- .type = PM_ARGUMENTS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_ARGUMENTS_NODE, 0),
.arguments = { 0 }
};
@@ -2083,14 +2075,17 @@ pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argumen
node->base.location.start = argument->location.start;
}
- node->base.location.end = argument->location.end;
+ if (node->base.location.end < argument->location.end) {
+ node->base.location.end = argument->location.end;
+ }
+
pm_node_list_append(&node->arguments, argument);
if (PM_NODE_TYPE_P(argument, PM_SPLAT_NODE)) {
if (PM_NODE_FLAG_P(node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) {
- pm_node_flag_set((pm_node_t *) node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS);
+ pm_node_flag_set(UP(node), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS);
} else {
- pm_node_flag_set((pm_node_t *) node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT);
+ pm_node_flag_set(UP(node), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT);
}
}
}
@@ -2103,12 +2098,7 @@ pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) {
pm_array_node_t *node = PM_NODE_ALLOC(parser, pm_array_node_t);
*node = (pm_array_node_t) {
- {
- .type = PM_ARRAY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(opening)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.elements = { 0 }
@@ -2132,11 +2122,11 @@ pm_array_node_elements_append(pm_array_node_t *node, pm_node_t *element) {
// If the element is not a static literal, then the array is not a static
// literal. Turn that flag off.
if (PM_NODE_TYPE_P(element, PM_ARRAY_NODE) || PM_NODE_TYPE_P(element, PM_HASH_NODE) || PM_NODE_TYPE_P(element, PM_RANGE_NODE) || !PM_NODE_FLAG_P(element, PM_NODE_FLAG_STATIC_LITERAL)) {
- pm_node_flag_unset((pm_node_t *)node, PM_NODE_FLAG_STATIC_LITERAL);
+ pm_node_flag_unset(UP(node), PM_NODE_FLAG_STATIC_LITERAL);
}
if (PM_NODE_TYPE_P(element, PM_SPLAT_NODE)) {
- pm_node_flag_set((pm_node_t *)node, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT);
+ pm_node_flag_set(UP(node), PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT);
}
}
@@ -2159,20 +2149,13 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node
pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = nodes->nodes[0]->location.start,
- .end = nodes->nodes[nodes->size - 1]->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_ARRAY_PATTERN_NODE, 0, nodes->nodes[0], nodes->nodes[nodes->size - 1]),
.constant = NULL,
.rest = NULL,
.requireds = { 0 },
.posts = { 0 },
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
// For now we're going to just copy over each pointer manually. This could be
@@ -2202,17 +2185,13 @@ pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) {
pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = rest->location,
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_ARRAY_PATTERN_NODE, 0, rest),
.constant = NULL,
.rest = rest,
.requireds = { 0 },
.posts = { 0 },
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
return node;
@@ -2227,14 +2206,7 @@ pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant,
pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = constant->location.start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_NODE_TOKEN(parser, PM_ARRAY_PATTERN_NODE, 0, constant, closing),
.constant = constant,
.rest = NULL,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -2255,14 +2227,7 @@ pm_array_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *openin
pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_ARRAY_PATTERN_NODE, 0, opening, closing),
.constant = NULL,
.rest = NULL,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -2313,15 +2278,7 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper
}
*node = (pm_assoc_node_t) {
- {
- .type = PM_ASSOC_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = key->location.start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_ASSOC_NODE, flags, key->location.start, end),
.key = key,
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -2339,14 +2296,11 @@ pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token
pm_assoc_splat_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_splat_node_t);
*node = (pm_assoc_splat_node_t) {
- {
- .type = PM_ASSOC_SPLAT_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = value == NULL ? operator->end : value->location.end
- },
- },
+ .base = (
+ (value == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_ASSOC_SPLAT_NODE, 0, operator)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_ASSOC_SPLAT_NODE, 0, operator, value)
+ ),
.value = value,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
};
@@ -2363,11 +2317,7 @@ pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name)
pm_back_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_back_reference_read_node_t);
*node = (pm_back_reference_read_node_t) {
- {
- .type = PM_BACK_REFERENCE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_BACK_REFERENCE_READ_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -2382,17 +2332,14 @@ pm_begin_node_create(pm_parser_t *parser, const pm_token_t *begin_keyword, pm_st
pm_begin_node_t *node = PM_NODE_ALLOC(parser, pm_begin_node_t);
*node = (pm_begin_node_t) {
- {
- .type = PM_BEGIN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = begin_keyword->start,
- .end = statements == NULL ? begin_keyword->end : statements->base.location.end
- },
- },
+ .base = (
+ (statements == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BEGIN_NODE, 0, begin_keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_BEGIN_NODE, 0, begin_keyword, statements)
+ ),
.begin_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(begin_keyword),
.statements = statements,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .end_keyword_loc = { 0 }
};
return node;
@@ -2448,14 +2395,11 @@ pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, p
pm_block_argument_node_t *node = PM_NODE_ALLOC(parser, pm_block_argument_node_t);
*node = (pm_block_argument_node_t) {
- {
- .type = PM_BLOCK_ARGUMENT_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = expression == NULL ? operator->end : expression->location.end
- },
- },
+ .base = (
+ (expression == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BLOCK_ARGUMENT_NODE, 0, operator)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_BLOCK_ARGUMENT_NODE, 0, operator, expression)
+ ),
.expression = expression,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
};
@@ -2471,11 +2415,7 @@ pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p
pm_block_node_t *node = PM_NODE_ALLOC(parser, pm_block_node_t);
*node = (pm_block_node_t) {
- {
- .type = PM_BLOCK_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = { .start = opening->start, .end = closing->end },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_BLOCK_NODE, 0, opening, closing),
.locals = *locals,
.parameters = parameters,
.body = body,
@@ -2495,14 +2435,11 @@ pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, cons
pm_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameter_node_t);
*node = (pm_block_parameter_node_t) {
- {
- .type = PM_BLOCK_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end)
- },
- },
+ .base = (
+ (name->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BLOCK_PARAMETER_NODE, 0, operator)
+ : PM_NODE_INIT_TOKENS(parser, PM_BLOCK_PARAMETER_NODE, 0, operator, name)
+ ),
.name = pm_parser_optional_constant_id_token(parser, name),
.name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -2537,17 +2474,10 @@ pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *param
}
*node = (pm_block_parameters_node_t) {
- {
- .type = PM_BLOCK_PARAMETERS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = start,
- .end = end
- }
- },
+ .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETERS_NODE, 0, start, end),
.parameters = parameters,
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .closing_loc = { 0 },
.locals = { 0 }
};
@@ -2573,11 +2503,7 @@ pm_block_local_variable_node_create(pm_parser_t *parser, const pm_token_t *name)
pm_block_local_variable_node_t *node = PM_NODE_ALLOC(parser, pm_block_local_variable_node_t);
*node = (pm_block_local_variable_node_t) {
- {
- .type = PM_BLOCK_LOCAL_VARIABLE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_BLOCK_LOCAL_VARIABLE_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -2589,7 +2515,7 @@ pm_block_local_variable_node_create(pm_parser_t *parser, const pm_token_t *name)
*/
static void
pm_block_parameters_node_append_local(pm_block_parameters_node_t *node, const pm_block_local_variable_node_t *local) {
- pm_node_list_append(&node->locals, (pm_node_t *) local);
+ pm_node_list_append(&node->locals, UP(local));
if (node->base.location.start == NULL) node->base.location.start = local->base.location.start;
node->base.location.end = local->base.location.end;
@@ -2604,14 +2530,11 @@ pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
pm_break_node_t *node = PM_NODE_ALLOC(parser, pm_break_node_t);
*node = (pm_break_node_t) {
- {
- .type = PM_BREAK_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = (arguments == NULL ? keyword->end : arguments->base.location.end)
- },
- },
+ .base = (
+ (arguments == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BREAK_NODE, 0, keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_BREAK_NODE, 0, keyword, arguments)
+ ),
.arguments = arguments,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
};
@@ -2622,10 +2545,11 @@ pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
// There are certain flags that we want to use internally but don't want to
// expose because they are not relevant beyond parsing. Therefore we'll define
// them here and not define them in config.yml/a header file.
-static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY = 0x4;
-static const pm_node_flags_t PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY = 0x40;
-static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = 0x80;
-static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = 0x100;
+static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY = (1 << 2);
+
+static const pm_node_flags_t PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY = ((PM_CALL_NODE_FLAGS_LAST - 1) << 1);
+static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = ((PM_CALL_NODE_FLAGS_LAST - 1) << 2);
+static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = ((PM_CALL_NODE_FLAGS_LAST - 1) << 3);
/**
* Allocate and initialize a new CallNode node. This sets everything to NULL or
@@ -2637,18 +2561,14 @@ pm_call_node_create(pm_parser_t *parser, pm_node_flags_t flags) {
pm_call_node_t *node = PM_NODE_ALLOC(parser, pm_call_node_t);
*node = (pm_call_node_t) {
- {
- .type = PM_CALL_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NULL_VALUE(parser),
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_CALL_NODE, flags),
.receiver = NULL,
- .call_operator_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .message_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .call_operator_loc = { 0 },
+ .message_loc = { 0 },
+ .opening_loc = { 0 },
.arguments = NULL,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .closing_loc = { 0 },
+ .equal_loc = { 0 },
.block = NULL,
.name = 0
};
@@ -2720,6 +2640,8 @@ pm_call_node_binary_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t
return node;
}
+static const uint8_t * parse_operator_symbol_name(const pm_token_t *);
+
/**
* Allocate and initialize a new CallNode node from a call expression.
*/
@@ -2745,10 +2667,14 @@ pm_call_node_call_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *o
node->block = arguments->block;
if (operator->type == PM_TOKEN_AMPERSAND_DOT) {
- pm_node_flag_set((pm_node_t *)node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
+ pm_node_flag_set(UP(node), PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
}
- node->name = pm_parser_constant_id_token(parser, message);
+ /**
+ * If the final character is `@` as is the case for `foo.~@`,
+ * we should ignore the @ in the same way we do for symbols.
+ */
+ node->name = pm_parser_constant_id_location(parser, message->start, parse_operator_symbol_name(message));
return node;
}
@@ -2854,7 +2780,7 @@ pm_call_node_shorthand_create(pm_parser_t *parser, pm_node_t *receiver, pm_token
node->block = arguments->block;
if (operator->type == PM_TOKEN_AMPERSAND_DOT) {
- pm_node_flag_set((pm_node_t *)node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
+ pm_node_flag_set(UP(node), PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
}
node->name = pm_parser_constant_id_constant(parser, "call", 4);
@@ -2942,15 +2868,7 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
pm_call_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_and_write_node_t);
*node = (pm_call_and_write_node_t) {
- {
- .type = PM_CALL_AND_WRITE_NODE,
- .flags = target->base.flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CALL_AND_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.message_loc = target->message_loc,
@@ -2976,7 +2894,7 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
*/
static void
pm_index_arguments_check(pm_parser_t *parser, const pm_arguments_node_t *arguments, const pm_node_t *block) {
- if (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) {
+ if (parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) {
if (arguments != NULL && PM_NODE_FLAG_P(arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS)) {
pm_node_t *node;
PM_NODE_LIST_FOREACH(&arguments->arguments, index, node) {
@@ -3005,15 +2923,7 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons
assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
*node = (pm_index_and_write_node_t) {
- {
- .type = PM_INDEX_AND_WRITE_NODE,
- .flags = target->base.flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INDEX_AND_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.opening_loc = target->opening_loc,
@@ -3041,15 +2951,7 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target,
pm_call_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_operator_write_node_t);
*node = (pm_call_operator_write_node_t) {
- {
- .type = PM_CALL_OPERATOR_WRITE_NODE,
- .flags = target->base.flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CALL_OPERATOR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.message_loc = target->message_loc,
@@ -3081,15 +2983,7 @@ pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target,
assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
*node = (pm_index_operator_write_node_t) {
- {
- .type = PM_INDEX_OPERATOR_WRITE_NODE,
- .flags = target->base.flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INDEX_OPERATOR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.opening_loc = target->opening_loc,
@@ -3119,15 +3013,7 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
pm_call_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_or_write_node_t);
*node = (pm_call_or_write_node_t) {
- {
- .type = PM_CALL_OR_WRITE_NODE,
- .flags = target->base.flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CALL_OR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.message_loc = target->message_loc,
@@ -3159,15 +3045,7 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
*node = (pm_index_or_write_node_t) {
- {
- .type = PM_INDEX_OR_WRITE_NODE,
- .flags = target->base.flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INDEX_OR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.opening_loc = target->opening_loc,
@@ -3195,18 +3073,24 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
pm_call_target_node_t *node = PM_NODE_ALLOC(parser, pm_call_target_node_t);
*node = (pm_call_target_node_t) {
- {
- .type = PM_CALL_TARGET_NODE,
- .flags = target->base.flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = target->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_CALL_TARGET_NODE, FL(target), target),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.name = target->name,
.message_loc = target->message_loc
};
+ /* It is possible to get here where we have parsed an invalid syntax tree
+ * where the call operator was not present. In that case we will have a
+ * problem because it is a required location. In this case we need to fill
+ * it in with a fake location so that the syntax tree remains valid. */
+ if (node->call_operator_loc.start == NULL) {
+ node->call_operator_loc = (pm_location_t) {
+ .start = target->base.location.start,
+ .end = target->base.location.start
+ };
+ }
+
// Here we're going to free the target, since it is no longer necessary.
// However, we don't want to call `pm_node_destroy` because we want to keep
// around all of its children since we just reused them.
@@ -3222,18 +3106,12 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
static pm_index_target_node_t *
pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
pm_index_target_node_t *node = PM_NODE_ALLOC(parser, pm_index_target_node_t);
- pm_node_flags_t flags = target->base.flags;
pm_index_arguments_check(parser, target->arguments, target->block);
-
assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
+
*node = (pm_index_target_node_t) {
- {
- .type = PM_INDEX_TARGET_NODE,
- .flags = flags | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = target->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_INDEX_TARGET_NODE, FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, target),
.receiver = target->receiver,
.opening_loc = target->opening_loc,
.arguments = target->arguments,
@@ -3257,14 +3135,7 @@ pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_v
pm_capture_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_capture_pattern_node_t);
*node = (pm_capture_pattern_node_t) {
- {
- .type = PM_CAPTURE_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = value->location.start,
- .end = target->base.location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CAPTURE_PATTERN_NODE, 0, value, target),
.value = value,
.target = target,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -3281,14 +3152,7 @@ pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node
pm_case_node_t *node = PM_NODE_ALLOC(parser, pm_case_node_t);
*node = (pm_case_node_t) {
- {
- .type = PM_CASE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = case_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CASE_NODE, 0, case_keyword, end_keyword),
.predicate = predicate,
.else_clause = NULL,
.case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
@@ -3336,14 +3200,7 @@ pm_case_match_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, p
pm_case_match_node_t *node = PM_NODE_ALLOC(parser, pm_case_match_node_t);
*node = (pm_case_match_node_t) {
- {
- .type = PM_CASE_MATCH_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = case_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CASE_MATCH_NODE, 0, case_keyword, end_keyword),
.predicate = predicate,
.else_clause = NULL,
.case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
@@ -3391,11 +3248,7 @@ pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p
pm_class_node_t *node = PM_NODE_ALLOC(parser, pm_class_node_t);
*node = (pm_class_node_t) {
- {
- .type = PM_CLASS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = { .start = class_keyword->start, .end = end_keyword->end },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CLASS_NODE, 0, class_keyword, end_keyword),
.locals = *locals,
.class_keyword_loc = PM_LOCATION_TOKEN_VALUE(class_keyword),
.constant_path = constant_path,
@@ -3418,14 +3271,7 @@ pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_r
pm_class_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_and_write_node_t);
*node = (pm_class_variable_and_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_AND_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3443,14 +3289,7 @@ pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_varia
pm_class_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_operator_write_node_t);
*node = (pm_class_variable_operator_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3470,14 +3309,7 @@ pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_re
pm_class_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_or_write_node_t);
*node = (pm_class_variable_or_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_OR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3496,11 +3328,7 @@ pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token)
pm_class_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_read_node_t);
*node = (pm_class_variable_read_node_t) {
- {
- .type = PM_CLASS_VARIABLE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_CLASS_VARIABLE_READ_NODE, 0, token),
.name = pm_parser_constant_id_token(parser, token)
};
@@ -3527,19 +3355,12 @@ pm_implicit_array_write_flags(const pm_node_t *node, pm_node_flags_t flags) {
static pm_class_variable_write_node_t *
pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) {
pm_class_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_class_variable_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_WRITE_NODE,
- .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY),
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = read_node->base.location.start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_WRITE_NODE, flags, read_node, value),
.name = read_node->name,
- .name_loc = PM_LOCATION_NODE_VALUE((pm_node_t *) read_node),
+ .name_loc = PM_LOCATION_NODE_VALUE(UP(read_node)),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
};
@@ -3556,14 +3377,7 @@ pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_nod
pm_constant_path_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_and_write_node_t);
*node = (pm_constant_path_and_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_AND_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_AND_WRITE_NODE, 0, target, value),
.target = target,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -3580,14 +3394,7 @@ pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_pat
pm_constant_path_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_operator_write_node_t);
*node = (pm_constant_path_operator_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_OPERATOR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_OPERATOR_WRITE_NODE, 0, target, value),
.target = target,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -3606,14 +3413,7 @@ pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node
pm_constant_path_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_or_write_node_t);
*node = (pm_constant_path_or_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_OR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_OR_WRITE_NODE, 0, target, value),
.target = target,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -3635,20 +3435,23 @@ pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_to
name = pm_parser_constant_id_token(parser, name_token);
}
- *node = (pm_constant_path_node_t) {
- {
- .type = PM_CONSTANT_PATH_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = parent == NULL ? delimiter->start : parent->location.start,
- .end = name_token->end
- },
- },
- .parent = parent,
- .name = name,
- .delimiter_loc = PM_LOCATION_TOKEN_VALUE(delimiter),
- .name_loc = PM_LOCATION_TOKEN_VALUE(name_token)
- };
+ if (parent == NULL) {
+ *node = (pm_constant_path_node_t) {
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CONSTANT_PATH_NODE, 0, delimiter, name_token),
+ .parent = parent,
+ .name = name,
+ .delimiter_loc = PM_LOCATION_TOKEN_VALUE(delimiter),
+ .name_loc = PM_LOCATION_TOKEN_VALUE(name_token)
+ };
+ } else {
+ *node = (pm_constant_path_node_t) {
+ .base = PM_NODE_INIT_NODE_TOKEN(parser, PM_CONSTANT_PATH_NODE, 0, parent, name_token),
+ .parent = parent,
+ .name = name,
+ .delimiter_loc = PM_LOCATION_TOKEN_VALUE(delimiter),
+ .name_loc = PM_LOCATION_TOKEN_VALUE(name_token)
+ };
+ }
return node;
}
@@ -3659,17 +3462,10 @@ pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_to
static pm_constant_path_write_node_t *
pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) {
pm_constant_path_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_constant_path_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_WRITE_NODE,
- .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY),
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_WRITE_NODE, flags, target, value),
.target = target,
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -3687,14 +3483,7 @@ pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *
pm_constant_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_and_write_node_t);
*node = (pm_constant_and_write_node_t) {
- {
- .type = PM_CONSTANT_AND_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_AND_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3712,14 +3501,7 @@ pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_nod
pm_constant_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_operator_write_node_t);
*node = (pm_constant_operator_write_node_t) {
- {
- .type = PM_CONSTANT_OPERATOR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_OPERATOR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3739,14 +3521,7 @@ pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *t
pm_constant_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_or_write_node_t);
*node = (pm_constant_or_write_node_t) {
- {
- .type = PM_CONSTANT_OR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_OR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3765,11 +3540,7 @@ pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
pm_constant_read_node_t *node = PM_NODE_ALLOC(parser, pm_constant_read_node_t);
*node = (pm_constant_read_node_t) {
- {
- .type = PM_CONSTANT_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(name)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_CONSTANT_READ_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -3782,17 +3553,10 @@ pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
static pm_constant_write_node_t *
pm_constant_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
pm_constant_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_constant_write_node_t) {
- {
- .type = PM_CONSTANT_WRITE_NODE,
- .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY),
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_WRITE_NODE, flags, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
@@ -3810,7 +3574,7 @@ pm_def_node_receiver_check(pm_parser_t *parser, const pm_node_t *node) {
switch (PM_NODE_TYPE(node)) {
case PM_BEGIN_NODE: {
const pm_begin_node_t *cast = (pm_begin_node_t *) node;
- if (cast->statements != NULL) pm_def_node_receiver_check(parser, (pm_node_t *) cast->statements);
+ if (cast->statements != NULL) pm_def_node_receiver_check(parser, UP(cast->statements));
break;
}
case PM_PARENTHESES_NODE: {
@@ -3866,24 +3630,17 @@ pm_def_node_create(
const pm_token_t *end_keyword
) {
pm_def_node_t *node = PM_NODE_ALLOC(parser, pm_def_node_t);
- const uint8_t *end;
-
- if (end_keyword->type == PM_TOKEN_NOT_PROVIDED) {
- end = body->location.end;
- } else {
- end = end_keyword->end;
- }
if (receiver != NULL) {
pm_def_node_receiver_check(parser, receiver);
}
*node = (pm_def_node_t) {
- {
- .type = PM_DEF_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = { .start = def_keyword->start, .end = end },
- },
+ .base = (
+ (end_keyword->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN_NODE(parser, PM_DEF_NODE, 0, def_keyword, body)
+ : PM_NODE_INIT_TOKENS(parser, PM_DEF_NODE, 0, def_keyword, end_keyword)
+ ),
.name = name,
.name_loc = PM_LOCATION_TOKEN_VALUE(name_loc),
.receiver = receiver,
@@ -3905,22 +3662,19 @@ pm_def_node_create(
* Allocate a new DefinedNode node.
*/
static pm_defined_node_t *
-pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t *value, const pm_token_t *rparen, const pm_location_t *keyword_loc) {
+pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t *value, const pm_token_t *rparen, const pm_token_t *keyword) {
pm_defined_node_t *node = PM_NODE_ALLOC(parser, pm_defined_node_t);
*node = (pm_defined_node_t) {
- {
- .type = PM_DEFINED_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword_loc->start,
- .end = (rparen->type == PM_TOKEN_NOT_PROVIDED ? value->location.end : rparen->end)
- },
- },
+ .base = (
+ (rparen->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN_NODE(parser, PM_DEFINED_NODE, 0, keyword, value)
+ : PM_NODE_INIT_TOKENS(parser, PM_DEFINED_NODE, 0, keyword, rparen)
+ ),
.lparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(lparen),
.value = value,
.rparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(rparen),
- .keyword_loc = *keyword_loc
+ .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
};
return node;
@@ -3932,22 +3686,13 @@ pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t
static pm_else_node_t *
pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) {
pm_else_node_t *node = PM_NODE_ALLOC(parser, pm_else_node_t);
- const uint8_t *end = NULL;
- if ((end_keyword->type == PM_TOKEN_NOT_PROVIDED) && (statements != NULL)) {
- end = statements->base.location.end;
- } else {
- end = end_keyword->end;
- }
*node = (pm_else_node_t) {
- {
- .type = PM_ELSE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = else_keyword->start,
- .end = end,
- },
- },
+ .base = (
+ ((end_keyword->type == PM_TOKEN_NOT_PROVIDED) && (statements != NULL))
+ ? PM_NODE_INIT_TOKEN_NODE(parser, PM_ELSE_NODE, 0, else_keyword, statements)
+ : PM_NODE_INIT_TOKENS(parser, PM_ELSE_NODE, 0, else_keyword, end_keyword)
+ ),
.else_keyword_loc = PM_LOCATION_TOKEN_VALUE(else_keyword),
.statements = statements,
.end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
@@ -3964,14 +3709,7 @@ pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *openin
pm_embedded_statements_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_statements_node_t);
*node = (pm_embedded_statements_node_t) {
- {
- .type = PM_EMBEDDED_STATEMENTS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_EMBEDDED_STATEMENTS_NODE, 0, opening, closing),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.statements = statements,
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
@@ -3988,14 +3726,7 @@ pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator
pm_embedded_variable_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_variable_node_t);
*node = (pm_embedded_variable_node_t) {
- {
- .type = PM_EMBEDDED_VARIABLE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = variable->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_EMBEDDED_VARIABLE_NODE, 0, operator, variable),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.variable = variable
};
@@ -4011,14 +3742,7 @@ pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_
pm_ensure_node_t *node = PM_NODE_ALLOC(parser, pm_ensure_node_t);
*node = (pm_ensure_node_t) {
- {
- .type = PM_ENSURE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = ensure_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_ENSURE_NODE, 0, ensure_keyword, end_keyword),
.ensure_keyword_loc = PM_LOCATION_TOKEN_VALUE(ensure_keyword),
.statements = statements,
.end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword)
@@ -4035,12 +3759,9 @@ pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_FALSE);
pm_false_node_t *node = PM_NODE_ALLOC(parser, pm_false_node_t);
- *node = (pm_false_node_t) {{
- .type = PM_FALSE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_false_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FALSE_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -4060,7 +3781,7 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) {
pm_node_t *right;
if (nodes->size == 1) {
- right = (pm_node_t *) pm_missing_node_create(parser, left->location.end, left->location.end);
+ right = UP(pm_missing_node_create(parser, left->location.end, left->location.end));
} else {
right = nodes->nodes[nodes->size - 1];
assert(PM_NODE_TYPE_P(right, PM_SPLAT_NODE));
@@ -4074,20 +3795,13 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) {
pm_node_t *right_splat_node = right;
#endif
*node = (pm_find_pattern_node_t) {
- {
- .type = PM_FIND_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = left->location.start,
- .end = right->location.end,
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_FIND_PATTERN_NODE, 0, left, right),
.constant = NULL,
.left = left_splat_node,
.right = right_splat_node,
.requireds = { 0 },
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
// For now we're going to just copy over each pointer manually. This could be
@@ -4182,12 +3896,7 @@ pm_float_node_create(pm_parser_t *parser, const pm_token_t *token) {
pm_float_node_t *node = PM_NODE_ALLOC(parser, pm_float_node_t);
*node = (pm_float_node_t) {
- {
- .type = PM_FLOAT_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FLOAT_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
.value = pm_double_parse(parser, token)
};
@@ -4203,17 +3912,12 @@ pm_float_node_imaginary_create(pm_parser_t *parser, const pm_token_t *token) {
pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_float_node_create(parser, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_float_node_create(parser, &((pm_token_t) {
.type = PM_TOKEN_FLOAT,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -4228,12 +3932,7 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) {
pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t);
*node = (pm_rational_node_t) {
- {
- .type = PM_RATIONAL_NODE,
- .flags = PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RATIONAL_NODE, PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, token),
.numerator = { 0 },
.denominator = { 0 }
};
@@ -4263,9 +3962,13 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) {
memcpy(digits + (point - start), point + 1, (unsigned long) (end - point - 1));
pm_integer_parse(&node->numerator, PM_INTEGER_BASE_DEFAULT, digits, digits + length - 1);
+ size_t fract_length = 0;
+ for (const uint8_t *fract = point; fract < end; ++fract) {
+ if (*fract != '_') ++fract_length;
+ }
digits[0] = '1';
- if (end - point > 1) memset(digits + 1, '0', (size_t) (end - point - 1));
- pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + (end - point));
+ if (fract_length > 1) memset(digits + 1, '0', fract_length - 1);
+ pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + fract_length);
xfree(digits);
pm_integers_reduce(&node->numerator, &node->denominator);
@@ -4282,17 +3985,12 @@ pm_float_node_rational_imaginary_create(pm_parser_t *parser, const pm_token_t *t
pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_float_node_rational_create(parser, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_float_node_rational_create(parser, &((pm_token_t) {
.type = PM_TOKEN_FLOAT_RATIONAL,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -4315,14 +4013,7 @@ pm_for_node_create(
pm_for_node_t *node = PM_NODE_ALLOC(parser, pm_for_node_t);
*node = (pm_for_node_t) {
- {
- .type = PM_FOR_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = for_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_FOR_NODE, 0, for_keyword, end_keyword),
.index = index,
.collection = collection,
.statements = statements,
@@ -4343,11 +4034,9 @@ pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token
assert(token->type == PM_TOKEN_UDOT_DOT_DOT);
pm_forwarding_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_arguments_node_t);
- *node = (pm_forwarding_arguments_node_t) {{
- .type = PM_FORWARDING_ARGUMENTS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_forwarding_arguments_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FORWARDING_ARGUMENTS_NODE, 0, token)
+ };
return node;
}
@@ -4360,11 +4049,9 @@ pm_forwarding_parameter_node_create(pm_parser_t *parser, const pm_token_t *token
assert(token->type == PM_TOKEN_UDOT_DOT_DOT);
pm_forwarding_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_parameter_node_t);
- *node = (pm_forwarding_parameter_node_t) {{
- .type = PM_FORWARDING_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_forwarding_parameter_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FORWARDING_PARAMETER_NODE, 0, token)
+ };
return node;
}
@@ -4384,14 +4071,11 @@ pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm
}
*node = (pm_forwarding_super_node_t) {
- {
- .type = PM_FORWARDING_SUPER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = token->start,
- .end = block != NULL ? block->base.location.end : token->end
- },
- },
+ .base = (
+ (block == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_FORWARDING_SUPER_NODE, 0, token)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_FORWARDING_SUPER_NODE, 0, token, block)
+ ),
.block = block
};
@@ -4407,14 +4091,7 @@ pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening
pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t);
*node = (pm_hash_pattern_node_t) {
- {
- .type = PM_HASH_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_HASH_PATTERN_NODE, 0, opening, closing),
.constant = NULL,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
@@ -4437,8 +4114,8 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme
if (elements->size > 0) {
if (rest) {
- start = elements->nodes[0]->location.start;
- end = rest->location.end;
+ start = MIN(rest->location.start, elements->nodes[0]->location.start);
+ end = MAX(rest->location.end, elements->nodes[elements->size - 1]->location.end);
} else {
start = elements->nodes[0]->location.start;
end = elements->nodes[elements->size - 1]->location.end;
@@ -4450,26 +4127,15 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme
}
*node = (pm_hash_pattern_node_t) {
- {
- .type = PM_HASH_PATTERN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, start, end),
.constant = NULL,
.elements = { 0 },
.rest = rest,
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
- pm_node_t *element;
- PM_NODE_LIST_FOREACH(elements, index, element) {
- pm_node_list_append(&node->elements, element);
- }
-
+ pm_node_list_concat(&node->elements, elements);
return node;
}
@@ -4502,14 +4168,7 @@ pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target,
pm_global_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_and_write_node_t);
*node = (pm_global_variable_and_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_AND_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -4527,14 +4186,7 @@ pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *ta
pm_global_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_operator_write_node_t);
*node = (pm_global_variable_operator_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = target->location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -4554,14 +4206,7 @@ pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target,
pm_global_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_or_write_node_t);
*node = (pm_global_variable_or_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_OR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -4579,11 +4224,7 @@ pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name)
pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t);
*node = (pm_global_variable_read_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -4598,11 +4239,7 @@ pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant
pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t);
*node = (pm_global_variable_read_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0),
.name = name
};
@@ -4615,17 +4252,10 @@ pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant
static pm_global_variable_write_node_t *
pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) {
pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_global_variable_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY),
- .location = {
- .start = target->location.start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, flags, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = PM_LOCATION_NODE_VALUE(target),
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
@@ -4643,11 +4273,7 @@ pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constan
pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t);
*node = (pm_global_variable_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, 0),
.name = name,
.name_loc = PM_LOCATION_NULL_VALUE(parser),
.operator_loc = PM_LOCATION_NULL_VALUE(parser),
@@ -4666,12 +4292,7 @@ pm_hash_node_create(pm_parser_t *parser, const pm_token_t *opening) {
pm_hash_node_t *node = PM_NODE_ALLOC(parser, pm_hash_node_t);
*node = (pm_hash_node_t) {
- {
- .type = PM_HASH_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(opening)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_HASH_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_NULL_VALUE(parser),
.elements = { 0 }
@@ -4696,7 +4317,7 @@ pm_hash_node_elements_append(pm_hash_node_t *hash, pm_node_t *element) {
}
if (!static_literal) {
- pm_node_flag_unset((pm_node_t *)hash, PM_NODE_FLAG_STATIC_LITERAL);
+ pm_node_flag_unset(UP(hash), PM_NODE_FLAG_STATIC_LITERAL);
}
}
@@ -4733,15 +4354,7 @@ pm_if_node_create(pm_parser_t *parser,
}
*node = (pm_if_node_t) {
- {
- .type = PM_IF_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = if_keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, if_keyword->start, end),
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
.predicate = predicate,
.then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
@@ -4765,21 +4378,13 @@ pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_t
pm_statements_node_body_append(parser, statements, statement, true);
*node = (pm_if_node_t) {
- {
- .type = PM_IF_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = statement->location.start,
- .end = predicate->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, statement, predicate),
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
.predicate = predicate,
- .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .then_keyword_loc = { 0 },
.statements = statements,
.subsequent = NULL,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .end_keyword_loc = { 0 }
};
return node;
@@ -4805,21 +4410,13 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to
pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t);
*node = (pm_if_node_t) {
- {
- .type = PM_IF_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = predicate->location.start,
- .end = false_expression->location.end,
- },
- },
- .if_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .base = PM_NODE_INIT_NODES(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, predicate, false_expression),
+ .if_keyword_loc = { 0 },
.predicate = predicate,
.then_keyword_loc = PM_LOCATION_TOKEN_VALUE(qmark),
.statements = if_statements,
- .subsequent = (pm_node_t *) else_node,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .subsequent = UP(else_node),
+ .end_keyword_loc = { 0 }
};
return node;
@@ -4846,11 +4443,7 @@ pm_implicit_node_create(pm_parser_t *parser, pm_node_t *value) {
pm_implicit_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_node_t);
*node = (pm_implicit_node_t) {
- {
- .type = PM_IMPLICIT_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = value->location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_IMPLICIT_NODE, 0, value),
.value = value
};
@@ -4867,11 +4460,7 @@ pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) {
pm_implicit_rest_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_rest_node_t);
*node = (pm_implicit_rest_node_t) {
- {
- .type = PM_IMPLICIT_REST_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMPLICIT_REST_NODE, 0, token)
};
return node;
@@ -4886,12 +4475,7 @@ pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token
pm_integer_node_t *node = PM_NODE_ALLOC(parser, pm_integer_node_t);
*node = (pm_integer_node_t) {
- {
- .type = PM_INTEGER_NODE,
- .flags = base | PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_INTEGER_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, token),
.value = { 0 }
};
@@ -4918,17 +4502,12 @@ pm_integer_node_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, cons
pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_integer_node_create(parser, base, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_integer_node_create(parser, base, &((pm_token_t) {
.type = PM_TOKEN_INTEGER,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -4944,12 +4523,7 @@ pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const
pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t);
*node = (pm_rational_node_t) {
- {
- .type = PM_RATIONAL_NODE,
- .flags = base | PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RATIONAL_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, token),
.numerator = { 0 },
.denominator = { .value = 1, 0 }
};
@@ -4978,17 +4552,12 @@ pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t b
pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_integer_node_rational_create(parser, base, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_integer_node_rational_create(parser, base, &((pm_token_t) {
.type = PM_TOKEN_INTEGER_RATIONAL,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -5011,14 +4580,7 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t
}
*node = (pm_in_node_t) {
- {
- .type = PM_IN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = in_keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_IN_NODE, 0, in_keyword->start, end),
.pattern = pattern,
.statements = statements,
.in_loc = PM_LOCATION_TOKEN_VALUE(in_keyword),
@@ -5037,14 +4599,7 @@ pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_vari
pm_instance_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_and_write_node_t);
*node = (pm_instance_variable_and_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_AND_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -5062,14 +4617,7 @@ pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance
pm_instance_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_operator_write_node_t);
*node = (pm_instance_variable_operator_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -5089,14 +4637,7 @@ pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_varia
pm_instance_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_or_write_node_t);
*node = (pm_instance_variable_or_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_OR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -5115,11 +4656,7 @@ pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *tok
pm_instance_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_read_node_t);
*node = (pm_instance_variable_read_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_INSTANCE_VARIABLE_READ_NODE, 0, token),
.name = pm_parser_constant_id_token(parser, token)
};
@@ -5133,18 +4670,12 @@ pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *tok
static pm_instance_variable_write_node_t *
pm_instance_variable_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) {
pm_instance_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
+
*node = (pm_instance_variable_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_WRITE_NODE,
- .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY),
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = read_node->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_WRITE_NODE, flags, read_node, value),
.name = read_node->name,
- .name_loc = PM_LOCATION_NODE_BASE_VALUE(read_node),
+ .name_loc = PM_LOCATION_NODE_VALUE(read_node),
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
.value = value
};
@@ -5186,7 +4717,7 @@ pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *p
break;
}
case PM_EMBEDDED_VARIABLE_NODE:
- pm_node_flag_unset((pm_node_t *) node, PM_NODE_FLAG_STATIC_LITERAL);
+ pm_node_flag_unset(UP(node), PM_NODE_FLAG_STATIC_LITERAL);
break;
default:
assert(false && "unexpected node type");
@@ -5204,15 +4735,7 @@ pm_interpolated_regular_expression_node_create(pm_parser_t *parser, const pm_tok
pm_interpolated_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_regular_expression_node_t);
*node = (pm_interpolated_regular_expression_node_t) {
- {
- .type = PM_INTERPOLATED_REGULAR_EXPRESSION_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = NULL,
- },
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_INTERPOLATED_REGULAR_EXPRESSION_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_TOKEN_VALUE(opening),
.parts = { 0 }
@@ -5230,14 +4753,14 @@ pm_interpolated_regular_expression_node_append(pm_interpolated_regular_expressio
node->base.location.end = part->location.end;
}
- pm_interpolated_node_append((pm_node_t *) node, &node->parts, part);
+ pm_interpolated_node_append(UP(node), &node->parts, part);
}
static inline void
pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_interpolated_regular_expression_node_t *node, const pm_token_t *closing) {
node->closing_loc = PM_LOCATION_TOKEN_VALUE(closing);
node->base.location.end = closing->end;
- pm_node_flag_set((pm_node_t *) node, pm_regular_expression_flags_create(parser, closing));
+ pm_node_flag_set(UP(node), pm_regular_expression_flags_create(parser, closing));
}
/**
@@ -5266,10 +4789,10 @@ pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_inte
static inline void
pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_t *part) {
#define CLEAR_FLAGS(node) \
- node->base.flags = (pm_node_flags_t) (node->base.flags & ~(PM_NODE_FLAG_STATIC_LITERAL | PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE))
+ node->base.flags = (pm_node_flags_t) (FL(node) & ~(PM_NODE_FLAG_STATIC_LITERAL | PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE))
#define MUTABLE_FLAGS(node) \
- node->base.flags = (pm_node_flags_t) ((node->base.flags | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE) & ~PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN);
+ node->base.flags = (pm_node_flags_t) ((FL(node) | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE) & ~PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN);
if (node->parts.size == 0 && node->opening_loc.start == NULL) {
node->base.location.start = part->location.start;
@@ -5279,6 +4802,12 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
switch (PM_NODE_TYPE(part)) {
case PM_STRING_NODE:
+ // If inner string is not frozen, it stops being a static literal. We should *not* clear other flags,
+ // because concatenating two frozen strings (`'foo' 'bar'`) is still frozen. This holds true for
+ // as long as this interpolation only consists of other string literals.
+ if (!PM_NODE_FLAG_P(part, PM_STRING_FLAGS_FROZEN)) {
+ pm_node_flag_unset(UP(node), PM_NODE_FLAG_STATIC_LITERAL);
+ }
part->flags = (pm_node_flags_t) ((part->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE);
break;
case PM_INTERPOLATED_STRING_NODE:
@@ -5330,8 +4859,10 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
break;
case PM_X_STRING_NODE:
case PM_INTERPOLATED_X_STRING_NODE:
- // If this is an x string, then this is a syntax error. But we want
- // to handle it here so that we don't fail the assertion.
+ case PM_SYMBOL_NODE:
+ case PM_INTERPOLATED_SYMBOL_NODE:
+ // These will only happen in error cases. But we want to handle it
+ // here so that we don't fail the assertion.
CLEAR_FLAGS(node);
break;
default:
@@ -5363,15 +4894,7 @@ pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *openin
}
*node = (pm_interpolated_string_node_t) {
- {
- .type = PM_INTERPOLATED_STRING_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end,
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_INTERPOLATED_STRING_NODE, flags, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.parts = { 0 }
@@ -5402,7 +4925,7 @@ pm_interpolated_symbol_node_append(pm_interpolated_symbol_node_t *node, pm_node_
node->base.location.start = part->location.start;
}
- pm_interpolated_node_append((pm_node_t *) node, &node->parts, part);
+ pm_interpolated_node_append(UP(node), &node->parts, part);
node->base.location.end = MAX(node->base.location.end, part->location.end);
}
@@ -5420,15 +4943,7 @@ pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *openin
pm_interpolated_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_symbol_node_t);
*node = (pm_interpolated_symbol_node_t) {
- {
- .type = PM_INTERPOLATED_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end,
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_INTERPOLATED_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.parts = { 0 }
@@ -5452,14 +4967,7 @@ pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *openi
pm_interpolated_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_x_string_node_t);
*node = (pm_interpolated_x_string_node_t) {
- {
- .type = PM_INTERPOLATED_X_STRING_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_INTERPOLATED_X_STRING_NODE, 0, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.parts = { 0 }
@@ -5470,7 +4978,7 @@ pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *openi
static inline void
pm_interpolated_xstring_node_append(pm_interpolated_x_string_node_t *node, pm_node_t *part) {
- pm_interpolated_node_append((pm_node_t *) node, &node->parts, part);
+ pm_interpolated_node_append(UP(node), &node->parts, part);
node->base.location.end = part->location.end;
}
@@ -5488,11 +4996,7 @@ pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *nam
pm_it_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_it_local_variable_read_node_t);
*node = (pm_it_local_variable_read_node_t) {
- {
- .type = PM_IT_LOCAL_VARIABLE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(name)
- }
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IT_LOCAL_VARIABLE_READ_NODE, 0, name),
};
return node;
@@ -5506,14 +5010,7 @@ pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, con
pm_it_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_it_parameters_node_t);
*node = (pm_it_parameters_node_t) {
- {
- .type = PM_IT_PARAMETERS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- }
+ .base = PM_NODE_INIT_TOKENS(parser, PM_IT_PARAMETERS_NODE, 0, opening, closing),
};
return node;
@@ -5527,12 +5024,7 @@ pm_keyword_hash_node_create(pm_parser_t *parser) {
pm_keyword_hash_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_hash_node_t);
*node = (pm_keyword_hash_node_t) {
- .base = {
- .type = PM_KEYWORD_HASH_NODE,
- .flags = PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
- },
+ .base = PM_NODE_INIT_UNSET(parser, PM_KEYWORD_HASH_NODE, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS),
.elements = { 0 }
};
@@ -5547,7 +5039,7 @@ pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *el
// If the element being added is not an AssocNode or does not have a symbol
// key, then we want to turn the SYMBOL_KEYS flag off.
if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE) || !PM_NODE_TYPE_P(((pm_assoc_node_t *) element)->key, PM_SYMBOL_NODE)) {
- pm_node_flag_unset((pm_node_t *)hash, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS);
+ pm_node_flag_unset(UP(hash), PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS);
}
pm_node_list_append(&hash->elements, element);
@@ -5565,14 +5057,7 @@ pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t
pm_required_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_keyword_parameter_node_t);
*node = (pm_required_keyword_parameter_node_t) {
- {
- .type = PM_REQUIRED_KEYWORD_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = name->start,
- .end = name->end
- },
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_REQUIRED_KEYWORD_PARAMETER_NODE, 0, name),
.name = pm_parser_constant_id_location(parser, name->start, name->end - 1),
.name_loc = PM_LOCATION_TOKEN_VALUE(name),
};
@@ -5588,14 +5073,7 @@ pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t
pm_optional_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_keyword_parameter_node_t);
*node = (pm_optional_keyword_parameter_node_t) {
- {
- .type = PM_OPTIONAL_KEYWORD_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = name->start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_OPTIONAL_KEYWORD_PARAMETER_NODE, 0, name, value),
.name = pm_parser_constant_id_location(parser, name->start, name->end - 1),
.name_loc = PM_LOCATION_TOKEN_VALUE(name),
.value = value
@@ -5612,14 +5090,11 @@ pm_keyword_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *ope
pm_keyword_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_rest_parameter_node_t);
*node = (pm_keyword_rest_parameter_node_t) {
- {
- .type = PM_KEYWORD_REST_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end)
- },
- },
+ .base = (
+ (name->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN(parser, PM_KEYWORD_REST_PARAMETER_NODE, 0, operator)
+ : PM_NODE_INIT_TOKENS(parser, PM_KEYWORD_REST_PARAMETER_NODE, 0, operator, name)
+ ),
.name = pm_parser_optional_constant_id_token(parser, name),
.name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -5644,14 +5119,7 @@ pm_lambda_node_create(
pm_lambda_node_t *node = PM_NODE_ALLOC(parser, pm_lambda_node_t);
*node = (pm_lambda_node_t) {
- {
- .type = PM_LAMBDA_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_LAMBDA_NODE, 0, operator, closing),
.locals = *locals,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -5673,14 +5141,7 @@ pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target,
pm_local_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_and_write_node_t);
*node = (pm_local_variable_and_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_AND_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_LOCAL_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -5699,14 +5160,7 @@ pm_local_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *tar
pm_local_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_operator_write_node_t);
*node = (pm_local_variable_operator_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name_loc = target->location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -5728,14 +5182,7 @@ pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, c
pm_local_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_or_write_node_t);
*node = (pm_local_variable_or_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_OR_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_LOCAL_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -5756,11 +5203,7 @@ pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_tok
pm_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_read_node_t);
*node = (pm_local_variable_read_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(name)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_LOCAL_VARIABLE_READ_NODE, 0, name),
.name = name_id,
.depth = depth
};
@@ -5793,17 +5236,10 @@ pm_local_variable_read_node_missing_create(pm_parser_t *parser, const pm_token_t
static pm_local_variable_write_node_t *
pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name, uint32_t depth, pm_node_t *value, const pm_location_t *name_loc, const pm_token_t *operator) {
pm_local_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_local_variable_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_WRITE_NODE,
- .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY),
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = name_loc->start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_LOCAL_VARIABLE_WRITE_NODE, flags, name_loc, value),
.name = name,
.depth = depth,
.value = value,
@@ -5852,11 +5288,7 @@ pm_local_variable_target_node_create(pm_parser_t *parser, const pm_location_t *l
pm_local_variable_target_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_target_node_t);
*node = (pm_local_variable_target_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_TARGET_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = *location
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_LOCAL_VARIABLE_TARGET_NODE, 0, location),
.name = name,
.depth = depth
};
@@ -5874,14 +5306,7 @@ pm_match_predicate_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t
pm_match_predicate_node_t *node = PM_NODE_ALLOC(parser, pm_match_predicate_node_t);
*node = (pm_match_predicate_node_t) {
- {
- .type = PM_MATCH_PREDICATE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = value->location.start,
- .end = pattern->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_MATCH_PREDICATE_NODE, 0, value, pattern),
.value = value,
.pattern = pattern,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -5900,14 +5325,7 @@ pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *
pm_match_required_node_t *node = PM_NODE_ALLOC(parser, pm_match_required_node_t);
*node = (pm_match_required_node_t) {
- {
- .type = PM_MATCH_REQUIRED_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = value->location.start,
- .end = pattern->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_MATCH_REQUIRED_NODE, 0, value, pattern),
.value = value,
.pattern = pattern,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -5924,11 +5342,7 @@ pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) {
pm_match_write_node_t *node = PM_NODE_ALLOC(parser, pm_match_write_node_t);
*node = (pm_match_write_node_t) {
- {
- .type = PM_MATCH_WRITE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = call->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_MATCH_WRITE_NODE, 0, call),
.call = call,
.targets = { 0 }
};
@@ -5944,14 +5358,7 @@ pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const
pm_module_node_t *node = PM_NODE_ALLOC(parser, pm_module_node_t);
*node = (pm_module_node_t) {
- {
- .type = PM_MODULE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = module_keyword->start,
- .end = end_keyword->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_MODULE_NODE, 0, module_keyword, end_keyword),
.locals = (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals),
.module_keyword_loc = PM_LOCATION_TOKEN_VALUE(module_keyword),
.constant_path = constant_path,
@@ -5971,16 +5378,12 @@ pm_multi_target_node_create(pm_parser_t *parser) {
pm_multi_target_node_t *node = PM_NODE_ALLOC(parser, pm_multi_target_node_t);
*node = (pm_multi_target_node_t) {
- {
- .type = PM_MULTI_TARGET_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = { .start = NULL, .end = NULL }
- },
+ .base = PM_NODE_INIT_UNSET(parser, PM_MULTI_TARGET_NODE, 0),
.lefts = { 0 },
.rest = NULL,
.rights = { 0 },
- .lparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .rparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .lparen_loc = { 0 },
+ .rparen_loc = { 0 }
};
return node;
@@ -6044,17 +5447,10 @@ pm_multi_target_node_closing_set(pm_multi_target_node_t *node, const pm_token_t
static pm_multi_write_node_t *
pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, const pm_token_t *operator, pm_node_t *value) {
pm_multi_write_node_t *node = PM_NODE_ALLOC(parser, pm_multi_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_multi_write_node_t) {
- {
- .type = PM_MULTI_WRITE_NODE,
- .flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY),
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_MULTI_WRITE_NODE, flags, target, value),
.lefts = target->lefts,
.rest = target->rest,
.rights = target->rights,
@@ -6080,14 +5476,11 @@ pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments
pm_next_node_t *node = PM_NODE_ALLOC(parser, pm_next_node_t);
*node = (pm_next_node_t) {
- {
- .type = PM_NEXT_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = (arguments == NULL ? keyword->end : arguments->base.location.end)
- }
- },
+ .base = (
+ (arguments == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_NEXT_NODE, 0, keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_NEXT_NODE, 0, keyword, arguments)
+ ),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.arguments = arguments
};
@@ -6103,12 +5496,9 @@ pm_nil_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_NIL);
pm_nil_node_t *node = PM_NODE_ALLOC(parser, pm_nil_node_t);
- *node = (pm_nil_node_t) {{
- .type = PM_NIL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_nil_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_NIL_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -6123,14 +5513,7 @@ pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *oper
pm_no_keywords_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_keywords_parameter_node_t);
*node = (pm_no_keywords_parameter_node_t) {
- {
- .type = PM_NO_KEYWORDS_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = keyword->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_NO_KEYWORDS_PARAMETER_NODE, 0, operator, keyword),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
};
@@ -6146,11 +5529,7 @@ pm_numbered_parameters_node_create(pm_parser_t *parser, const pm_location_t *loc
pm_numbered_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_parameters_node_t);
*node = (pm_numbered_parameters_node_t) {
- {
- .type = PM_NUMBERED_PARAMETERS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = *location
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_NUMBERED_PARAMETERS_NODE, 0, location),
.maximum = maximum
};
@@ -6215,11 +5594,7 @@ pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *na
pm_numbered_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_reference_read_node_t);
*node = (pm_numbered_reference_read_node_t) {
- {
- .type = PM_NUMBERED_REFERENCE_READ_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_NUMBERED_REFERENCE_READ_NODE, 0, name),
.number = pm_numbered_reference_read_node_number(parser, name)
};
@@ -6234,14 +5609,7 @@ pm_optional_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, c
pm_optional_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_parameter_node_t);
*node = (pm_optional_parameter_node_t) {
- {
- .type = PM_OPTIONAL_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = name->start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_OPTIONAL_PARAMETER_NODE, 0, name, value),
.name = pm_parser_constant_id_token(parser, name),
.name_loc = PM_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -6261,14 +5629,7 @@ pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operat
pm_or_node_t *node = PM_NODE_ALLOC(parser, pm_or_node_t);
*node = (pm_or_node_t) {
- {
- .type = PM_OR_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = left->location.start,
- .end = right->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_OR_NODE, 0, left, right),
.left = left,
.right = right,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -6285,11 +5646,7 @@ pm_parameters_node_create(pm_parser_t *parser) {
pm_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_parameters_node_t);
*node = (pm_parameters_node_t) {
- {
- .type = PM_PARAMETERS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(&parser->current)
- },
+ .base = PM_NODE_INIT_UNSET(parser, PM_PARAMETERS_NODE, 0),
.rest = NULL,
.keyword_rest = NULL,
.block = NULL,
@@ -6334,8 +5691,8 @@ pm_parameters_node_requireds_append(pm_parameters_node_t *params, pm_node_t *par
*/
static void
pm_parameters_node_optionals_append(pm_parameters_node_t *params, pm_optional_parameter_node_t *param) {
- pm_parameters_node_location_set(params, (pm_node_t *) param);
- pm_node_list_append(&params->optionals, (pm_node_t *) param);
+ pm_parameters_node_location_set(params, UP(param));
+ pm_node_list_append(&params->optionals, UP(param));
}
/**
@@ -6381,7 +5738,7 @@ pm_parameters_node_keyword_rest_set(pm_parameters_node_t *params, pm_node_t *par
static void
pm_parameters_node_block_set(pm_parameters_node_t *params, pm_block_parameter_node_t *param) {
assert(params->block == NULL);
- pm_parameters_node_location_set(params, (pm_node_t *) param);
+ pm_parameters_node_location_set(params, UP(param));
params->block = param;
}
@@ -6393,14 +5750,7 @@ pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_st
pm_program_node_t *node = PM_NODE_ALLOC(parser, pm_program_node_t);
*node = (pm_program_node_t) {
- {
- .type = PM_PROGRAM_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = statements == NULL ? parser->start : statements->base.location.start,
- .end = statements == NULL ? parser->end : statements->base.location.end
- }
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_PROGRAM_NODE, 0, statements),
.locals = *locals,
.statements = statements
};
@@ -6416,15 +5766,7 @@ pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_no
pm_parentheses_node_t *node = PM_NODE_ALLOC(parser, pm_parentheses_node_t);
*node = (pm_parentheses_node_t) {
- {
- .type = PM_PARENTHESES_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_PARENTHESES_NODE, flags, opening, closing),
.body = body,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
@@ -6441,14 +5783,7 @@ pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, con
pm_pinned_expression_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_expression_node_t);
*node = (pm_pinned_expression_node_t) {
- {
- .type = PM_PINNED_EXPRESSION_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = rparen->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_PINNED_EXPRESSION_NODE, 0, operator, rparen),
.expression = expression,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.lparen_loc = PM_LOCATION_TOKEN_VALUE(lparen),
@@ -6466,14 +5801,7 @@ pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator,
pm_pinned_variable_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_variable_node_t);
*node = (pm_pinned_variable_node_t) {
- {
- .type = PM_PINNED_VARIABLE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = variable->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_PINNED_VARIABLE_NODE, 0, operator, variable),
.variable = variable,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
};
@@ -6489,14 +5817,7 @@ pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, co
pm_post_execution_node_t *node = PM_NODE_ALLOC(parser, pm_post_execution_node_t);
*node = (pm_post_execution_node_t) {
- {
- .type = PM_POST_EXECUTION_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_POST_EXECUTION_NODE, 0, keyword, closing),
.statements = statements,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -6514,14 +5835,7 @@ pm_pre_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, con
pm_pre_execution_node_t *node = PM_NODE_ALLOC(parser, pm_pre_execution_node_t);
*node = (pm_pre_execution_node_t) {
- {
- .type = PM_PRE_EXECUTION_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_PRE_EXECUTION_NODE, 0, keyword, closing),
.statements = statements,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -6558,15 +5872,7 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope
}
*node = (pm_range_node_t) {
- {
- .type = PM_RANGE_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = (left == NULL ? operator->start : left->location.start),
- .end = (right == NULL ? operator->end : right->location.end)
- }
- },
+ .base = PM_NODE_INIT(parser, PM_RANGE_NODE, flags, (left == NULL ? operator->start : left->location.start), (right == NULL ? operator->end : right->location.end)),
.left = left,
.right = right,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -6583,11 +5889,9 @@ pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_REDO);
pm_redo_node_t *node = PM_NODE_ALLOC(parser, pm_redo_node_t);
- *node = (pm_redo_node_t) {{
- .type = PM_REDO_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_redo_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_REDO_NODE, 0, token)
+ };
return node;
}
@@ -6599,17 +5903,10 @@ pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) {
static pm_regular_expression_node_t *
pm_regular_expression_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *unescaped) {
pm_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_regular_expression_node_t);
+ pm_node_flags_t flags = pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL;
*node = (pm_regular_expression_node_t) {
- {
- .type = PM_REGULAR_EXPRESSION_NODE,
- .flags = pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = MIN(opening->start, closing->start),
- .end = MAX(opening->end, closing->end)
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_REGULAR_EXPRESSION_NODE, flags, opening, closing),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.content_loc = PM_LOCATION_TOKEN_VALUE(content),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
@@ -6635,11 +5932,7 @@ pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token)
pm_required_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_parameter_node_t);
*node = (pm_required_parameter_node_t) {
- {
- .type = PM_REQUIRED_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_REQUIRED_PARAMETER_NODE, 0, token),
.name = pm_parser_constant_id_token(parser, token)
};
@@ -6654,14 +5947,7 @@ pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const
pm_rescue_modifier_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_modifier_node_t);
*node = (pm_rescue_modifier_node_t) {
- {
- .type = PM_RESCUE_MODIFIER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = expression->location.start,
- .end = rescue_expression->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_RESCUE_MODIFIER_NODE, 0, expression, rescue_expression),
.expression = expression,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.rescue_expression = rescue_expression
@@ -6678,14 +5964,10 @@ pm_rescue_node_create(pm_parser_t *parser, const pm_token_t *keyword) {
pm_rescue_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_node_t);
*node = (pm_rescue_node_t) {
- {
- .type = PM_RESCUE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(keyword)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RESCUE_NODE, 0, keyword),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
- .operator_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .operator_loc = { 0 },
+ .then_keyword_loc = { 0 },
.reference = NULL,
.statements = NULL,
.subsequent = NULL,
@@ -6746,14 +6028,11 @@ pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, c
pm_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_rest_parameter_node_t);
*node = (pm_rest_parameter_node_t) {
- {
- .type = PM_REST_PARAMETER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end)
- }
- },
+ .base = (
+ (name->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN(parser, PM_REST_PARAMETER_NODE, 0, operator)
+ : PM_NODE_INIT_TOKENS(parser, PM_REST_PARAMETER_NODE, 0, operator, name)
+ ),
.name = pm_parser_optional_constant_id_token(parser, name),
.name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -6770,11 +6049,9 @@ pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_RETRY);
pm_retry_node_t *node = PM_NODE_ALLOC(parser, pm_retry_node_t);
- *node = (pm_retry_node_t) {{
- .type = PM_RETRY_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_retry_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RETRY_NODE, 0, token)
+ };
return node;
}
@@ -6787,14 +6064,11 @@ pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argumen
pm_return_node_t *node = PM_NODE_ALLOC(parser, pm_return_node_t);
*node = (pm_return_node_t) {
- {
- .type = PM_RETURN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = (arguments == NULL ? keyword->end : arguments->base.location.end)
- }
- },
+ .base = (
+ (arguments == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_RETURN_NODE, 0, keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_RETURN_NODE, 0, keyword, arguments)
+ ),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.arguments = arguments
};
@@ -6810,11 +6084,9 @@ pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_SELF);
pm_self_node_t *node = PM_NODE_ALLOC(parser, pm_self_node_t);
- *node = (pm_self_node_t) {{
- .type = PM_SELF_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_self_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SELF_NODE, 0, token)
+ };
return node;
}
@@ -6827,12 +6099,7 @@ pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shar
pm_shareable_constant_node_t *node = PM_NODE_ALLOC(parser, pm_shareable_constant_node_t);
*node = (pm_shareable_constant_node_t) {
- {
- .type = PM_SHAREABLE_CONSTANT_NODE,
- .flags = (pm_node_flags_t) value,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NODE_VALUE(write)
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_SHAREABLE_CONSTANT_NODE, (pm_node_flags_t) value, write),
.write = write
};
@@ -6847,14 +6114,7 @@ pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *local
pm_singleton_class_node_t *node = PM_NODE_ALLOC(parser, pm_singleton_class_node_t);
*node = (pm_singleton_class_node_t) {
- {
- .type = PM_SINGLETON_CLASS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = class_keyword->start,
- .end = end_keyword->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_SINGLETON_CLASS_NODE, 0, class_keyword, end_keyword),
.locals = *locals,
.class_keyword_loc = PM_LOCATION_TOKEN_VALUE(class_keyword),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -6874,12 +6134,9 @@ pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD___ENCODING__);
pm_source_encoding_node_t *node = PM_NODE_ALLOC(parser, pm_source_encoding_node_t);
- *node = (pm_source_encoding_node_t) {{
- .type = PM_SOURCE_ENCODING_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_source_encoding_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SOURCE_ENCODING_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -6904,12 +6161,7 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword)
}
*node = (pm_source_file_node_t) {
- {
- .type = PM_SOURCE_FILE_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(file_keyword),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SOURCE_FILE_NODE, flags, file_keyword),
.filepath = parser->filepath
};
@@ -6924,12 +6176,9 @@ pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD___LINE__);
pm_source_line_node_t *node = PM_NODE_ALLOC(parser, pm_source_line_node_t);
- *node = (pm_source_line_node_t) {{
- .type = PM_SOURCE_LINE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_source_line_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SOURCE_LINE_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -6942,14 +6191,11 @@ pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t
pm_splat_node_t *node = PM_NODE_ALLOC(parser, pm_splat_node_t);
*node = (pm_splat_node_t) {
- {
- .type = PM_SPLAT_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = operator->start,
- .end = (expression == NULL ? operator->end : expression->location.end)
- }
- },
+ .base = (
+ (expression == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_SPLAT_NODE, 0, operator)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_SPLAT_NODE, 0, operator, expression)
+ ),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.expression = expression
};
@@ -6965,11 +6211,7 @@ pm_statements_node_create(pm_parser_t *parser) {
pm_statements_node_t *node = PM_NODE_ALLOC(parser, pm_statements_node_t);
*node = (pm_statements_node_t) {
- {
- .type = PM_STATEMENTS_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_STATEMENTS_NODE, 0),
.body = { 0 }
};
@@ -7061,16 +6303,11 @@ pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening,
break;
}
+ const uint8_t *start = (opening->type == PM_TOKEN_NOT_PROVIDED ? content->start : opening->start);
+ const uint8_t *end = (closing->type == PM_TOKEN_NOT_PROVIDED ? content->end : closing->end);
+
*node = (pm_string_node_t) {
- {
- .type = PM_STRING_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = (opening->type == PM_TOKEN_NOT_PROVIDED ? content->start : opening->start),
- .end = (closing->type == PM_TOKEN_NOT_PROVIDED ? content->end : closing->end)
- }
- },
+ .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, start, end),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.content_loc = PM_LOCATION_TOKEN_VALUE(content),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7113,14 +6350,7 @@ pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
}
*node = (pm_super_node_t) {
- {
- .type = PM_SUPER_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = end,
- }
- },
+ .base = PM_NODE_INIT(parser, PM_SUPER_NODE, 0, keyword->start, end),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.lparen_loc = arguments->opening_loc,
.arguments = arguments->arguments,
@@ -7349,16 +6579,11 @@ static pm_symbol_node_t *
pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing, const pm_string_t *unescaped, pm_node_flags_t flags) {
pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t);
+ const uint8_t *start = (opening->type == PM_TOKEN_NOT_PROVIDED ? value->start : opening->start);
+ const uint8_t *end = (closing->type == PM_TOKEN_NOT_PROVIDED ? value->end : closing->end);
+
*node = (pm_symbol_node_t) {
- {
- .type = PM_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL | flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = (opening->type == PM_TOKEN_NOT_PROVIDED ? value->start : opening->start),
- .end = (closing->type == PM_TOKEN_NOT_PROVIDED ? value->end : closing->end)
- }
- },
+ .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | flags, start, end),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.value_loc = PM_LOCATION_TOKEN_VALUE(value),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7403,7 +6628,7 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) {
assert((label.end - label.start) >= 0);
pm_string_shared_init(&node->unescaped, label.start, label.end);
- pm_node_flag_set((pm_node_t *) node, parse_symbol_encoding(parser, &label, &node->unescaped, false));
+ pm_node_flag_set(UP(node), parse_symbol_encoding(parser, &label, &node->unescaped, false));
break;
}
@@ -7432,12 +6657,7 @@ pm_symbol_node_synthesized_create(pm_parser_t *parser, const char *content) {
pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t);
*node = (pm_symbol_node_t) {
- {
- .type = PM_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING),
.value_loc = PM_LOCATION_NULL_VALUE(parser),
.unescaped = { 0 }
};
@@ -7475,15 +6695,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const
pm_symbol_node_t *new_node = PM_NODE_ALLOC(parser, pm_symbol_node_t);
*new_node = (pm_symbol_node_t) {
- {
- .type = PM_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.value_loc = node->content_loc,
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7491,7 +6703,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const
};
pm_token_t content = { .type = PM_TOKEN_IDENTIFIER, .start = node->content_loc.start, .end = node->content_loc.end };
- pm_node_flag_set((pm_node_t *) new_node, parse_symbol_encoding(parser, &content, &node->unescaped, true));
+ pm_node_flag_set(UP(new_node), parse_symbol_encoding(parser, &content, &node->unescaped, true));
// We are explicitly _not_ using pm_node_destroy here because we don't want
// to trash the unescaped string. We could instead copy the string if we
@@ -7519,12 +6731,7 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) {
}
*new_node = (pm_string_node_t) {
- {
- .type = PM_STRING_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = node->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_STRING_NODE, flags, node),
.opening_loc = node->opening_loc,
.content_loc = node->value_loc,
.closing_loc = node->closing_loc,
@@ -7547,12 +6754,9 @@ pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_TRUE);
pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t);
- *node = (pm_true_node_t) {{
- .type = PM_TRUE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_true_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -7564,12 +6768,9 @@ static pm_true_node_t *
pm_true_node_synthesized_create(pm_parser_t *parser) {
pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t);
- *node = (pm_true_node_t) {{
- .type = PM_TRUE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = { .start = parser->start, .end = parser->end }
- }};
+ *node = (pm_true_node_t) {
+ .base = PM_NODE_INIT_BASE(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL)
+ };
return node;
}
@@ -7583,11 +6784,7 @@ pm_undef_node_create(pm_parser_t *parser, const pm_token_t *token) {
pm_undef_node_t *node = PM_NODE_ALLOC(parser, pm_undef_node_t);
*node = (pm_undef_node_t) {
- {
- .type = PM_UNDEF_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_TOKEN_VALUE(token),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_UNDEF_NODE, 0, token),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(token),
.names = { 0 }
};
@@ -7610,31 +6807,18 @@ pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) {
static pm_unless_node_t *
pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements) {
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
- pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t);
- const uint8_t *end;
- if (statements != NULL) {
- end = statements->base.location.end;
- } else {
- end = predicate->location.end;
- }
+ pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t);
+ pm_node_t *end = statements == NULL ? predicate : UP(statements);
*node = (pm_unless_node_t) {
- {
- .type = PM_UNLESS_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, keyword, end),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.predicate = predicate,
.then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
.statements = statements,
.else_clause = NULL,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .end_keyword_loc = { 0 }
};
return node;
@@ -7652,21 +6836,13 @@ pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const
pm_statements_node_body_append(parser, statements, statement, true);
*node = (pm_unless_node_t) {
- {
- .type = PM_UNLESS_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = statement->location.start,
- .end = predicate->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, statement, predicate),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(unless_keyword),
.predicate = predicate,
- .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .then_keyword_loc = { 0 },
.statements = statements,
.else_clause = NULL,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .end_keyword_loc = { 0 }
};
return node;
@@ -7710,15 +6886,7 @@ pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
*node = (pm_until_node_t) {
- {
- .type = PM_UNTIL_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = closing->end,
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_UNTIL_NODE, flags, keyword, closing),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.do_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(do_keyword),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7739,18 +6907,10 @@ pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm
pm_loop_modifier_block_exits(parser, statements);
*node = (pm_until_node_t) {
- {
- .type = PM_UNTIL_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = statements->base.location.start,
- .end = predicate->location.end,
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_UNTIL_NODE, flags, statements, predicate),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
- .do_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .do_keyword_loc = { 0 },
+ .closing_loc = { 0 },
.predicate = predicate,
.statements = statements
};
@@ -7766,17 +6926,10 @@ pm_when_node_create(pm_parser_t *parser, const pm_token_t *keyword) {
pm_when_node_t *node = PM_NODE_ALLOC(parser, pm_when_node_t);
*node = (pm_when_node_t) {
- {
- .type = PM_WHEN_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = NULL
- }
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_WHEN_NODE, 0, keyword),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.statements = NULL,
- .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .then_keyword_loc = { 0 },
.conditions = { 0 }
};
@@ -7822,15 +6975,7 @@ pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
*node = (pm_while_node_t) {
- {
- .type = PM_WHILE_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_WHILE_NODE, flags, keyword, closing),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.do_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(do_keyword),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7851,18 +6996,10 @@ pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm
pm_loop_modifier_block_exits(parser, statements);
*node = (pm_while_node_t) {
- {
- .type = PM_WHILE_NODE,
- .flags = flags,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = statements->base.location.start,
- .end = predicate->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_WHILE_NODE, flags, statements, predicate),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
- .do_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .do_keyword_loc = { 0 },
+ .closing_loc = { 0 },
.predicate = predicate,
.statements = statements
};
@@ -7878,11 +7015,7 @@ pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_s
pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t);
*node = (pm_while_node_t) {
- {
- .type = PM_WHILE_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_WHILE_NODE, 0),
.keyword_loc = PM_LOCATION_NULL_VALUE(parser),
.do_keyword_loc = PM_LOCATION_NULL_VALUE(parser),
.closing_loc = PM_LOCATION_NULL_VALUE(parser),
@@ -7902,15 +7035,7 @@ pm_xstring_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening,
pm_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_x_string_node_t);
*node = (pm_x_string_node_t) {
- {
- .type = PM_X_STRING_NODE,
- .flags = PM_STRING_FLAGS_FROZEN,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_X_STRING_NODE, PM_STRING_FLAGS_FROZEN, opening, closing),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.content_loc = PM_LOCATION_TOKEN_VALUE(content),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
@@ -7947,14 +7072,7 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo
}
*node = (pm_yield_node_t) {
- {
- .type = PM_YIELD_NODE,
- .node_id = PM_NODE_IDENTIFY(parser),
- .location = {
- .start = keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_YIELD_NODE, 0, keyword->start, end),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.lparen_loc = *lparen_loc,
.arguments = arguments,
@@ -7964,9 +7082,6 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo
return node;
}
-#undef PM_NODE_ALLOC
-#undef PM_NODE_IDENTIFY
-
/**
* Check if any of the currently visible scopes contain a local variable
* described by the given constant id.
@@ -8429,7 +7544,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
if (*cursor == '\\' && (cursor + 1 < end)) cursor++;
}
value_end = cursor;
- if (*cursor == '"') cursor++;
+ if (cursor < end && *cursor == '"') cursor++;
} else {
value_start = cursor;
while (cursor < end && *cursor != '"' && *cursor != ';' && !pm_char_is_whitespace(*cursor)) cursor++;
@@ -8582,85 +7697,67 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
/* Context manipulations */
/******************************************************************************/
-static bool
-context_terminator(pm_context_t context, pm_token_t *token) {
- switch (context) {
- case PM_CONTEXT_MAIN:
- case PM_CONTEXT_DEF_PARAMS:
- case PM_CONTEXT_DEFINED:
- case PM_CONTEXT_MULTI_TARGET:
- case PM_CONTEXT_TERNARY:
- case PM_CONTEXT_RESCUE_MODIFIER:
- return token->type == PM_TOKEN_EOF;
- case PM_CONTEXT_DEFAULT_PARAMS:
- return token->type == PM_TOKEN_COMMA || token->type == PM_TOKEN_PARENTHESIS_RIGHT;
- case PM_CONTEXT_PREEXE:
- case PM_CONTEXT_POSTEXE:
- return token->type == PM_TOKEN_BRACE_RIGHT;
- case PM_CONTEXT_MODULE:
- case PM_CONTEXT_CLASS:
- case PM_CONTEXT_SCLASS:
- case PM_CONTEXT_LAMBDA_DO_END:
- case PM_CONTEXT_DEF:
- case PM_CONTEXT_BLOCK_KEYWORDS:
- return token->type == PM_TOKEN_KEYWORD_END || token->type == PM_TOKEN_KEYWORD_RESCUE || token->type == PM_TOKEN_KEYWORD_ENSURE;
- case PM_CONTEXT_WHILE:
- case PM_CONTEXT_UNTIL:
- case PM_CONTEXT_ELSE:
- case PM_CONTEXT_FOR:
- case PM_CONTEXT_BEGIN_ENSURE:
- case PM_CONTEXT_BLOCK_ENSURE:
- case PM_CONTEXT_CLASS_ENSURE:
- case PM_CONTEXT_DEF_ENSURE:
- case PM_CONTEXT_LAMBDA_ENSURE:
- case PM_CONTEXT_MODULE_ENSURE:
- case PM_CONTEXT_SCLASS_ENSURE:
- return token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_LOOP_PREDICATE:
- return token->type == PM_TOKEN_KEYWORD_DO || token->type == PM_TOKEN_KEYWORD_THEN;
- case PM_CONTEXT_FOR_INDEX:
- return token->type == PM_TOKEN_KEYWORD_IN;
- case PM_CONTEXT_CASE_WHEN:
- return token->type == PM_TOKEN_KEYWORD_WHEN || token->type == PM_TOKEN_KEYWORD_END || token->type == PM_TOKEN_KEYWORD_ELSE;
- case PM_CONTEXT_CASE_IN:
- return token->type == PM_TOKEN_KEYWORD_IN || token->type == PM_TOKEN_KEYWORD_END || token->type == PM_TOKEN_KEYWORD_ELSE;
- case PM_CONTEXT_IF:
- case PM_CONTEXT_ELSIF:
- return token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_ELSIF || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_UNLESS:
- return token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_EMBEXPR:
- return token->type == PM_TOKEN_EMBEXPR_END;
- case PM_CONTEXT_BLOCK_BRACES:
- return token->type == PM_TOKEN_BRACE_RIGHT;
- case PM_CONTEXT_PARENS:
- return token->type == PM_TOKEN_PARENTHESIS_RIGHT;
- case PM_CONTEXT_BEGIN:
- case PM_CONTEXT_BEGIN_RESCUE:
- case PM_CONTEXT_BLOCK_RESCUE:
- case PM_CONTEXT_CLASS_RESCUE:
- case PM_CONTEXT_DEF_RESCUE:
- case PM_CONTEXT_LAMBDA_RESCUE:
- case PM_CONTEXT_MODULE_RESCUE:
- case PM_CONTEXT_SCLASS_RESCUE:
- return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_RESCUE || token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_BEGIN_ELSE:
- case PM_CONTEXT_BLOCK_ELSE:
- case PM_CONTEXT_CLASS_ELSE:
- case PM_CONTEXT_DEF_ELSE:
- case PM_CONTEXT_LAMBDA_ELSE:
- case PM_CONTEXT_MODULE_ELSE:
- case PM_CONTEXT_SCLASS_ELSE:
- return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_LAMBDA_BRACES:
- return token->type == PM_TOKEN_BRACE_RIGHT;
- case PM_CONTEXT_PREDICATE:
- return token->type == PM_TOKEN_KEYWORD_THEN || token->type == PM_TOKEN_NEWLINE || token->type == PM_TOKEN_SEMICOLON;
- case PM_CONTEXT_NONE:
- return false;
- }
+static const uint32_t context_terminators[] = {
+ [PM_CONTEXT_NONE] = 0,
+ [PM_CONTEXT_BEGIN] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BEGIN_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BEGIN_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BEGIN_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BLOCK_BRACES] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_BLOCK_KEYWORDS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_BLOCK_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BLOCK_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BLOCK_PARAMETERS] = (1U << PM_TOKEN_PIPE),
+ [PM_CONTEXT_BLOCK_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_CASE_WHEN] = (1U << PM_TOKEN_KEYWORD_WHEN) | (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_ELSE),
+ [PM_CONTEXT_CASE_IN] = (1U << PM_TOKEN_KEYWORD_IN) | (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_ELSE),
+ [PM_CONTEXT_CLASS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_CLASS_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_CLASS_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_CLASS_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_DEF_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF_PARAMS] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_DEFINED] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_DEFAULT_PARAMS] = (1U << PM_TOKEN_COMMA) | (1U << PM_TOKEN_PARENTHESIS_RIGHT),
+ [PM_CONTEXT_ELSE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_ELSIF] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_ELSIF) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_EMBEXPR] = (1U << PM_TOKEN_EMBEXPR_END),
+ [PM_CONTEXT_FOR] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_FOR_INDEX] = (1U << PM_TOKEN_KEYWORD_IN),
+ [PM_CONTEXT_IF] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_ELSIF) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LAMBDA_BRACES] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_LAMBDA_DO_END] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_LAMBDA_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LAMBDA_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LAMBDA_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LOOP_PREDICATE] = (1U << PM_TOKEN_KEYWORD_DO) | (1U << PM_TOKEN_KEYWORD_THEN),
+ [PM_CONTEXT_MAIN] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_MODULE] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_MODULE_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_MODULE_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_MODULE_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_MULTI_TARGET] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_PARENS] = (1U << PM_TOKEN_PARENTHESIS_RIGHT),
+ [PM_CONTEXT_POSTEXE] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_PREDICATE] = (1U << PM_TOKEN_KEYWORD_THEN) | (1U << PM_TOKEN_NEWLINE) | (1U << PM_TOKEN_SEMICOLON),
+ [PM_CONTEXT_PREEXE] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_RESCUE_MODIFIER] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_SCLASS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_SCLASS_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_SCLASS_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_SCLASS_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_TERNARY] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_UNLESS] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_UNTIL] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_WHILE] = (1U << PM_TOKEN_KEYWORD_END),
+};
- return false;
+static inline bool
+context_terminator(pm_context_t context, pm_token_t *token) {
+ return token->type < 32 && (context_terminators[context] & (1U << token->type));
}
/**
@@ -8761,6 +7858,7 @@ context_human(pm_context_t context) {
case PM_CONTEXT_BEGIN: return "begin statement";
case PM_CONTEXT_BLOCK_BRACES: return "'{'..'}' block";
case PM_CONTEXT_BLOCK_KEYWORDS: return "'do'..'end' block";
+ case PM_CONTEXT_BLOCK_PARAMETERS: return "'|'..'|' block parameter";
case PM_CONTEXT_CASE_WHEN: return "'when' clause";
case PM_CONTEXT_CASE_IN: return "'in' clause";
case PM_CONTEXT_CLASS: return "class definition";
@@ -9109,7 +8207,7 @@ lex_global_variable(pm_parser_t *parser) {
} while ((width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end)) > 0);
// $0 isn't allowed to be followed by anything.
- pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
+ pm_diagnostic_id_t diag_id = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->current, diag_id);
}
@@ -9146,7 +8244,7 @@ lex_global_variable(pm_parser_t *parser) {
} else {
// If we get here, then we have a $ followed by something that
// isn't recognized as a global variable.
- pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
+ pm_diagnostic_id_t diag_id = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
const uint8_t *end = parser->current.end + parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
PM_PARSER_ERR_FORMAT(parser, parser->current.start, end, diag_id, (int) (end - parser->current.start), (const char *) parser->current.start);
}
@@ -9519,7 +8617,7 @@ escape_hexadecimal_digit(const uint8_t value) {
* validated.
*/
static inline uint32_t
-escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length) {
+escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const pm_location_t *error_location) {
uint32_t value = 0;
for (size_t index = 0; index < length; index++) {
if (index != 0) value <<= 4;
@@ -9529,7 +8627,11 @@ escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length) {
// Here we're going to verify that the value is actually a valid Unicode
// codepoint and not a surrogate pair.
if (value >= 0xD800 && value <= 0xDFFF) {
- pm_parser_err(parser, string, string + length, PM_ERR_ESCAPE_INVALID_UNICODE);
+ if (error_location != NULL) {
+ pm_parser_err(parser, error_location->start, error_location->end, PM_ERR_ESCAPE_INVALID_UNICODE);
+ } else {
+ pm_parser_err(parser, string, string + length, PM_ERR_ESCAPE_INVALID_UNICODE);
+ }
return 0xFFFD;
}
@@ -9829,7 +8931,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
extra_codepoints_start = unicode_start;
}
- uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length);
+ uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length, NULL);
escape_write_unicode(parser, buffer, flags, unicode_start, parser->current.end, value);
parser->current.end += pm_strspn_inline_whitespace(parser->current.end, parser->end - parser->current.end);
@@ -9870,7 +8972,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
PM_PARSER_ERR_FORMAT(parser, start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_SHORT, 2, start);
}
} else if (length == 4) {
- uint32_t value = escape_unicode(parser, parser->current.end, 4);
+ uint32_t value = escape_unicode(parser, parser->current.end, 4, NULL);
if (flags & PM_ESCAPE_FLAG_REGEXP) {
pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end + 4 - start));
@@ -10173,7 +9275,7 @@ lex_at_variable(pm_parser_t *parser) {
}
} else if (parser->current.end < end && pm_char_is_decimal_digit(*parser->current.end)) {
pm_diagnostic_id_t diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_INCOMPLETE_VARIABLE_CLASS : PM_ERR_INCOMPLETE_VARIABLE_INSTANCE;
- if (parser->version == PM_OPTIONS_VERSION_CRUBY_3_3) {
+ if (parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3) {
diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_INCOMPLETE_VARIABLE_CLASS_3_3 : PM_ERR_INCOMPLETE_VARIABLE_INSTANCE_3_3;
}
@@ -10849,14 +9951,37 @@ parser_lex(pm_parser_t *parser) {
following = next_newline(following, parser->end - following);
}
- // If the lex state was ignored, or we hit a '.' or a '&.',
- // we will lex the ignored newline
+ // If the lex state was ignored, we will lex the
+ // ignored newline.
+ if (lex_state_ignored_p(parser)) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lexed_comment = false;
+ goto lex_next_token;
+ }
+
+ // If we hit a '.' or a '&.' we will lex the ignored
+ // newline.
+ if (following && (
+ (peek_at(parser, following) == '.') ||
+ (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '.')
+ )) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lexed_comment = false;
+ goto lex_next_token;
+ }
+
+
+ // If we are parsing as CRuby 4.0 or later and we
+ // hit a '&&' or a '||' then we will lex the ignored
+ // newline.
if (
- lex_state_ignored_p(parser) ||
- (following && (
- (peek_at(parser, following) == '.') ||
- (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '.')
- ))
+ (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) &&
+ following && (
+ (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '&') ||
+ (peek_at(parser, following) == '|' && peek_at(parser, following + 1) == '|') ||
+ (peek_at(parser, following) == 'a' && peek_at(parser, following + 1) == 'n' && peek_at(parser, following + 2) == 'd' && !char_is_identifier(parser, following + 3, parser->end - (following + 3))) ||
+ (peek_at(parser, following) == 'o' && peek_at(parser, following + 1) == 'r' && !char_is_identifier(parser, following + 2, parser->end - (following + 2)))
+ )
) {
if (!lexed_comment) parser_lex_ignored_newline(parser);
lexed_comment = false;
@@ -10896,6 +10021,63 @@ parser_lex(pm_parser_t *parser) {
parser->next_start = NULL;
LEX(PM_TOKEN_AMPERSAND_DOT);
}
+
+ if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) {
+ // If we hit an && then we are in a logical chain
+ // and we need to return the logical operator.
+ if (peek_at(parser, next_content) == '&' && peek_at(parser, next_content + 1) == '&') {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 2;
+ parser->next_start = NULL;
+ LEX(PM_TOKEN_AMPERSAND_AMPERSAND);
+ }
+
+ // If we hit a || then we are in a logical chain and
+ // we need to return the logical operator.
+ if (peek_at(parser, next_content) == '|' && peek_at(parser, next_content + 1) == '|') {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 2;
+ parser->next_start = NULL;
+ LEX(PM_TOKEN_PIPE_PIPE);
+ }
+
+ // If we hit an 'and' then we are in a logical chain
+ // and we need to return the logical operator.
+ if (
+ peek_at(parser, next_content) == 'a' &&
+ peek_at(parser, next_content + 1) == 'n' &&
+ peek_at(parser, next_content + 2) == 'd' &&
+ !char_is_identifier(parser, next_content + 3, parser->end - (next_content + 3))
+ ) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 3;
+ parser->next_start = NULL;
+ parser->command_start = true;
+ LEX(PM_TOKEN_KEYWORD_AND);
+ }
+
+ // If we hit a 'or' then we are in a logical chain
+ // and we need to return the logical operator.
+ if (
+ peek_at(parser, next_content) == 'o' &&
+ peek_at(parser, next_content + 1) == 'r' &&
+ !char_is_identifier(parser, next_content + 2, parser->end - (next_content + 2))
+ ) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 2;
+ parser->next_start = NULL;
+ parser->command_start = true;
+ LEX(PM_TOKEN_KEYWORD_OR);
+ }
+ }
}
// At this point we know this is a regular newline, and we can set the
@@ -12170,7 +11352,13 @@ parser_lex(pm_parser_t *parser) {
size_t eol_length = match_eol_at(parser, breakpoint);
if (eol_length) {
parser->current.end = breakpoint + eol_length;
- pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+
+ // Track the newline if we're not in a heredoc that
+ // would have already have added the newline to the
+ // list.
+ if (parser->heredoc_end == NULL) {
+ pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+ }
} else {
parser->current.end = breakpoint + 1;
}
@@ -12424,7 +11612,13 @@ parser_lex(pm_parser_t *parser) {
size_t eol_length = match_eol_at(parser, breakpoint);
if (eol_length) {
parser->current.end = breakpoint + eol_length;
- pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+
+ // Track the newline if we're not in a heredoc that
+ // would have already have added the newline to the
+ // list.
+ if (parser->heredoc_end == NULL) {
+ pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+ }
} else {
parser->current.end = breakpoint + 1;
}
@@ -12436,6 +11630,13 @@ parser_lex(pm_parser_t *parser) {
LEX(PM_TOKEN_LABEL_END);
}
+ // When the delimiter itself is a newline, we won't
+ // get a chance to flush heredocs in the usual places since
+ // the newline is already consumed.
+ if (term == '\n' && parser->heredoc_end) {
+ parser_flush_heredoc_end(parser);
+ }
+
lex_state_set(parser, PM_LEX_STATE_END);
lex_mode_pop(parser);
LEX(PM_TOKEN_STRING_END);
@@ -12841,7 +12042,10 @@ parser_lex(pm_parser_t *parser) {
// string content.
if (heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE) {
const uint8_t *end = parser->current.end;
- pm_newline_list_append(&parser->newline_list, end);
+
+ if (parser->heredoc_end == NULL) {
+ pm_newline_list_append(&parser->newline_list, end);
+ }
// Here we want the buffer to only
// include up to the backslash.
@@ -13143,14 +12347,6 @@ match8(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2,
}
/**
- * Returns true if the current token is any of the nine given types.
- */
-static inline bool
-match9(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_token_type_t type4, pm_token_type_t type5, pm_token_type_t type6, pm_token_type_t type7, pm_token_type_t type8, pm_token_type_t type9) {
- return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6) || match1(parser, type7) || match1(parser, type8) || match1(parser, type9);
-}
-
-/**
* If the current token is of the specified type, lex forward by one token and
* return true. Otherwise, return false. For example:
*
@@ -13230,6 +12426,22 @@ expect1_heredoc_term(pm_parser_t *parser, const uint8_t *ident_start, size_t ide
}
}
+/**
+ * A special expect1 that attaches the error to the opening token location
+ * rather than the current position. This is useful for errors about missing
+ * closing tokens, where we want to point to the line with the opening token
+ * (e.g., `def`, `class`, `if`, `{`) rather than the end of the file.
+ */
+static void
+expect1_opening(pm_parser_t *parser, pm_token_type_t type, pm_diagnostic_id_t diag_id, const pm_token_t *opening) {
+ if (accept1(parser, type)) return;
+
+ pm_parser_err(parser, opening->start, opening->end, diag_id);
+
+ parser->previous.start = parser->previous.end;
+ parser->previous.type = PM_TOKEN_MISSING;
+}
+
static pm_node_t *
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth);
@@ -13327,12 +12539,87 @@ parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power,
if (accept1(parser, PM_TOKEN_USTAR)) {
pm_token_t operator = parser->previous;
pm_node_t *expression = parse_value_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
+ return UP(pm_splat_node_create(parser, &operator, expression));
}
return parse_value_expression(parser, binding_power, accepts_command_call, false, diag_id, depth);
}
+static bool
+pm_node_unreference_each(const pm_node_t *node, void *data) {
+ switch (PM_NODE_TYPE(node)) {
+ /* When we are about to destroy a set of nodes that could potentially
+ * contain block exits for the current scope, we need to check if they
+ * are contained in the list of block exits and remove them if they are.
+ */
+ case PM_BREAK_NODE:
+ case PM_NEXT_NODE:
+ case PM_REDO_NODE: {
+ pm_parser_t *parser = (pm_parser_t *) data;
+ size_t index = 0;
+
+ while (index < parser->current_block_exits->size) {
+ pm_node_t *block_exit = parser->current_block_exits->nodes[index];
+
+ if (block_exit == node) {
+ if (index + 1 < parser->current_block_exits->size) {
+ memmove(
+ &parser->current_block_exits->nodes[index],
+ &parser->current_block_exits->nodes[index + 1],
+ (parser->current_block_exits->size - index - 1) * sizeof(pm_node_t *)
+ );
+ }
+ parser->current_block_exits->size--;
+
+ /* Note returning true here because these nodes could have
+ * arguments that are themselves block exits. */
+ return true;
+ }
+
+ index++;
+ }
+
+ return true;
+ }
+ /* When an implicit local variable is written to or targeted, it becomes
+ * a regular, named local variable. This branch removes it from the list
+ * of implicit parameters when that happens. */
+ case PM_LOCAL_VARIABLE_READ_NODE:
+ case PM_IT_LOCAL_VARIABLE_READ_NODE: {
+ pm_parser_t *parser = (pm_parser_t *) data;
+ pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters;
+
+ for (size_t index = 0; index < implicit_parameters->size; index++) {
+ if (implicit_parameters->nodes[index] == node) {
+ /* If the node is not the last one in the list, we need to
+ * shift the remaining nodes down to fill the gap. This is
+ * extremely unlikely to happen. */
+ if (index != implicit_parameters->size - 1) {
+ memmove(&implicit_parameters->nodes[index], &implicit_parameters->nodes[index + 1], (implicit_parameters->size - index - 1) * sizeof(pm_node_t *));
+ }
+
+ implicit_parameters->size--;
+ break;
+ }
+ }
+
+ return false;
+ }
+ default:
+ return true;
+ }
+}
+
+/**
+ * When we are about to destroy a set of nodes that could potentially be
+ * referenced by one or more lists on the parser, then remove them from those
+ * lists so we don't get a use-after-free.
+ */
+static void
+pm_node_unreference(pm_parser_t *parser, const pm_node_t *node) {
+ pm_visit_node(node, pm_node_unreference_each, parser);
+}
+
/**
* Convert the name of a method into the corresponding write method name. For
* example, foo would be turned into foo=.
@@ -13380,31 +12667,7 @@ parse_unwriteable_target(pm_parser_t *parser, pm_node_t *target) {
pm_local_variable_target_node_t *result = pm_local_variable_target_node_create(parser, &target->location, name, 0);
pm_node_destroy(parser, target);
- return (pm_node_t *) result;
-}
-
-/**
- * When an implicit local variable is written to or targeted, it becomes a
- * regular, named local variable. This function removes it from the list of
- * implicit parameters when that happens.
- */
-static void
-parse_target_implicit_parameter(pm_parser_t *parser, pm_node_t *node) {
- pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters;
-
- for (size_t index = 0; index < implicit_parameters->size; index++) {
- if (implicit_parameters->nodes[index] == node) {
- // If the node is not the last one in the list, we need to shift the
- // remaining nodes down to fill the gap. This is extremely unlikely
- // to happen.
- if (index != implicit_parameters->size - 1) {
- memcpy(&implicit_parameters->nodes[index], &implicit_parameters->nodes[index + 1], (implicit_parameters->size - index - 1) * sizeof(pm_node_t *));
- }
-
- implicit_parameters->size--;
- break;
- }
- }
+ return UP(result);
}
/**
@@ -13464,7 +12727,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p
case PM_LOCAL_VARIABLE_READ_NODE: {
if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) {
PM_PARSER_ERR_FORMAT(parser, target->location.start, target->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, target->location.start);
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
}
const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) target;
@@ -13479,9 +12742,9 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p
}
case PM_IT_LOCAL_VARIABLE_READ_NODE: {
pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2);
- pm_node_t *node = (pm_node_t *) pm_local_variable_target_node_create(parser, &target->location, name, 0);
+ pm_node_t *node = UP(pm_local_variable_target_node_create(parser, &target->location, name, 0));
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
pm_node_destroy(parser, target);
return node;
@@ -13505,7 +12768,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p
splat->expression = parse_target(parser, splat->expression, multiple, true);
}
- return (pm_node_t *) splat;
+ return UP(splat);
}
case PM_CALL_NODE: {
pm_call_node_t *call = (pm_call_node_t *) target;
@@ -13536,16 +12799,16 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p
pm_constant_id_t name = pm_parser_local_add_location(parser, message_loc.start, message_loc.end, 0);
pm_node_destroy(parser, target);
- return (pm_node_t *) pm_local_variable_target_node_create(parser, &message_loc, name, 0);
+ return UP(pm_local_variable_target_node_create(parser, &message_loc, name, 0));
}
- if (*call->message_loc.start == '_' || parser->encoding->alnum_char(call->message_loc.start, call->message_loc.end - call->message_loc.start)) {
+ if (peek_at(parser, call->message_loc.start) == '_' || parser->encoding->alnum_char(call->message_loc.start, call->message_loc.end - call->message_loc.start)) {
if (multiple && PM_NODE_FLAG_P(call, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
pm_parser_err_node(parser, (const pm_node_t *) call, PM_ERR_UNEXPECTED_SAFE_NAVIGATION);
}
parse_write_name(parser, &call->name);
- return (pm_node_t *) pm_call_target_node_create(parser, call);
+ return UP(pm_call_target_node_create(parser, call));
}
}
@@ -13553,7 +12816,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p
// an aref expression, and we can transform it into an aset
// expression.
if (PM_NODE_FLAG_P(call, PM_CALL_NODE_FLAGS_INDEX)) {
- return (pm_node_t *) pm_index_target_node_create(parser, call);
+ return UP(pm_index_target_node_create(parser, call));
}
}
PRISM_FALLTHROUGH
@@ -13596,7 +12859,7 @@ parse_shareable_constant_write(pm_parser_t *parser, pm_node_t *write) {
pm_shareable_constant_value_t shareable_constant = pm_parser_scope_shareable_constant_get(parser);
if (shareable_constant != PM_SCOPE_SHAREABLE_CONSTANT_NONE) {
- return (pm_node_t *) pm_shareable_constant_node_create(parser, write, shareable_constant);
+ return UP(pm_shareable_constant_node_create(parser, write, shareable_constant));
}
return write;
@@ -13614,10 +12877,10 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
case PM_CLASS_VARIABLE_READ_NODE: {
pm_class_variable_write_node_t *node = pm_class_variable_write_node_create(parser, (pm_class_variable_read_node_t *) target, operator, value);
pm_node_destroy(parser, target);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_CONSTANT_PATH_NODE: {
- pm_node_t *node = (pm_node_t *) pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value);
+ pm_node_t *node = UP(pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value));
if (context_def_p(parser)) {
pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_IN_METHOD);
@@ -13626,7 +12889,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
return parse_shareable_constant_write(parser, node);
}
case PM_CONSTANT_READ_NODE: {
- pm_node_t *node = (pm_node_t *) pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value);
+ pm_node_t *node = UP(pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value));
if (context_def_p(parser)) {
pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_IN_METHOD);
@@ -13642,7 +12905,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
case PM_GLOBAL_VARIABLE_READ_NODE: {
pm_global_variable_write_node_t *node = pm_global_variable_write_node_create(parser, target, operator, value);
pm_node_destroy(parser, target);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_LOCAL_VARIABLE_READ_NODE: {
pm_local_variable_read_node_t *local_read = (pm_local_variable_read_node_t *) target;
@@ -13656,30 +12919,30 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) {
pm_diagnostic_id_t diag_id = (scope->parameters & PM_SCOPE_PARAMETERS_NUMBERED_FOUND) ? PM_ERR_EXPRESSION_NOT_WRITABLE_NUMBERED : PM_ERR_PARAMETER_NUMBERED_RESERVED;
PM_PARSER_ERR_FORMAT(parser, target->location.start, target->location.end, diag_id, target->location.start);
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
}
pm_locals_unread(&scope->locals, name);
pm_node_destroy(parser, target);
- return (pm_node_t *) pm_local_variable_write_node_create(parser, name, depth, value, &name_loc, operator);
+ return UP(pm_local_variable_write_node_create(parser, name, depth, value, &name_loc, operator));
}
case PM_IT_LOCAL_VARIABLE_READ_NODE: {
pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2);
- pm_node_t *node = (pm_node_t *) pm_local_variable_write_node_create(parser, name, 0, value, &target->location, operator);
+ pm_node_t *node = UP(pm_local_variable_write_node_create(parser, name, 0, value, &target->location, operator));
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
pm_node_destroy(parser, target);
return node;
}
case PM_INSTANCE_VARIABLE_READ_NODE: {
- pm_node_t *write_node = (pm_node_t *) pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value);
+ pm_node_t *write_node = UP(pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value));
pm_node_destroy(parser, target);
return write_node;
}
case PM_MULTI_TARGET_NODE:
- return (pm_node_t *) pm_multi_write_node_create(parser, (pm_multi_target_node_t *) target, operator, value);
+ return UP(pm_multi_write_node_create(parser, (pm_multi_target_node_t *) target, operator, value));
case PM_SPLAT_NODE: {
pm_splat_node_t *splat = (pm_splat_node_t *) target;
@@ -13688,9 +12951,9 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
}
pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser);
- pm_multi_target_node_targets_append(parser, multi_target, (pm_node_t *) splat);
+ pm_multi_target_node_targets_append(parser, multi_target, UP(splat));
- return (pm_node_t *) pm_multi_write_node_create(parser, multi_target, operator, value);
+ return UP(pm_multi_write_node_create(parser, multi_target, operator, value));
}
case PM_CALL_NODE: {
pm_call_node_t *call = (pm_call_node_t *) target;
@@ -13722,7 +12985,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
pm_node_destroy(parser, target);
pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, message.start, message.end);
- target = (pm_node_t *) pm_local_variable_write_node_create(parser, constant_id, 0, value, &message, operator);
+ target = UP(pm_local_variable_write_node_create(parser, constant_id, 0, value, &message, operator));
pm_refute_numbered_parameter(parser, message.start, message.end);
return target;
@@ -13744,11 +13007,12 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
pm_arguments_node_arguments_append(arguments, value);
call->base.location.end = arguments->base.location.end;
+ call->equal_loc = PM_LOCATION_TOKEN_VALUE(operator);
parse_write_name(parser, &call->name);
- pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY));
+ pm_node_flag_set(UP(call), PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY));
- return (pm_node_t *) call;
+ return UP(call);
}
}
@@ -13765,19 +13029,26 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
// Replace the name with "[]=".
call->name = pm_parser_constant_id_constant(parser, "[]=", 3);
+ call->equal_loc = PM_LOCATION_TOKEN_VALUE(operator);
// Ensure that the arguments for []= don't contain keywords
pm_index_arguments_check(parser, call->arguments, call->block);
- pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY));
+ pm_node_flag_set(UP(call), PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY));
return target;
}
- // If there are arguments on the call node, then it can't be a method
- // call ending with = or a local variable write, so it must be a
- // syntax error. In this case we'll fall through to our default
+ // If there are arguments on the call node, then it can't be a
+ // method call ending with = or a local variable write, so it must
+ // be a syntax error. In this case we'll fall through to our default
// handling. We need to free the value that we parsed because there
// is no way for us to attach it to the tree at this point.
+ //
+ // Since it is possible for the value to contain an implicit
+ // parameter somewhere in its subtree, we need to walk it and remove
+ // any implicit parameters from the list of implicit parameters for
+ // the current scope.
+ pm_node_unreference(parser, value);
pm_node_destroy(parser, value);
}
PRISM_FALLTHROUGH
@@ -13813,7 +13084,7 @@ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t
pm_local_variable_write_node_t *result = pm_local_variable_write_node_create(parser, name, 0, value, &target->location, equals);
pm_node_destroy(parser, target);
- return (pm_node_t *) result;
+ return UP(result);
}
/**
@@ -13850,7 +13121,7 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
name = parse_target(parser, name, true, true);
}
- pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
+ pm_node_t *splat = UP(pm_splat_node_create(parser, &star_operator, name));
pm_multi_target_node_targets_append(parser, result, splat);
has_rest = true;
} else if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
@@ -13868,13 +13139,13 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
} else if (!match1(parser, PM_TOKEN_EOF)) {
// If we get here, then we have a trailing , in a multi target node.
// We'll add an implicit rest node to represent this.
- pm_node_t *rest = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ pm_node_t *rest = UP(pm_implicit_rest_node_create(parser, &parser->previous));
pm_multi_target_node_targets_append(parser, result, rest);
break;
}
}
- return (pm_node_t *) result;
+ return UP(result);
}
/**
@@ -14068,7 +13339,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
pm_parser_scope_forwarding_keywords_check(parser, &operator);
}
- element = (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator);
+ element = UP(pm_assoc_splat_node_create(parser, value, &operator));
contains_keyword_splat = true;
break;
}
@@ -14076,7 +13347,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
pm_token_t label = parser->current;
parser_lex(parser);
- pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &label);
+ pm_node_t *key = UP(pm_symbol_node_label_create(parser, &label));
pm_hash_key_static_literals_add(parser, literals, key);
pm_token_t operator = not_provided(parser);
@@ -14087,7 +13358,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
} else {
if (parser->encoding->isupper_char(label.start, (label.end - 1) - label.start)) {
pm_token_t constant = { .type = PM_TOKEN_CONSTANT, .start = label.start, .end = label.end - 1 };
- value = (pm_node_t *) pm_constant_read_node_create(parser, &constant);
+ value = UP(pm_constant_read_node_create(parser, &constant));
} else {
int depth = -1;
pm_token_t identifier = { .type = PM_TOKEN_IDENTIFIER, .start = label.start, .end = label.end - 1 };
@@ -14099,17 +13370,17 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
}
if (depth == -1) {
- value = (pm_node_t *) pm_call_node_variable_call_create(parser, &identifier);
+ value = UP(pm_call_node_variable_call_create(parser, &identifier));
} else {
- value = (pm_node_t *) pm_local_variable_read_node_create(parser, &identifier, (uint32_t) depth);
+ value = UP(pm_local_variable_read_node_create(parser, &identifier, (uint32_t) depth));
}
}
value->location.end++;
- value = (pm_node_t *) pm_implicit_node_create(parser, value);
+ value = UP(pm_implicit_node_create(parser, value));
}
- element = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
+ element = UP(pm_assoc_node_create(parser, key, &operator, value));
break;
}
default: {
@@ -14132,7 +13403,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
}
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1));
- element = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
+ element = UP(pm_assoc_node_create(parser, key, &operator, value));
break;
}
}
@@ -14161,6 +13432,30 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
return contains_keyword_splat;
}
+static inline bool
+argument_allowed_for_bare_hash(pm_parser_t *parser, pm_node_t *argument) {
+ if (pm_symbol_node_label_p(argument)) {
+ return true;
+ }
+
+ switch (PM_NODE_TYPE(argument)) {
+ case PM_CALL_NODE: {
+ pm_call_node_t *cast = (pm_call_node_t *) argument;
+ if (cast->opening_loc.start == NULL && cast->arguments != NULL) {
+ if (PM_NODE_FLAG_P(cast->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS | PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) {
+ return false;
+ }
+ if (cast->block != NULL) {
+ return false;
+ }
+ }
+ break;
+ }
+ default: break;
+ }
+ return accept1(parser, PM_TOKEN_EQUAL_GREATER);
+}
+
/**
* Append an argument to a list of arguments.
*/
@@ -14210,16 +13505,16 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
}
pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser);
- argument = (pm_node_t *) hash;
+ argument = UP(hash);
pm_static_literals_t hash_keys = { 0 };
- bool contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) hash, (uint16_t) (depth + 1));
+ bool contains_keyword_splat = parse_assocs(parser, &hash_keys, UP(hash), (uint16_t) (depth + 1));
parse_arguments_append(parser, arguments, argument);
pm_node_flags_t flags = PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS;
if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT;
- pm_node_flag_set((pm_node_t *) arguments->arguments, flags);
+ pm_node_flag_set(UP(arguments->arguments), flags);
pm_static_literals_free(&hash_keys);
parsed_bare_hash = true;
@@ -14237,7 +13532,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_parser_scope_forwarding_block_check(parser, &operator);
}
- argument = (pm_node_t *) pm_block_argument_node_create(parser, &operator, expression);
+ argument = UP(pm_block_argument_node_create(parser, &operator, expression));
if (parsed_block_argument) {
parse_arguments_append(parser, arguments, argument);
} else {
@@ -14257,7 +13552,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
if (match4(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_SEMICOLON, PM_TOKEN_BRACKET_RIGHT)) {
pm_parser_scope_forwarding_positionals_check(parser, &operator);
- argument = (pm_node_t *) pm_splat_node_create(parser, &operator, NULL);
+ argument = UP(pm_splat_node_create(parser, &operator, NULL));
if (parsed_bare_hash) {
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT);
}
@@ -14268,7 +13563,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_parser_err(parser, operator.start, expression->location.end, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT);
}
- argument = (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
+ argument = UP(pm_splat_node_create(parser, &operator, expression));
}
parse_arguments_append(parser, arguments, argument);
@@ -14293,16 +13588,16 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_parser_err(parser, range->operator_loc.start, range->operator_loc.end, PM_ERR_UNEXPECTED_RANGE_OPERATOR);
}
- argument = (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ argument = UP(pm_range_node_create(parser, NULL, &operator, right));
} else {
pm_parser_scope_forwarding_all_check(parser, &parser->previous);
if (parsed_first_argument && terminator == PM_TOKEN_EOF) {
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORWARDING_UNBOUND);
}
- argument = (pm_node_t *) pm_forwarding_arguments_node_create(parser, &parser->previous);
+ argument = UP(pm_forwarding_arguments_node_create(parser, &parser->previous));
parse_arguments_append(parser, arguments, argument);
- pm_node_flag_set((pm_node_t *) arguments->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING);
+ pm_node_flag_set(UP(arguments->arguments), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING);
arguments->has_forwarding = true;
parsed_forwarding_arguments = true;
break;
@@ -14318,7 +13613,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
bool contains_keywords = false;
bool contains_keyword_splat = false;
- if (pm_symbol_node_label_p(argument) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) {
+ if (argument_allowed_for_bare_hash(parser, argument)){
if (parsed_bare_hash) {
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_BARE_HASH);
}
@@ -14339,17 +13634,17 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
// Finish parsing the one we are part way through.
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1));
- argument = (pm_node_t *) pm_assoc_node_create(parser, argument, &operator, value);
+ argument = UP(pm_assoc_node_create(parser, argument, &operator, value));
pm_keyword_hash_node_elements_append(bare_hash, argument);
- argument = (pm_node_t *) bare_hash;
+ argument = UP(bare_hash);
// Then parse more if we have a comma
if (accept1(parser, PM_TOKEN_COMMA) && (
token_begins_expression_p(parser->current.type) ||
match2(parser, PM_TOKEN_USTAR_STAR, PM_TOKEN_LABEL)
)) {
- contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) bare_hash, (uint16_t) (depth + 1));
+ contains_keyword_splat = parse_assocs(parser, &hash_keys, UP(bare_hash), (uint16_t) (depth + 1));
}
pm_static_literals_free(&hash_keys);
@@ -14361,7 +13656,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_node_flags_t flags = 0;
if (contains_keywords) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS;
if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT;
- pm_node_flag_set((pm_node_t *) arguments->arguments, flags);
+ pm_node_flag_set(UP(arguments->arguments), flags);
break;
}
@@ -14390,6 +13685,17 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
if (accepted_newline) {
pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
}
+
+ // If this is a command call and an argument takes a block,
+ // there can be no further arguments. For example,
+ // `foo(bar 1 do end, 2)` should be rejected.
+ if (PM_NODE_TYPE_P(argument, PM_CALL_NODE)) {
+ pm_call_node_t *call = (pm_call_node_t *) argument;
+ if (call->opening_loc.start == NULL && call->arguments != NULL && call->block != NULL) {
+ pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
+ break;
+ }
+ }
} else {
// If there is no comma at the end of the argument list then we're
// done parsing arguments and can break out of this loop.
@@ -14427,33 +13733,33 @@ parse_required_destructured_parameter(pm_parser_t *parser) {
// commas, so here we'll assume this is a mistake of the user not
// knowing it's not allowed here.
if (node->lefts.size > 0 && match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
- param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ param = UP(pm_implicit_rest_node_create(parser, &parser->previous));
pm_multi_target_node_targets_append(parser, node, param);
pm_parser_err_current(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
break;
}
if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
- param = (pm_node_t *) parse_required_destructured_parameter(parser);
+ param = UP(parse_required_destructured_parameter(parser));
} else if (accept1(parser, PM_TOKEN_USTAR)) {
pm_token_t star = parser->previous;
pm_node_t *value = NULL;
if (accept1(parser, PM_TOKEN_IDENTIFIER)) {
pm_token_t name = parser->previous;
- value = (pm_node_t *) pm_required_parameter_node_create(parser, &name);
+ value = UP(pm_required_parameter_node_create(parser, &name));
if (pm_parser_parameter_name_check(parser, &name)) {
pm_node_flag_set_repeated_parameter(value);
}
pm_parser_local_add_token(parser, &name, 1);
}
- param = (pm_node_t *) pm_splat_node_create(parser, &star, value);
+ param = UP(pm_splat_node_create(parser, &star, value));
} else {
expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_EXPECT_IDENT_REQ_PARAMETER);
pm_token_t name = parser->previous;
- param = (pm_node_t *) pm_required_parameter_node_create(parser, &name);
+ param = UP(pm_required_parameter_node_create(parser, &name));
if (pm_parser_parameter_name_check(parser, &name)) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14566,7 +13872,7 @@ parse_parameters(
switch (parser->current.type) {
case PM_TOKEN_PARENTHESIS_LEFT: {
update_parameter_state(parser, &parser->current, &order);
- pm_node_t *param = (pm_node_t *) parse_required_destructured_parameter(parser);
+ pm_node_t *param = UP(parse_required_destructured_parameter(parser));
if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
pm_parameters_node_requireds_append(params, param);
@@ -14595,13 +13901,13 @@ parse_parameters(
pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *)param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
if (params->block == NULL) {
pm_parameters_node_block_set(params, param);
} else {
- pm_parser_err_node(parser, (pm_node_t *) param, PM_ERR_PARAMETER_BLOCK_MULTI);
- pm_parameters_node_posts_append(params, (pm_node_t *) param);
+ pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_BLOCK_MULTI);
+ pm_parameters_node_posts_append(params, UP(param));
}
break;
@@ -14626,7 +13932,7 @@ parse_parameters(
params->keyword_rest = NULL;
}
- pm_parameters_node_keyword_rest_set(params, (pm_node_t *) param);
+ pm_parameters_node_keyword_rest_set(params, UP(param));
break;
}
case PM_TOKEN_CLASS_VARIABLE:
@@ -14671,7 +13977,7 @@ parse_parameters(
parser_lex(parser);
pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &name);
- uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
+ uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true);
pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT, (uint16_t) (depth + 1));
@@ -14680,14 +13986,14 @@ parse_parameters(
pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *) param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
pm_parameters_node_optionals_append(params, param);
// If the value of the parameter increased the number of
// reads of that parameter, then we need to warn that we
// have a circular definition.
- if ((parser->version == PM_OPTIONS_VERSION_CRUBY_3_3) && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
+ if ((parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3) && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, name, PM_ERR_PARAMETER_CIRCULAR);
}
@@ -14703,15 +14009,15 @@ parse_parameters(
} else if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *)param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
- pm_parameters_node_requireds_append(params, (pm_node_t *) param);
+ pm_parameters_node_requireds_append(params, UP(param));
} else {
pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *)param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
- pm_parameters_node_posts_append(params, (pm_node_t *) param);
+ pm_parameters_node_posts_append(params, UP(param));
}
break;
@@ -14742,7 +14048,7 @@ parse_parameters(
case PM_TOKEN_PIPE: {
context_pop(parser);
- pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
+ pm_node_t *param = UP(pm_required_keyword_parameter_node_create(parser, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14759,7 +14065,7 @@ parse_parameters(
break;
}
- pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
+ pm_node_t *param = UP(pm_required_keyword_parameter_node_create(parser, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14772,20 +14078,20 @@ parse_parameters(
if (token_begins_expression_p(parser->current.type)) {
pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &local);
- uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
+ uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true);
pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT_KW, (uint16_t) (depth + 1));
if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser);
- if (parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
+ if (parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_PARAMETER_CIRCULAR);
}
- param = (pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value);
+ param = UP(pm_optional_keyword_parameter_node_create(parser, &name, value));
}
else {
- param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
+ param = UP(pm_required_keyword_parameter_node_create(parser, &name));
}
if (repeated) {
@@ -14826,7 +14132,7 @@ parse_parameters(
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS;
}
- pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name);
+ pm_node_t *param = UP(pm_rest_parameter_node_create(parser, &operator, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14854,7 +14160,7 @@ parse_parameters(
pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_NO_KW);
}
- param = (pm_node_t *) pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous);
+ param = UP(pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous));
} else {
pm_token_t name;
@@ -14868,7 +14174,7 @@ parse_parameters(
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS;
}
- param = (pm_node_t *) pm_keyword_rest_parameter_node_create(parser, &operator, &name);
+ param = UP(pm_keyword_rest_parameter_node_create(parser, &operator, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14888,13 +14194,13 @@ parse_parameters(
if (allows_trailing_comma && order >= PM_PARAMETERS_ORDER_NAMED) {
// If we get here, then we have a trailing comma in a
// block parameter list.
- pm_node_t *param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ pm_node_t *param = UP(pm_implicit_rest_node_create(parser, &parser->previous));
if (params->rest == NULL) {
pm_parameters_node_rest_set(params, param);
} else {
- pm_parser_err_node(parser, (pm_node_t *) param, PM_ERR_PARAMETER_SPLAT_MULTI);
- pm_parameters_node_posts_append(params, (pm_node_t *) param);
+ pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI);
+ pm_parameters_node_posts_append(params, UP(param));
}
} else {
pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
@@ -14931,7 +14237,7 @@ parse_parameters(
// If we don't have any parameters, return `NULL` instead of an empty `ParametersNode`.
if (params->base.location.start == params->base.location.end) {
- pm_node_destroy(parser, (pm_node_t *) params);
+ pm_node_destroy(parser, UP(params));
return NULL;
}
@@ -15203,7 +14509,7 @@ parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_
// If we don't have a `current` rescue node, then this is a dangling
// else, and it's an error.
- if (current == NULL) pm_parser_err_node(parser, (pm_node_t *) else_clause, PM_ERR_BEGIN_LONELY_ELSE);
+ if (current == NULL) pm_parser_err_node(parser, UP(else_clause), PM_ERR_BEGIN_LONELY_ELSE);
}
if (match1(parser, PM_TOKEN_KEYWORD_ENSURE)) {
@@ -15277,6 +14583,9 @@ parse_block_parameters(
) {
pm_parameters_node_t *parameters = NULL;
if (!match1(parser, PM_TOKEN_SEMICOLON)) {
+ if (!is_lambda_literal) {
+ context_push(parser, PM_CONTEXT_BLOCK_PARAMETERS);
+ }
parameters = parse_parameters(
parser,
is_lambda_literal ? PM_BINDING_POWER_DEFINED : PM_BINDING_POWER_INDEX,
@@ -15287,6 +14596,9 @@ parse_block_parameters(
true,
(uint16_t) (depth + 1)
);
+ if (!is_lambda_literal) {
+ context_pop(parser);
+ }
}
pm_block_parameters_node_t *block_parameters = pm_block_parameters_node_create(parser, parameters, opening);
@@ -15321,7 +14633,7 @@ parse_block_parameters(
pm_parser_local_add_token(parser, &parser->previous, 1);
pm_block_local_variable_node_t *local = pm_block_local_variable_node_create(parser, &parser->previous);
- if (repeated) pm_node_flag_set_repeated_parameter((pm_node_t *) local);
+ if (repeated) pm_node_flag_set_repeated_parameter(UP(local));
pm_block_parameters_node_append_local(block_parameters, local);
} while (accept1(parser, PM_TOKEN_COMMA));
@@ -15425,11 +14737,11 @@ parse_blocklike_parameters(pm_parser_t *parser, pm_node_t *parameters, const pm_
}
const pm_location_t location = { .start = opening->start, .end = closing->end };
- return (pm_node_t *) pm_numbered_parameters_node_create(parser, &location, numbered_parameter);
+ return UP(pm_numbered_parameters_node_create(parser, &location, numbered_parameter));
}
if (it_parameter) {
- return (pm_node_t *) pm_it_parameters_node_create(parser, opening, closing);
+ return UP(pm_it_parameters_node_create(parser, opening, closing));
}
return NULL;
@@ -15469,30 +14781,30 @@ parse_block(pm_parser_t *parser, uint16_t depth) {
if (opening.type == PM_TOKEN_BRACE_LEFT) {
if (!match1(parser, PM_TOKEN_BRACE_RIGHT)) {
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_BRACES, (uint16_t) (depth + 1));
+ statements = UP(parse_statements(parser, PM_CONTEXT_BLOCK_BRACES, (uint16_t) (depth + 1)));
}
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BLOCK_TERM_BRACE);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BLOCK_TERM_BRACE, &opening);
} else {
if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_ENSURE)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_KEYWORDS, (uint16_t) (depth + 1));
+ statements = UP(parse_statements(parser, PM_CONTEXT_BLOCK_KEYWORDS, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, 0, NULL, opening.start, (pm_statements_node_t *) statements, PM_RESCUES_BLOCK, (uint16_t) (depth + 1));
+ statements = UP(parse_rescues_implicit_begin(parser, 0, NULL, opening.start, (pm_statements_node_t *) statements, PM_RESCUES_BLOCK, (uint16_t) (depth + 1)));
}
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BLOCK_TERM_END);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BLOCK_TERM_END, &opening);
}
pm_constant_id_list_t locals;
pm_locals_order(parser, &parser->current_scope->locals, &locals, pm_parser_scope_toplevel_p(parser));
- pm_node_t *parameters = parse_blocklike_parameters(parser, (pm_node_t *) block_parameters, &opening, &parser->previous);
+ pm_node_t *parameters = parse_blocklike_parameters(parser, UP(block_parameters), &opening, &parser->previous);
pm_parser_scope_pop(parser);
pm_accepts_block_stack_pop(parser);
@@ -15564,9 +14876,9 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
if (block != NULL) {
if (arguments->block == NULL && !arguments->has_forwarding) {
- arguments->block = (pm_node_t *) block;
+ arguments->block = UP(block);
} else {
- pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI);
+ pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_BLOCK_MULTI);
if (arguments->block != NULL) {
if (arguments->arguments == NULL) {
@@ -15574,7 +14886,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
}
pm_arguments_node_arguments_append(arguments->arguments, arguments->block);
}
- arguments->block = (pm_node_t *) block;
+ arguments->block = UP(block);
}
}
}
@@ -15642,6 +14954,7 @@ parse_return(pm_parser_t *parser, pm_node_t *node) {
case PM_CONTEXT_BLOCK_ENSURE:
case PM_CONTEXT_BLOCK_KEYWORDS:
case PM_CONTEXT_BLOCK_RESCUE:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
case PM_CONTEXT_DEF_ELSE:
case PM_CONTEXT_DEF_ENSURE:
case PM_CONTEXT_DEF_PARAMS:
@@ -15661,7 +14974,7 @@ parse_return(pm_parser_t *parser, pm_node_t *node) {
break;
}
}
- if (in_sclass) {
+ if (in_sclass && parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) {
pm_parser_err_node(parser, node, PM_ERR_RETURN_INVALID);
}
}
@@ -15678,6 +14991,7 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node) {
case PM_CONTEXT_BLOCK_KEYWORDS:
case PM_CONTEXT_BLOCK_ELSE:
case PM_CONTEXT_BLOCK_ENSURE:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
case PM_CONTEXT_BLOCK_RESCUE:
case PM_CONTEXT_DEFINED:
case PM_CONTEXT_FOR:
@@ -15860,10 +15174,10 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl
switch (context) {
case PM_CONTEXT_IF:
- parent = (pm_node_t *) pm_if_node_create(parser, &keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
+ parent = UP(pm_if_node_create(parser, &keyword, predicate, &then_keyword, statements, NULL, &end_keyword));
break;
case PM_CONTEXT_UNLESS:
- parent = (pm_node_t *) pm_unless_node_create(parser, &keyword, predicate, &then_keyword, statements);
+ parent = UP(pm_unless_node_create(parser, &keyword, predicate, &then_keyword, statements));
break;
default:
assert(false && "unreachable");
@@ -15891,7 +15205,7 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
- pm_node_t *elsif = (pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
+ pm_node_t *elsif = UP(pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword));
((pm_if_node_t *) current)->subsequent = elsif;
current = elsif;
}
@@ -15910,13 +15224,13 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
parser_warn_indentation_mismatch(parser, opening_newline_index, &else_keyword, false, false);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM_ELSE);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM_ELSE, &keyword);
pm_else_node_t *else_node = pm_else_node_create(parser, &else_keyword, else_statements, &parser->previous);
switch (context) {
case PM_CONTEXT_IF:
- ((pm_if_node_t *) current)->subsequent = (pm_node_t *) else_node;
+ ((pm_if_node_t *) current)->subsequent = UP(else_node);
break;
case PM_CONTEXT_UNLESS:
((pm_unless_node_t *) parent)->else_clause = else_node;
@@ -15927,7 +15241,7 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl
}
} else {
parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, if_after_else, false);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM, &keyword);
}
// Set the appropriate end location for all of the nodes in the subtree.
@@ -16074,7 +15388,7 @@ parse_string_part(pm_parser_t *parser, uint16_t depth) {
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
+ pm_node_t *node = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
pm_node_flag_set(node, parse_unescaped_encoding(parser));
parser_lex(parser);
@@ -16120,7 +15434,7 @@ parse_string_part(pm_parser_t *parser, uint16_t depth) {
pm_node_flag_unset(statements->body.nodes[0], PM_NODE_FLAG_NEWLINE);
}
- return (pm_node_t *) pm_embedded_statements_node_create(parser, &opening, statements, &closing);
+ return UP(pm_embedded_statements_node_create(parser, &opening, statements, &closing));
}
// Here the lexer has returned the beginning of an embedded variable.
@@ -16145,42 +15459,42 @@ parse_string_part(pm_parser_t *parser, uint16_t depth) {
// create a global variable read node.
case PM_TOKEN_BACK_REFERENCE:
parser_lex(parser);
- variable = (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ variable = UP(pm_back_reference_read_node_create(parser, &parser->previous));
break;
// In this case an nth reference is being interpolated. We'll
// create a global variable read node.
case PM_TOKEN_NUMBERED_REFERENCE:
parser_lex(parser);
- variable = (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ variable = UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
break;
// In this case a global variable is being interpolated. We'll
// create a global variable read node.
case PM_TOKEN_GLOBAL_VARIABLE:
parser_lex(parser);
- variable = (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ variable = UP(pm_global_variable_read_node_create(parser, &parser->previous));
break;
// In this case an instance variable is being interpolated.
// We'll create an instance variable read node.
case PM_TOKEN_INSTANCE_VARIABLE:
parser_lex(parser);
- variable = (pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->previous);
+ variable = UP(pm_instance_variable_read_node_create(parser, &parser->previous));
break;
// In this case a class variable is being interpolated. We'll
// create a class variable read node.
case PM_TOKEN_CLASS_VARIABLE:
parser_lex(parser);
- variable = (pm_node_t *) pm_class_variable_read_node_create(parser, &parser->previous);
+ variable = UP(pm_class_variable_read_node_create(parser, &parser->previous));
break;
// We can hit here if we got an invalid token. In that case
// we'll not attempt to lex this token and instead just return a
// missing node.
default:
expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_EMBVAR_INVALID);
- variable = (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ variable = UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
break;
}
- return (pm_node_t *) pm_embedded_variable_node_create(parser, &operator, variable);
+ return UP(pm_embedded_variable_node_create(parser, &operator, variable));
}
default:
parser_lex(parser);
@@ -16217,9 +15531,9 @@ parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_sta
parser_lex(parser);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, end);
- pm_node_flag_set((pm_node_t *) symbol, PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING);
+ pm_node_flag_set(UP(symbol), PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING);
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
/**
@@ -16257,9 +15571,9 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end);
- pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
+ pm_node_flag_set(UP(symbol), parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
if (lex_mode->as.string.interpolation) {
@@ -16270,7 +15584,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
pm_token_t content = not_provided(parser);
pm_token_t closing = parser->previous;
- return (pm_node_t *) pm_symbol_node_create(parser, &opening, &content, &closing);
+ return UP(pm_symbol_node_create(parser, &opening, &content, &closing));
}
// Now we can parse the first part of the symbol.
@@ -16282,7 +15596,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_INTERPOLATED);
- return (pm_node_t *) pm_string_node_to_symbol_node(parser, (pm_string_node_t *) part, &opening, &parser->previous);
+ return UP(pm_string_node_to_symbol_node(parser, (pm_string_node_t *) part, &opening, &parser->previous));
}
pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening);
@@ -16302,7 +15616,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
}
pm_interpolated_symbol_node_closing_loc_set(symbol, &parser->previous);
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
pm_token_t content;
@@ -16326,10 +15640,10 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening);
pm_token_t bounds = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &unescaped));
pm_interpolated_symbol_node_append(symbol, part);
- part = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &parser->current, &bounds, &parser->current_string);
+ part = UP(pm_string_node_create_unescaped(parser, &bounds, &parser->current, &bounds, &parser->current_string));
pm_interpolated_symbol_node_append(symbol, part);
if (next_state != PM_LEX_STATE_NONE) {
@@ -16340,7 +15654,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC);
pm_interpolated_symbol_node_closing_loc_set(symbol, &parser->previous);
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
} else {
content = (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = parser->previous.end, .end = parser->previous.end };
@@ -16357,7 +15671,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC);
}
- return (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, false));
+ return UP(pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, false)));
}
/**
@@ -16382,9 +15696,9 @@ parse_undef_argument(pm_parser_t *parser, uint16_t depth) {
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end);
- pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
+ pm_node_flag_set(UP(symbol), parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
case PM_TOKEN_SYMBOL_BEGIN: {
pm_lex_mode_t lex_mode = *parser->lex_modes.current;
@@ -16394,7 +15708,7 @@ parse_undef_argument(pm_parser_t *parser, uint16_t depth) {
}
default:
pm_parser_err_current(parser, PM_ERR_UNDEF_ARGUMENT);
- return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
}
}
@@ -16423,9 +15737,9 @@ parse_alias_argument(pm_parser_t *parser, bool first, uint16_t depth) {
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end);
- pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
+ pm_node_flag_set(UP(symbol), parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
case PM_TOKEN_SYMBOL_BEGIN: {
pm_lex_mode_t lex_mode = *parser->lex_modes.current;
@@ -16435,16 +15749,16 @@ parse_alias_argument(pm_parser_t *parser, bool first, uint16_t depth) {
}
case PM_TOKEN_BACK_REFERENCE:
parser_lex(parser);
- return (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ return UP(pm_back_reference_read_node_create(parser, &parser->previous));
case PM_TOKEN_NUMBERED_REFERENCE:
parser_lex(parser);
- return (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ return UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
case PM_TOKEN_GLOBAL_VARIABLE:
parser_lex(parser);
- return (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ return UP(pm_global_variable_read_node_create(parser, &parser->previous));
default:
pm_parser_err_current(parser, PM_ERR_ALIAS_ARGUMENT);
- return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
}
}
@@ -16459,7 +15773,7 @@ parse_variable(pm_parser_t *parser) {
bool is_numbered_param = pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end);
if (!is_numbered_param && ((depth = pm_parser_local_depth_constant_id(parser, name_id)) != -1)) {
- return (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, (uint32_t) depth, false);
+ return UP(pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, (uint32_t) depth, false));
}
pm_scope_t *current_scope = parser->current_scope;
@@ -16478,12 +15792,12 @@ parse_variable(pm_parser_t *parser) {
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_NUMBERED_FOUND;
}
- pm_node_t *node = (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false);
+ pm_node_t *node = UP(pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false));
pm_node_list_append(&current_scope->implicit_parameters, node);
return node;
- } else if ((parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) && pm_token_is_it(parser->previous.start, parser->previous.end)) {
- pm_node_t *node = (pm_node_t *) pm_it_local_variable_read_node_create(parser, &parser->previous);
+ } else if ((parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) && pm_token_is_it(parser->previous.start, parser->previous.end)) {
+ pm_node_t *node = UP(pm_it_local_variable_read_node_create(parser, &parser->previous));
pm_node_list_append(&current_scope->implicit_parameters, node);
return node;
@@ -16507,9 +15821,9 @@ parse_variable_call(pm_parser_t *parser) {
}
pm_call_node_t *node = pm_call_node_variable_call_create(parser, &parser->previous);
- pm_node_flag_set((pm_node_t *)node, flags);
+ pm_node_flag_set(UP(node), flags);
- return (pm_node_t *) node;
+ return UP(node);
}
/**
@@ -16658,7 +15972,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
pm_string_node_t *string = pm_string_node_create(parser, &opening, &content, &parser->previous);
pm_string_shared_init(&string->unescaped, content.start, content.end);
- node = (pm_node_t *) string;
+ node = UP(string);
} else if (accept1(parser, PM_TOKEN_LABEL_END)) {
// If we get here, then we have an end of a label immediately
// after a start. In that case we'll create an empty symbol
@@ -16667,7 +15981,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &content, &parser->previous);
pm_string_shared_init(&symbol->unescaped, content.start, content.end);
- node = (pm_node_t *) symbol;
+ node = UP(symbol);
if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
} else if (!lex_interpolation) {
@@ -16700,32 +16014,32 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
pm_node_list_t parts = { 0 };
pm_token_t delimiters = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &delimiters, &content, &delimiters, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &delimiters, &content, &delimiters, &unescaped));
pm_node_list_append(&parts, part);
do {
- part = (pm_node_t *) pm_string_node_create_current_string(parser, &delimiters, &parser->current, &delimiters);
+ part = UP(pm_string_node_create_current_string(parser, &delimiters, &parser->current, &delimiters));
pm_node_list_append(&parts, part);
parser_lex(parser);
} while (match1(parser, PM_TOKEN_STRING_CONTENT));
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous));
pm_node_list_free(&parts);
} else if (accept1(parser, PM_TOKEN_LABEL_END)) {
- node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true));
+ node = UP(pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)));
if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
} else if (match1(parser, PM_TOKEN_EOF)) {
pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_EOF);
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped));
} else if (accept1(parser, PM_TOKEN_STRING_END)) {
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped));
} else {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_type_human(parser->previous.type));
parser->previous.start = parser->previous.end;
parser->previous.type = PM_TOKEN_MISSING;
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped));
}
} else if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
// In this case we've hit string content so we know the string
@@ -16737,7 +16051,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
parser_lex(parser);
if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped));
pm_node_flag_set(node, parse_unescaped_encoding(parser));
// Kind of odd behavior, but basically if we have an
@@ -16753,7 +16067,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
parser->previous.type = PM_TOKEN_MISSING;
}
} else if (accept1(parser, PM_TOKEN_LABEL_END)) {
- node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true));
+ node = UP(pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)));
if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
} else {
// If we get here, then we have interpolation so we'll need
@@ -16762,7 +16076,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
pm_token_t string_opening = not_provided(parser);
pm_token_t string_closing = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &string_opening, &parser->previous, &string_closing, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &string_opening, &parser->previous, &string_closing, &unescaped));
pm_node_flag_set(part, parse_unescaped_encoding(parser));
pm_node_list_append(&parts, part);
@@ -16773,14 +16087,14 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
}
if (accept1(parser, PM_TOKEN_LABEL_END)) {
- node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous);
+ node = UP(pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous));
if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
} else if (match1(parser, PM_TOKEN_EOF)) {
pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current));
} else {
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous));
}
pm_node_list_free(&parts);
@@ -16799,14 +16113,14 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
}
if (accept1(parser, PM_TOKEN_LABEL_END)) {
- node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous);
+ node = UP(pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous));
if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
} else if (match1(parser, PM_TOKEN_EOF)) {
pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current));
} else {
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous));
}
pm_node_list_free(&parts);
@@ -16843,7 +16157,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1
pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, &bounds, NULL, &bounds);
pm_interpolated_string_node_append(container, current);
- current = (pm_node_t *) container;
+ current = UP(container);
}
pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node);
@@ -16868,7 +16182,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
static void
parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_constant_id_t capture, const pm_location_t *location) {
// Skip this capture if it starts with an underscore.
- if (*location->start == '_') return;
+ if (peek_at(parser, location->start) == '_') return;
if (pm_constant_id_list_includes(captures, capture)) {
pm_parser_err(parser, location->start, location->end, PM_ERR_PATTERN_CAPTURE_DUPLICATE);
@@ -16887,7 +16201,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
while (accept1(parser, PM_TOKEN_COLON_COLON)) {
pm_token_t delimiter = parser->previous;
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- node = (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous);
+ node = UP(pm_constant_path_node_create(parser, node, &delimiter, &parser->previous));
}
// If there is a [ or ( that follows, then this is part of a larger pattern
@@ -16908,7 +16222,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) {
inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET);
+ expect1_opening(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET, &opening);
}
closing = parser->previous;
@@ -16920,7 +16234,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN);
+ expect1_opening(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN, &opening);
}
closing = parser->previous;
@@ -16929,7 +16243,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
if (!inner) {
// If there was no inner pattern, then we have something like Foo() or
// Foo[]. In that case we'll create an array pattern with no requireds.
- return (pm_node_t *) pm_array_pattern_node_constant_create(parser, node, &opening, &closing);
+ return UP(pm_array_pattern_node_constant_create(parser, node, &opening, &closing));
}
// Now that we have the inner pattern, check to see if it's an array, find,
@@ -16948,7 +16262,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16964,7 +16278,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16980,7 +16294,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16994,7 +16308,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
// attach our constant to it.
pm_array_pattern_node_t *pattern_node = pm_array_pattern_node_constant_create(parser, node, &opening, &closing);
pm_array_pattern_node_requireds_append(pattern_node, inner);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
/**
@@ -17019,12 +16333,12 @@ parse_pattern_rest(pm_parser_t *parser, pm_constant_id_list_t *captures) {
}
parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&identifier));
- name = (pm_node_t *) pm_local_variable_target_node_create(
+ name = UP(pm_local_variable_target_node_create(
parser,
&PM_LOCATION_TOKEN_VALUE(&identifier),
constant_id,
(uint32_t) (depth == -1 ? 0 : depth)
- );
+ ));
}
// Finally we can return the created node.
@@ -17043,7 +16357,7 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures)
pm_node_t *value = NULL;
if (accept1(parser, PM_TOKEN_KEYWORD_NIL)) {
- return (pm_node_t *) pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous);
+ return UP(pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous));
}
if (accept1(parser, PM_TOKEN_IDENTIFIER)) {
@@ -17055,15 +16369,15 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures)
}
parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&parser->previous));
- value = (pm_node_t *) pm_local_variable_target_node_create(
+ value = UP(pm_local_variable_target_node_create(
parser,
&PM_LOCATION_TOKEN_VALUE(&parser->previous),
constant_id,
(uint32_t) (depth == -1 ? 0 : depth)
- );
+ ));
}
- return (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator);
+ return UP(pm_assoc_splat_node_create(parser, value, &operator));
}
/**
@@ -17126,7 +16440,7 @@ parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_list_t *ca
(uint32_t) (depth == -1 ? 0 : depth)
);
- return (pm_node_t *) pm_implicit_node_create(parser, (pm_node_t *) target);
+ return UP(pm_implicit_node_create(parser, UP(target)));
}
/**
@@ -17170,7 +16484,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
}
pm_token_t operator = not_provided(parser);
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, first_node, &operator, value);
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, &operator, value));
pm_node_list_append(&assocs, assoc);
break;
@@ -17185,8 +16499,8 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
pm_parser_err_node(parser, first_node, diag_id);
pm_token_t operator = not_provided(parser);
- pm_node_t *value = (pm_node_t *) pm_missing_node_create(parser, first_node->location.start, first_node->location.end);
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, first_node, &operator, value);
+ pm_node_t *value = UP(pm_missing_node_create(parser, first_node->location.start, first_node->location.end));
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, &operator, value));
pm_node_list_append(&assocs, assoc);
break;
@@ -17227,20 +16541,24 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
}
} else {
expect1(parser, PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA);
- key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous);
+ key = UP(pm_symbol_node_label_create(parser, &parser->previous));
}
parse_pattern_hash_key(parser, &keys, key);
pm_node_t *value = NULL;
if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) {
- value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key);
+ if (PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)) {
+ value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key);
+ } else {
+ value = UP(pm_missing_node_create(parser, key->location.end, key->location.end));
+ }
} else {
value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY, (uint16_t) (depth + 1));
}
pm_token_t operator = not_provided(parser);
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, key, &operator, value));
if (rest != NULL) {
pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST);
@@ -17274,12 +16592,12 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
}
parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&parser->previous));
- return (pm_node_t *) pm_local_variable_target_node_create(
+ return UP(pm_local_variable_target_node_create(
parser,
&PM_LOCATION_TOKEN_VALUE(&parser->previous),
constant_id,
(uint32_t) (depth == -1 ? 0 : depth)
- );
+ ));
}
case PM_TOKEN_BRACKET_LEFT_ARRAY: {
pm_token_t opening = parser->current;
@@ -17288,7 +16606,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
if (accept1(parser, PM_TOKEN_BRACKET_RIGHT)) {
// If we have an empty array pattern, then we'll just return a new
// array pattern node.
- return (pm_node_t *) pm_array_pattern_node_empty_create(parser, &opening, &parser->previous);
+ return UP(pm_array_pattern_node_empty_create(parser, &opening, &parser->previous));
}
// Otherwise, we'll parse the inner pattern, then deal with it depending
@@ -17296,7 +16614,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pm_node_t *inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET);
+ expect1_opening(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET, &opening);
pm_token_t closing = parser->previous;
switch (PM_NODE_TYPE(inner)) {
@@ -17309,7 +16627,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -17323,7 +16641,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -17334,7 +16652,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pm_array_pattern_node_t *node = pm_array_pattern_node_empty_create(parser, &opening, &closing);
pm_array_pattern_node_requireds_append(node, inner);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_BRACE_LEFT: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -17354,7 +16672,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
switch (parser->current.type) {
case PM_TOKEN_LABEL:
parser_lex(parser);
- first_node = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous);
+ first_node = UP(pm_symbol_node_label_create(parser, &parser->previous));
break;
case PM_TOKEN_USTAR_STAR:
first_node = parse_pattern_keyword_rest(parser, captures);
@@ -17366,7 +16684,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_PATTERN_HASH_KEY, pm_token_type_human(parser->current.type));
parser_lex(parser);
- first_node = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ first_node = UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
break;
}
}
@@ -17374,7 +16692,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
node = parse_pattern_hash(parser, captures, first_node, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_PATTERN_TERM_BRACE);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_PATTERN_TERM_BRACE, &opening);
pm_token_t closing = parser->previous;
node->base.location.start = opening.start;
@@ -17385,7 +16703,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
}
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_UDOT_DOT:
case PM_TOKEN_UDOT_DOT_DOT: {
@@ -17397,12 +16715,12 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
switch (parser->current.type) {
case PM_CASE_PRIMITIVE: {
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ return UP(pm_range_node_create(parser, NULL, &operator, right));
}
default: {
pm_parser_err_token(parser, &operator, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
- pm_node_t *right = (pm_node_t *) pm_missing_node_create(parser, operator.start, operator.end);
- return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ pm_node_t *right = UP(pm_missing_node_create(parser, operator.start, operator.end));
+ return UP(pm_range_node_create(parser, NULL, &operator, right));
}
}
}
@@ -17412,6 +16730,16 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
// If we found a label, we need to immediately return to the caller.
if (pm_symbol_node_label_p(node)) return node;
+ // Call nodes (arithmetic operations) are not allowed in patterns
+ if (PM_NODE_TYPE(node) == PM_CALL_NODE) {
+ pm_parser_err_node(parser, node, diag_id);
+ pm_missing_node_t *missing_node = pm_missing_node_create(parser, node->location.start, node->location.end);
+
+ pm_node_unreference(parser, node);
+ pm_node_destroy(parser, node);
+ return UP(missing_node);
+ }
+
// Now that we have a primitive, we need to check if it's part of a range.
if (accept2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) {
pm_token_t operator = parser->previous;
@@ -17422,10 +16750,10 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
switch (parser->current.type) {
case PM_CASE_PRIMITIVE: {
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_range_node_create(parser, node, &operator, right);
+ return UP(pm_range_node_create(parser, node, &operator, right));
}
default:
- return (pm_node_t *) pm_range_node_create(parser, node, &operator, NULL);
+ return UP(pm_range_node_create(parser, node, &operator, NULL));
}
}
@@ -17440,44 +16768,44 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
switch (parser->current.type) {
case PM_TOKEN_IDENTIFIER: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) parse_variable(parser);
+ pm_node_t *variable = UP(parse_variable(parser));
if (variable == NULL) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE);
- variable = (pm_node_t *) pm_local_variable_read_node_missing_create(parser, &parser->previous, 0);
+ variable = UP(pm_local_variable_read_node_missing_create(parser, &parser->previous, 0));
}
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_INSTANCE_VARIABLE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_instance_variable_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_CLASS_VARIABLE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_class_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_class_variable_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_GLOBAL_VARIABLE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_global_variable_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_NUMBERED_REFERENCE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_BACK_REFERENCE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_back_reference_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_PARENTHESIS_LEFT: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -17490,15 +16818,15 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN);
- return (pm_node_t *) pm_pinned_expression_node_create(parser, expression, &operator, &lparen, &parser->previous);
+ expect1_opening(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN, &lparen);
+ return UP(pm_pinned_expression_node_create(parser, expression, &operator, &lparen, &parser->previous));
}
default: {
// If we get here, then we have a pin operator followed by something
// not understood. We'll create a missing node and return that.
pm_parser_err_token(parser, &operator, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
- pm_node_t *variable = (pm_node_t *) pm_missing_node_create(parser, operator.start, operator.end);
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ pm_node_t *variable = UP(pm_missing_node_create(parser, operator.start, operator.end));
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
}
}
@@ -17509,31 +16837,54 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
pm_constant_path_node_t *node = pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous);
- return parse_pattern_constant_path(parser, captures, (pm_node_t *) node, (uint16_t) (depth + 1));
+ return parse_pattern_constant_path(parser, captures, UP(node), (uint16_t) (depth + 1));
}
case PM_TOKEN_CONSTANT: {
pm_token_t constant = parser->current;
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_constant_read_node_create(parser, &constant);
+ pm_node_t *node = UP(pm_constant_read_node_create(parser, &constant));
return parse_pattern_constant_path(parser, captures, node, (uint16_t) (depth + 1));
}
default:
pm_parser_err_current(parser, diag_id);
- return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
+ }
+}
+
+static bool
+parse_pattern_alternation_error_each(const pm_node_t *node, void *data) {
+ switch (PM_NODE_TYPE(node)) {
+ case PM_LOCAL_VARIABLE_TARGET_NODE:
+ pm_parser_err((pm_parser_t *) data, node->location.start, node->location.end, PM_ERR_PATTERN_CAPTURE_IN_ALTERNATIVE);
+ return false;
+ default:
+ return true;
}
}
/**
+ * When we get here, we know that we already have a syntax error, because we
+ * know we have captured a variable and that we are in an alternation.
+ */
+static void
+parse_pattern_alternation_error(pm_parser_t *parser, const pm_node_t *node) {
+ pm_visit_node(node, parse_pattern_alternation_error_each, parser);
+}
+
+/**
* Parse any number of primitives joined by alternation and ended optionally by
* assignment.
*/
static pm_node_t *
parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node, pm_diagnostic_id_t diag_id, uint16_t depth) {
pm_node_t *node = first_node;
+ bool alternation = false;
- while ((node == NULL) || accept1(parser, PM_TOKEN_PIPE)) {
- pm_token_t operator = parser->previous;
+ while ((node == NULL) || (alternation = accept1(parser, PM_TOKEN_PIPE))) {
+ if (alternation && !PM_NODE_TYPE_P(node, PM_ALTERNATION_PATTERN_NODE) && captures->size) {
+ parse_pattern_alternation_error(parser, node);
+ }
switch (parser->current.type) {
case PM_TOKEN_IDENTIFIER:
@@ -17545,41 +16896,47 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p
case PM_TOKEN_UDOT_DOT:
case PM_TOKEN_UDOT_DOT_DOT:
case PM_CASE_PRIMITIVE: {
- if (node == NULL) {
+ if (!alternation) {
node = parse_pattern_primitive(parser, captures, diag_id, (uint16_t) (depth + 1));
} else {
+ pm_token_t operator = parser->previous;
pm_node_t *right = parse_pattern_primitive(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE, (uint16_t) (depth + 1));
- node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator);
+
+ if (captures->size) parse_pattern_alternation_error(parser, right);
+ node = UP(pm_alternation_pattern_node_create(parser, node, right, &operator));
}
break;
}
case PM_TOKEN_PARENTHESIS_LEFT:
case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: {
+ pm_token_t operator = parser->previous;
pm_token_t opening = parser->current;
parser_lex(parser);
pm_node_t *body = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN);
- pm_node_t *right = (pm_node_t *) pm_parentheses_node_create(parser, &opening, body, &parser->previous, 0);
+ expect1_opening(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN, &opening);
+ pm_node_t *right = UP(pm_parentheses_node_create(parser, &opening, body, &parser->previous, 0));
- if (node == NULL) {
+ if (!alternation) {
node = right;
} else {
- node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator);
+ if (captures->size) parse_pattern_alternation_error(parser, right);
+ node = UP(pm_alternation_pattern_node_create(parser, node, right, &operator));
}
break;
}
default: {
pm_parser_err_current(parser, diag_id);
- pm_node_t *right = (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ pm_node_t *right = UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
- if (node == NULL) {
+ if (!alternation) {
node = right;
} else {
- node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator);
+ if (captures->size) parse_pattern_alternation_error(parser, right);
+ node = UP(pm_alternation_pattern_node_create(parser, node, right, &parser->previous));
}
break;
@@ -17608,7 +16965,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p
(uint32_t) (depth == -1 ? 0 : depth)
);
- node = (pm_node_t *) pm_capture_pattern_node_create(parser, node, target, &operator);
+ node = UP(pm_capture_pattern_node_create(parser, node, target, &operator));
}
return node;
@@ -17627,8 +16984,8 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
switch (parser->current.type) {
case PM_TOKEN_LABEL: {
parser_lex(parser);
- pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous);
- node = (pm_node_t *) parse_pattern_hash(parser, captures, key, (uint16_t) (depth + 1));
+ pm_node_t *key = UP(pm_symbol_node_label_create(parser, &parser->previous));
+ node = UP(parse_pattern_hash(parser, captures, key, (uint16_t) (depth + 1)));
if (!(flags & PM_PARSE_PATTERN_TOP)) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT);
@@ -17638,7 +16995,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
}
case PM_TOKEN_USTAR_STAR: {
node = parse_pattern_keyword_rest(parser, captures);
- node = (pm_node_t *) parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1));
+ node = UP(parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)));
if (!(flags & PM_PARSE_PATTERN_TOP)) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT);
@@ -17652,7 +17009,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
node = parse_pattern_primitive(parser, captures, diag_id, (uint16_t) (depth + 1));
if (pm_symbol_node_label_p(node)) {
- node = (pm_node_t *) parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1));
+ node = UP(parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)));
if (!(flags & PM_PARSE_PATTERN_TOP)) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT);
@@ -17667,7 +17024,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
case PM_TOKEN_USTAR: {
if (flags & (PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI)) {
parser_lex(parser);
- node = (pm_node_t *) parse_pattern_rest(parser, captures);
+ node = UP(parse_pattern_rest(parser, captures));
leading_rest = true;
break;
}
@@ -17681,7 +17038,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
// If we got a dynamic label symbol, then we need to treat it like the
// beginning of a hash pattern.
if (pm_symbol_node_label_p(node)) {
- return (pm_node_t *) parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1));
+ return UP(parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)));
}
if ((flags & PM_PARSE_PATTERN_MULTI) && match1(parser, PM_TOKEN_COMMA)) {
@@ -17694,15 +17051,15 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
// Gather up all of the patterns into the list.
while (accept1(parser, PM_TOKEN_COMMA)) {
// Break early here in case we have a trailing comma.
- if (match9(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE, PM_TOKEN_EOF,PM_TOKEN_KEYWORD_AND, PM_TOKEN_KEYWORD_OR)) {
- node = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ if (match7(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_SEMICOLON, PM_TOKEN_KEYWORD_AND, PM_TOKEN_KEYWORD_OR)) {
+ node = UP(pm_implicit_rest_node_create(parser, &parser->previous));
pm_node_list_append(&nodes, node);
trailing_rest = true;
break;
}
if (accept1(parser, PM_TOKEN_USTAR)) {
- node = (pm_node_t *) parse_pattern_rest(parser, captures);
+ node = UP(parse_pattern_rest(parser, captures));
// If we have already parsed a splat pattern, then this is an
// error. We will continue to parse the rest of the patterns,
@@ -17724,13 +17081,13 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
// are in between because we know we already added the appropriate
// errors. Otherwise we will create an array pattern.
if (leading_rest && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) {
- node = (pm_node_t *) pm_find_pattern_node_create(parser, &nodes);
+ node = UP(pm_find_pattern_node_create(parser, &nodes));
if (nodes.size == 2) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_FIND_MISSING_INNER);
}
} else {
- node = (pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes);
+ node = UP(pm_array_pattern_node_node_list_create(parser, &nodes));
if (leading_rest && trailing_rest) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS);
@@ -17741,7 +17098,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
} else if (leading_rest) {
// Otherwise, if we parsed a single splat pattern, then we know we have
// an array pattern, so we can go ahead and create that node.
- node = (pm_node_t *) pm_array_pattern_node_rest_create(parser, node);
+ node = UP(pm_array_pattern_node_rest_create(parser, node));
}
return node;
@@ -17887,6 +17244,7 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_BEGIN:
case PM_CONTEXT_BLOCK_BRACES:
case PM_CONTEXT_BLOCK_KEYWORDS:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
case PM_CONTEXT_CASE_IN:
case PM_CONTEXT_CASE_WHEN:
case PM_CONTEXT_DEFAULT_PARAMS:
@@ -17967,6 +17325,7 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_BLOCK_KEYWORDS:
case PM_CONTEXT_BLOCK_ELSE:
case PM_CONTEXT_BLOCK_ENSURE:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
case PM_CONTEXT_BLOCK_RESCUE:
case PM_CONTEXT_CASE_IN:
case PM_CONTEXT_CASE_WHEN:
@@ -18117,13 +17476,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
}
- element = (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
+ element = UP(pm_splat_node_create(parser, &operator, expression));
} else if (match2(parser, PM_TOKEN_LABEL, PM_TOKEN_USTAR_STAR)) {
if (parsed_bare_hash) {
pm_parser_err_current(parser, PM_ERR_EXPRESSION_BARE_HASH);
}
- element = (pm_node_t *) pm_keyword_hash_node_create(parser);
+ element = UP(pm_keyword_hash_node_create(parser));
pm_static_literals_t hash_keys = { 0 };
if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) {
@@ -18152,10 +17511,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1));
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, element, &operator, value);
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, element, &operator, value));
pm_keyword_hash_node_elements_append(hash, assoc);
- element = (pm_node_t *) hash;
+ element = UP(hash);
if (accept1(parser, PM_TOKEN_COMMA) && !match1(parser, PM_TOKEN_BRACKET_RIGHT)) {
parse_assocs(parser, &hash_keys, element, (uint16_t) (depth + 1));
}
@@ -18180,7 +17539,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_array_node_close_set(array, &parser->previous);
pm_accepts_block_stack_pop(parser);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PARENTHESIS_LEFT:
case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: {
@@ -18207,7 +17566,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, flags);
+ return UP(pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, flags));
}
// Otherwise, we're going to parse the first statement in the list
@@ -18276,10 +17635,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *result;
if (match1(parser, PM_TOKEN_COMMA) && (binding_power == PM_BINDING_POWER_STATEMENT)) {
- result = parse_targets(parser, (pm_node_t *) multi_target, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
+ result = parse_targets(parser, UP(multi_target), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
} else {
- result = (pm_node_t *) multi_target;
+ result = UP(multi_target);
}
if (context_p(parser, PM_CONTEXT_MULTI_TARGET)) {
@@ -18308,7 +17667,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_statements_node_t *statements = pm_statements_node_create(parser);
pm_statements_node_body_append(parser, statements, statement, true);
- return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous, flags);
+ return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags));
}
// If we have more than one statement in the set of parentheses,
@@ -18373,16 +17732,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser);
pm_multi_target_node_targets_append(parser, multi_target, statement);
- statement = (pm_node_t *) multi_target;
+ statement = UP(multi_target);
statements->body.nodes[statements->body.size - 1] = statement;
}
if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE)) {
const uint8_t *offset = statement->location.end;
pm_token_t operator = { .type = PM_TOKEN_EQUAL, .start = offset, .end = offset };
- pm_node_t *value = (pm_node_t *) pm_missing_node_create(parser, offset, offset);
+ pm_node_t *value = UP(pm_missing_node_create(parser, offset, offset));
- statement = (pm_node_t *) pm_multi_write_node_create(parser, (pm_multi_target_node_t *) statement, &operator, value);
+ statement = UP(pm_multi_write_node_create(parser, (pm_multi_target_node_t *) statement, &operator, value));
statements->body.nodes[statements->body.size - 1] = statement;
pm_parser_err_node(parser, statement, PM_ERR_WRITE_TARGET_UNEXPECTED);
@@ -18393,7 +17752,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_list_free(&current_block_exits);
pm_void_statements_check(parser, statements, true);
- return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous, flags);
+ return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags));
}
case PM_TOKEN_BRACE_LEFT: {
// If we were passed a current_hash_keys via the parser, then that
@@ -18409,14 +17768,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_accepts_block_stack_push(parser, true);
parser_lex(parser);
- pm_hash_node_t *node = pm_hash_node_create(parser, &parser->previous);
+ pm_token_t opening = parser->previous;
+ pm_hash_node_t *node = pm_hash_node_create(parser, &opening);
if (!match2(parser, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_EOF)) {
if (current_hash_keys != NULL) {
- parse_assocs(parser, current_hash_keys, (pm_node_t *) node, (uint16_t) (depth + 1));
+ parse_assocs(parser, current_hash_keys, UP(node), (uint16_t) (depth + 1));
} else {
pm_static_literals_t hash_keys = { 0 };
- parse_assocs(parser, &hash_keys, (pm_node_t *) node, (uint16_t) (depth + 1));
+ parse_assocs(parser, &hash_keys, UP(node), (uint16_t) (depth + 1));
pm_static_literals_free(&hash_keys);
}
@@ -18424,26 +17784,34 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_accepts_block_stack_pop(parser);
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_HASH_TERM);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_HASH_TERM, &opening);
pm_hash_node_closing_loc_set(node, &parser->previous);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_CHARACTER_LITERAL: {
- parser_lex(parser);
-
- pm_token_t opening = parser->previous;
- opening.type = PM_TOKEN_STRING_BEGIN;
- opening.end = opening.start + 1;
-
- pm_token_t content = parser->previous;
- content.type = PM_TOKEN_STRING_CONTENT;
- content.start = content.start + 1;
-
pm_token_t closing = not_provided(parser);
- pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &content, &closing);
+ pm_node_t *node = UP(pm_string_node_create_current_string(
+ parser,
+ &(pm_token_t) {
+ .type = PM_TOKEN_STRING_BEGIN,
+ .start = parser->current.start,
+ .end = parser->current.start + 1
+ },
+ &(pm_token_t) {
+ .type = PM_TOKEN_STRING_CONTENT,
+ .start = parser->current.start + 1,
+ .end = parser->current.end
+ },
+ &closing
+ ));
+
pm_node_flag_set(node, parse_unescaped_encoding(parser));
+ // Skip past the character literal here, since now we have handled
+ // parser->explicit_encoding correctly.
+ parser_lex(parser);
+
// Characters can be followed by strings in which case they are
// automatically concatenated.
if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
@@ -18454,7 +17822,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
case PM_TOKEN_CLASS_VARIABLE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_class_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_class_variable_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
@@ -18476,10 +17844,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
) {
pm_arguments_t arguments = { 0 };
parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_node_fcall_create(parser, &constant, &arguments);
+ return UP(pm_call_node_fcall_create(parser, &constant, &arguments));
}
- pm_node_t *node = (pm_node_t *) pm_constant_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_constant_read_node_create(parser, &parser->previous));
if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) {
// If we get here, then we have a comma immediately following a
@@ -18494,7 +17862,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t delimiter = parser->previous;
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- pm_node_t *node = (pm_node_t *) pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous);
+ pm_node_t *node = UP(pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous));
if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) {
node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
@@ -18517,23 +17885,23 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_current(parser, PM_ERR_UNEXPECTED_RANGE_OPERATOR);
}
- return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ return UP(pm_range_node_create(parser, NULL, &operator, right));
}
case PM_TOKEN_FLOAT:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_create(parser, &parser->previous);
+ return UP(pm_float_node_create(parser, &parser->previous));
case PM_TOKEN_FLOAT_IMAGINARY:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_imaginary_create(parser, &parser->previous);
+ return UP(pm_float_node_imaginary_create(parser, &parser->previous));
case PM_TOKEN_FLOAT_RATIONAL:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_rational_create(parser, &parser->previous);
+ return UP(pm_float_node_rational_create(parser, &parser->previous));
case PM_TOKEN_FLOAT_RATIONAL_IMAGINARY:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_rational_imaginary_create(parser, &parser->previous);
+ return UP(pm_float_node_rational_imaginary_create(parser, &parser->previous));
case PM_TOKEN_NUMBERED_REFERENCE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
@@ -18543,7 +17911,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
case PM_TOKEN_GLOBAL_VARIABLE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_global_variable_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
@@ -18553,7 +17921,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
case PM_TOKEN_BACK_REFERENCE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_back_reference_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
@@ -18578,24 +17946,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1))) {
// Since we found arguments, we need to turn off the
// variable call bit in the flags.
- pm_node_flag_unset((pm_node_t *)call, PM_CALL_NODE_FLAGS_VARIABLE_CALL);
+ pm_node_flag_unset(UP(call), PM_CALL_NODE_FLAGS_VARIABLE_CALL);
call->opening_loc = arguments.opening_loc;
call->arguments = arguments.arguments;
call->closing_loc = arguments.closing_loc;
call->block = arguments.block;
- if (arguments.block != NULL) {
- call->base.location.end = arguments.block->location.end;
- } else if (arguments.closing_loc.start == NULL) {
- if (arguments.arguments != NULL) {
- call->base.location.end = arguments.arguments->base.location.end;
- } else {
- call->base.location.end = call->message_loc.end;
- }
- } else {
- call->base.location.end = arguments.closing_loc.end;
+ const uint8_t *end = pm_arguments_end(&arguments);
+ if (!end) {
+ end = call->message_loc.end;
}
+ call->base.location.end = end;
}
} else {
// Otherwise, we know the identifier is in the local table. This
@@ -18614,7 +17976,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// If we're about to convert an 'it' implicit local
// variable read into a method call, we need to remove
// it from the list of implicit local variables.
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
} else {
// Otherwise, we're about to convert a regular local
// variable read into a method call, in which case we
@@ -18623,7 +17985,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
assert(PM_NODE_TYPE_P(node, PM_LOCAL_VARIABLE_READ_NODE));
if (pm_token_is_numbered_parameter(identifier.start, identifier.end)) {
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
} else {
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
pm_locals_unread(&pm_parser_scope_find(parser, cast->depth)->locals, cast->name);
@@ -18631,7 +17993,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_node_destroy(parser, node);
- return (pm_node_t *) fcall;
+ return UP(fcall);
}
}
@@ -18663,9 +18025,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t content = parse_strings_empty_content(parser->previous.start);
if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) {
- node = (pm_node_t *) pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY);
+ node = UP(pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY));
} else {
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY);
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY));
}
node->location.end = opening.end;
@@ -18676,7 +18038,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
//
// parse_string_part handles its own errors, so there is no need
// for us to add one here.
- node = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ node = UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
} else if (PM_NODE_TYPE_P(part, PM_STRING_NODE) && match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) {
// If we get here, then the part that we parsed was plain string
// content and we're at the end of the heredoc, so we can return
@@ -18698,7 +18060,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parse_heredoc_dedent_string(&cast->unescaped, common_whitespace);
}
- node = (pm_node_t *) cast;
+ node = UP(cast);
expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length);
} else {
// If we get here, then we have multiple parts in the heredoc,
@@ -18723,7 +18085,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_xstring_node_closing_set(cast, &parser->previous);
cast->base.location = cast->opening_loc;
- node = (pm_node_t *) cast;
+ node = UP(cast);
} else {
pm_interpolated_string_node_t *cast = pm_interpolated_string_node_create(parser, &opening, &parts, &opening);
pm_node_list_free(&parts);
@@ -18732,7 +18094,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_string_node_closing_set(cast, &parser->previous);
cast->base.location = cast->opening_loc;
- node = (pm_node_t *) cast;
+ node = UP(cast);
}
// If this is a heredoc that is indented with a ~, then we need
@@ -18757,7 +18119,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
case PM_TOKEN_INSTANCE_VARIABLE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_instance_variable_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
@@ -18768,32 +18130,32 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
case PM_TOKEN_INTEGER: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_create(parser, base, &parser->previous));
}
case PM_TOKEN_INTEGER_IMAGINARY: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_imaginary_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_imaginary_create(parser, base, &parser->previous));
}
case PM_TOKEN_INTEGER_RATIONAL: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_rational_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_rational_create(parser, base, &parser->previous));
}
case PM_TOKEN_INTEGER_RATIONAL_IMAGINARY: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_rational_imaginary_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_rational_imaginary_create(parser, base, &parser->previous));
}
case PM_TOKEN_KEYWORD___ENCODING__:
parser_lex(parser);
- return (pm_node_t *) pm_source_encoding_node_create(parser, &parser->previous);
+ return UP(pm_source_encoding_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD___FILE__:
parser_lex(parser);
- return (pm_node_t *) pm_source_file_node_create(parser, &parser->previous);
+ return UP(pm_source_file_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD___LINE__:
parser_lex(parser);
- return (pm_node_t *) pm_source_line_node_create(parser, &parser->previous);
+ return UP(pm_source_line_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_ALIAS: {
if (binding_power != PM_BINDING_POWER_STATEMENT) {
pm_parser_err_current(parser, PM_ERR_STATEMENT_ALIAS);
@@ -18817,7 +18179,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_node(parser, old_name, PM_ERR_ALIAS_ARGUMENT);
}
- return (pm_node_t *) pm_alias_global_variable_node_create(parser, &keyword, new_name, old_name);
+ return UP(pm_alias_global_variable_node_create(parser, &keyword, new_name, old_name));
}
case PM_SYMBOL_NODE:
case PM_INTERPOLATED_SYMBOL_NODE: {
@@ -18827,7 +18189,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
PRISM_FALLTHROUGH
default:
- return (pm_node_t *) pm_alias_method_node_create(parser, &keyword, new_name, old_name);
+ return UP(pm_alias_method_node_create(parser, &keyword, new_name, old_name));
}
}
case PM_TOKEN_KEYWORD_CASE: {
@@ -18860,7 +18222,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_list_free(&current_block_exits);
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
- return (pm_node_t *) pm_case_node_create(parser, &case_keyword, predicate, &parser->previous);
+ return UP(pm_case_node_create(parser, &case_keyword, predicate, &parser->previous));
}
// At this point we can create a case node, though we don't yet know
@@ -18888,7 +18250,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
pm_splat_node_t *splat_node = pm_splat_node_create(parser, &operator, expression);
- pm_when_node_conditions_append(when_node, (pm_node_t *) splat_node);
+ pm_when_node_conditions_append(when_node, UP(splat_node));
if (PM_NODE_TYPE_P(expression, PM_MISSING_NODE)) break;
} else {
@@ -18927,7 +18289,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
}
- pm_case_node_condition_append(case_node, (pm_node_t *) when_node);
+ pm_case_node_condition_append(case_node, UP(when_node));
}
// If we didn't parse any conditions (in or when) then we need
@@ -18937,7 +18299,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_static_literals_free(&literals);
- node = (pm_node_t *) case_node;
+ node = UP(case_node);
} else {
pm_case_match_node_t *case_node = pm_case_match_node_create(parser, &case_keyword, predicate, &end_keyword);
@@ -18974,11 +18336,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (accept1(parser, PM_TOKEN_KEYWORD_IF_MODIFIER)) {
pm_token_t keyword = parser->previous;
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1));
- pattern = (pm_node_t *) pm_if_node_modifier_create(parser, pattern, &keyword, predicate);
+ pattern = UP(pm_if_node_modifier_create(parser, pattern, &keyword, predicate));
} else if (accept1(parser, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) {
pm_token_t keyword = parser->previous;
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1));
- pattern = (pm_node_t *) pm_unless_node_modifier_create(parser, pattern, &keyword, predicate);
+ pattern = UP(pm_unless_node_modifier_create(parser, pattern, &keyword, predicate));
}
// Now we need to check for the terminator of the in node's
@@ -19007,7 +18369,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// Now that we have the full pattern and statements, we can
// create the node and attach it to the case node.
- pm_node_t *condition = (pm_node_t *) pm_in_node_create(parser, pattern, statements, &in_keyword, &then_keyword);
+ pm_node_t *condition = UP(pm_in_node_create(parser, pattern, statements, &in_keyword, &then_keyword));
pm_case_match_node_condition_append(case_node, condition);
}
@@ -19017,7 +18379,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
}
- node = (pm_node_t *) case_node;
+ node = UP(case_node);
}
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
@@ -19039,7 +18401,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, false);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CASE_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CASE_TERM, &case_keyword);
if (PM_NODE_TYPE_P(node, PM_CASE_NODE)) {
pm_case_node_end_keyword_loc_set((pm_case_node_t *) node, &parser->previous);
@@ -19072,7 +18434,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_begin_node_t *begin_node = pm_begin_node_create(parser, &begin_keyword, begin_statements);
parse_rescues(parser, opening_newline_index, &begin_keyword, begin_node, PM_RESCUES_BEGIN, (uint16_t) (depth + 1));
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BEGIN_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BEGIN_TERM, &begin_keyword);
begin_node->base.location.end = parser->previous.end;
pm_begin_node_end_keyword_set(begin_node, &parser->previous);
@@ -19080,7 +18442,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) begin_node;
+ return UP(begin_node);
}
case PM_TOKEN_KEYWORD_BEGIN_UPCASE: {
pm_node_list_t current_block_exits = { 0 };
@@ -19097,7 +18459,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = parser->previous;
pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_PREEXE, (uint16_t) (depth + 1));
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BEGIN_UPCASE_TERM);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BEGIN_UPCASE_TERM, &opening);
pm_context_t context = parser->current_context->context;
if ((context != PM_CONTEXT_MAIN) && (context != PM_CONTEXT_PREEXE)) {
pm_parser_err_token(parser, &keyword, PM_ERR_BEGIN_UPCASE_TOPLEVEL);
@@ -19106,7 +18468,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
flush_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->previous);
+ return UP(pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_BREAK:
case PM_TOKEN_KEYWORD_NEXT:
@@ -19123,29 +18485,35 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_binding_power_t binding_power = pm_binding_powers[parser->current.type].left;
if (binding_power == PM_BINDING_POWER_UNSET || binding_power >= PM_BINDING_POWER_RANGE) {
+ pm_token_t next = parser->current;
parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, (uint16_t) (depth + 1));
+
+ // Reject `foo && return bar`.
+ if (!accepts_command_call && arguments.arguments != NULL) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(next.type));
+ }
}
}
switch (keyword.type) {
case PM_TOKEN_KEYWORD_BREAK: {
- pm_node_t *node = (pm_node_t *) pm_break_node_create(parser, &keyword, arguments.arguments);
+ pm_node_t *node = UP(pm_break_node_create(parser, &keyword, arguments.arguments));
if (!parser->partial_script) parse_block_exit(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_NEXT: {
- pm_node_t *node = (pm_node_t *) pm_next_node_create(parser, &keyword, arguments.arguments);
+ pm_node_t *node = UP(pm_next_node_create(parser, &keyword, arguments.arguments));
if (!parser->partial_script) parse_block_exit(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_RETURN: {
- pm_node_t *node = (pm_node_t *) pm_return_node_create(parser, &keyword, arguments.arguments);
+ pm_node_t *node = UP(pm_return_node_create(parser, &keyword, arguments.arguments));
parse_return(parser, node);
return node;
}
default:
assert(false && "unreachable");
- return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ return UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
}
}
case PM_TOKEN_KEYWORD_SUPER: {
@@ -19160,10 +18528,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
arguments.arguments == NULL &&
((arguments.block == NULL) || PM_NODE_TYPE_P(arguments.block, PM_BLOCK_NODE))
) {
- return (pm_node_t *) pm_forwarding_super_node_create(parser, &keyword, &arguments);
+ return UP(pm_forwarding_super_node_create(parser, &keyword, &arguments));
}
- return (pm_node_t *) pm_super_node_create(parser, &keyword, &arguments);
+ return UP(pm_super_node_create(parser, &keyword, &arguments));
}
case PM_TOKEN_KEYWORD_YIELD: {
parser_lex(parser);
@@ -19178,11 +18546,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// yield node.
if (arguments.block != NULL) {
pm_parser_err_node(parser, arguments.block, PM_ERR_UNEXPECTED_BLOCK_ARGUMENT);
+ pm_node_unreference(parser, arguments.block);
pm_node_destroy(parser, arguments.block);
arguments.block = NULL;
}
- pm_node_t *node = (pm_node_t *) pm_yield_node_create(parser, &keyword, &arguments.opening_loc, arguments.arguments, &arguments.closing_loc);
+ pm_node_t *node = UP(pm_yield_node_create(parser, &keyword, &arguments.opening_loc, arguments.arguments, &arguments.closing_loc));
if (!parser->parsing_eval && !parser->partial_script) parse_yield(parser, node);
return node;
@@ -19209,18 +18578,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *statements = NULL;
if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_SCLASS, (uint16_t) (depth + 1));
+ statements = UP(parse_statements(parser, PM_CONTEXT_SCLASS, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_SCLASS, (uint16_t) (depth + 1));
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_SCLASS, (uint16_t) (depth + 1)));
} else {
parser_warn_indentation_mismatch(parser, opening_newline_index, &class_keyword, false, false);
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM, &class_keyword);
pm_constant_id_list_t locals;
pm_locals_order(parser, &parser->current_scope->locals, &locals, false);
@@ -19231,7 +18600,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
flush_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous);
+ return UP(pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous));
}
pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_CLASS_NAME, (uint16_t) (depth + 1));
@@ -19267,18 +18636,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_CLASS, (uint16_t) (depth + 1));
+ statements = UP(parse_statements(parser, PM_CONTEXT_CLASS, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_CLASS, (uint16_t) (depth + 1));
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_CLASS, (uint16_t) (depth + 1)));
} else {
parser_warn_indentation_mismatch(parser, opening_newline_index, &class_keyword, false, false);
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM, &class_keyword);
if (context_def_p(parser)) {
pm_parser_err_token(parser, &class_keyword, PM_ERR_CLASS_IN_METHOD);
@@ -19297,7 +18666,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, &inheritance_operator, superclass, statements, &parser->previous);
+ return UP(pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, &inheritance_operator, superclass, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_DEF: {
pm_node_list_t current_block_exits = { 0 };
@@ -19374,37 +18743,37 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
switch (identifier.type) {
case PM_TOKEN_CONSTANT:
- receiver = (pm_node_t *) pm_constant_read_node_create(parser, &identifier);
+ receiver = UP(pm_constant_read_node_create(parser, &identifier));
break;
case PM_TOKEN_INSTANCE_VARIABLE:
- receiver = (pm_node_t *) pm_instance_variable_read_node_create(parser, &identifier);
+ receiver = UP(pm_instance_variable_read_node_create(parser, &identifier));
break;
case PM_TOKEN_CLASS_VARIABLE:
- receiver = (pm_node_t *) pm_class_variable_read_node_create(parser, &identifier);
+ receiver = UP(pm_class_variable_read_node_create(parser, &identifier));
break;
case PM_TOKEN_GLOBAL_VARIABLE:
- receiver = (pm_node_t *) pm_global_variable_read_node_create(parser, &identifier);
+ receiver = UP(pm_global_variable_read_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_NIL:
- receiver = (pm_node_t *) pm_nil_node_create(parser, &identifier);
+ receiver = UP(pm_nil_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_SELF:
- receiver = (pm_node_t *) pm_self_node_create(parser, &identifier);
+ receiver = UP(pm_self_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_TRUE:
- receiver = (pm_node_t *) pm_true_node_create(parser, &identifier);
+ receiver = UP(pm_true_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_FALSE:
- receiver = (pm_node_t *) pm_false_node_create(parser, &identifier);
+ receiver = UP(pm_false_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD___FILE__:
- receiver = (pm_node_t *) pm_source_file_node_create(parser, &identifier);
+ receiver = UP(pm_source_file_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD___LINE__:
- receiver = (pm_node_t *) pm_source_line_node_create(parser, &identifier);
+ receiver = UP(pm_source_line_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD___ENCODING__:
- receiver = (pm_node_t *) pm_source_encoding_node_create(parser, &identifier);
+ receiver = UP(pm_source_encoding_node_create(parser, &identifier));
break;
default:
break;
@@ -19439,7 +18808,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
expect2(parser, PM_TOKEN_DOT, PM_TOKEN_COLON_COLON, PM_ERR_DEF_RECEIVER_TERM);
operator = parser->previous;
- receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, expression, &rparen, 0);
+ receiver = UP(pm_parentheses_node_create(parser, &lparen, expression, &rparen, 0));
// To push `PM_CONTEXT_DEF_PARAMS` again is for the same
// reason as described the above.
@@ -19458,6 +18827,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t rparen;
pm_parameters_node_t *params;
+ bool accept_endless_def = true;
switch (parser->current.type) {
case PM_TOKEN_PARENTHESIS_LEFT: {
parser_lex(parser);
@@ -19493,6 +18863,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
rparen = not_provided(parser);
params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, false, (uint16_t) (depth + 1));
+ // Reject `def * = 1` and similar. We have to specifically check
+ // for them because they create ambiguity with optional arguments.
+ accept_endless_def = false;
+
context_pop(parser);
break;
}
@@ -19514,13 +18888,30 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (token_is_setter_name(&name)) {
pm_parser_err_token(parser, &name, PM_ERR_DEF_ENDLESS_SETTER);
}
+ if (!accept_endless_def) {
+ pm_parser_err_previous(parser, PM_ERR_DEF_ENDLESS_PARAMETERS);
+ }
+ if (
+ parser->current_context->context == PM_CONTEXT_DEFAULT_PARAMS &&
+ parser->current_context->prev->context == PM_CONTEXT_BLOCK_PARAMETERS
+ ) {
+ PM_PARSER_ERR_FORMAT(parser, def_keyword.start, parser->previous.end, PM_ERR_UNEXPECTED_PARAMETER_DEFAULT_VALUE, "endless method definition");
+ }
equal = parser->previous;
context_push(parser, PM_CONTEXT_DEF);
pm_do_loop_stack_push(parser, false);
- statements = (pm_node_t *) pm_statements_node_create(parser);
+ statements = UP(pm_statements_node_create(parser));
+
+ bool allow_command_call;
+ if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) {
+ allow_command_call = accepts_command_call;
+ } else {
+ // Allow `def foo = puts "Hello"` but not `private def foo = puts "Hello"`
+ allow_command_call = binding_power == PM_BINDING_POWER_ASSIGNMENT || binding_power < PM_BINDING_POWER_COMPOSITION;
+ }
- pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, binding_power < PM_BINDING_POWER_COMPOSITION, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1));
+ pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_command_call, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1));
if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
context_push(parser, PM_CONTEXT_RESCUE_MODIFIER);
@@ -19529,7 +18920,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *value = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- statement = (pm_node_t *) pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value);
+ statement = UP(pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value));
}
pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement, false);
@@ -19552,13 +18943,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_DEF, (uint16_t) (depth + 1));
+ statements = UP(parse_statements(parser, PM_CONTEXT_DEF, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &def_keyword, def_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_DEF, (uint16_t) (depth + 1));
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &def_keyword, def_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_DEF, (uint16_t) (depth + 1)));
} else {
parser_warn_indentation_mismatch(parser, opening_newline_index, &def_keyword, false, false);
}
@@ -19566,7 +18957,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_accepts_block_stack_pop(parser);
pm_do_loop_stack_pop(parser);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_DEF_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_DEF_TERM, &def_keyword);
end_keyword = parser->previous;
}
@@ -19575,7 +18966,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_scope_pop(parser);
/**
- * If the final character is @. As is the case when defining
+ * If the final character is `@` as is the case when defining
* methods to override the unary operators, we should ignore
* the @ in the same way we do for symbols.
*/
@@ -19584,7 +18975,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
flush_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_def_node_create(
+ return UP(pm_def_node_create(
parser,
name_id,
&name,
@@ -19598,7 +18989,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
&rparen,
&equal,
&end_keyword
- );
+ ));
}
case PM_TOKEN_KEYWORD_DEFINED: {
parser_lex(parser);
@@ -19615,7 +19006,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
lparen = parser->previous;
if (newline && accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
- expression = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0);
+ expression = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0));
lparen = not_provided(parser);
rparen = not_provided(parser);
} else {
@@ -19636,13 +19027,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
context_pop(parser);
- return (pm_node_t *) pm_defined_node_create(
+ return UP(pm_defined_node_create(
parser,
&lparen,
expression,
&rparen,
- &PM_LOCATION_TOKEN_VALUE(&keyword)
- );
+ &keyword
+ ));
}
case PM_TOKEN_KEYWORD_END_UPCASE: {
if (binding_power != PM_BINDING_POWER_STATEMENT) {
@@ -19660,12 +19051,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = parser->previous;
pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_POSTEXE, (uint16_t) (depth + 1));
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_END_UPCASE_TERM);
- return (pm_node_t *) pm_post_execution_node_create(parser, &keyword, &opening, statements, &parser->previous);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_END_UPCASE_TERM, &opening);
+ return UP(pm_post_execution_node_create(parser, &keyword, &opening, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_FALSE:
parser_lex(parser);
- return (pm_node_t *) pm_false_node_create(parser, &parser->previous);
+ return UP(pm_false_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_FOR: {
size_t opening_newline_index = token_newline_index(parser);
parser_lex(parser);
@@ -19684,12 +19075,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
}
- index = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
+ index = UP(pm_splat_node_create(parser, &star_operator, name));
} else if (token_begins_expression_p(parser->current.type)) {
index = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
} else {
pm_parser_err_token(parser, &for_keyword, PM_ERR_FOR_INDEX);
- index = (pm_node_t *) pm_missing_node_create(parser, for_keyword.start, for_keyword.end);
+ index = UP(pm_missing_node_create(parser, for_keyword.start, for_keyword.end));
}
// Now, if there are multiple index expressions, parse them out.
@@ -19724,9 +19115,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
parser_warn_indentation_mismatch(parser, opening_newline_index, &for_keyword, false, false);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM, &for_keyword);
- return (pm_node_t *) pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->previous);
+ return UP(pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->previous));
}
case PM_TOKEN_KEYWORD_IF:
if (parser_end_of_line_p(parser)) {
@@ -19766,7 +19157,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
}
- return (pm_node_t *) undef;
+ return UP(undef);
}
case PM_TOKEN_KEYWORD_NOT: {
parser_lex(parser);
@@ -19775,13 +19166,27 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_arguments_t arguments = { 0 };
pm_node_t *receiver = NULL;
+ // If we do not accept a command call, then we also do not accept a
+ // not without parentheses. In this case we need to reject this
+ // syntax.
+ if (!accepts_command_call && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
+ if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES)) {
+ pm_parser_err(parser, parser->previous.end, parser->previous.end + 1, PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN);
+ } else {
+ accept1(parser, PM_TOKEN_NEWLINE);
+ pm_parser_err_current(parser, PM_ERR_EXPECT_LPAREN_AFTER_NOT_OTHER);
+ }
+
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
+ }
+
accept1(parser, PM_TOKEN_NEWLINE);
if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
pm_token_t lparen = parser->previous;
if (accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
- receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0);
+ receiver = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0));
} else {
arguments.opening_loc = PM_LOCATION_TOKEN_VALUE(&lparen);
receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1));
@@ -19796,7 +19201,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1));
}
- return (pm_node_t *) pm_call_node_not_create(parser, receiver, &message, &arguments);
+ return UP(pm_call_node_not_create(parser, receiver, &message, &arguments));
}
case PM_TOKEN_KEYWORD_UNLESS: {
size_t opening_newline_index = token_newline_index(parser);
@@ -19822,14 +19227,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_list_free(&current_block_exits);
pm_token_t missing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
- return (pm_node_t *) pm_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing);
+ return UP(pm_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing));
}
while (accept1(parser, PM_TOKEN_COLON_COLON)) {
pm_token_t double_colon = parser->previous;
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- constant_path = (pm_node_t *) pm_constant_path_node_create(parser, constant_path, &double_colon, &parser->previous);
+ constant_path = UP(pm_constant_path_node_create(parser, constant_path, &double_colon, &parser->previous));
}
// Here we retrieve the name of the module. If it wasn't a constant,
@@ -19846,13 +19251,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_MODULE, (uint16_t) (depth + 1));
+ statements = UP(parse_statements(parser, PM_CONTEXT_MODULE, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &module_keyword, module_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_MODULE, (uint16_t) (depth + 1));
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &module_keyword, module_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_MODULE, (uint16_t) (depth + 1)));
} else {
parser_warn_indentation_mismatch(parser, opening_newline_index, &module_keyword, false, false);
}
@@ -19861,7 +19266,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_locals_order(parser, &parser->current_scope->locals, &locals, false);
pm_parser_scope_pop(parser);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_MODULE_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_MODULE_TERM, &module_keyword);
if (context_def_p(parser)) {
pm_parser_err_token(parser, &module_keyword, PM_ERR_MODULE_IN_METHOD);
@@ -19870,15 +19275,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->previous);
+ return UP(pm_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_NIL:
parser_lex(parser);
- return (pm_node_t *) pm_nil_node_create(parser, &parser->previous);
+ return UP(pm_nil_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_REDO: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_redo_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_redo_node_create(parser, &parser->previous));
if (!parser->partial_script) parse_block_exit(parser, node);
return node;
@@ -19886,17 +19291,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
case PM_TOKEN_KEYWORD_RETRY: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_retry_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_retry_node_create(parser, &parser->previous));
parse_retry(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_SELF:
parser_lex(parser);
- return (pm_node_t *) pm_self_node_create(parser, &parser->previous);
+ return UP(pm_self_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_TRUE:
parser_lex(parser);
- return (pm_node_t *) pm_true_node_create(parser, &parser->previous);
+ return UP(pm_true_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_UNTIL: {
size_t opening_newline_index = token_newline_index(parser);
@@ -19927,9 +19332,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_UNTIL_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_UNTIL_TERM, &keyword);
- return (pm_node_t *) pm_until_node_create(parser, &keyword, &do_keyword, &parser->previous, predicate, statements, 0);
+ return UP(pm_until_node_create(parser, &keyword, &do_keyword, &parser->previous, predicate, statements, 0));
}
case PM_TOKEN_KEYWORD_WHILE: {
size_t opening_newline_index = token_newline_index(parser);
@@ -19961,26 +19366,60 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_WHILE_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_WHILE_TERM, &keyword);
- return (pm_node_t *) pm_while_node_create(parser, &keyword, &do_keyword, &parser->previous, predicate, statements, 0);
+ return UP(pm_while_node_create(parser, &keyword, &do_keyword, &parser->previous, predicate, statements, 0));
}
case PM_TOKEN_PERCENT_LOWER_I: {
parser_lex(parser);
pm_token_t opening = parser->previous;
pm_array_node_t *array = pm_array_node_create(parser, &opening);
+ pm_node_t *current = NULL;
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
accept1(parser, PM_TOKEN_WORDS_SEP);
if (match1(parser, PM_TOKEN_STRING_END)) break;
- if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
+ // Interpolation is not possible but nested heredocs can still lead to
+ // consecutive (disjoint) string tokens when the final newline is escaped.
+ while (match1(parser, PM_TOKEN_STRING_CONTENT)) {
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_array_node_elements_append(array, (pm_node_t *) pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing));
+
+ // Record the string node, moving to interpolation if needed.
+ if (current == NULL) {
+ current = UP(pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing));
+ parser_lex(parser);
+ } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) {
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
+ parser_lex(parser);
+ pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string);
+ } else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) {
+ pm_symbol_node_t *cast = (pm_symbol_node_t *) current;
+ pm_token_t bounds = not_provided(parser);
+
+ pm_token_t content = { .type = PM_TOKEN_STRING_CONTENT, .start = cast->value_loc.start, .end = cast->value_loc.end };
+ pm_node_t *first_string = UP(pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &cast->unescaped));
+ pm_node_t *second_string = UP(pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing));
+ parser_lex(parser);
+
+ pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
+ pm_interpolated_symbol_node_append(interpolated, first_string);
+ pm_interpolated_symbol_node_append(interpolated, second_string);
+
+ xfree(current);
+ current = UP(interpolated);
+ } else {
+ assert(false && "unreachable");
+ }
}
- expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_I_LOWER_ELEMENT);
+ if (current) {
+ pm_array_node_elements_append(array, current);
+ current = NULL;
+ } else {
+ expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_I_LOWER_ELEMENT);
+ }
}
pm_token_t closing = parser->current;
@@ -19992,7 +19431,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PERCENT_UPPER_I: {
parser_lex(parser);
@@ -20027,13 +19466,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// If we hit content and the current node is NULL, then this is
// the first string content we've seen. In that case we're going
// to create a new string node and set that to the current.
- current = (pm_node_t *) pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing);
+ current = UP(pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing));
parser_lex(parser);
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) {
// If we hit string content and the current node is an
// interpolated string, then we need to append the string content
// to the list of child nodes.
- pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
parser_lex(parser);
pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string);
@@ -20045,8 +19484,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t bounds = not_provided(parser);
pm_token_t content = { .type = PM_TOKEN_STRING_CONTENT, .start = cast->value_loc.start, .end = cast->value_loc.end };
- pm_node_t *first_string = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &cast->unescaped);
- pm_node_t *second_string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing);
+ pm_node_t *first_string = UP(pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &cast->unescaped));
+ pm_node_t *second_string = UP(pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing));
parser_lex(parser);
pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
@@ -20054,7 +19493,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_symbol_node_append(interpolated, second_string);
xfree(current);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
assert(false && "unreachable");
}
@@ -20069,7 +19508,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// node to a new interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) {
// If we hit an embedded variable and the current node is a string
// node, then we'll convert the current into an interpolated
@@ -20078,11 +19517,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
- current = (pm_node_t *) pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current);
+ current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current));
pm_interpolated_symbol_node_append(interpolated, current);
interpolated->base.location.start = current->location.start;
start_location_set = true;
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
// If we hit an embedded variable and the current node is an
// interpolated string, then we'll just add the embedded variable.
@@ -20103,7 +19542,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// node to a new interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) {
// If we hit an embedded expression and the current node is a
// string node, then we'll convert the current into an
@@ -20113,11 +19552,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
- current = (pm_node_t *) pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current);
+ current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current));
pm_interpolated_symbol_node_append(interpolated, current);
interpolated->base.location.start = current->location.start;
start_location_set = true;
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) {
// If we hit an embedded expression and the current node is an
// interpolated string, then we'll just continue on.
@@ -20153,29 +19592,48 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PERCENT_LOWER_W: {
parser_lex(parser);
pm_token_t opening = parser->previous;
pm_array_node_t *array = pm_array_node_create(parser, &opening);
-
- // skip all leading whitespaces
- accept1(parser, PM_TOKEN_WORDS_SEP);
+ pm_node_t *current = NULL;
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
accept1(parser, PM_TOKEN_WORDS_SEP);
if (match1(parser, PM_TOKEN_STRING_END)) break;
- if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
+ // Interpolation is not possible but nested heredocs can still lead to
+ // consecutive (disjoint) string tokens when the final newline is escaped.
+ while (match1(parser, PM_TOKEN_STRING_CONTENT)) {
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
- pm_array_node_elements_append(array, string);
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
+
+ // Record the string node, moving to interpolation if needed.
+ if (current == NULL) {
+ current = string;
+ } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) {
+ pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, string);
+ } else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
+ pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
+ pm_interpolated_string_node_append(interpolated, current);
+ pm_interpolated_string_node_append(interpolated, string);
+ current = UP(interpolated);
+ } else {
+ assert(false && "unreachable");
+ }
+ parser_lex(parser);
}
- expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_W_LOWER_ELEMENT);
+ if (current) {
+ pm_array_node_elements_append(array, current);
+ current = NULL;
+ } else {
+ expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_W_LOWER_ELEMENT);
+ }
}
pm_token_t closing = parser->current;
@@ -20187,7 +19645,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PERCENT_UPPER_W: {
parser_lex(parser);
@@ -20223,7 +19681,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
pm_node_flag_set(string, parse_unescaped_encoding(parser));
parser_lex(parser);
@@ -20246,7 +19704,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
pm_interpolated_string_node_append(interpolated, current);
pm_interpolated_string_node_append(interpolated, string);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
assert(false && "unreachable");
}
@@ -20261,7 +19719,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_string_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
// If we hit an embedded variable and the current
// node is a string node, then we'll convert the
@@ -20271,7 +19729,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
pm_interpolated_string_node_append(interpolated, current);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
// If we hit an embedded variable and the current
// node is an interpolated string, then we'll just
@@ -20290,7 +19748,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_string_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
// If we hit an embedded expression and the current
// node is a string node, then we'll convert the
@@ -20300,7 +19758,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
pm_interpolated_string_node_append(interpolated, current);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) {
// If we hit an embedded expression and the current
// node is an interpolated string, then we'll just
@@ -20334,7 +19792,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_REGEXP_BEGIN: {
pm_token_t opening = parser->current;
@@ -20352,7 +19810,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_regular_expression_node_create(parser, &opening, &content, &parser->previous);
+ pm_node_t *node = UP(pm_regular_expression_node_create(parser, &opening, &content, &parser->previous));
pm_node_flag_set(node, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING);
return node;
@@ -20384,8 +19842,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parse_regular_expression_errors(parser, node);
}
- pm_node_flag_set((pm_node_t *) node, parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, node->base.flags));
- return (pm_node_t *) node;
+ pm_node_flag_set(UP(node), parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, FL(node)));
+ return UP(node);
}
// If we get here, then we have interpolation so we'll need to create
@@ -20394,7 +19852,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped));
if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) {
// This is extremely strange, but the first string part of a
@@ -20429,7 +19887,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_interpolated_regular_expression_node_closing_set(parser, interpolated, &closing);
- return (pm_node_t *) interpolated;
+ return UP(interpolated);
}
case PM_TOKEN_BACKTICK:
case PM_TOKEN_PERCENT_LOWER_X: {
@@ -20451,7 +19909,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
};
parser_lex(parser);
- return (pm_node_t *) pm_xstring_node_create(parser, &opening, &content, &parser->previous);
+ return UP(pm_xstring_node_create(parser, &opening, &content, &parser->previous));
}
pm_interpolated_x_string_node_t *node;
@@ -20466,7 +19924,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser_lex(parser);
if (match1(parser, PM_TOKEN_STRING_END)) {
- pm_node_t *node = (pm_node_t *) pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
+ pm_node_t *node = UP(pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped));
pm_node_flag_set(node, parse_unescaped_encoding(parser));
parser_lex(parser);
return node;
@@ -20479,7 +19937,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped));
pm_node_flag_set(part, parse_unescaped_encoding(parser));
pm_interpolated_xstring_node_append(node, part);
@@ -20506,7 +19964,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_interpolated_xstring_node_closing_set(node, &closing);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_USTAR: {
parser_lex(parser);
@@ -20516,7 +19974,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// still lex past it though and create a missing node place.
if (binding_power != PM_BINDING_POWER_STATEMENT) {
pm_parser_err_prefix(parser, diag_id);
- return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ return UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
}
pm_token_t operator = parser->previous;
@@ -20526,7 +19984,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
}
- pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &operator, name);
+ pm_node_t *splat = UP(pm_splat_node_create(parser, &operator, name));
if (match1(parser, PM_TOKEN_COMMA)) {
return parse_targets_validate(parser, splat, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
@@ -20546,7 +20004,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!");
pm_conditional_predicate(parser, receiver, PM_CONDITIONAL_PREDICATE_TYPE_NOT);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_TILDE: {
if (binding_power > PM_BINDING_POWER_UNARY) {
@@ -20558,7 +20016,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~");
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_UMINUS: {
if (binding_power > PM_BINDING_POWER_UNARY) {
@@ -20570,7 +20028,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@");
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_UMINUS_NUM: {
parser_lex(parser);
@@ -20581,8 +20039,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (accept1(parser, PM_TOKEN_STAR_STAR)) {
pm_token_t exponent_operator = parser->previous;
pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, false, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1));
- node = (pm_node_t *) pm_call_node_binary_create(parser, node, &exponent_operator, exponent, 0);
- node = (pm_node_t *) pm_call_node_unary_create(parser, &operator, node, "-@");
+ node = UP(pm_call_node_binary_create(parser, node, &exponent_operator, exponent, 0));
+ node = UP(pm_call_node_unary_create(parser, &operator, node, "-@"));
} else {
switch (PM_NODE_TYPE(node)) {
case PM_INTEGER_NODE:
@@ -20592,7 +20050,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parse_negative_numeric(node);
break;
default:
- node = (pm_node_t *) pm_call_node_unary_create(parser, &operator, node, "-@");
+ node = UP(pm_call_node_unary_create(parser, &operator, node, "-@"));
break;
}
}
@@ -20650,39 +20108,39 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
opening = parser->previous;
if (!match1(parser, PM_TOKEN_BRACE_RIGHT)) {
- body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_BRACES, (uint16_t) (depth + 1));
+ body = UP(parse_statements(parser, PM_CONTEXT_LAMBDA_BRACES, (uint16_t) (depth + 1)));
}
parser_warn_indentation_mismatch(parser, opening_newline_index, &operator, false, false);
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_LAMBDA_TERM_BRACE);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_LAMBDA_TERM_BRACE, &opening);
} else {
expect1(parser, PM_TOKEN_KEYWORD_DO, PM_ERR_LAMBDA_OPEN);
opening = parser->previous;
if (!match3(parser, PM_TOKEN_KEYWORD_END, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
pm_accepts_block_stack_push(parser, true);
- body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_DO_END, (uint16_t) (depth + 1));
+ body = UP(parse_statements(parser, PM_CONTEXT_LAMBDA_DO_END, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(body == NULL || PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE));
- body = (pm_node_t *) parse_rescues_implicit_begin(parser, opening_newline_index, &operator, opening.start, (pm_statements_node_t *) body, PM_RESCUES_LAMBDA, (uint16_t) (depth + 1));
+ body = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &operator, opening.start, (pm_statements_node_t *) body, PM_RESCUES_LAMBDA, (uint16_t) (depth + 1)));
} else {
parser_warn_indentation_mismatch(parser, opening_newline_index, &operator, false, false);
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END, &operator);
}
pm_constant_id_list_t locals;
pm_locals_order(parser, &parser->current_scope->locals, &locals, pm_parser_scope_toplevel_p(parser));
- pm_node_t *parameters = parse_blocklike_parameters(parser, (pm_node_t *) block_parameters, &operator, &parser->previous);
+ pm_node_t *parameters = parse_blocklike_parameters(parser, UP(block_parameters), &operator, &parser->previous);
pm_parser_scope_pop(parser);
pm_accepts_block_stack_pop(parser);
- return (pm_node_t *) pm_lambda_node_create(parser, &locals, &operator, &opening, &parser->previous, parameters, body);
+ return UP(pm_lambda_node_create(parser, &locals, &operator, &opening, &parser->previous, parameters, body));
}
case PM_TOKEN_UPLUS: {
if (binding_power > PM_BINDING_POWER_UNARY) {
@@ -20694,7 +20152,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@");
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_STRING_BEGIN:
return parse_strings(parser, NULL, accepts_label, (uint16_t) (depth + 1));
@@ -20730,7 +20188,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_prefix(parser, diag_id);
}
- return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ return UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
}
}
}
@@ -20759,7 +20217,7 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_
pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
+ return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right));
}
return value;
@@ -20818,7 +20276,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
bool permitted = true;
if (previous_binding_power != PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_USTAR)) permitted = false;
- pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id, (uint16_t) (depth + 1));
+ pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MODIFIER, diag_id, (uint16_t) (depth + 1));
if (!permitted) pm_parser_err_node(parser, value, PM_ERR_UNEXPECTED_MULTI_WRITE);
parse_assignment_value_local(parser, value);
@@ -20831,7 +20289,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
pm_array_node_t *array = pm_array_node_create(parser, &opening);
pm_array_node_elements_append(array, value);
- value = (pm_node_t *) array;
+ value = UP(array);
while (accept1(parser, PM_TOKEN_COMMA)) {
pm_node_t *element = parse_starred_expression(parser, binding_power, false, PM_ERR_ARRAY_ELEMENT, (uint16_t) (depth + 1));
@@ -20865,7 +20323,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, accepts_command_call_inner, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
+ return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right));
}
return value;
@@ -20882,13 +20340,15 @@ static void
parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const pm_token_t *operator) {
if (call_node->arguments != NULL) {
pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_ARGUMENTS);
- pm_node_destroy(parser, (pm_node_t *) call_node->arguments);
+ pm_node_unreference(parser, UP(call_node->arguments));
+ pm_node_destroy(parser, UP(call_node->arguments));
call_node->arguments = NULL;
}
if (call_node->block != NULL) {
pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_BLOCK);
- pm_node_destroy(parser, (pm_node_t *) call_node->block);
+ pm_node_unreference(parser, UP(call_node->block));
+ pm_node_destroy(parser, UP(call_node->block));
call_node->block = NULL;
}
}
@@ -20959,7 +20419,7 @@ pm_named_capture_escape_octal(pm_buffer_t *unescaped, const uint8_t *cursor, con
}
static inline const uint8_t *
-pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end) {
+pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end, const pm_location_t *error_location) {
const uint8_t *start = cursor - 1;
cursor++;
@@ -20970,7 +20430,7 @@ pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, con
if (*cursor != '{') {
size_t length = pm_strspn_hexadecimal_digit(cursor, MIN(end - cursor, 4));
- uint32_t value = escape_unicode(parser, cursor, length);
+ uint32_t value = escape_unicode(parser, cursor, length, error_location);
if (!pm_buffer_append_unicode_codepoint(unescaped, value)) {
pm_buffer_append_string(unescaped, (const char *) start, (size_t) ((cursor + length) - start));
@@ -20990,7 +20450,10 @@ pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, con
}
size_t length = pm_strspn_hexadecimal_digit(cursor, end - cursor);
- uint32_t value = escape_unicode(parser, cursor, length);
+ if (length == 0) {
+ break;
+ }
+ uint32_t value = escape_unicode(parser, cursor, length, error_location);
(void) pm_buffer_append_unicode_codepoint(unescaped, value);
cursor += length;
@@ -21000,7 +20463,7 @@ pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, con
}
static void
-pm_named_capture_escape(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8_t *source, const size_t length, const uint8_t *cursor) {
+pm_named_capture_escape(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8_t *source, const size_t length, const uint8_t *cursor, const pm_location_t *error_location) {
const uint8_t *end = source + length;
pm_buffer_append_string(unescaped, (const char *) source, (size_t) (cursor - source));
@@ -21018,7 +20481,7 @@ pm_named_capture_escape(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8
cursor = pm_named_capture_escape_octal(unescaped, cursor, end);
break;
case 'u':
- cursor = pm_named_capture_escape_unicode(parser, unescaped, cursor, end);
+ cursor = pm_named_capture_escape_unicode(parser, unescaped, cursor, end, error_location);
break;
default:
pm_buffer_append_byte(unescaped, '\\');
@@ -21061,7 +20524,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) {
// unescaped, which is what we need.
const uint8_t *cursor = pm_memchr(source, '\\', length, parser->encoding_changed, parser->encoding);
if (PRISM_UNLIKELY(cursor != NULL)) {
- pm_named_capture_escape(parser, &unescaped, source, length, cursor);
+ pm_named_capture_escape(parser, &unescaped, source, length, cursor, callback_data->shared ? NULL : &call->receiver->location);
source = (const uint8_t *) pm_buffer_value(&unescaped);
length = pm_buffer_length(&unescaped);
}
@@ -21120,7 +20583,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) {
// Next, create the local variable target and add it to the list of
// targets for the match.
- pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth);
+ pm_node_t *target = UP(pm_local_variable_target_node_create(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth));
pm_node_list_append(&callback_data->match->targets, target);
}
@@ -21151,9 +20614,9 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *
pm_constant_id_list_free(&callback_data.names);
if (callback_data.match != NULL) {
- return (pm_node_t *) callback_data.match;
+ return UP(callback_data.match);
} else {
- return (pm_node_t *) call;
+ return UP(call);
}
}
@@ -21176,6 +20639,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
}
PRISM_FALLTHROUGH
case PM_CASE_WRITABLE: {
+ // When we have `it = value`, we need to add `it` as a local
+ // variable before parsing the value, in case the value
+ // references the variable.
+ if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) {
+ pm_parser_local_add_location(parser, node->location.start, node->location.end, 0);
+ }
+
parser_lex(parser);
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1));
@@ -21191,7 +20661,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1));
- return parse_write(parser, (pm_node_t *) multi_target, &token, value);
+ return parse_write(parser, UP(multi_target), &token, value);
}
case PM_SOURCE_ENCODING_NODE:
case PM_FALSE_NODE:
@@ -21225,7 +20695,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_global_variable_and_write_node_create(parser, node, &token, value);
+ pm_node_t *result = UP(pm_global_variable_and_write_node_create(parser, node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21234,7 +20704,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
+ pm_node_t *result = UP(pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21243,7 +20713,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *write = (pm_node_t *) pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
+ pm_node_t *write = UP(pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value));
return parse_shareable_constant_write(parser, write);
}
@@ -21251,7 +20721,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *write = (pm_node_t *) pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
+ pm_node_t *write = UP(pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return parse_shareable_constant_write(parser, write);
@@ -21260,7 +20730,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
+ pm_node_t *result = UP(pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21270,23 +20740,23 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, node, &token, value, name, 0);
+ pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, name, 0));
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
pm_node_destroy(parser, node);
return result;
}
case PM_LOCAL_VARIABLE_READ_NODE: {
if (pm_token_is_numbered_parameter(node->location.start, node->location.end)) {
PM_PARSER_ERR_FORMAT(parser, node->location.start, node->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, node->location.start);
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
}
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth);
+ pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth));
pm_node_destroy(parser, node);
return result;
@@ -21305,9 +20775,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
+ pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, UP(cast), &token, value, constant_id, 0));
- pm_node_destroy(parser, (pm_node_t *) cast);
+ pm_node_destroy(parser, UP(cast));
return result;
}
@@ -21320,7 +20790,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// an aset expression.
if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) {
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_index_and_write_node_create(parser, cast, &token, value);
+ return UP(pm_index_and_write_node_create(parser, cast, &token, value));
}
// If this node cannot be writable, then we have an error.
@@ -21332,7 +20802,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parse_call_operator_write(parser, cast, &token);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_and_write_node_create(parser, cast, &token, value);
+ return UP(pm_call_and_write_node_create(parser, cast, &token, value));
}
case PM_MULTI_WRITE_NODE: {
parser_lex(parser);
@@ -21359,7 +20829,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_global_variable_or_write_node_create(parser, node, &token, value);
+ pm_node_t *result = UP(pm_global_variable_or_write_node_create(parser, node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21368,7 +20838,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
+ pm_node_t *result = UP(pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21377,7 +20847,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *write = (pm_node_t *) pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
+ pm_node_t *write = UP(pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value));
return parse_shareable_constant_write(parser, write);
}
@@ -21385,7 +20855,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *write = (pm_node_t *) pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
+ pm_node_t *write = UP(pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return parse_shareable_constant_write(parser, write);
@@ -21394,7 +20864,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
+ pm_node_t *result = UP(pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21404,23 +20874,23 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, node, &token, value, name, 0);
+ pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, name, 0));
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
pm_node_destroy(parser, node);
return result;
}
case PM_LOCAL_VARIABLE_READ_NODE: {
if (pm_token_is_numbered_parameter(node->location.start, node->location.end)) {
PM_PARSER_ERR_FORMAT(parser, node->location.start, node->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, node->location.start);
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
}
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth);
+ pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth));
pm_node_destroy(parser, node);
return result;
@@ -21439,9 +20909,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
+ pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, UP(cast), &token, value, constant_id, 0));
- pm_node_destroy(parser, (pm_node_t *) cast);
+ pm_node_destroy(parser, UP(cast));
return result;
}
@@ -21454,7 +20924,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// an aset expression.
if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) {
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_index_or_write_node_create(parser, cast, &token, value);
+ return UP(pm_index_or_write_node_create(parser, cast, &token, value));
}
// If this node cannot be writable, then we have an error.
@@ -21466,7 +20936,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parse_call_operator_write(parser, cast, &token);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_or_write_node_create(parser, cast, &token, value);
+ return UP(pm_call_or_write_node_create(parser, cast, &token, value));
}
case PM_MULTI_WRITE_NODE: {
parser_lex(parser);
@@ -21503,7 +20973,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_global_variable_operator_write_node_create(parser, node, &token, value);
+ pm_node_t *result = UP(pm_global_variable_operator_write_node_create(parser, node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21512,7 +20982,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
+ pm_node_t *result = UP(pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21521,7 +20991,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *write = (pm_node_t *) pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
+ pm_node_t *write = UP(pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value));
return parse_shareable_constant_write(parser, write);
}
@@ -21529,7 +20999,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *write = (pm_node_t *) pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
+ pm_node_t *write = UP(pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return parse_shareable_constant_write(parser, write);
@@ -21538,7 +21008,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
+ pm_node_t *result = UP(pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -21548,23 +21018,23 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, name, 0);
+ pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, name, 0));
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
pm_node_destroy(parser, node);
return result;
}
case PM_LOCAL_VARIABLE_READ_NODE: {
if (pm_token_is_numbered_parameter(node->location.start, node->location.end)) {
PM_PARSER_ERR_FORMAT(parser, node->location.start, node->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, node->location.start);
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
}
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
parser_lex(parser);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth);
+ pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth));
pm_node_destroy(parser, node);
return result;
@@ -21582,9 +21052,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end, 1);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
+ pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, UP(cast), &token, value, constant_id, 0));
- pm_node_destroy(parser, (pm_node_t *) cast);
+ pm_node_destroy(parser, UP(cast));
return result;
}
@@ -21593,7 +21063,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// an aset expression.
if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) {
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_index_operator_write_node_create(parser, cast, &token, value);
+ return UP(pm_index_operator_write_node_create(parser, cast, &token, value));
}
// If this node cannot be writable, then we have an error.
@@ -21605,7 +21075,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parse_call_operator_write(parser, cast, &token);
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_operator_write_node_create(parser, cast, &token, value);
+ return UP(pm_call_operator_write_node_create(parser, cast, &token, value));
}
case PM_MULTI_WRITE_NODE: {
parser_lex(parser);
@@ -21627,14 +21097,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_AND, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_and_node_create(parser, node, &token, right);
+ return UP(pm_and_node_create(parser, node, &token, right));
}
case PM_TOKEN_KEYWORD_OR:
case PM_TOKEN_PIPE_PIPE: {
parser_lex(parser);
pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_OR, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_or_node_create(parser, node, &token, right);
+ return UP(pm_or_node_create(parser, node, &token, right));
}
case PM_TOKEN_EQUAL_TILDE: {
// Note that we _must_ parse the value before adding the local
@@ -21649,7 +21119,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// By default, we're going to create a call node and then return it.
pm_call_node_t *call = pm_call_node_binary_create(parser, node, &token, argument, 0);
- pm_node_t *result = (pm_node_t *) call;
+ pm_node_t *result = UP(call);
// If the receiver of this =~ is a regular expression node, then we
// need to introduce local variables for it based on its named
@@ -21752,7 +21222,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
}
pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument, 0);
+ return UP(pm_call_node_binary_create(parser, node, &token, argument, 0));
}
case PM_TOKEN_GREATER:
case PM_TOKEN_GREATER_EQUAL:
@@ -21764,7 +21234,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument, PM_CALL_NODE_FLAGS_COMPARISON);
+ return UP(pm_call_node_binary_create(parser, node, &token, argument, PM_CALL_NODE_FLAGS_COMPARISON));
}
case PM_TOKEN_AMPERSAND_DOT:
case PM_TOKEN_DOT: {
@@ -21775,7 +21245,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// This if statement handles the foo.() syntax.
if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
parse_arguments_list(parser, &arguments, true, false, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &operator, &arguments);
+ return UP(pm_call_node_shorthand_create(parser, node, &operator, &arguments));
}
switch (PM_NODE_TYPE(node)) {
@@ -21831,9 +21301,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
arguments.opening_loc.start == NULL &&
match1(parser, PM_TOKEN_COMMA)
) {
- return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
+ return parse_targets_validate(parser, UP(call), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
} else {
- return (pm_node_t *) call;
+ return UP(call);
}
}
case PM_TOKEN_DOT_DOT:
@@ -21845,21 +21315,21 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
right = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
}
- return (pm_node_t *) pm_range_node_create(parser, node, &token, right);
+ return UP(pm_range_node_create(parser, node, &token, right));
}
case PM_TOKEN_KEYWORD_IF_MODIFIER: {
pm_token_t keyword = parser->current;
parser_lex(parser);
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_if_node_modifier_create(parser, node, &keyword, predicate);
+ return UP(pm_if_node_modifier_create(parser, node, &keyword, predicate));
}
case PM_TOKEN_KEYWORD_UNLESS_MODIFIER: {
pm_token_t keyword = parser->current;
parser_lex(parser);
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_unless_node_modifier_create(parser, node, &keyword, predicate);
+ return UP(pm_unless_node_modifier_create(parser, node, &keyword, predicate));
}
case PM_TOKEN_KEYWORD_UNTIL_MODIFIER: {
parser_lex(parser);
@@ -21867,7 +21337,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_statements_node_body_append(parser, statements, node, true);
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
+ return UP(pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0));
}
case PM_TOKEN_KEYWORD_WHILE_MODIFIER: {
parser_lex(parser);
@@ -21875,7 +21345,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_statements_node_body_append(parser, statements, node, true);
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
+ return UP(pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0));
}
case PM_TOKEN_QUESTION_MARK: {
context_push(parser, PM_CONTEXT_TERNARY);
@@ -21895,13 +21365,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// accidentally move past a ':' token that occurs after the syntax
// error.
pm_token_t colon = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
- pm_node_t *false_expression = (pm_node_t *) pm_missing_node_create(parser, colon.start, colon.end);
+ pm_node_t *false_expression = UP(pm_missing_node_create(parser, colon.start, colon.end));
context_pop(parser);
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
+ return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression));
}
accept1(parser, PM_TOKEN_NEWLINE);
@@ -21914,7 +21384,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
+ return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression));
}
case PM_TOKEN_COLON_COLON: {
parser_lex(parser);
@@ -21939,10 +21409,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_arguments_t arguments = { 0 };
parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
- path = (pm_node_t *) pm_call_node_call_create(parser, node, &delimiter, &message, &arguments);
+ path = UP(pm_call_node_call_create(parser, node, &delimiter, &message, &arguments));
} else {
// Otherwise, this is a constant path. That would look like Foo::Bar.
- path = (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous);
+ path = UP(pm_constant_path_node_create(parser, node, &delimiter, &parser->previous));
}
// If this is followed by a comma then it is a multiple assignment.
@@ -21967,10 +21437,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// If this is followed by a comma then it is a multiple assignment.
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
+ return parse_targets_validate(parser, UP(call), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
- return (pm_node_t *) call;
+ return UP(call);
}
case PM_TOKEN_PARENTHESIS_LEFT: {
// If we have a parenthesis following a '::' operator, then it is the
@@ -21978,11 +21448,11 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_arguments_t arguments = { 0 };
parse_arguments_list(parser, &arguments, true, false, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &delimiter, &arguments);
+ return UP(pm_call_node_shorthand_create(parser, node, &delimiter, &arguments));
}
default: {
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- return (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous);
+ return UP(pm_constant_path_node_create(parser, node, &delimiter, &parser->previous));
}
}
}
@@ -21994,7 +21464,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_node_t *value = parse_expression(parser, binding_power, true, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- return (pm_node_t *) pm_rescue_modifier_node_create(parser, node, &token, value);
+ return UP(pm_rescue_modifier_node_create(parser, node, &token, value));
}
case PM_TOKEN_BRACKET_LEFT: {
parser_lex(parser);
@@ -22015,7 +21485,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// assignment and we should parse the targets.
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
pm_call_node_t *aref = pm_call_node_aref_create(parser, node, &arguments);
- return parse_targets_validate(parser, (pm_node_t *) aref, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
+ return parse_targets_validate(parser, UP(aref), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
// If we're at the end of the arguments, we can now check if there is a
@@ -22031,17 +21501,17 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
if (block != NULL) {
if (arguments.block != NULL) {
- pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_AFTER_BLOCK);
+ pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_AFTER_BLOCK);
if (arguments.arguments == NULL) {
arguments.arguments = pm_arguments_node_create(parser);
}
pm_arguments_node_arguments_append(arguments.arguments, arguments.block);
}
- arguments.block = (pm_node_t *) block;
+ arguments.block = UP(block);
}
- return (pm_node_t *) pm_call_node_aref_create(parser, node, &arguments);
+ return UP(pm_call_node_aref_create(parser, node, &arguments));
}
case PM_TOKEN_KEYWORD_IN: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -22058,7 +21528,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
pm_constant_id_list_free(&captures);
- return (pm_node_t *) pm_match_predicate_node_create(parser, node, pattern, &operator);
+ return UP(pm_match_predicate_node_create(parser, node, pattern, &operator));
}
case PM_TOKEN_EQUAL_GREATER: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -22075,7 +21545,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
pm_constant_id_list_free(&captures);
- return (pm_node_t *) pm_match_required_node_create(parser, node, pattern, &operator);
+ return UP(pm_match_required_node_create(parser, node, pattern, &operator));
}
default:
assert(false && "unreachable");
@@ -22112,7 +21582,7 @@ static pm_node_t *
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) {
if (PRISM_UNLIKELY(depth >= PRISM_DEPTH_MAXIMUM)) {
pm_parser_err_current(parser, PM_ERR_NESTING_TOO_DEEP);
- return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
}
pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth);
@@ -22169,6 +21639,12 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
) {
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1));
+ if (context_terminator(parser->current_context->context, &parser->current)) {
+ // If this token terminates the current context, then we need to
+ // stop parsing the expression, as it has become a statement.
+ return node;
+ }
+
switch (PM_NODE_TYPE(node)) {
case PM_MULTI_WRITE_NODE:
// Multi-write nodes are statements, and cannot be followed by
@@ -22300,14 +21776,14 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) {
pm_arguments_node_t *arguments = pm_arguments_node_create(parser);
pm_arguments_node_arguments_append(
arguments,
- (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2))
+ UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2)))
);
- pm_statements_node_body_append(parser, statements, (pm_node_t *) pm_call_node_fcall_synthesized_create(
+ pm_statements_node_body_append(parser, statements, UP(pm_call_node_fcall_synthesized_create(
parser,
arguments,
pm_parser_constant_id_constant(parser, "print", 5)
- ), true);
+ )), true);
}
if (PM_PARSER_COMMAND_LINE_OPTION_N(parser)) {
@@ -22319,46 +21795,46 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) {
pm_arguments_node_t *arguments = pm_arguments_node_create(parser);
pm_arguments_node_arguments_append(
arguments,
- (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$;", 2))
+ UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$;", 2)))
);
pm_global_variable_read_node_t *receiver = pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2));
- pm_call_node_t *call = pm_call_node_call_synthesized_create(parser, (pm_node_t *) receiver, "split", arguments);
+ pm_call_node_t *call = pm_call_node_call_synthesized_create(parser, UP(receiver), "split", arguments);
pm_global_variable_write_node_t *write = pm_global_variable_write_node_synthesized_create(
parser,
pm_parser_constant_id_constant(parser, "$F", 2),
- (pm_node_t *) call
+ UP(call)
);
- pm_statements_node_body_prepend(statements, (pm_node_t *) write);
+ pm_statements_node_body_prepend(statements, UP(write));
}
pm_arguments_node_t *arguments = pm_arguments_node_create(parser);
pm_arguments_node_arguments_append(
arguments,
- (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$/", 2))
+ UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$/", 2)))
);
if (PM_PARSER_COMMAND_LINE_OPTION_L(parser)) {
pm_keyword_hash_node_t *keywords = pm_keyword_hash_node_create(parser);
- pm_keyword_hash_node_elements_append(keywords, (pm_node_t *) pm_assoc_node_create(
+ pm_keyword_hash_node_elements_append(keywords, UP(pm_assoc_node_create(
parser,
- (pm_node_t *) pm_symbol_node_synthesized_create(parser, "chomp"),
+ UP(pm_symbol_node_synthesized_create(parser, "chomp")),
&(pm_token_t) { .type = PM_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start },
- (pm_node_t *) pm_true_node_synthesized_create(parser)
- ));
+ UP(pm_true_node_synthesized_create(parser))
+ )));
- pm_arguments_node_arguments_append(arguments, (pm_node_t *) keywords);
- pm_node_flag_set((pm_node_t *) arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS);
+ pm_arguments_node_arguments_append(arguments, UP(keywords));
+ pm_node_flag_set(UP(arguments), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS);
}
pm_statements_node_t *wrapped_statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, wrapped_statements, (pm_node_t *) pm_while_node_synthesized_create(
+ pm_statements_node_body_append(parser, wrapped_statements, UP(pm_while_node_synthesized_create(
parser,
- (pm_node_t *) pm_call_node_fcall_synthesized_create(parser, arguments, pm_parser_constant_id_constant(parser, "gets", 4)),
+ UP(pm_call_node_fcall_synthesized_create(parser, arguments, pm_parser_constant_id_constant(parser, "gets", 4))),
statements
- ), true);
+ )), true);
statements = wrapped_statements;
}
@@ -22402,9 +21878,10 @@ parse_program(pm_parser_t *parser) {
statements = wrap_statements(parser, statements);
} else {
flush_block_exits(parser, previous_block_exits);
- pm_node_list_free(&current_block_exits);
}
+ pm_node_list_free(&current_block_exits);
+
// If this is an empty file, then we're still going to parse all of the
// statements in order to gather up all of the comments and such. Here we'll
// correct the location information.
@@ -22413,7 +21890,7 @@ parse_program(pm_parser_t *parser) {
pm_statements_node_location_set(statements, parser->start, parser->start);
}
- return (pm_node_t *) pm_program_node_create(parser, &locals, statements);
+ return UP(pm_program_node_create(parser, &locals, statements));
}
/******************************************************************************/
@@ -22433,7 +21910,7 @@ static const char *
pm_strnstr(const char *big, const char *little, size_t big_length) {
size_t little_length = strlen(little);
- for (const char *big_end = big + big_length; big < big_end; big++) {
+ for (const char *max = big + big_length - little_length; big <= max; big++) {
if (*big == *little && memcmp(big, little, little_length) == 0) return big;
}
@@ -22623,6 +22100,12 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
}
}
+ // Now that we have established the user-provided options, check if
+ // a version was given and parse as the latest version otherwise.
+ if (parser->version == PM_OPTIONS_VERSION_UNSET) {
+ parser->version = PM_OPTIONS_VERSION_LATEST;
+ }
+
pm_accepts_block_stack_push(parser, true);
// Skip past the UTF-8 BOM if it exists.
@@ -22656,8 +22139,8 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
// If the shebang does not include "ruby" and this is the main script being
// parsed, then we will start searching the file for a shebang that does
// contain "ruby" as if -x were passed on the command line.
- const uint8_t *newline = next_newline(parser->start, parser->end - parser->start);
- size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->start);
+ const uint8_t *newline = next_newline(parser->current.end, parser->end - parser->current.end);
+ size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->current.end);
if (length > 2 && parser->current.end[0] == '#' && parser->current.end[1] == '!') {
const char *engine;
@@ -22676,7 +22159,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
}
search_shebang = false;
- } else if (options->main_script && !parser->parsing_eval) {
+ } else if (options != NULL && options->main_script && !parser->parsing_eval) {
search_shebang = true;
}
}
@@ -22816,7 +22299,7 @@ pm_parse(pm_parser_t *parser) {
* otherwise return true.
*/
static bool
-pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets) {
+pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof) {
#define LINE_SIZE 4096
char line[LINE_SIZE];
@@ -22852,6 +22335,12 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t
if (strncmp(line, "__END__\r\n", 9) == 0) return false;
break;
}
+
+ // All data should be read via gets. If the string returned by gets
+ // _doesn't_ end with a newline, then we assume we hit EOF condition.
+ if (stream_feof(stream)) {
+ break;
+ }
}
return true;
@@ -22887,16 +22376,17 @@ pm_parse_stream_unterminated_heredoc_p(pm_parser_t *parser) {
* can stream stdin in to Ruby so we need to support a streaming API.
*/
PRISM_EXPORTED_FUNCTION pm_node_t *
-pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, const pm_options_t *options) {
+pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) {
pm_buffer_init(buffer);
- bool eof = pm_parse_stream_read(buffer, stream, stream_fgets);
+ bool eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof);
+
pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options);
pm_node_t *node = pm_parse(parser);
while (!eof && parser->error_list.size > 0 && (parser->lex_modes.index > 0 || pm_parse_stream_unterminated_heredoc_p(parser))) {
pm_node_destroy(parser, node);
- eof = pm_parse_stream_read(buffer, stream, stream_fgets);
+ eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof);
pm_parser_free(parser);
pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options);
@@ -22931,10 +22421,6 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) {
#undef PM_CASE_OPERATOR
#undef PM_CASE_WRITABLE
#undef PM_STRING_EMPTY
-#undef PM_LOCATION_NODE_BASE_VALUE
-#undef PM_LOCATION_NODE_VALUE
-#undef PM_LOCATION_NULL_VALUE
-#undef PM_LOCATION_TOKEN_VALUE
// We optionally support serializing to a binary string. For systems that don't
// want or need this functionality, it can be turned off with the
@@ -22988,13 +22474,13 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons
* given stream into to the given buffer.
*/
PRISM_EXPORTED_FUNCTION void
-pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, const char *data) {
+pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) {
pm_parser_t parser;
pm_options_t options = { 0 };
pm_options_read(&options, data);
pm_buffer_t parser_buffer;
- pm_node_t *node = pm_parse_stream(&parser, &parser_buffer, stream, stream_fgets, &options);
+ pm_node_t *node = pm_parse_stream(&parser, &parser_buffer, stream, stream_fgets, stream_feof, &options);
pm_serialize_header(buffer);
pm_serialize_content(&parser, node, buffer);
pm_buffer_append_byte(buffer, '\0');
diff --git a/prism/prism.h b/prism/prism.h
index 317568aa0c..c468db18be 100644
--- a/prism/prism.h
+++ b/prism/prism.h
@@ -49,10 +49,15 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void);
/**
* Initialize a parser with the given start and end pointers.
*
+ * The resulting parser must eventually be freed with `pm_parser_free()`.
+ *
* @param parser The parser to initialize.
* @param source The source to parse.
* @param size The size of the source.
- * @param options The optional options to use when parsing.
+ * @param options The optional options to use when parsing. These options must
+ * live for the whole lifetime of this parser.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options);
@@ -62,13 +67,20 @@ PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *
*
* @param parser The parser to register the callback with.
* @param callback The callback to register.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION void pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_changed_callback_t callback);
/**
* Free any memory associated with the given parser.
*
+ * This does not free the `pm_options_t` object that was used to initialize the
+ * parser.
+ *
* @param parser The parser to free.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser);
@@ -77,27 +89,39 @@ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser);
*
* @param parser The parser to use.
* @return The AST representing the source.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser);
/**
- * This function is used in pm_parse_stream to retrieve a line of input from a
+ * This function is used in pm_parse_stream() to retrieve a line of input from a
* stream. It closely mirrors that of fgets so that fgets can be used as the
* default implementation.
*/
typedef char * (pm_parse_stream_fgets_t)(char *string, int size, void *stream);
/**
+ * This function is used in pm_parse_stream to check whether a stream is EOF.
+ * It closely mirrors that of feof so that feof can be used as the
+ * default implementation.
+ */
+typedef int (pm_parse_stream_feof_t)(void *stream);
+
+/**
* Parse a stream of Ruby source and return the tree.
*
* @param parser The parser to use.
* @param buffer The buffer to use.
* @param stream The stream to parse.
* @param stream_fgets The function to use to read from the stream.
+ * @param stream_feof The function to use to determine if the stream has hit eof.
* @param options The optional options to use when parsing.
* @return The AST representing the source.
+ *
+ * \public \memberof pm_parser
*/
-PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, const pm_options_t *options);
+PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options);
// We optionally support serializing to a binary string. For systems that don't
// want or need this functionality, it can be turned off with the
@@ -111,9 +135,10 @@ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buff
* @param buffer The buffer to serialize to.
* @param stream The stream to parse.
* @param stream_fgets The function to use to read from the stream.
+ * @param stream_feof The function to use to tell if the stream has hit eof.
* @param data The optional data to pass to the parser.
*/
-PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, const char *data);
+PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data);
/**
* Serialize the given list of comments to the given buffer.
@@ -289,7 +314,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint
* dependencies. It is currently being integrated into
* [CRuby](https://github.com/ruby/ruby),
* [JRuby](https://github.com/jruby/jruby),
- * [TruffleRuby](https://github.com/oracle/truffleruby),
+ * [TruffleRuby](https://github.com/truffleruby/truffleruby),
* [Sorbet](https://github.com/sorbet/sorbet), and
* [Syntax Tree](https://github.com/ruby-syntax-tree/syntax_tree).
*
@@ -307,10 +332,10 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint
* to want to use and be aware of are:
*
* * `pm_parser_t` - the main parser structure
- * * `pm_parser_init` - initialize a parser
- * * `pm_parse` - parse and return the root node
- * * `pm_node_destroy` - deallocate the root node returned by `pm_parse`
- * * `pm_parser_free` - free the internal memory of the parser
+ * * `pm_parser_init()` - initialize a parser
+ * * `pm_parse()` - parse and return the root node
+ * * `pm_node_destroy()` - deallocate the root node returned by `pm_parse()`
+ * * `pm_parser_free()` - free the internal memory of the parser
*
* Putting all of this together would look something like:
*
@@ -327,8 +352,8 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint
* }
* ```
*
- * All of the nodes "inherit" from `pm_node_t` by embedding those structures as
- * their first member. This means you can downcast and upcast any node in the
+ * All of the nodes "inherit" from `pm_node_t` by embedding those structures
+ * as their first member. This means you can downcast and upcast any node in the
* tree to a `pm_node_t`.
*
* @section serializing Serializing
@@ -340,9 +365,9 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint
* use and be aware of are:
*
* * `pm_buffer_t` - a small buffer object that will hold the serialized AST
- * * `pm_buffer_free` - free the memory associated with the buffer
- * * `pm_serialize` - serialize the AST into a buffer
- * * `pm_serialize_parse` - parse and serialize the AST into a buffer
+ * * `pm_buffer_free()` - free the memory associated with the buffer
+ * * `pm_serialize()` - serialize the AST into a buffer
+ * * `pm_serialize_parse()` - parse and serialize the AST into a buffer
*
* Putting all of this together would look something like:
*
@@ -360,7 +385,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint
* @section inspecting Inspecting
*
* Prism provides the ability to inspect the AST by pretty-printing nodes. You
- * can do this with the `pm_prettyprint` function, which you would use like:
+ * can do this with the `pm_prettyprint()` function, which you would use like:
*
* ```c
* void prettyprint(const uint8_t *source, size_t length) {
diff --git a/prism/regexp.h b/prism/regexp.h
index c0b3163e93..5366b5a5a0 100644
--- a/prism/regexp.h
+++ b/prism/regexp.h
@@ -17,12 +17,12 @@
#include <string.h>
/**
- * This callback is called when a named capture group is found.
+ * This callback is called by pm_regexp_parse() when a named capture group is found.
*/
typedef void (*pm_regexp_name_callback_t)(const pm_string_t *name, void *data);
/**
- * This callback is called when a parse error is found.
+ * This callback is called by pm_regexp_parse() when a parse error is found.
*/
typedef void (*pm_regexp_error_callback_t)(const uint8_t *start, const uint8_t *end, const char *message, void *data);
diff --git a/prism/srcs.mk b/prism/srcs.mk
new file mode 100644
index 0000000000..022662a00b
--- /dev/null
+++ b/prism/srcs.mk
@@ -0,0 +1,150 @@
+PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates
+PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb
+PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml
+
+srcs uncommon.mk: prism/.srcs.mk.time
+
+prism/.srcs.mk.time: $(order_only) $(PRISM_BUILD_DIR)/.time
+prism/$(HAVE_BASERUBY:no=.srcs.mk.time):
+ touch $@
+prism/$(HAVE_BASERUBY:yes=.srcs.mk.time): \
+ $(PRISM_SRCDIR)/templates/template.rb \
+ $(PRISM_SRCDIR)/srcs.mk.in
+ $(BASERUBY) $(tooldir)/generic_erb.rb -c -t$@ -o $(PRISM_SRCDIR)/srcs.mk $(PRISM_SRCDIR)/srcs.mk.in
+
+distclean-prism-srcs::
+ $(RM) prism/.srcs.mk.time
+ $(RMDIRS) prism || $(NULLCMD)
+
+distclean-srcs-local:: distclean-prism-srcs
+
+realclean-prism-srcs:: distclean-prism-srcs
+ $(RM) $(PRISM_SRCDIR)/srcs.mk
+
+realclean-srcs-local:: realclean-prism-srcs
+
+main srcs: $(srcdir)/prism/api_node.c
+$(srcdir)/prism/api_node.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/ext/prism/api_node.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) ext/prism/api_node.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/api_node.c
+
+main incs: $(srcdir)/prism/ast.h
+$(srcdir)/prism/ast.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/include/prism/ast.h.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) include/prism/ast.h $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/ast.h
+
+main incs: $(srcdir)/prism/diagnostic.h
+$(srcdir)/prism/diagnostic.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/include/prism/diagnostic.h.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) include/prism/diagnostic.h $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/diagnostic.h
+
+main srcs: $(srcdir)/lib/prism/compiler.rb
+$(srcdir)/lib/prism/compiler.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/compiler.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/compiler.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/compiler.rb
+
+main srcs: $(srcdir)/lib/prism/dispatcher.rb
+$(srcdir)/lib/prism/dispatcher.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dispatcher.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dispatcher.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dispatcher.rb
+
+main srcs: $(srcdir)/lib/prism/dot_visitor.rb
+$(srcdir)/lib/prism/dot_visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dot_visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dot_visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dot_visitor.rb
+
+main srcs: $(srcdir)/lib/prism/dsl.rb
+$(srcdir)/lib/prism/dsl.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dsl.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dsl.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dsl.rb
+
+main srcs: $(srcdir)/lib/prism/inspect_visitor.rb
+$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/inspect_visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/inspect_visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/inspect_visitor.rb
+
+main srcs: $(srcdir)/lib/prism/mutation_compiler.rb
+$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/mutation_compiler.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/mutation_compiler.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/mutation_compiler.rb
+
+main srcs: $(srcdir)/lib/prism/node.rb
+$(srcdir)/lib/prism/node.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/node.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/node.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/node.rb
+
+main srcs: $(srcdir)/lib/prism/reflection.rb
+$(srcdir)/lib/prism/reflection.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/reflection.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/reflection.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/reflection.rb
+
+main srcs: $(srcdir)/lib/prism/serialize.rb
+$(srcdir)/lib/prism/serialize.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/serialize.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/serialize.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/serialize.rb
+
+main srcs: $(srcdir)/lib/prism/visitor.rb
+$(srcdir)/lib/prism/visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/visitor.rb
+
+main srcs: $(srcdir)/prism/diagnostic.c
+$(srcdir)/prism/diagnostic.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/diagnostic.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/diagnostic.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/diagnostic.c
+
+main srcs: $(srcdir)/prism/node.c
+$(srcdir)/prism/node.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/node.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/node.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/node.c
+
+main srcs: $(srcdir)/prism/prettyprint.c
+$(srcdir)/prism/prettyprint.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/prettyprint.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/prettyprint.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/prettyprint.c
+
+main srcs: $(srcdir)/prism/serialize.c
+$(srcdir)/prism/serialize.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/serialize.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/serialize.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/serialize.c
+
+main srcs: $(srcdir)/prism/token_type.c
+$(srcdir)/prism/token_type.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/token_type.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/token_type.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/token_type.c
diff --git a/prism/srcs.mk.in b/prism/srcs.mk.in
new file mode 100644
index 0000000000..cc263fd1b4
--- /dev/null
+++ b/prism/srcs.mk.in
@@ -0,0 +1,48 @@
+<% # -*- ruby -*-
+require_relative 'templates/template'
+
+script = File.basename(__FILE__)
+srcs = output ? File.basename(output) : script.chomp('.in')
+mk = 'uncommon.mk'
+
+# %>
+PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates
+PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb
+PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml
+
+srcs <%=%><%=mk%>: prism/.srcs.mk.time
+
+prism/.srcs.mk.time: $(order_only) $(PRISM_BUILD_DIR)/.time
+prism/$(HAVE_BASERUBY:no=.srcs.mk.time):
+ touch $@
+prism/$(HAVE_BASERUBY:yes=.srcs.mk.time): \
+ $(PRISM_SRCDIR)/templates/template.rb \
+ $(PRISM_SRCDIR)/<%=%><%=script%>
+ $(BASERUBY) $(tooldir)/generic_erb.rb -c -t$@ -o $(PRISM_SRCDIR)/<%=%><%=srcs%> $(PRISM_SRCDIR)/<%=%><%=script%>
+
+distclean-prism-srcs::
+ $(RM) prism/.srcs.mk.time
+ $(RMDIRS) prism || $(NULLCMD)
+
+distclean-srcs-local:: distclean-prism-srcs
+
+realclean-prism-srcs:: distclean-prism-srcs
+ $(RM) $(PRISM_SRCDIR)/<%=%><%=srcs%>
+
+realclean-srcs-local:: realclean-prism-srcs
+<% Prism::Template::TEMPLATES.map do |t|
+ /\.(?:[ch]|rb)\z/ =~ t or next
+ s = '$(srcdir)/' + t.sub(%r[\A(?:(src)|ext|include)/]) {$1 && 'prism/'}
+ s.sub!(%r[\A\$(srcdir)/prism/], '$(PRISM_SRCDIR)/')
+ target = s.end_with?('.h') ? 'incs' : 'srcs'
+# %>
+
+main <%=%><%=target%>: <%=%><%=s%>
+<%=%><%=s%>: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/<%=%><%=t%>.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) <%=%><%=t%> $@
+
+realclean-prism-srcs::
+ $(RM) <%=%><%=s%>
+<%
+end
+# %>
diff --git a/prism/templates/include/prism/ast.h.erb b/prism/templates/include/prism/ast.h.erb
index 751c0b43c2..790cf9ebb8 100644
--- a/prism/templates/include/prism/ast.h.erb
+++ b/prism/templates/include/prism/ast.h.erb
@@ -2,6 +2,8 @@
* @file ast.h
*
* The abstract syntax tree.
+ *
+ * --
*/
#ifndef PRISM_AST_H
#define PRISM_AST_H
@@ -104,22 +106,6 @@ static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = 0x1;
static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = 0x2;
/**
- * Cast the type to an enum to allow the compiler to provide exhaustiveness
- * checking.
- */
-#define PM_NODE_TYPE(node) ((enum pm_node_type) (node)->type)
-
-/**
- * Return true if the type of the given node matches the given type.
- */
-#define PM_NODE_TYPE_P(node, type) (PM_NODE_TYPE(node) == (type))
-
-/**
- * Return true if the given flag is set on the given node.
- */
-#define PM_NODE_FLAG_P(node, flag) ((((pm_node_t *)(node))->flags & (flag)) != 0)
-
-/**
* This is the base structure that represents a node in the syntax tree. It is
* embedded into every node type.
*/
@@ -148,6 +134,32 @@ typedef struct pm_node {
*/
pm_location_t location;
} pm_node_t;
+
+/**
+ * Cast the given node to the base pm_node_t type.
+ */
+#define PM_NODE_UPCAST(node_) ((pm_node_t *) (node_))
+
+/**
+ * Cast the type to an enum to allow the compiler to provide exhaustiveness
+ * checking.
+ */
+#define PM_NODE_TYPE(node_) ((enum pm_node_type) (node_)->type)
+
+/**
+ * Return true if the type of the given node matches the given type.
+ */
+#define PM_NODE_TYPE_P(node_, type_) (PM_NODE_TYPE(node_) == (type_))
+
+/**
+ * Return the flags associated with the given node.
+ */
+#define PM_NODE_FLAGS(node_) (PM_NODE_UPCAST(node_)->flags)
+
+/**
+ * Return true if the given flag is set on the given node.
+ */
+#define PM_NODE_FLAG_P(node_, flag_) ((PM_NODE_FLAGS(node_) & (flag_)) != 0)
<%- nodes.each do |node| -%>
/**
@@ -210,6 +222,8 @@ typedef enum pm_<%= flag.human %> {
/** <%= value.comment %> */
PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << (index + Prism::Template::COMMON_FLAGS_COUNT) %>,
<%- end -%>
+
+ PM_<%= flag.human.upcase %>_LAST,
} pm_<%= flag.human %>_t;
<%- end -%>
diff --git a/prism/templates/lib/prism/compiler.rb.erb b/prism/templates/lib/prism/compiler.rb.erb
index 45ed88d8de..66dbe666b9 100644
--- a/prism/templates/lib/prism/compiler.rb.erb
+++ b/prism/templates/lib/prism/compiler.rb.erb
@@ -29,13 +29,15 @@ module Prism
# Visit the child nodes of the given node.
def visit_child_nodes(node)
- node.compact_child_nodes.map { |node| node.accept(self) }
+ node.each_child_node.map { |node| node.accept(self) }
end
<%- nodes.each_with_index do |node, index| -%>
<%= "\n" if index != 0 -%>
# Compile a <%= node.name %> node
- alias visit_<%= node.human %> visit_child_nodes
+ def visit_<%= node.human %>(node)
+ node.each_child_node.map { |node| node.accept(self) }
+ end
<%- end -%>
end
end
diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb
index ceee2b0ffe..8225bfb328 100644
--- a/prism/templates/lib/prism/node.rb.erb
+++ b/prism/templates/lib/prism/node.rb.erb
@@ -184,24 +184,13 @@ module Prism
queue = [self] #: Array[Prism::node]
result = [] #: Array[Prism::node]
+ search_offset = source.line_to_byte_offset(line) + column
+
while (node = queue.shift)
result << node
- node.compact_child_nodes.each do |child_node|
- child_location = child_node.location
-
- start_line = child_location.start_line
- end_line = child_location.end_line
-
- if start_line == end_line
- if line == start_line && column >= child_location.start_column && column < child_location.end_column
- queue << child_node
- break
- end
- elsif (line == start_line && column >= child_location.start_column) || (line == end_line && column < child_location.end_column)
- queue << child_node
- break
- elsif line > start_line && line < end_line
+ node.each_child_node do |child_node|
+ if child_node.start_offset <= search_offset && search_offset < child_node.end_offset
queue << child_node
break
end
@@ -259,6 +248,13 @@ module Prism
alias deconstruct child_nodes
+ # With a block given, yields each child node. Without a block, returns
+ # an enumerator that contains each child node. Excludes any `nil`s in
+ # the place of optional nodes that were not present.
+ def each_child_node
+ raise NoMethodError, "undefined method `each_child_node' for #{inspect}"
+ end
+
# Returns an array of child nodes, excluding any `nil`s in the place of
# optional nodes that were not present.
def compact_child_nodes
@@ -335,6 +331,22 @@ module Prism
}.compact.join(", ") %>]
end
+ # def each_child_node: () { (Prism::node) -> void } -> void | () -> Enumerator[Prism::node]
+ def each_child_node
+ return to_enum(:each_child_node) unless block_given?
+
+ <%- node.fields.each do |field| -%>
+ <%- case field -%>
+ <%- when Prism::Template::NodeField -%>
+ yield <%= field.name %>
+ <%- when Prism::Template::OptionalNodeField -%>
+ yield <%= field.name %> if <%= field.name %>
+ <%- when Prism::Template::NodeListField -%>
+ <%= field.name %>.each { |node| yield node }
+ <%- end -%>
+ <%- end -%>
+ end
+
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
<%- if node.fields.any? { |field| field.is_a?(Prism::Template::OptionalNodeField) } -%>
diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb
index 104b60f484..6902df5c01 100644
--- a/prism/templates/lib/prism/serialize.rb.erb
+++ b/prism/templates/lib/prism/serialize.rb.erb
@@ -10,7 +10,7 @@ module Prism
# The minor version of prism that we are expecting to find in the serialized
# strings.
- MINOR_VERSION = 4
+ MINOR_VERSION = 8
# The patch version of prism that we are expecting to find in the serialized
# strings.
diff --git a/prism/templates/lib/prism/visitor.rb.erb b/prism/templates/lib/prism/visitor.rb.erb
index 4b30a1815b..76f907724f 100644
--- a/prism/templates/lib/prism/visitor.rb.erb
+++ b/prism/templates/lib/prism/visitor.rb.erb
@@ -20,7 +20,7 @@ module Prism
# Visits the child nodes of `node` by calling `accept` on each one.
def visit_child_nodes(node)
# @type self: _Visitor
- node.compact_child_nodes.each { |node| node.accept(self) }
+ node.each_child_node { |node| node.accept(self) }
end
end
@@ -34,7 +34,7 @@ module Prism
#
# class FooCalls < Prism::Visitor
# def visit_call_node(node)
- # if node.name == "foo"
+ # if node.name == :foo
# # Do something with the node
# end
#
@@ -47,7 +47,9 @@ module Prism
<%- nodes.each_with_index do |node, index| -%>
<%= "\n" if index != 0 -%>
# Visit a <%= node.name %> node
- alias visit_<%= node.human %> visit_child_nodes
+ def visit_<%= node.human %>(node)
+ node.each_child_node { |node| node.accept(self) }
+ end
<%- end -%>
end
end
diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb
index ce98dc5acd..121dd4b2b6 100644
--- a/prism/templates/src/diagnostic.c.erb
+++ b/prism/templates/src/diagnostic.c.erb
@@ -144,6 +144,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_CONDITIONAL_WHILE_PREDICATE] = { "expected a predicate expression for the `while` statement", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = { "expected a constant after the `::` operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_DEF_ENDLESS_PARAMETERS] = { "could not parse the endless method parameters", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX },
@@ -184,6 +185,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_EXPECT_FOR_DELIMITER] = { "unexpected %s; expected a 'do', newline, or ';' after the 'for' loop collection", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_IN_DELIMITER] = { "expected a delimiter after the patterns of an `in` clause", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN] = { "expected a `(` immediately after `not`", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_LPAREN_AFTER_NOT_OTHER] = { "expected a `(` after `not`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_MESSAGE] = { "unexpected %s; expecting a message to send to the receiver", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_LEVEL_SYNTAX },
@@ -298,6 +301,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_PARAMETER_UNEXPECTED_NO_KW] = { "unexpected **nil; no keywords marker disallowed after keywords", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS] = { "unexpected multiple '*' rest patterns in an array pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_CAPTURE_DUPLICATE] = { "duplicated variable name", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_PATTERN_CAPTURE_IN_ALTERNATIVE] = { "variable capture in alternative pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET] = { "expected a pattern expression after `=>`", PM_ERROR_LEVEL_SYNTAX },
@@ -358,6 +362,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_UNEXPECTED_INDEX_KEYWORDS] = { "unexpected keyword arg given in index assignment; keywords are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_LABEL] = { "unexpected label", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_MULTI_WRITE] = { "unexpected multiple assignment; multiple assignment is not allowed in this context", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_UNEXPECTED_PARAMETER_DEFAULT_VALUE] = { "unexpected %s; expected a default value for a parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_RANGE_OPERATOR] = { "unexpected range operator; .. and ... are non-associative and cannot be chained", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_SAFE_NAVIGATION] = { "&. inside multiple assignment destination", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT] = { "unexpected %s, assuming it is closing the parent %s", PM_ERROR_LEVEL_SYNTAX },
diff --git a/prism/templates/src/serialize.c.erb b/prism/templates/src/serialize.c.erb
index 3e15a11039..0f0aace445 100644
--- a/prism/templates/src/serialize.c.erb
+++ b/prism/templates/src/serialize.c.erb
@@ -315,7 +315,7 @@ pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer)
// buffer offset. We will add a leading 1 to indicate that this
// is a buffer offset.
uint32_t content_offset = pm_sizet_to_u32(buffer->length);
- uint32_t owned_mask = (uint32_t) (1 << 31);
+ uint32_t owned_mask = 1U << 31;
assert(content_offset < owned_mask);
content_offset |= owned_mask;
diff --git a/prism/templates/template.rb b/prism/templates/template.rb
index 30cb60cabd..6c3efd7e6c 100755
--- a/prism/templates/template.rb
+++ b/prism/templates/template.rb
@@ -551,11 +551,14 @@ module Prism
when ".rb"
<<~HEADING
# frozen_string_literal: true
+ # :markup: markdown
=begin
+ --
This file is generated by the templates/template.rb script and should not be
modified manually. See #{filepath}
if you are looking to modify the template
+ ++
=end
HEADING
@@ -579,10 +582,12 @@ module Prism
HEADING
else
<<~HEADING
+ /* :markup: markdown */
+
/*----------------------------------------------------------------------------*/
/* This file is generated by the templates/template.rb script and should not */
/* be modified manually. See */
- /* #{filepath + " " * (74 - filepath.size) } */
+ /* #{filepath.ljust(74)} */
/* if you are looking to modify the */
/* template */
/*----------------------------------------------------------------------------*/
diff --git a/prism/util/pm_buffer.h b/prism/util/pm_buffer.h
index f3c20ab2a5..cb80f8b3ce 100644
--- a/prism/util/pm_buffer.h
+++ b/prism/util/pm_buffer.h
@@ -51,6 +51,8 @@ bool pm_buffer_init_capacity(pm_buffer_t *buffer, size_t capacity);
*
* @param buffer The buffer to initialize.
* @returns True if the buffer was initialized successfully, false otherwise.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION bool pm_buffer_init(pm_buffer_t *buffer);
@@ -59,6 +61,8 @@ PRISM_EXPORTED_FUNCTION bool pm_buffer_init(pm_buffer_t *buffer);
*
* @param buffer The buffer to get the value of.
* @returns The value of the buffer.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer);
@@ -67,6 +71,8 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer);
*
* @param buffer The buffer to get the length of.
* @returns The length of the buffer.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer);
@@ -222,6 +228,8 @@ void pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size
* Free the memory associated with the buffer.
*
* @param buffer The buffer to free.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer);
diff --git a/prism/util/pm_constant_pool.c b/prism/util/pm_constant_pool.c
index 38ea01a228..922ce6a18c 100644
--- a/prism/util/pm_constant_pool.c
+++ b/prism/util/pm_constant_pool.c
@@ -264,7 +264,7 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l
// constant and replace it with the shared constant.
xfree((void *) constant->start);
constant->start = start;
- bucket->type = (unsigned int) (PM_CONSTANT_POOL_BUCKET_DEFAULT & 0x3);
+ bucket->type = (unsigned int) (type & 0x3);
}
return bucket->id;
diff --git a/prism/util/pm_integer.h b/prism/util/pm_integer.h
index a9e2966703..304665e620 100644
--- a/prism/util/pm_integer.h
+++ b/prism/util/pm_integer.h
@@ -112,6 +112,8 @@ void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator);
*
* @param buffer The buffer to append the string to.
* @param integer The integer to convert to a string.
+ *
+ * \public \memberof pm_integer_t
*/
PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer);
@@ -120,6 +122,8 @@ PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_int
* the integer exceeds the size of a single node in the linked list.
*
* @param integer The integer to free.
+ *
+ * \public \memberof pm_integer_t
*/
PRISM_EXPORTED_FUNCTION void pm_integer_free(pm_integer_t *integer);
diff --git a/prism/util/pm_list.h b/prism/util/pm_list.h
index 3512dee979..f544bb2943 100644
--- a/prism/util/pm_list.h
+++ b/prism/util/pm_list.h
@@ -68,6 +68,8 @@ typedef struct {
*
* @param list The list to check.
* @return True if the given list is empty, otherwise false.
+ *
+ * \public \memberof pm_list_t
*/
PRISM_EXPORTED_FUNCTION bool pm_list_empty_p(pm_list_t *list);
@@ -76,6 +78,8 @@ PRISM_EXPORTED_FUNCTION bool pm_list_empty_p(pm_list_t *list);
*
* @param list The list to check.
* @return The size of the list.
+ *
+ * \public \memberof pm_list_t
*/
PRISM_EXPORTED_FUNCTION size_t pm_list_size(pm_list_t *list);
@@ -91,6 +95,8 @@ void pm_list_append(pm_list_t *list, pm_list_node_t *node);
* Deallocate the internal state of the given list.
*
* @param list The list to free.
+ *
+ * \public \memberof pm_list_t
*/
PRISM_EXPORTED_FUNCTION void pm_list_free(pm_list_t *list);
diff --git a/prism/util/pm_string.c b/prism/util/pm_string.c
index 75422fbdf2..a7493c468b 100644
--- a/prism/util/pm_string.c
+++ b/prism/util/pm_string.c
@@ -1,5 +1,7 @@
#include "prism/util/pm_string.h"
+static const uint8_t empty_source[] = "";
+
/**
* Returns the size of the pm_string_t struct. This is necessary to allocate the
* correct amount of memory in the FFI backend.
@@ -133,8 +135,7 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
// the source to a constant empty string and return.
if (file_size == 0) {
pm_string_file_handle_close(&handle);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
return PM_STRING_INIT_SUCCESS;
}
@@ -182,8 +183,7 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
if (size == 0) {
close(fd);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
return PM_STRING_INIT_SUCCESS;
}
@@ -225,8 +225,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) {
// the source to a constant empty string and return.
if (file_size == 0) {
pm_string_file_handle_close(&handle);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
return PM_STRING_INIT_SUCCESS;
}
@@ -278,8 +277,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) {
size_t size = (size_t) sb.st_size;
if (size == 0) {
close(fd);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
return PM_STRING_INIT_SUCCESS;
}
diff --git a/prism/util/pm_string.h b/prism/util/pm_string.h
index f99f1abdf3..d8456ff294 100644
--- a/prism/util/pm_string.h
+++ b/prism/util/pm_string.h
@@ -45,11 +45,11 @@ typedef struct {
/** This is a slice of another string, and should not be freed. */
PM_STRING_SHARED,
- /** This string owns its memory, and should be freed using `pm_string_free`. */
+ /** This string owns its memory, and should be freed using `pm_string_free()`. */
PM_STRING_OWNED,
#ifdef PRISM_HAS_MMAP
- /** This string is a memory-mapped file, and should be freed using `pm_string_free`. */
+ /** This string is a memory-mapped file, and should be freed using `pm_string_free()`. */
PM_STRING_MAPPED
#endif
} type;
@@ -130,6 +130,8 @@ typedef enum {
* @param string The string to initialize.
* @param filepath The filepath to read.
* @return The success of the read, indicated by the value of the enum.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath);
@@ -141,6 +143,8 @@ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_
* @param string The string to initialize.
* @param filepath The filepath to read.
* @return The success of the read, indicated by the value of the enum.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath);
@@ -169,6 +173,8 @@ int pm_string_compare(const pm_string_t *left, const pm_string_t *right);
*
* @param string The string to get the length of.
* @return The length of the string.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string);
@@ -177,6 +183,8 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string);
*
* @param string The string to get the start pointer of.
* @return The start pointer of the string.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string);
@@ -184,6 +192,8 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *stri
* Free the associated memory of the given string.
*
* @param string The string to free.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION void pm_string_free(pm_string_t *string);
diff --git a/prism/version.h b/prism/version.h
index 0a2a8c8fce..0ef7435c17 100644
--- a/prism/version.h
+++ b/prism/version.h
@@ -14,7 +14,7 @@
/**
* The minor version of the Prism library as an int.
*/
-#define PRISM_VERSION_MINOR 4
+#define PRISM_VERSION_MINOR 8
/**
* The patch version of the Prism library as an int.
@@ -24,6 +24,6 @@
/**
* The version of the Prism library as a constant string.
*/
-#define PRISM_VERSION "1.4.0"
+#define PRISM_VERSION "1.8.0"
#endif