From 407dd02c1b52b05ba55a179554b29a14e44a4b82 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Mon, 23 Feb 2026 18:40:29 -0800 Subject: [PATCH 1/6] Map M:N thread stack chunks initially as PROT_NONE Previously we initially mapped the full 512MB chunk as PROT_READ|PROD_WRITE and then set a guard page to PROT_NONE the first time a new thread stack is needed. Usually that's okay as we don't touch that memory until it is needed and so it doesn't count towards RSS. However, on Linux even with vm.overcommit_memory=0 (the default) if on a system (like a tiny cloud VM) with <512MB of RAM+swap that would error with. Thread#initialize': can't create Thread: Cannot allocate memory (ThreadError) This changes the chunk to be mapped initially with PROT_NONE, then instead of mapping the guard pages we map in the machine and VM stacks using mprotect. This ensures we don't commit stack memory until it is first used, and as a side benefit any stray pointers into unused stack should segfault. When a stack is freed/reused there is no change from the previous behaviour, we just use madvise and leave the same regions in place. [Bug #21944] --- thread_pthread_mn.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/thread_pthread_mn.c b/thread_pthread_mn.c index 69e81e5fbcf00f..a17d5597d39028 100644 --- a/thread_pthread_mn.c +++ b/thread_pthread_mn.c @@ -194,7 +194,7 @@ nt_alloc_thread_stack_chunk(void) mmap_flags |= MAP_STACK; #endif - const char *m = (void *)mmap(NULL, MSTACK_CHUNK_SIZE, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); + const char *m = (void *)mmap(NULL, MSTACK_CHUNK_SIZE, PROT_NONE, mmap_flags, -1, 0); if (m == MAP_FAILED) { return NULL; } @@ -213,6 +213,12 @@ nt_alloc_thread_stack_chunk(void) VM_ASSERT(stack_count <= UINT16_MAX); + // Enable read/write for the header pages + if (mprotect((void *)m, (size_t)header_page_cnt * MSTACK_PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) { + munmap((void *)m, MSTACK_CHUNK_SIZE); + return NULL; + } + struct nt_stack_chunk_header *ch = (struct nt_stack_chunk_header *)m; ch->start_page = header_page_cnt; @@ -241,7 +247,7 @@ nt_stack_chunk_get_msf(const rb_vm_t *vm, const char *mstack) return (struct nt_machine_stack_footer *)&mstack[msz - sizeof(struct nt_machine_stack_footer)]; } -static void * +static void nt_stack_chunk_get_stack(const rb_vm_t *vm, struct nt_stack_chunk_header *ch, size_t idx, void **vm_stack, void **machine_stack) { // TODO: only support stack going down @@ -266,8 +272,6 @@ nt_stack_chunk_get_stack(const rb_vm_t *vm, struct nt_stack_chunk_header *ch, si *vm_stack = (void *)vstack; *machine_stack = (void *)mstack; - - return (void *)guard_page; } RBIMPL_ATTR_MAYBE_UNUSED() @@ -290,17 +294,6 @@ nt_stack_chunk_dump(void) } } -static int -nt_guard_page(const char *p, size_t len) -{ - if (mprotect((void *)p, len, PROT_NONE) != -1) { - return 0; - } - else { - return errno; - } -} - static int nt_alloc_stack(rb_vm_t *vm, void **vm_stack, void **machine_stack) { @@ -319,8 +312,20 @@ nt_alloc_stack(rb_vm_t *vm, void **vm_stack, void **machine_stack) RUBY_DEBUG_LOG("uninitialized_stack_count:%d", ch->uninitialized_stack_count); size_t idx = ch->stack_count - ch->uninitialized_stack_count--; - void *guard_page = nt_stack_chunk_get_stack(vm, ch, idx, vm_stack, machine_stack); - err = nt_guard_page(guard_page, MSTACK_PAGE_SIZE); + + // The chunk was mapped PROT_NONE; enable the VM stack and + // machine stack pages, leaving the guard page as PROT_NONE. + char *stack_start = nt_stack_chunk_get_stack_start(ch, idx); + size_t vm_stack_size = vm->default_params.thread_vm_stack_size; + size_t mstack_size = nt_thread_stack_size() - vm_stack_size - MSTACK_PAGE_SIZE; + + if (mprotect(stack_start, vm_stack_size, PROT_READ | PROT_WRITE) != 0 || + mprotect(stack_start + vm_stack_size + MSTACK_PAGE_SIZE, mstack_size, PROT_READ | PROT_WRITE) != 0) { + err = errno; + } + else { + nt_stack_chunk_get_stack(vm, ch, idx, vm_stack, machine_stack); + } } else { nt_free_stack_chunks = ch->prev_free_chunk; From 6a4402c905c6b33d1ea640de543cdde5a416170f Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 5 Mar 2026 15:51:08 -0500 Subject: [PATCH 2/6] ZJIT: Optimize load store forwarding (#16228) This PR introduces an almost verbatim implementation of load_store_forward optimization as described in Max's [blog post](https://bernsteinbear.com/blog/toy-load-store/). After this PR is merged, we will add type based alias analysis. --- zjit/src/hir.rs | 71 ++++++++++++++++- zjit/src/hir/opt_tests.rs | 155 +++++++++++++++++++++++++++++++++++--- zjit/src/stats.rs | 1 + 3 files changed, 216 insertions(+), 11 deletions(-) diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 7d8e6041717117..a71946b3c915e3 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -1482,7 +1482,9 @@ impl Insn { Insn::LoadSelf { .. } => Effect::read_write(abstract_heaps::Frame, abstract_heaps::Empty), Insn::LoadField { .. } => Effect::read_write(abstract_heaps::Memory, abstract_heaps::Empty), Insn::StoreField { .. } => effects::Any, - Insn::WriteBarrier { .. } => effects::Any, + // WriteBarrier can write to object flags and mark bits in Allocator memory. + // This is why WriteBarrier writes to the "Memory" effect. We do not yet have a more granular specialization for flags + Insn::WriteBarrier { .. } => Effect::read_write(abstract_heaps::Allocator, abstract_heaps::Allocator.union(abstract_heaps::Memory)), Insn::SetLocal { .. } => effects::Any, Insn::GetSpecialSymbol { .. } => effects::Any, Insn::GetSpecialNumber { .. } => effects::Any, @@ -3385,6 +3387,10 @@ impl Function { } pub fn load_rbasic_flags(&mut self, block: BlockId, recv: InsnId) -> InsnId { + // Technically this also includes the shape (_shape_id) because the (shape, flags) tuple is + // a (u32, u32) inside a u64 at RUBY_OFFSET_RBASIC_FLAGS (offset 0). It's fine to load the + // shape alongside the flags, but make sure not to *store* the shape accidentally by + // writing a u64. self.push_insn(block, Insn::LoadField { recv, id: ID!(_rbasic_flags), offset: RUBY_OFFSET_RBASIC_FLAGS, return_type: types::CUInt64 }) } @@ -4902,6 +4908,66 @@ impl Function { self.infer_types(); } + fn optimize_load_store(&mut self) { + let mut compile_time_heap: HashMap<(InsnId, i32), InsnId> = HashMap::new(); + for block in self.rpo() { + let old_insns = std::mem::take(&mut self.blocks[block.0].insns); + let mut new_insns = vec![]; + for insn_id in old_insns { + let replacement_insn: InsnId = match self.find(insn_id) { + Insn::StoreField { recv, offset, val, .. } => { + let key = (self.chase_insn(recv), offset); + let heap_entry = compile_time_heap.get(&key).copied(); + // TODO(Jacob): Switch from actual to partial equality + if Some(val) == heap_entry { + // If the value is already stored, short circuit and don't add an instruction to the block + continue + } + // TODO(Jacob): Add TBAA to avoid removing so many entries + compile_time_heap.retain(|(_, off), _| *off != offset); + compile_time_heap.insert(key, val); + insn_id + }, + Insn::LoadField { recv, offset, .. } => { + let key = (self.chase_insn(recv), offset); + match compile_time_heap.entry(key) { + std::collections::hash_map::Entry::Occupied(entry) => { + // If the value is stored already, we should short circuit. + // However, we need to replace insn_id with its representative in the SSA union. + self.make_equal_to(insn_id, *entry.get()); + continue + } + std::collections::hash_map::Entry::Vacant(_) => { + // If the value has not been accessed, cache a copy to optimize future loads or stores. + compile_time_heap.insert(key, insn_id); + } + } + insn_id + } + Insn::WriteBarrier { .. } => { + // Currently, WriteBarrier write effects are Allocator and Memory when we'd really like them to be flags. + // We don't use LoadField for mark bits so we can ignore them for now. + // But flags does not exist in our effects abstract heap modeling and we don't want to add special casing to effects. + // This special casing in this pass here should be removed once we refine our effects system to provide greater granularity for WriteBarrier. + // TODO: use TBAA + let offset = RUBY_OFFSET_RBASIC_FLAGS; + compile_time_heap.retain(|(_, off), _| *off != offset); + insn_id + }, + insn => { + // If an instruction affects memory and we haven't modeled it, the compile_time_heap is invalidated + if insn.effects_of().includes(Effect::write(abstract_heaps::Memory)) { + compile_time_heap.clear(); + } + insn_id + } + }; + new_insns.push(replacement_insn); + } + self.blocks[block.0].insns = new_insns; + } + } + /// Fold a binary operator on fixnums. fn fold_fixnum_bop(&mut self, insn_id: InsnId, left: InsnId, right: InsnId, f: impl FnOnce(Option, Option) -> Option) -> InsnId { f(self.type_of(left).fixnum_value(), self.type_of(right).fixnum_value()) @@ -5471,6 +5537,8 @@ impl Function { || ident_equal!($name, optimize_getivar) || ident_equal!($name, optimize_c_calls) { Counter::compile_hir_strength_reduce_time_ns + } else if ident_equal!($name, optimize_load_store) { + Counter::compile_hir_optimize_load_store_time_ns } else if ident_equal!($name, fold_constants) { Counter::compile_hir_fold_constants_time_ns } else if ident_equal!($name, clean_cfg) { @@ -5501,6 +5569,7 @@ impl Function { run_pass!(inline); run_pass!(optimize_getivar); run_pass!(optimize_c_calls); + run_pass!(optimize_load_store); run_pass!(fold_constants); run_pass!(clean_cfg); run_pass!(remove_redundant_patch_points); diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs index b7b11a47f77d2e..239e3c65949860 100644 --- a/zjit/src/hir/opt_tests.rs +++ b/zjit/src/hir/opt_tests.rs @@ -5205,8 +5205,6 @@ mod hir_opt_tests { v14:HeapBasicObject = RefineType v6, HeapBasicObject v17:Fixnum[2] = Const Value(2) PatchPoint SingleRactorMode - v36:CShape = LoadField v14, :_shape_id@0x1000 - v37:CShape[0x1003] = GuardBitEquals v36, CShape(0x1003) StoreField v14, :@bar@0x1004, v17 WriteBarrier v14, v17 v40:CShape[0x1005] = Const CShape(0x1005) @@ -8782,8 +8780,7 @@ mod hir_opt_tests { v33:ArrayExact = GuardType v10, ArrayExact v34:CUInt64 = LoadField v33, :_rbasic_flags@0x1040 v35:CUInt64 = GuardNoBitsSet v34, RUBY_FL_FREEZE=CUInt64(2048) - v36:CUInt64 = LoadField v33, :_rbasic_flags@0x1040 - v37:CUInt64 = GuardNoBitsSet v36, RUBY_ELTS_SHARED=CUInt64(4096) + v37:CUInt64 = GuardNoBitsSet v34, RUBY_ELTS_SHARED=CUInt64(4096) v38:CInt64[1] = UnboxFixnum v17 v39:CInt64 = ArrayLength v33 v40:CInt64[1] = GuardLess v38, v39 @@ -8829,8 +8826,7 @@ mod hir_opt_tests { v38:Fixnum = GuardType v15, Fixnum v39:CUInt64 = LoadField v37, :_rbasic_flags@0x1040 v40:CUInt64 = GuardNoBitsSet v39, RUBY_FL_FREEZE=CUInt64(2048) - v41:CUInt64 = LoadField v37, :_rbasic_flags@0x1040 - v42:CUInt64 = GuardNoBitsSet v41, RUBY_ELTS_SHARED=CUInt64(4096) + v42:CUInt64 = GuardNoBitsSet v39, RUBY_ELTS_SHARED=CUInt64(4096) v43:CInt64 = UnboxFixnum v38 v44:CInt64 = ArrayLength v37 v45:CInt64 = GuardLess v43, v44 @@ -13670,8 +13666,6 @@ mod hir_opt_tests { v14:HeapBasicObject = RefineType v6, HeapBasicObject v17:Fixnum[2] = Const Value(2) PatchPoint SingleRactorMode - v50:CShape = LoadField v14, :_shape_id@0x1000 - v51:CShape[0x1003] = GuardBitEquals v50, CShape(0x1003) StoreField v14, :@b@0x1004, v17 WriteBarrier v14, v17 v54:CShape[0x1005] = Const CShape(0x1005) @@ -13679,8 +13673,6 @@ mod hir_opt_tests { v21:HeapBasicObject = RefineType v14, HeapBasicObject v24:Fixnum[3] = Const Value(3) PatchPoint SingleRactorMode - v57:CShape = LoadField v21, :_shape_id@0x1000 - v58:CShape[0x1005] = GuardBitEquals v57, CShape(0x1005) StoreField v21, :@c@0x1006, v24 WriteBarrier v21, v24 v61:CShape[0x1007] = Const CShape(0x1007) @@ -13851,4 +13843,147 @@ mod hir_opt_tests { Jump bb8(v67, v94) "); } + + #[test] + fn test_delete_duplicate_store() { + eval(" + class C + def initialize + a = 1 + @a = a + @a = a + end + end + + C.new + "); + assert_snapshot!(hir_string_proc("C.instance_method(:initialize)"), @" + fn initialize@:4: + bb1(): + EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:NilClass = Const Value(nil) + Jump bb3(v1, v2) + bb2(): + EntryPoint JIT(0) + v5:BasicObject = LoadArg :self@0 + v6:NilClass = Const Value(nil) + Jump bb3(v5, v6) + bb3(v8:BasicObject, v9:NilClass): + v13:Fixnum[1] = Const Value(1) + PatchPoint SingleRactorMode + v35:HeapBasicObject = GuardType v8, HeapBasicObject + v36:CShape = LoadField v35, :_shape_id@0x1000 + v37:CShape[0x1001] = GuardBitEquals v36, CShape(0x1001) + StoreField v35, :@a@0x1002, v13 + WriteBarrier v35, v13 + v40:CShape[0x1003] = Const CShape(0x1003) + StoreField v35, :_shape_id@0x1000, v40 + v20:HeapBasicObject = RefineType v8, HeapBasicObject + PatchPoint NoEPEscape(initialize) + PatchPoint SingleRactorMode + WriteBarrier v20, v13 + CheckInterrupts + Return v13 + "); + } + + #[test] + fn test_remove_duplicate_store_with_non_effectful_insns_between() { + eval(" + class C + def initialize + a = 1 + @a = a + b = 5 + b += a + @a = a + end + end + + C.new + "); + assert_snapshot!(hir_string_proc("C.instance_method(:initialize)"), @" + fn initialize@:4: + bb1(): + EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:NilClass = Const Value(nil) + v3:NilClass = Const Value(nil) + Jump bb3(v1, v2, v3) + bb2(): + EntryPoint JIT(0) + v6:BasicObject = LoadArg :self@0 + v7:NilClass = Const Value(nil) + v8:NilClass = Const Value(nil) + Jump bb3(v6, v7, v8) + bb3(v10:BasicObject, v11:NilClass, v12:NilClass): + v16:Fixnum[1] = Const Value(1) + PatchPoint SingleRactorMode + v49:HeapBasicObject = GuardType v10, HeapBasicObject + v50:CShape = LoadField v49, :_shape_id@0x1000 + v51:CShape[0x1001] = GuardBitEquals v50, CShape(0x1001) + StoreField v49, :@a@0x1002, v16 + WriteBarrier v49, v16 + v54:CShape[0x1003] = Const CShape(0x1003) + StoreField v49, :_shape_id@0x1000, v54 + v23:HeapBasicObject = RefineType v10, HeapBasicObject + v26:Fixnum[5] = Const Value(5) + PatchPoint NoEPEscape(initialize) + PatchPoint MethodRedefined(Integer@0x1008, +@0x1010, cme:0x1018) + v65:Fixnum[6] = Const Value(6) + IncrCounter inline_cfunc_optimized_send_count + PatchPoint SingleRactorMode + WriteBarrier v23, v16 + CheckInterrupts + Return v16 + "); + } + + #[test] + fn test_remove_two_stores() { + eval(" + class C + def initialize + a = 1 + @a = a + @a = a + @a = a + end + end + + C.new + "); + assert_snapshot!(hir_string_proc("C.instance_method(:initialize)"), @" + fn initialize@:4: + bb1(): + EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:NilClass = Const Value(nil) + Jump bb3(v1, v2) + bb2(): + EntryPoint JIT(0) + v5:BasicObject = LoadArg :self@0 + v6:NilClass = Const Value(nil) + Jump bb3(v5, v6) + bb3(v8:BasicObject, v9:NilClass): + v13:Fixnum[1] = Const Value(1) + PatchPoint SingleRactorMode + v43:HeapBasicObject = GuardType v8, HeapBasicObject + v44:CShape = LoadField v43, :_shape_id@0x1000 + v45:CShape[0x1001] = GuardBitEquals v44, CShape(0x1001) + StoreField v43, :@a@0x1002, v13 + WriteBarrier v43, v13 + v48:CShape[0x1003] = Const CShape(0x1003) + StoreField v43, :_shape_id@0x1000, v48 + v20:HeapBasicObject = RefineType v8, HeapBasicObject + PatchPoint NoEPEscape(initialize) + PatchPoint SingleRactorMode + WriteBarrier v20, v13 + v28:HeapBasicObject = RefineType v20, HeapBasicObject + WriteBarrier v28, v13 + CheckInterrupts + Return v13 + "); + } } diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs index 6b5f46a0b06bfa..42dd39fdd047e9 100644 --- a/zjit/src/stats.rs +++ b/zjit/src/stats.rs @@ -167,6 +167,7 @@ make_counters! { compile_hir_time_ns, compile_hir_build_time_ns, compile_hir_strength_reduce_time_ns, + compile_hir_optimize_load_store_time_ns, compile_hir_fold_constants_time_ns, compile_hir_clean_cfg_time_ns, compile_hir_remove_redundant_patch_points_time_ns, From a81136b646f189acc0e08f34ca7b90120c2dac8a Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 5 Mar 2026 21:42:44 +0100 Subject: [PATCH 3/6] [ruby/prism] Revert "Recompile when config.yml changes" * This reverts commit https://github.com/ruby/prism/commit/ffe8f7a6e236. * No longer necessary as the Makefile depends on all *.c and *.h. https://github.com/ruby/prism/commit/5a33460adc --- lib/prism/prism.gemspec | 2 -- prism/depend | 2 -- 2 files changed, 4 deletions(-) delete mode 100644 prism/depend diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 74d54127319aca..b85eeab85516c1 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -42,8 +42,6 @@ Gem::Specification.new do |spec| "docs/serialization.md", "docs/testing.md", "ext/prism/api_node.c", - "ext/prism/depend", - "ext/prism/extconf.rb", "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", diff --git a/prism/depend b/prism/depend deleted file mode 100644 index ac0e7a9bb378ed..00000000000000 --- a/prism/depend +++ /dev/null @@ -1,2 +0,0 @@ -$(OBJS): $(HDRS) $(ruby_headers) -$(OBJS): $(srcdir)/../../config.yml From d789558994b9fc891b88a7751b781cfde521afcf Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 5 Mar 2026 21:43:56 +0100 Subject: [PATCH 4/6] [ruby/prism] Include ext/prism/extconf.rb explicitly in prism.gemspec * For consistency. https://github.com/ruby/prism/commit/d4575f651a --- lib/prism/prism.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index b85eeab85516c1..ae5c56a45de643 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -42,6 +42,7 @@ Gem::Specification.new do |spec| "docs/serialization.md", "docs/testing.md", "ext/prism/api_node.c", + "ext/prism/extconf.rb", "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", From 54eb330f8cc9f5a5b67ccfa5247cd8b98fb1ef44 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 5 Mar 2026 20:41:21 +0100 Subject: [PATCH 5/6] [ruby/prism] Correctly handle `and?` and similar on ruby 4.0 It gets confused for syntax introduced in https://bugs.ruby-lang.org/issues/20925 But it actually should be a plain method call. `!`/`?` are not valid as part of an identifier, methods however allow them as the last character. Fixes [Bug #21946] https://github.com/ruby/prism/commit/5d80bc5e1a --- prism/prism.c | 21 +++++++++++++++++++-- test/prism/fixtures/4.0/leading_logical.txt | 5 ----- test/prism/fixtures/and_or_with_suffix.txt | 17 +++++++++++++++++ test/prism/ruby/ripper_test.rb | 7 +++++++ 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 test/prism/fixtures/and_or_with_suffix.txt diff --git a/prism/prism.c b/prism/prism.c index e10a7710af3de6..b6bc90ebd77234 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -10034,8 +10034,21 @@ parser_lex(pm_parser_t *parser) { 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))) + ( + peek_at(parser, following) == 'a' && + peek_at(parser, following + 1) == 'n' && + peek_at(parser, following + 2) == 'd' && + peek_at(parser, next_content + 3) != '!' && + peek_at(parser, next_content + 3) != '?' && + !char_is_identifier(parser, following + 3, parser->end - (following + 3)) + ) || + ( + peek_at(parser, following) == 'o' && + peek_at(parser, following + 1) == 'r' && + peek_at(parser, next_content + 2) != '!' && + peek_at(parser, next_content + 2) != '?' && + !char_is_identifier(parser, following + 2, parser->end - (following + 2)) + ) ) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); @@ -10106,6 +10119,8 @@ parser_lex(pm_parser_t *parser) { peek_at(parser, next_content) == 'a' && peek_at(parser, next_content + 1) == 'n' && peek_at(parser, next_content + 2) == 'd' && + peek_at(parser, next_content + 3) != '!' && + peek_at(parser, next_content + 3) != '?' && !char_is_identifier(parser, next_content + 3, parser->end - (next_content + 3)) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); @@ -10122,6 +10137,8 @@ parser_lex(pm_parser_t *parser) { if ( peek_at(parser, next_content) == 'o' && peek_at(parser, next_content + 1) == 'r' && + peek_at(parser, next_content + 2) != '!' && + peek_at(parser, next_content + 2) != '?' && !char_is_identifier(parser, next_content + 2, parser->end - (next_content + 2)) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); diff --git a/test/prism/fixtures/4.0/leading_logical.txt b/test/prism/fixtures/4.0/leading_logical.txt index feb5ee245c8b2f..ee87e00d4f10c8 100644 --- a/test/prism/fixtures/4.0/leading_logical.txt +++ b/test/prism/fixtures/4.0/leading_logical.txt @@ -14,8 +14,3 @@ and 3 or 2 or 3 -1 -andfoo - -2 -orfoo diff --git a/test/prism/fixtures/and_or_with_suffix.txt b/test/prism/fixtures/and_or_with_suffix.txt new file mode 100644 index 00000000000000..59ee4d0b88bfe0 --- /dev/null +++ b/test/prism/fixtures/and_or_with_suffix.txt @@ -0,0 +1,17 @@ +foo +and? + +foo +or? + +foo +and! + +foo +or! + +foo +andbar + +foo +orbar diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index ba01732bcb2823..92aa1ad0b31ecc 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -37,6 +37,13 @@ class RipperTest < TestCase ] end + if RUBY_VERSION.start_with?("4.") + incorrect += [ + # https://bugs.ruby-lang.org/issues/21945 + "and_or_with_suffix.txt", + ] + end + # https://bugs.ruby-lang.org/issues/21669 incorrect << "4.1/void_value.txt" # https://bugs.ruby-lang.org/issues/19107 From 45f030f9d7777ba326cb90cf2161d5cb493b35ad Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 5 Mar 2026 17:29:09 -0500 Subject: [PATCH 6/6] [PRISM] Template out node creation functions --- depend | 1 + lib/prism/prism.gemspec | 1 + prism/node_new.h | 4071 ++++++++++++++++++ prism/prism.c | 3206 +++++++------- prism/srcs.mk | 7 + prism/templates/include/prism/node_new.h.erb | 42 + prism/templates/template.rb | 50 + 7 files changed, 5742 insertions(+), 1636 deletions(-) create mode 100644 prism/node_new.h create mode 100644 prism/templates/include/prism/node_new.h.erb diff --git a/depend b/depend index 4d204c82f23a92..ced1dfd6ad8a75 100644 --- a/depend +++ b/depend @@ -11686,6 +11686,7 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/node_new.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/options.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index ae5c56a45de643..d8b86c6fbaa01c 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -52,6 +52,7 @@ Gem::Specification.new do |spec| "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/node.h", + "include/prism/node_new.h", "include/prism/options.h", "include/prism/parser.h", "include/prism/prettyprint.h", diff --git a/prism/node_new.h b/prism/node_new.h new file mode 100644 index 00000000000000..09bfc1a9dc065b --- /dev/null +++ b/prism/node_new.h @@ -0,0 +1,4071 @@ +/*----------------------------------------------------------------------------*/ +/* This file is generated by the templates/template.rb script and should not */ +/* be modified manually. See */ +/* templates/include/prism/node_new.h.erb */ +/* if you are looking to modify the */ +/* template */ +/*----------------------------------------------------------------------------*/ + +/** + * @file node_new.h + * + * Static inline functions for allocating and initializing AST nodes. + * + * -- + */ +#ifndef PRISM_NODE_NEW_H +#define PRISM_NODE_NEW_H + +#include "prism/node.h" + +/** + * Allocate and initialize a new AliasGlobalVariableNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param new_name Represents the new name of the global variable that can be used after aliasing\. + * @param old_name Represents the old name of the global variable that can be used before aliasing\. + * @param keyword_loc The Location of the \`alias\` keyword\. + * @return The newly allocated and initialized node. + */ +static inline pm_alias_global_variable_node_t * +pm_alias_global_variable_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *new_name, struct pm_node *old_name, pm_location_t keyword_loc) { + pm_alias_global_variable_node_t *node = (pm_alias_global_variable_node_t *) pm_arena_alloc(arena, sizeof(pm_alias_global_variable_node_t), PRISM_ALIGNOF(pm_alias_global_variable_node_t)); + + *node = (pm_alias_global_variable_node_t) { + .base = { .type = PM_ALIAS_GLOBAL_VARIABLE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .new_name = new_name, + .old_name = old_name, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new AliasMethodNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param new_name Represents the new name of the method that will be aliased\. + * @param old_name Represents the old name of the method that will be aliased\. + * @param keyword_loc Represents the Location of the \`alias\` keyword\. + * @return The newly allocated and initialized node. + */ +static inline pm_alias_method_node_t * +pm_alias_method_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *new_name, struct pm_node *old_name, pm_location_t keyword_loc) { + pm_alias_method_node_t *node = (pm_alias_method_node_t *) pm_arena_alloc(arena, sizeof(pm_alias_method_node_t), PRISM_ALIGNOF(pm_alias_method_node_t)); + + *node = (pm_alias_method_node_t) { + .base = { .type = PM_ALIAS_METHOD_NODE, .flags = flags, .node_id = node_id, .location = location }, + .new_name = new_name, + .old_name = old_name, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new AlternationPatternNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param left Represents the left side of the expression\. + * @param right Represents the right side of the expression\. + * @param operator_loc Represents the alternation operator Location\. + * @return The newly allocated and initialized node. + */ +static inline pm_alternation_pattern_node_t * +pm_alternation_pattern_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *left, struct pm_node *right, pm_location_t operator_loc) { + pm_alternation_pattern_node_t *node = (pm_alternation_pattern_node_t *) pm_arena_alloc(arena, sizeof(pm_alternation_pattern_node_t), PRISM_ALIGNOF(pm_alternation_pattern_node_t)); + + *node = (pm_alternation_pattern_node_t) { + .base = { .type = PM_ALTERNATION_PATTERN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .left = left, + .right = right, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new AndNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param left Represents the left side of the expression\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param right Represents the right side of the expression\. + * @param operator_loc The Location of the \`and\` keyword or the \`&&\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_and_node_t * +pm_and_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *left, struct pm_node *right, pm_location_t operator_loc) { + pm_and_node_t *node = (pm_and_node_t *) pm_arena_alloc(arena, sizeof(pm_and_node_t), PRISM_ALIGNOF(pm_and_node_t)); + + *node = (pm_and_node_t) { + .base = { .type = PM_AND_NODE, .flags = flags, .node_id = node_id, .location = location }, + .left = left, + .right = right, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ArgumentsNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param arguments The list of arguments, if present\. These can be any [non\-void expressions](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @return The newly allocated and initialized node. + */ +static inline pm_arguments_node_t * +pm_arguments_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t arguments) { + pm_arguments_node_t *node = (pm_arguments_node_t *) pm_arena_alloc(arena, sizeof(pm_arguments_node_t), PRISM_ALIGNOF(pm_arguments_node_t)); + + *node = (pm_arguments_node_t) { + .base = { .type = PM_ARGUMENTS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .arguments = arguments + }; + + return node; +} + +/** + * Allocate and initialize a new ArrayNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param elements Represent the list of zero or more [non\-void expressions](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression) within the array\. + * @param opening_loc Represents the optional source Location for the opening token\. + * @param closing_loc Represents the optional source Location for the closing token\. + * @return The newly allocated and initialized node. + */ +static inline pm_array_node_t * +pm_array_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t elements, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_array_node_t *node = (pm_array_node_t *) pm_arena_alloc(arena, sizeof(pm_array_node_t), PRISM_ALIGNOF(pm_array_node_t)); + + *node = (pm_array_node_t) { + .base = { .type = PM_ARRAY_NODE, .flags = flags, .node_id = node_id, .location = location }, + .elements = elements, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ArrayPatternNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param constant Represents the optional constant preceding the Array + * @param requireds Represents the required elements of the array pattern\. + * @param rest Represents the rest element of the array pattern\. + * @param posts Represents the elements after the rest element of the array pattern\. + * @param opening_loc Represents the opening Location of the array pattern\. + * @param closing_loc Represents the closing Location of the array pattern\. + * @return The newly allocated and initialized node. + */ +static inline pm_array_pattern_node_t * +pm_array_pattern_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *constant, pm_node_list_t requireds, struct pm_node *rest, pm_node_list_t posts, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_array_pattern_node_t *node = (pm_array_pattern_node_t *) pm_arena_alloc(arena, sizeof(pm_array_pattern_node_t), PRISM_ALIGNOF(pm_array_pattern_node_t)); + + *node = (pm_array_pattern_node_t) { + .base = { .type = PM_ARRAY_PATTERN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .constant = constant, + .requireds = requireds, + .rest = rest, + .posts = posts, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new AssocNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param key The key of the association\. This can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param value The value of the association, if present\. This can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc The Location of the \`=\>\` operator, if present\. + * @return The newly allocated and initialized node. + */ +static inline pm_assoc_node_t * +pm_assoc_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *key, struct pm_node *value, pm_location_t operator_loc) { + pm_assoc_node_t *node = (pm_assoc_node_t *) pm_arena_alloc(arena, sizeof(pm_assoc_node_t), PRISM_ALIGNOF(pm_assoc_node_t)); + + *node = (pm_assoc_node_t) { + .base = { .type = PM_ASSOC_NODE, .flags = flags, .node_id = node_id, .location = location }, + .key = key, + .value = value, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new AssocSplatNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param value The value to be splatted, if present\. Will be missing when keyword rest argument forwarding is used\. + * @param operator_loc The Location of the \`\*\*\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_assoc_splat_node_t * +pm_assoc_splat_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *value, pm_location_t operator_loc) { + pm_assoc_splat_node_t *node = (pm_assoc_splat_node_t *) pm_arena_alloc(arena, sizeof(pm_assoc_splat_node_t), PRISM_ALIGNOF(pm_assoc_splat_node_t)); + + *node = (pm_assoc_splat_node_t) { + .base = { .type = PM_ASSOC_SPLAT_NODE, .flags = flags, .node_id = node_id, .location = location }, + .value = value, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new BackReferenceReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the back\-reference variable, including the leading \`$\`\. + * @return The newly allocated and initialized node. + */ +static inline pm_back_reference_read_node_t * +pm_back_reference_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_back_reference_read_node_t *node = (pm_back_reference_read_node_t *) pm_arena_alloc(arena, sizeof(pm_back_reference_read_node_t), PRISM_ALIGNOF(pm_back_reference_read_node_t)); + + *node = (pm_back_reference_read_node_t) { + .base = { .type = PM_BACK_REFERENCE_READ_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new BeginNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param begin_keyword_loc Represents the Location of the \`begin\` keyword\. + * @param statements Represents the statements within the begin block\. + * @param rescue_clause Represents the rescue clause within the begin block\. + * @param else_clause Represents the else clause within the begin block\. + * @param ensure_clause Represents the ensure clause within the begin block\. + * @param end_keyword_loc Represents the Location of the \`end\` keyword\. + * @return The newly allocated and initialized node. + */ +static inline pm_begin_node_t * +pm_begin_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t begin_keyword_loc, struct pm_statements_node *statements, struct pm_rescue_node *rescue_clause, struct pm_else_node *else_clause, struct pm_ensure_node *ensure_clause, pm_location_t end_keyword_loc) { + pm_begin_node_t *node = (pm_begin_node_t *) pm_arena_alloc(arena, sizeof(pm_begin_node_t), PRISM_ALIGNOF(pm_begin_node_t)); + + *node = (pm_begin_node_t) { + .base = { .type = PM_BEGIN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .begin_keyword_loc = begin_keyword_loc, + .statements = statements, + .rescue_clause = rescue_clause, + .else_clause = else_clause, + .ensure_clause = ensure_clause, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new BlockArgumentNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param expression The expression that is being passed as a block argument\. This can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc Represents the Location of the \`&\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_block_argument_node_t * +pm_block_argument_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *expression, pm_location_t operator_loc) { + pm_block_argument_node_t *node = (pm_block_argument_node_t *) pm_arena_alloc(arena, sizeof(pm_block_argument_node_t), PRISM_ALIGNOF(pm_block_argument_node_t)); + + *node = (pm_block_argument_node_t) { + .base = { .type = PM_BLOCK_ARGUMENT_NODE, .flags = flags, .node_id = node_id, .location = location }, + .expression = expression, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new BlockLocalVariableNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the block local variable\. + * @return The newly allocated and initialized node. + */ +static inline pm_block_local_variable_node_t * +pm_block_local_variable_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_block_local_variable_node_t *node = (pm_block_local_variable_node_t *) pm_arena_alloc(arena, sizeof(pm_block_local_variable_node_t), PRISM_ALIGNOF(pm_block_local_variable_node_t)); + + *node = (pm_block_local_variable_node_t) { + .base = { .type = PM_BLOCK_LOCAL_VARIABLE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new BlockNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param locals The local variables declared in the block\. + * @param parameters The parameters of the block\. + * @param body The body of the block\. + * @param opening_loc Represents the Location of the opening \`{\` or \`do\`\. + * @param closing_loc Represents the Location of the closing \`}\` or \`end\`\. + * @return The newly allocated and initialized node. + */ +static inline pm_block_node_t * +pm_block_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_list_t locals, struct pm_node *parameters, struct pm_node *body, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_block_node_t *node = (pm_block_node_t *) pm_arena_alloc(arena, sizeof(pm_block_node_t), PRISM_ALIGNOF(pm_block_node_t)); + + *node = (pm_block_node_t) { + .base = { .type = PM_BLOCK_NODE, .flags = flags, .node_id = node_id, .location = location }, + .locals = locals, + .parameters = parameters, + .body = body, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new BlockParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the block parameter\. + * @param name_loc Represents the Location of the block parameter name\. + * @param operator_loc Represents the Location of the \`&\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_block_parameter_node_t * +pm_block_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc) { + pm_block_parameter_node_t *node = (pm_block_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_block_parameter_node_t), PRISM_ALIGNOF(pm_block_parameter_node_t)); + + *node = (pm_block_parameter_node_t) { + .base = { .type = PM_BLOCK_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new BlockParametersNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param parameters Represents the parameters of the block\. + * @param locals Represents the local variables of the block\. + * @param opening_loc Represents the opening Location of the block parameters\. + * @param closing_loc Represents the closing Location of the block parameters\. + * @return The newly allocated and initialized node. + */ +static inline pm_block_parameters_node_t * +pm_block_parameters_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_parameters_node *parameters, pm_node_list_t locals, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_block_parameters_node_t *node = (pm_block_parameters_node_t *) pm_arena_alloc(arena, sizeof(pm_block_parameters_node_t), PRISM_ALIGNOF(pm_block_parameters_node_t)); + + *node = (pm_block_parameters_node_t) { + .base = { .type = PM_BLOCK_PARAMETERS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .parameters = parameters, + .locals = locals, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new BreakNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param arguments The arguments to the break statement, if present\. These can be any [non\-void expressions](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param keyword_loc The Location of the \`break\` keyword\. + * @return The newly allocated and initialized node. + */ +static inline pm_break_node_t * +pm_break_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_arguments_node *arguments, pm_location_t keyword_loc) { + pm_break_node_t *node = (pm_break_node_t *) pm_arena_alloc(arena, sizeof(pm_break_node_t), PRISM_ALIGNOF(pm_break_node_t)); + + *node = (pm_break_node_t) { + .base = { .type = PM_BREAK_NODE, .flags = flags, .node_id = node_id, .location = location }, + .arguments = arguments, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new CallAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The object that the method is being called on\. This can be either \`nil\` or any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param call_operator_loc Represents the Location of the call operator\. + * @param message_loc Represents the Location of the message\. + * @param read_name Represents the name of the method being called\. + * @param write_name Represents the name of the method being written to\. + * @param operator_loc Represents the Location of the operator\. + * @param value Represents the value being assigned\. + * @return The newly allocated and initialized node. + */ +static inline pm_call_and_write_node_t * +pm_call_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_location_t message_loc, pm_constant_id_t read_name, pm_constant_id_t write_name, pm_location_t operator_loc, struct pm_node *value) { + pm_call_and_write_node_t *node = (pm_call_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_call_and_write_node_t), PRISM_ALIGNOF(pm_call_and_write_node_t)); + + *node = (pm_call_and_write_node_t) { + .base = { .type = PM_CALL_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .message_loc = message_loc, + .read_name = read_name, + .write_name = write_name, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new CallNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The object that the method is being called on\. This can be either \`nil\` or any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param call_operator_loc Represents the Location of the call operator\. + * @param name Represents the name of the method being called\. + * @param message_loc Represents the Location of the message\. + * @param opening_loc Represents the Location of the left parenthesis\. + * @param arguments Represents the arguments to the method call\. These can be any [non\-void expressions](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param closing_loc Represents the Location of the right parenthesis\. + * @param equal_loc Represents the Location of the equal sign, in the case that this is an attribute write\. + * @param block Represents the block that is being passed to the method\. + * @return The newly allocated and initialized node. + */ +static inline pm_call_node_t * +pm_call_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_constant_id_t name, pm_location_t message_loc, pm_location_t opening_loc, struct pm_arguments_node *arguments, pm_location_t closing_loc, pm_location_t equal_loc, struct pm_node *block) { + pm_call_node_t *node = (pm_call_node_t *) pm_arena_alloc(arena, sizeof(pm_call_node_t), PRISM_ALIGNOF(pm_call_node_t)); + + *node = (pm_call_node_t) { + .base = { .type = PM_CALL_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .name = name, + .message_loc = message_loc, + .opening_loc = opening_loc, + .arguments = arguments, + .closing_loc = closing_loc, + .equal_loc = equal_loc, + .block = block + }; + + return node; +} + +/** + * Allocate and initialize a new CallOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The object that the method is being called on\. This can be either \`nil\` or any [non\-void expressions](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param call_operator_loc Represents the Location of the call operator\. + * @param message_loc Represents the Location of the message\. + * @param read_name Represents the name of the method being called\. + * @param write_name Represents the name of the method being written to\. + * @param binary_operator Represents the binary operator being used\. + * @param binary_operator_loc Represents the Location of the binary operator\. + * @param value Represents the value being assigned\. + * @return The newly allocated and initialized node. + */ +static inline pm_call_operator_write_node_t * +pm_call_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_location_t message_loc, pm_constant_id_t read_name, pm_constant_id_t write_name, pm_constant_id_t binary_operator, pm_location_t binary_operator_loc, struct pm_node *value) { + pm_call_operator_write_node_t *node = (pm_call_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_call_operator_write_node_t), PRISM_ALIGNOF(pm_call_operator_write_node_t)); + + *node = (pm_call_operator_write_node_t) { + .base = { .type = PM_CALL_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .message_loc = message_loc, + .read_name = read_name, + .write_name = write_name, + .binary_operator = binary_operator, + .binary_operator_loc = binary_operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new CallOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The object that the method is being called on\. This can be either \`nil\` or any [non\-void expressions](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param call_operator_loc Represents the Location of the call operator\. + * @param message_loc Represents the Location of the message\. + * @param read_name Represents the name of the method being called\. + * @param write_name Represents the name of the method being written to\. + * @param operator_loc Represents the Location of the operator\. + * @param value Represents the value being assigned\. + * @return The newly allocated and initialized node. + */ +static inline pm_call_or_write_node_t * +pm_call_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_location_t message_loc, pm_constant_id_t read_name, pm_constant_id_t write_name, pm_location_t operator_loc, struct pm_node *value) { + pm_call_or_write_node_t *node = (pm_call_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_call_or_write_node_t), PRISM_ALIGNOF(pm_call_or_write_node_t)); + + *node = (pm_call_or_write_node_t) { + .base = { .type = PM_CALL_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .message_loc = message_loc, + .read_name = read_name, + .write_name = write_name, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new CallTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The object that the method is being called on\. This can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param call_operator_loc Represents the Location of the call operator\. + * @param name Represents the name of the method being called\. + * @param message_loc Represents the Location of the message\. + * @return The newly allocated and initialized node. + */ +static inline pm_call_target_node_t * +pm_call_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_constant_id_t name, pm_location_t message_loc) { + pm_call_target_node_t *node = (pm_call_target_node_t *) pm_arena_alloc(arena, sizeof(pm_call_target_node_t), PRISM_ALIGNOF(pm_call_target_node_t)); + + *node = (pm_call_target_node_t) { + .base = { .type = PM_CALL_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .name = name, + .message_loc = message_loc + }; + + return node; +} + +/** + * Allocate and initialize a new CapturePatternNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param value Represents the value to capture\. + * @param target Represents the target of the capture\. + * @param operator_loc Represents the Location of the \`=\>\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_capture_pattern_node_t * +pm_capture_pattern_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *value, struct pm_local_variable_target_node *target, pm_location_t operator_loc) { + pm_capture_pattern_node_t *node = (pm_capture_pattern_node_t *) pm_arena_alloc(arena, sizeof(pm_capture_pattern_node_t), PRISM_ALIGNOF(pm_capture_pattern_node_t)); + + *node = (pm_capture_pattern_node_t) { + .base = { .type = PM_CAPTURE_PATTERN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .value = value, + .target = target, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new CaseMatchNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param predicate Represents the predicate of the case match\. This can be either \`nil\` or any [non\-void expressions](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param conditions Represents the conditions of the case match\. + * @param else_clause Represents the else clause of the case match\. + * @param case_keyword_loc Represents the Location of the \`case\` keyword\. + * @param end_keyword_loc Represents the Location of the \`end\` keyword\. + * @return The newly allocated and initialized node. + */ +static inline pm_case_match_node_t * +pm_case_match_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *predicate, pm_node_list_t conditions, struct pm_else_node *else_clause, pm_location_t case_keyword_loc, pm_location_t end_keyword_loc) { + pm_case_match_node_t *node = (pm_case_match_node_t *) pm_arena_alloc(arena, sizeof(pm_case_match_node_t), PRISM_ALIGNOF(pm_case_match_node_t)); + + *node = (pm_case_match_node_t) { + .base = { .type = PM_CASE_MATCH_NODE, .flags = flags, .node_id = node_id, .location = location }, + .predicate = predicate, + .conditions = conditions, + .else_clause = else_clause, + .case_keyword_loc = case_keyword_loc, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new CaseNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param predicate 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)\. + * @param conditions Represents the conditions of the case statement\. + * @param else_clause Represents the else clause of the case statement\. + * @param case_keyword_loc Represents the Location of the \`case\` keyword\. + * @param end_keyword_loc Represents the Location of the \`end\` keyword\. + * @return The newly allocated and initialized node. + */ +static inline pm_case_node_t * +pm_case_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *predicate, pm_node_list_t conditions, struct pm_else_node *else_clause, pm_location_t case_keyword_loc, pm_location_t end_keyword_loc) { + pm_case_node_t *node = (pm_case_node_t *) pm_arena_alloc(arena, sizeof(pm_case_node_t), PRISM_ALIGNOF(pm_case_node_t)); + + *node = (pm_case_node_t) { + .base = { .type = PM_CASE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .predicate = predicate, + .conditions = conditions, + .else_clause = else_clause, + .case_keyword_loc = case_keyword_loc, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ClassNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param locals The locals field. + * @param class_keyword_loc Represents the Location of the \`class\` keyword\. + * @param constant_path The constant_path field. + * @param inheritance_operator_loc Represents the Location of the \`\<\` operator\. + * @param superclass Represents the superclass of the class\. + * @param body Represents the body of the class\. + * @param end_keyword_loc Represents the Location of the \`end\` keyword\. + * @param name The name of the class\. + * @return The newly allocated and initialized node. + */ +static inline pm_class_node_t * +pm_class_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_list_t locals, pm_location_t class_keyword_loc, struct pm_node *constant_path, pm_location_t inheritance_operator_loc, struct pm_node *superclass, struct pm_node *body, pm_location_t end_keyword_loc, pm_constant_id_t name) { + pm_class_node_t *node = (pm_class_node_t *) pm_arena_alloc(arena, sizeof(pm_class_node_t), PRISM_ALIGNOF(pm_class_node_t)); + + *node = (pm_class_node_t) { + .base = { .type = PM_CLASS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .locals = locals, + .class_keyword_loc = class_keyword_loc, + .constant_path = constant_path, + .inheritance_operator_loc = inheritance_operator_loc, + .superclass = superclass, + .body = body, + .end_keyword_loc = end_keyword_loc, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new ClassVariableAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the class variable, which is a \`@@\` followed by an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifiers)\. + * @param name_loc Represents the Location of the variable name\. + * @param operator_loc Represents the Location of the \`&&=\` operator\. + * @param value Represents the value being assigned\. This can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @return The newly allocated and initialized node. + */ +static inline pm_class_variable_and_write_node_t * +pm_class_variable_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_class_variable_and_write_node_t *node = (pm_class_variable_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_class_variable_and_write_node_t), PRISM_ALIGNOF(pm_class_variable_and_write_node_t)); + + *node = (pm_class_variable_and_write_node_t) { + .base = { .type = PM_CLASS_VARIABLE_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ClassVariableOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param binary_operator_loc The binary_operator_loc field. + * @param value The value field. + * @param binary_operator The binary_operator field. + * @return The newly allocated and initialized node. + */ +static inline pm_class_variable_operator_write_node_t * +pm_class_variable_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t binary_operator_loc, struct pm_node *value, pm_constant_id_t binary_operator) { + pm_class_variable_operator_write_node_t *node = (pm_class_variable_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_class_variable_operator_write_node_t), PRISM_ALIGNOF(pm_class_variable_operator_write_node_t)); + + *node = (pm_class_variable_operator_write_node_t) { + .base = { .type = PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .binary_operator_loc = binary_operator_loc, + .value = value, + .binary_operator = binary_operator + }; + + return node; +} + +/** + * Allocate and initialize a new ClassVariableOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_class_variable_or_write_node_t * +pm_class_variable_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_class_variable_or_write_node_t *node = (pm_class_variable_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_class_variable_or_write_node_t), PRISM_ALIGNOF(pm_class_variable_or_write_node_t)); + + *node = (pm_class_variable_or_write_node_t) { + .base = { .type = PM_CLASS_VARIABLE_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ClassVariableReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the class variable, which is a \`@@\` followed by an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifiers)\. + * @return The newly allocated and initialized node. + */ +static inline pm_class_variable_read_node_t * +pm_class_variable_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_class_variable_read_node_t *node = (pm_class_variable_read_node_t *) pm_arena_alloc(arena, sizeof(pm_class_variable_read_node_t), PRISM_ALIGNOF(pm_class_variable_read_node_t)); + + *node = (pm_class_variable_read_node_t) { + .base = { .type = PM_CLASS_VARIABLE_READ_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new ClassVariableTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @return The newly allocated and initialized node. + */ +static inline pm_class_variable_target_node_t * +pm_class_variable_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_class_variable_target_node_t *node = (pm_class_variable_target_node_t *) pm_arena_alloc(arena, sizeof(pm_class_variable_target_node_t), PRISM_ALIGNOF(pm_class_variable_target_node_t)); + + *node = (pm_class_variable_target_node_t) { + .base = { .type = PM_CLASS_VARIABLE_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new ClassVariableWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the class variable, which is a \`@@\` followed by an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifiers)\. + * @param name_loc The Location of the variable name\. + * @param value The value to write to the class variable\. This can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc The Location of the \`=\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_class_variable_write_node_t * +pm_class_variable_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, struct pm_node *value, pm_location_t operator_loc) { + pm_class_variable_write_node_t *node = (pm_class_variable_write_node_t *) pm_arena_alloc(arena, sizeof(pm_class_variable_write_node_t), PRISM_ALIGNOF(pm_class_variable_write_node_t)); + + *node = (pm_class_variable_write_node_t) { + .base = { .type = PM_CLASS_VARIABLE_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .value = value, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_and_write_node_t * +pm_constant_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_constant_and_write_node_t *node = (pm_constant_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_and_write_node_t), PRISM_ALIGNOF(pm_constant_and_write_node_t)); + + *node = (pm_constant_and_write_node_t) { + .base = { .type = PM_CONSTANT_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param binary_operator_loc The binary_operator_loc field. + * @param value The value field. + * @param binary_operator The binary_operator field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_operator_write_node_t * +pm_constant_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t binary_operator_loc, struct pm_node *value, pm_constant_id_t binary_operator) { + pm_constant_operator_write_node_t *node = (pm_constant_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_operator_write_node_t), PRISM_ALIGNOF(pm_constant_operator_write_node_t)); + + *node = (pm_constant_operator_write_node_t) { + .base = { .type = PM_CONSTANT_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .binary_operator_loc = binary_operator_loc, + .value = value, + .binary_operator = binary_operator + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_or_write_node_t * +pm_constant_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_constant_or_write_node_t *node = (pm_constant_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_or_write_node_t), PRISM_ALIGNOF(pm_constant_or_write_node_t)); + + *node = (pm_constant_or_write_node_t) { + .base = { .type = PM_CONSTANT_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantPathAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param target The target field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_path_and_write_node_t * +pm_constant_path_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_constant_path_node *target, pm_location_t operator_loc, struct pm_node *value) { + pm_constant_path_and_write_node_t *node = (pm_constant_path_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_path_and_write_node_t), PRISM_ALIGNOF(pm_constant_path_and_write_node_t)); + + *node = (pm_constant_path_and_write_node_t) { + .base = { .type = PM_CONSTANT_PATH_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .target = target, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantPathNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param parent The left\-hand node of the path, if present\. It can be \`nil\` or any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. It will be \`nil\` when the constant lookup is at the root of the module tree\. + * @param name The name of the constant being accessed\. This could be \`nil\` in the event of a syntax error\. + * @param delimiter_loc The Location of the \`::\` delimiter\. + * @param name_loc The Location of the name of the constant\. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_path_node_t * +pm_constant_path_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *parent, pm_constant_id_t name, pm_location_t delimiter_loc, pm_location_t name_loc) { + pm_constant_path_node_t *node = (pm_constant_path_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_path_node_t), PRISM_ALIGNOF(pm_constant_path_node_t)); + + *node = (pm_constant_path_node_t) { + .base = { .type = PM_CONSTANT_PATH_NODE, .flags = flags, .node_id = node_id, .location = location }, + .parent = parent, + .name = name, + .delimiter_loc = delimiter_loc, + .name_loc = name_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantPathOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param target The target field. + * @param binary_operator_loc The binary_operator_loc field. + * @param value The value field. + * @param binary_operator The binary_operator field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_path_operator_write_node_t * +pm_constant_path_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_constant_path_node *target, pm_location_t binary_operator_loc, struct pm_node *value, pm_constant_id_t binary_operator) { + pm_constant_path_operator_write_node_t *node = (pm_constant_path_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_path_operator_write_node_t), PRISM_ALIGNOF(pm_constant_path_operator_write_node_t)); + + *node = (pm_constant_path_operator_write_node_t) { + .base = { .type = PM_CONSTANT_PATH_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .target = target, + .binary_operator_loc = binary_operator_loc, + .value = value, + .binary_operator = binary_operator + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantPathOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param target The target field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_path_or_write_node_t * +pm_constant_path_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_constant_path_node *target, pm_location_t operator_loc, struct pm_node *value) { + pm_constant_path_or_write_node_t *node = (pm_constant_path_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_path_or_write_node_t), PRISM_ALIGNOF(pm_constant_path_or_write_node_t)); + + *node = (pm_constant_path_or_write_node_t) { + .base = { .type = PM_CONSTANT_PATH_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .target = target, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantPathTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param parent The parent field. + * @param name The name field. + * @param delimiter_loc The delimiter_loc field. + * @param name_loc The name_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_path_target_node_t * +pm_constant_path_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *parent, pm_constant_id_t name, pm_location_t delimiter_loc, pm_location_t name_loc) { + pm_constant_path_target_node_t *node = (pm_constant_path_target_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_path_target_node_t), PRISM_ALIGNOF(pm_constant_path_target_node_t)); + + *node = (pm_constant_path_target_node_t) { + .base = { .type = PM_CONSTANT_PATH_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .parent = parent, + .name = name, + .delimiter_loc = delimiter_loc, + .name_loc = name_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantPathWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param target A node representing the constant path being written to\. + * @param operator_loc The Location of the \`=\` operator\. + * @param value The value to write to the constant path\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_path_write_node_t * +pm_constant_path_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_constant_path_node *target, pm_location_t operator_loc, struct pm_node *value) { + pm_constant_path_write_node_t *node = (pm_constant_path_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_path_write_node_t), PRISM_ALIGNOF(pm_constant_path_write_node_t)); + + *node = (pm_constant_path_write_node_t) { + .base = { .type = PM_CONSTANT_PATH_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .target = target, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the [constant](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#constants)\. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_read_node_t * +pm_constant_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_constant_read_node_t *node = (pm_constant_read_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_read_node_t), PRISM_ALIGNOF(pm_constant_read_node_t)); + + *node = (pm_constant_read_node_t) { + .base = { .type = PM_CONSTANT_READ_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_target_node_t * +pm_constant_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_constant_target_node_t *node = (pm_constant_target_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_target_node_t), PRISM_ALIGNOF(pm_constant_target_node_t)); + + *node = (pm_constant_target_node_t) { + .base = { .type = PM_CONSTANT_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new ConstantWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the [constant](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#constants)\. + * @param name_loc The Location of the constant name\. + * @param value The value to write to the constant\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc The Location of the \`=\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_constant_write_node_t * +pm_constant_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, struct pm_node *value, pm_location_t operator_loc) { + pm_constant_write_node_t *node = (pm_constant_write_node_t *) pm_arena_alloc(arena, sizeof(pm_constant_write_node_t), PRISM_ALIGNOF(pm_constant_write_node_t)); + + *node = (pm_constant_write_node_t) { + .base = { .type = PM_CONSTANT_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .value = value, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new DefNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param receiver The receiver field. + * @param parameters The parameters field. + * @param body The body field. + * @param locals The locals field. + * @param def_keyword_loc The def_keyword_loc field. + * @param operator_loc The operator_loc field. + * @param lparen_loc The lparen_loc field. + * @param rparen_loc The rparen_loc field. + * @param equal_loc The equal_loc field. + * @param end_keyword_loc The end_keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_def_node_t * +pm_def_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, struct pm_node *receiver, struct pm_parameters_node *parameters, struct pm_node *body, pm_constant_id_list_t locals, pm_location_t def_keyword_loc, pm_location_t operator_loc, pm_location_t lparen_loc, pm_location_t rparen_loc, pm_location_t equal_loc, pm_location_t end_keyword_loc) { + pm_def_node_t *node = (pm_def_node_t *) pm_arena_alloc(arena, sizeof(pm_def_node_t), PRISM_ALIGNOF(pm_def_node_t)); + + *node = (pm_def_node_t) { + .base = { .type = PM_DEF_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .receiver = receiver, + .parameters = parameters, + .body = body, + .locals = locals, + .def_keyword_loc = def_keyword_loc, + .operator_loc = operator_loc, + .lparen_loc = lparen_loc, + .rparen_loc = rparen_loc, + .equal_loc = equal_loc, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new DefinedNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param lparen_loc The lparen_loc field. + * @param value The value field. + * @param rparen_loc The rparen_loc field. + * @param keyword_loc The keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_defined_node_t * +pm_defined_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t lparen_loc, struct pm_node *value, pm_location_t rparen_loc, pm_location_t keyword_loc) { + pm_defined_node_t *node = (pm_defined_node_t *) pm_arena_alloc(arena, sizeof(pm_defined_node_t), PRISM_ALIGNOF(pm_defined_node_t)); + + *node = (pm_defined_node_t) { + .base = { .type = PM_DEFINED_NODE, .flags = flags, .node_id = node_id, .location = location }, + .lparen_loc = lparen_loc, + .value = value, + .rparen_loc = rparen_loc, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ElseNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param else_keyword_loc The else_keyword_loc field. + * @param statements The statements field. + * @param end_keyword_loc The end_keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_else_node_t * +pm_else_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t else_keyword_loc, struct pm_statements_node *statements, pm_location_t end_keyword_loc) { + pm_else_node_t *node = (pm_else_node_t *) pm_arena_alloc(arena, sizeof(pm_else_node_t), PRISM_ALIGNOF(pm_else_node_t)); + + *node = (pm_else_node_t) { + .base = { .type = PM_ELSE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .else_keyword_loc = else_keyword_loc, + .statements = statements, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new EmbeddedStatementsNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param statements The statements field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_embedded_statements_node_t * +pm_embedded_statements_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, struct pm_statements_node *statements, pm_location_t closing_loc) { + pm_embedded_statements_node_t *node = (pm_embedded_statements_node_t *) pm_arena_alloc(arena, sizeof(pm_embedded_statements_node_t), PRISM_ALIGNOF(pm_embedded_statements_node_t)); + + *node = (pm_embedded_statements_node_t) { + .base = { .type = PM_EMBEDDED_STATEMENTS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .statements = statements, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new EmbeddedVariableNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param operator_loc The operator_loc field. + * @param variable The variable field. + * @return The newly allocated and initialized node. + */ +static inline pm_embedded_variable_node_t * +pm_embedded_variable_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t operator_loc, struct pm_node *variable) { + pm_embedded_variable_node_t *node = (pm_embedded_variable_node_t *) pm_arena_alloc(arena, sizeof(pm_embedded_variable_node_t), PRISM_ALIGNOF(pm_embedded_variable_node_t)); + + *node = (pm_embedded_variable_node_t) { + .base = { .type = PM_EMBEDDED_VARIABLE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .operator_loc = operator_loc, + .variable = variable + }; + + return node; +} + +/** + * Allocate and initialize a new EnsureNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param ensure_keyword_loc The ensure_keyword_loc field. + * @param statements The statements field. + * @param end_keyword_loc The end_keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_ensure_node_t * +pm_ensure_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t ensure_keyword_loc, struct pm_statements_node *statements, pm_location_t end_keyword_loc) { + pm_ensure_node_t *node = (pm_ensure_node_t *) pm_arena_alloc(arena, sizeof(pm_ensure_node_t), PRISM_ALIGNOF(pm_ensure_node_t)); + + *node = (pm_ensure_node_t) { + .base = { .type = PM_ENSURE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .ensure_keyword_loc = ensure_keyword_loc, + .statements = statements, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new FalseNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_false_node_t * +pm_false_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_false_node_t *node = (pm_false_node_t *) pm_arena_alloc(arena, sizeof(pm_false_node_t), PRISM_ALIGNOF(pm_false_node_t)); + + *node = (pm_false_node_t) { + .base = { .type = PM_FALSE_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new FindPatternNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param constant Represents the optional constant preceding the pattern + * @param left Represents the first wildcard node in the pattern\. + * @param requireds Represents the nodes in between the wildcards\. + * @param right Represents the second wildcard node in the pattern\. + * @param opening_loc The Location of the opening brace\. + * @param closing_loc The Location of the closing brace\. + * @return The newly allocated and initialized node. + */ +static inline pm_find_pattern_node_t * +pm_find_pattern_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *constant, struct pm_splat_node *left, pm_node_list_t requireds, struct pm_node *right, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_find_pattern_node_t *node = (pm_find_pattern_node_t *) pm_arena_alloc(arena, sizeof(pm_find_pattern_node_t), PRISM_ALIGNOF(pm_find_pattern_node_t)); + + *node = (pm_find_pattern_node_t) { + .base = { .type = PM_FIND_PATTERN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .constant = constant, + .left = left, + .requireds = requireds, + .right = right, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new FlipFlopNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param left The left field. + * @param right The right field. + * @param operator_loc The operator_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_flip_flop_node_t * +pm_flip_flop_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *left, struct pm_node *right, pm_location_t operator_loc) { + pm_flip_flop_node_t *node = (pm_flip_flop_node_t *) pm_arena_alloc(arena, sizeof(pm_flip_flop_node_t), PRISM_ALIGNOF(pm_flip_flop_node_t)); + + *node = (pm_flip_flop_node_t) { + .base = { .type = PM_FLIP_FLOP_NODE, .flags = flags, .node_id = node_id, .location = location }, + .left = left, + .right = right, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new FloatNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param value The value of the floating point number as a Float\. + * @return The newly allocated and initialized node. + */ +static inline pm_float_node_t * +pm_float_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, double value) { + pm_float_node_t *node = (pm_float_node_t *) pm_arena_alloc(arena, sizeof(pm_float_node_t), PRISM_ALIGNOF(pm_float_node_t)); + + *node = (pm_float_node_t) { + .base = { .type = PM_FLOAT_NODE, .flags = flags, .node_id = node_id, .location = location }, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ForNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param index The index expression for \`for\` loops\. + * @param collection The collection to iterate over\. + * @param statements Represents the body of statements to execute for each iteration of the loop\. + * @param for_keyword_loc The Location of the \`for\` keyword\. + * @param in_keyword_loc The Location of the \`in\` keyword\. + * @param do_keyword_loc The Location of the \`do\` keyword, if present\. + * @param end_keyword_loc The Location of the \`end\` keyword\. + * @return The newly allocated and initialized node. + */ +static inline pm_for_node_t * +pm_for_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *index, struct pm_node *collection, struct pm_statements_node *statements, pm_location_t for_keyword_loc, pm_location_t in_keyword_loc, pm_location_t do_keyword_loc, pm_location_t end_keyword_loc) { + pm_for_node_t *node = (pm_for_node_t *) pm_arena_alloc(arena, sizeof(pm_for_node_t), PRISM_ALIGNOF(pm_for_node_t)); + + *node = (pm_for_node_t) { + .base = { .type = PM_FOR_NODE, .flags = flags, .node_id = node_id, .location = location }, + .index = index, + .collection = collection, + .statements = statements, + .for_keyword_loc = for_keyword_loc, + .in_keyword_loc = in_keyword_loc, + .do_keyword_loc = do_keyword_loc, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ForwardingArgumentsNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_forwarding_arguments_node_t * +pm_forwarding_arguments_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_forwarding_arguments_node_t *node = (pm_forwarding_arguments_node_t *) pm_arena_alloc(arena, sizeof(pm_forwarding_arguments_node_t), PRISM_ALIGNOF(pm_forwarding_arguments_node_t)); + + *node = (pm_forwarding_arguments_node_t) { + .base = { .type = PM_FORWARDING_ARGUMENTS_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new ForwardingParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_forwarding_parameter_node_t * +pm_forwarding_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_forwarding_parameter_node_t *node = (pm_forwarding_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_forwarding_parameter_node_t), PRISM_ALIGNOF(pm_forwarding_parameter_node_t)); + + *node = (pm_forwarding_parameter_node_t) { + .base = { .type = PM_FORWARDING_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new ForwardingSuperNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param block All other arguments are forwarded as normal, except the original block is replaced with the new block\. + * @return The newly allocated and initialized node. + */ +static inline pm_forwarding_super_node_t * +pm_forwarding_super_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_block_node *block) { + pm_forwarding_super_node_t *node = (pm_forwarding_super_node_t *) pm_arena_alloc(arena, sizeof(pm_forwarding_super_node_t), PRISM_ALIGNOF(pm_forwarding_super_node_t)); + + *node = (pm_forwarding_super_node_t) { + .base = { .type = PM_FORWARDING_SUPER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .block = block + }; + + return node; +} + +/** + * Allocate and initialize a new GlobalVariableAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_global_variable_and_write_node_t * +pm_global_variable_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_global_variable_and_write_node_t *node = (pm_global_variable_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_global_variable_and_write_node_t), PRISM_ALIGNOF(pm_global_variable_and_write_node_t)); + + *node = (pm_global_variable_and_write_node_t) { + .base = { .type = PM_GLOBAL_VARIABLE_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new GlobalVariableOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param binary_operator_loc The binary_operator_loc field. + * @param value The value field. + * @param binary_operator The binary_operator field. + * @return The newly allocated and initialized node. + */ +static inline pm_global_variable_operator_write_node_t * +pm_global_variable_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t binary_operator_loc, struct pm_node *value, pm_constant_id_t binary_operator) { + pm_global_variable_operator_write_node_t *node = (pm_global_variable_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_global_variable_operator_write_node_t), PRISM_ALIGNOF(pm_global_variable_operator_write_node_t)); + + *node = (pm_global_variable_operator_write_node_t) { + .base = { .type = PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .binary_operator_loc = binary_operator_loc, + .value = value, + .binary_operator = binary_operator + }; + + return node; +} + +/** + * Allocate and initialize a new GlobalVariableOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_global_variable_or_write_node_t * +pm_global_variable_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_global_variable_or_write_node_t *node = (pm_global_variable_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_global_variable_or_write_node_t), PRISM_ALIGNOF(pm_global_variable_or_write_node_t)); + + *node = (pm_global_variable_or_write_node_t) { + .base = { .type = PM_GLOBAL_VARIABLE_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new GlobalVariableReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the global variable, which is a \`$\` followed by an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifier)\. Alternatively, it can be one of the special global variables designated by a symbol\. + * @return The newly allocated and initialized node. + */ +static inline pm_global_variable_read_node_t * +pm_global_variable_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_global_variable_read_node_t *node = (pm_global_variable_read_node_t *) pm_arena_alloc(arena, sizeof(pm_global_variable_read_node_t), PRISM_ALIGNOF(pm_global_variable_read_node_t)); + + *node = (pm_global_variable_read_node_t) { + .base = { .type = PM_GLOBAL_VARIABLE_READ_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new GlobalVariableTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @return The newly allocated and initialized node. + */ +static inline pm_global_variable_target_node_t * +pm_global_variable_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_global_variable_target_node_t *node = (pm_global_variable_target_node_t *) pm_arena_alloc(arena, sizeof(pm_global_variable_target_node_t), PRISM_ALIGNOF(pm_global_variable_target_node_t)); + + *node = (pm_global_variable_target_node_t) { + .base = { .type = PM_GLOBAL_VARIABLE_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new GlobalVariableWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the global variable, which is a \`$\` followed by an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifier)\. Alternatively, it can be one of the special global variables designated by a symbol\. + * @param name_loc The Location of the global variable's name\. + * @param value The value to write to the global variable\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc The Location of the \`=\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_global_variable_write_node_t * +pm_global_variable_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, struct pm_node *value, pm_location_t operator_loc) { + pm_global_variable_write_node_t *node = (pm_global_variable_write_node_t *) pm_arena_alloc(arena, sizeof(pm_global_variable_write_node_t), PRISM_ALIGNOF(pm_global_variable_write_node_t)); + + *node = (pm_global_variable_write_node_t) { + .base = { .type = PM_GLOBAL_VARIABLE_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .value = value, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new HashNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The Location of the opening brace\. + * @param elements The elements of the hash\. These can be either \`AssocNode\`s or \`AssocSplatNode\`s\. + * @param closing_loc The Location of the closing brace\. + * @return The newly allocated and initialized node. + */ +static inline pm_hash_node_t * +pm_hash_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_node_list_t elements, pm_location_t closing_loc) { + pm_hash_node_t *node = (pm_hash_node_t *) pm_arena_alloc(arena, sizeof(pm_hash_node_t), PRISM_ALIGNOF(pm_hash_node_t)); + + *node = (pm_hash_node_t) { + .base = { .type = PM_HASH_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .elements = elements, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new HashPatternNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param constant Represents the optional constant preceding the Hash\. + * @param elements Represents the explicit named hash keys and values\. + * @param rest 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\`\. + * @param opening_loc The Location of the opening brace\. + * @param closing_loc The Location of the closing brace\. + * @return The newly allocated and initialized node. + */ +static inline pm_hash_pattern_node_t * +pm_hash_pattern_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *constant, pm_node_list_t elements, struct pm_node *rest, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_hash_pattern_node_t *node = (pm_hash_pattern_node_t *) pm_arena_alloc(arena, sizeof(pm_hash_pattern_node_t), PRISM_ALIGNOF(pm_hash_pattern_node_t)); + + *node = (pm_hash_pattern_node_t) { + .base = { .type = PM_HASH_PATTERN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .constant = constant, + .elements = elements, + .rest = rest, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new IfNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param if_keyword_loc The Location of the \`if\` keyword if present\. + * @param predicate The node for the condition the \`IfNode\` is testing\. + * @param then_keyword_loc The Location of the \`then\` keyword (if present) or the \`?\` in a ternary expression, \`nil\` otherwise\. + * @param statements Represents the body of statements that will be executed when the predicate is evaluated as truthy\. Will be \`nil\` when no body is provided\. + * @param subsequent Represents an \`ElseNode\` or an \`IfNode\` when there is an \`else\` or an \`elsif\` in the \`if\` statement\. + * @param end_keyword_loc The Location of the \`end\` keyword if present, \`nil\` otherwise\. + * @return The newly allocated and initialized node. + */ +static inline pm_if_node_t * +pm_if_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t if_keyword_loc, struct pm_node *predicate, pm_location_t then_keyword_loc, struct pm_statements_node *statements, struct pm_node *subsequent, pm_location_t end_keyword_loc) { + pm_if_node_t *node = (pm_if_node_t *) pm_arena_alloc(arena, sizeof(pm_if_node_t), PRISM_ALIGNOF(pm_if_node_t)); + + *node = (pm_if_node_t) { + .base = { .type = PM_IF_NODE, .flags = flags, .node_id = node_id, .location = location }, + .if_keyword_loc = if_keyword_loc, + .predicate = predicate, + .then_keyword_loc = then_keyword_loc, + .statements = statements, + .subsequent = subsequent, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ImaginaryNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param numeric The numeric field. + * @return The newly allocated and initialized node. + */ +static inline pm_imaginary_node_t * +pm_imaginary_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *numeric) { + pm_imaginary_node_t *node = (pm_imaginary_node_t *) pm_arena_alloc(arena, sizeof(pm_imaginary_node_t), PRISM_ALIGNOF(pm_imaginary_node_t)); + + *node = (pm_imaginary_node_t) { + .base = { .type = PM_IMAGINARY_NODE, .flags = flags, .node_id = node_id, .location = location }, + .numeric = numeric + }; + + return node; +} + +/** + * Allocate and initialize a new ImplicitNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_implicit_node_t * +pm_implicit_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *value) { + pm_implicit_node_t *node = (pm_implicit_node_t *) pm_arena_alloc(arena, sizeof(pm_implicit_node_t), PRISM_ALIGNOF(pm_implicit_node_t)); + + *node = (pm_implicit_node_t) { + .base = { .type = PM_IMPLICIT_NODE, .flags = flags, .node_id = node_id, .location = location }, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new ImplicitRestNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_implicit_rest_node_t * +pm_implicit_rest_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_implicit_rest_node_t *node = (pm_implicit_rest_node_t *) pm_arena_alloc(arena, sizeof(pm_implicit_rest_node_t), PRISM_ALIGNOF(pm_implicit_rest_node_t)); + + *node = (pm_implicit_rest_node_t) { + .base = { .type = PM_IMPLICIT_REST_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new InNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param pattern The pattern field. + * @param statements The statements field. + * @param in_loc The in_loc field. + * @param then_loc The then_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_in_node_t * +pm_in_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *pattern, struct pm_statements_node *statements, pm_location_t in_loc, pm_location_t then_loc) { + pm_in_node_t *node = (pm_in_node_t *) pm_arena_alloc(arena, sizeof(pm_in_node_t), PRISM_ALIGNOF(pm_in_node_t)); + + *node = (pm_in_node_t) { + .base = { .type = PM_IN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .pattern = pattern, + .statements = statements, + .in_loc = in_loc, + .then_loc = then_loc + }; + + return node; +} + +/** + * Allocate and initialize a new IndexAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The receiver field. + * @param call_operator_loc The call_operator_loc field. + * @param opening_loc The opening_loc field. + * @param arguments The arguments field. + * @param closing_loc The closing_loc field. + * @param block The block field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_index_and_write_node_t * +pm_index_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_location_t opening_loc, struct pm_arguments_node *arguments, pm_location_t closing_loc, struct pm_block_argument_node *block, pm_location_t operator_loc, struct pm_node *value) { + pm_index_and_write_node_t *node = (pm_index_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_index_and_write_node_t), PRISM_ALIGNOF(pm_index_and_write_node_t)); + + *node = (pm_index_and_write_node_t) { + .base = { .type = PM_INDEX_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .opening_loc = opening_loc, + .arguments = arguments, + .closing_loc = closing_loc, + .block = block, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new IndexOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The receiver field. + * @param call_operator_loc The call_operator_loc field. + * @param opening_loc The opening_loc field. + * @param arguments The arguments field. + * @param closing_loc The closing_loc field. + * @param block The block field. + * @param binary_operator The binary_operator field. + * @param binary_operator_loc The binary_operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_index_operator_write_node_t * +pm_index_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_location_t opening_loc, struct pm_arguments_node *arguments, pm_location_t closing_loc, struct pm_block_argument_node *block, pm_constant_id_t binary_operator, pm_location_t binary_operator_loc, struct pm_node *value) { + pm_index_operator_write_node_t *node = (pm_index_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_index_operator_write_node_t), PRISM_ALIGNOF(pm_index_operator_write_node_t)); + + *node = (pm_index_operator_write_node_t) { + .base = { .type = PM_INDEX_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .opening_loc = opening_loc, + .arguments = arguments, + .closing_loc = closing_loc, + .block = block, + .binary_operator = binary_operator, + .binary_operator_loc = binary_operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new IndexOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The receiver field. + * @param call_operator_loc The call_operator_loc field. + * @param opening_loc The opening_loc field. + * @param arguments The arguments field. + * @param closing_loc The closing_loc field. + * @param block The block field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_index_or_write_node_t * +pm_index_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t call_operator_loc, pm_location_t opening_loc, struct pm_arguments_node *arguments, pm_location_t closing_loc, struct pm_block_argument_node *block, pm_location_t operator_loc, struct pm_node *value) { + pm_index_or_write_node_t *node = (pm_index_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_index_or_write_node_t), PRISM_ALIGNOF(pm_index_or_write_node_t)); + + *node = (pm_index_or_write_node_t) { + .base = { .type = PM_INDEX_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .call_operator_loc = call_operator_loc, + .opening_loc = opening_loc, + .arguments = arguments, + .closing_loc = closing_loc, + .block = block, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new IndexTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param receiver The receiver field. + * @param opening_loc The opening_loc field. + * @param arguments The arguments field. + * @param closing_loc The closing_loc field. + * @param block The block field. + * @return The newly allocated and initialized node. + */ +static inline pm_index_target_node_t * +pm_index_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *receiver, pm_location_t opening_loc, struct pm_arguments_node *arguments, pm_location_t closing_loc, struct pm_block_argument_node *block) { + pm_index_target_node_t *node = (pm_index_target_node_t *) pm_arena_alloc(arena, sizeof(pm_index_target_node_t), PRISM_ALIGNOF(pm_index_target_node_t)); + + *node = (pm_index_target_node_t) { + .base = { .type = PM_INDEX_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .receiver = receiver, + .opening_loc = opening_loc, + .arguments = arguments, + .closing_loc = closing_loc, + .block = block + }; + + return node; +} + +/** + * Allocate and initialize a new InstanceVariableAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_instance_variable_and_write_node_t * +pm_instance_variable_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_instance_variable_and_write_node_t *node = (pm_instance_variable_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_instance_variable_and_write_node_t), PRISM_ALIGNOF(pm_instance_variable_and_write_node_t)); + + *node = (pm_instance_variable_and_write_node_t) { + .base = { .type = PM_INSTANCE_VARIABLE_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new InstanceVariableOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param binary_operator_loc The binary_operator_loc field. + * @param value The value field. + * @param binary_operator The binary_operator field. + * @return The newly allocated and initialized node. + */ +static inline pm_instance_variable_operator_write_node_t * +pm_instance_variable_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t binary_operator_loc, struct pm_node *value, pm_constant_id_t binary_operator) { + pm_instance_variable_operator_write_node_t *node = (pm_instance_variable_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_instance_variable_operator_write_node_t), PRISM_ALIGNOF(pm_instance_variable_operator_write_node_t)); + + *node = (pm_instance_variable_operator_write_node_t) { + .base = { .type = PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .binary_operator_loc = binary_operator_loc, + .value = value, + .binary_operator = binary_operator + }; + + return node; +} + +/** + * Allocate and initialize a new InstanceVariableOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_instance_variable_or_write_node_t * +pm_instance_variable_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_instance_variable_or_write_node_t *node = (pm_instance_variable_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_instance_variable_or_write_node_t), PRISM_ALIGNOF(pm_instance_variable_or_write_node_t)); + + *node = (pm_instance_variable_or_write_node_t) { + .base = { .type = PM_INSTANCE_VARIABLE_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new InstanceVariableReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the instance variable, which is a \`@\` followed by an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifiers)\. + * @return The newly allocated and initialized node. + */ +static inline pm_instance_variable_read_node_t * +pm_instance_variable_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_instance_variable_read_node_t *node = (pm_instance_variable_read_node_t *) pm_arena_alloc(arena, sizeof(pm_instance_variable_read_node_t), PRISM_ALIGNOF(pm_instance_variable_read_node_t)); + + *node = (pm_instance_variable_read_node_t) { + .base = { .type = PM_INSTANCE_VARIABLE_READ_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new InstanceVariableTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @return The newly allocated and initialized node. + */ +static inline pm_instance_variable_target_node_t * +pm_instance_variable_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_instance_variable_target_node_t *node = (pm_instance_variable_target_node_t *) pm_arena_alloc(arena, sizeof(pm_instance_variable_target_node_t), PRISM_ALIGNOF(pm_instance_variable_target_node_t)); + + *node = (pm_instance_variable_target_node_t) { + .base = { .type = PM_INSTANCE_VARIABLE_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new InstanceVariableWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the instance variable, which is a \`@\` followed by an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifiers)\. + * @param name_loc The Location of the variable name\. + * @param value The value to write to the instance variable\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc The Location of the \`=\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_instance_variable_write_node_t * +pm_instance_variable_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, struct pm_node *value, pm_location_t operator_loc) { + pm_instance_variable_write_node_t *node = (pm_instance_variable_write_node_t *) pm_arena_alloc(arena, sizeof(pm_instance_variable_write_node_t), PRISM_ALIGNOF(pm_instance_variable_write_node_t)); + + *node = (pm_instance_variable_write_node_t) { + .base = { .type = PM_INSTANCE_VARIABLE_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .value = value, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new IntegerNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param value The value of the integer literal as a number\. + * @return The newly allocated and initialized node. + */ +static inline pm_integer_node_t * +pm_integer_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_integer_t value) { + pm_integer_node_t *node = (pm_integer_node_t *) pm_arena_alloc(arena, sizeof(pm_integer_node_t), PRISM_ALIGNOF(pm_integer_node_t)); + + *node = (pm_integer_node_t) { + .base = { .type = PM_INTEGER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new InterpolatedMatchLastLineNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param parts The parts field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_interpolated_match_last_line_node_t * +pm_interpolated_match_last_line_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_node_list_t parts, pm_location_t closing_loc) { + pm_interpolated_match_last_line_node_t *node = (pm_interpolated_match_last_line_node_t *) pm_arena_alloc(arena, sizeof(pm_interpolated_match_last_line_node_t), PRISM_ALIGNOF(pm_interpolated_match_last_line_node_t)); + + *node = (pm_interpolated_match_last_line_node_t) { + .base = { .type = PM_INTERPOLATED_MATCH_LAST_LINE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .parts = parts, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new InterpolatedRegularExpressionNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param parts The parts field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_interpolated_regular_expression_node_t * +pm_interpolated_regular_expression_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_node_list_t parts, pm_location_t closing_loc) { + pm_interpolated_regular_expression_node_t *node = (pm_interpolated_regular_expression_node_t *) pm_arena_alloc(arena, sizeof(pm_interpolated_regular_expression_node_t), PRISM_ALIGNOF(pm_interpolated_regular_expression_node_t)); + + *node = (pm_interpolated_regular_expression_node_t) { + .base = { .type = PM_INTERPOLATED_REGULAR_EXPRESSION_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .parts = parts, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new InterpolatedStringNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param parts The parts field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_interpolated_string_node_t * +pm_interpolated_string_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_node_list_t parts, pm_location_t closing_loc) { + pm_interpolated_string_node_t *node = (pm_interpolated_string_node_t *) pm_arena_alloc(arena, sizeof(pm_interpolated_string_node_t), PRISM_ALIGNOF(pm_interpolated_string_node_t)); + + *node = (pm_interpolated_string_node_t) { + .base = { .type = PM_INTERPOLATED_STRING_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .parts = parts, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new InterpolatedSymbolNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param parts The parts field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_interpolated_symbol_node_t * +pm_interpolated_symbol_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_node_list_t parts, pm_location_t closing_loc) { + pm_interpolated_symbol_node_t *node = (pm_interpolated_symbol_node_t *) pm_arena_alloc(arena, sizeof(pm_interpolated_symbol_node_t), PRISM_ALIGNOF(pm_interpolated_symbol_node_t)); + + *node = (pm_interpolated_symbol_node_t) { + .base = { .type = PM_INTERPOLATED_SYMBOL_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .parts = parts, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new InterpolatedXStringNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param parts The parts field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_interpolated_x_string_node_t * +pm_interpolated_x_string_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_node_list_t parts, pm_location_t closing_loc) { + pm_interpolated_x_string_node_t *node = (pm_interpolated_x_string_node_t *) pm_arena_alloc(arena, sizeof(pm_interpolated_x_string_node_t), PRISM_ALIGNOF(pm_interpolated_x_string_node_t)); + + *node = (pm_interpolated_x_string_node_t) { + .base = { .type = PM_INTERPOLATED_X_STRING_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .parts = parts, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ItLocalVariableReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_it_local_variable_read_node_t * +pm_it_local_variable_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_it_local_variable_read_node_t *node = (pm_it_local_variable_read_node_t *) pm_arena_alloc(arena, sizeof(pm_it_local_variable_read_node_t), PRISM_ALIGNOF(pm_it_local_variable_read_node_t)); + + *node = (pm_it_local_variable_read_node_t) { + .base = { .type = PM_IT_LOCAL_VARIABLE_READ_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new ItParametersNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_it_parameters_node_t * +pm_it_parameters_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_it_parameters_node_t *node = (pm_it_parameters_node_t *) pm_arena_alloc(arena, sizeof(pm_it_parameters_node_t), PRISM_ALIGNOF(pm_it_parameters_node_t)); + + *node = (pm_it_parameters_node_t) { + .base = { .type = PM_IT_PARAMETERS_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new KeywordHashNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param elements The elements field. + * @return The newly allocated and initialized node. + */ +static inline pm_keyword_hash_node_t * +pm_keyword_hash_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t elements) { + pm_keyword_hash_node_t *node = (pm_keyword_hash_node_t *) pm_arena_alloc(arena, sizeof(pm_keyword_hash_node_t), PRISM_ALIGNOF(pm_keyword_hash_node_t)); + + *node = (pm_keyword_hash_node_t) { + .base = { .type = PM_KEYWORD_HASH_NODE, .flags = flags, .node_id = node_id, .location = location }, + .elements = elements + }; + + return node; +} + +/** + * Allocate and initialize a new KeywordRestParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_keyword_rest_parameter_node_t * +pm_keyword_rest_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc) { + pm_keyword_rest_parameter_node_t *node = (pm_keyword_rest_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_keyword_rest_parameter_node_t), PRISM_ALIGNOF(pm_keyword_rest_parameter_node_t)); + + *node = (pm_keyword_rest_parameter_node_t) { + .base = { .type = PM_KEYWORD_REST_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new LambdaNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param locals The locals field. + * @param operator_loc The operator_loc field. + * @param opening_loc The opening_loc field. + * @param closing_loc The closing_loc field. + * @param parameters The parameters field. + * @param body The body field. + * @return The newly allocated and initialized node. + */ +static inline pm_lambda_node_t * +pm_lambda_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_list_t locals, pm_location_t operator_loc, pm_location_t opening_loc, pm_location_t closing_loc, struct pm_node *parameters, struct pm_node *body) { + pm_lambda_node_t *node = (pm_lambda_node_t *) pm_arena_alloc(arena, sizeof(pm_lambda_node_t), PRISM_ALIGNOF(pm_lambda_node_t)); + + *node = (pm_lambda_node_t) { + .base = { .type = PM_LAMBDA_NODE, .flags = flags, .node_id = node_id, .location = location }, + .locals = locals, + .operator_loc = operator_loc, + .opening_loc = opening_loc, + .closing_loc = closing_loc, + .parameters = parameters, + .body = body + }; + + return node; +} + +/** + * Allocate and initialize a new LocalVariableAndWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @param name The name field. + * @param depth The depth field. + * @return The newly allocated and initialized node. + */ +static inline pm_local_variable_and_write_node_t * +pm_local_variable_and_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value, pm_constant_id_t name, uint32_t depth) { + pm_local_variable_and_write_node_t *node = (pm_local_variable_and_write_node_t *) pm_arena_alloc(arena, sizeof(pm_local_variable_and_write_node_t), PRISM_ALIGNOF(pm_local_variable_and_write_node_t)); + + *node = (pm_local_variable_and_write_node_t) { + .base = { .type = PM_LOCAL_VARIABLE_AND_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value, + .name = name, + .depth = depth + }; + + return node; +} + +/** + * Allocate and initialize a new LocalVariableOperatorWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name_loc The name_loc field. + * @param binary_operator_loc The binary_operator_loc field. + * @param value The value field. + * @param name The name field. + * @param binary_operator The binary_operator field. + * @param depth The depth field. + * @return The newly allocated and initialized node. + */ +static inline pm_local_variable_operator_write_node_t * +pm_local_variable_operator_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t name_loc, pm_location_t binary_operator_loc, struct pm_node *value, pm_constant_id_t name, pm_constant_id_t binary_operator, uint32_t depth) { + pm_local_variable_operator_write_node_t *node = (pm_local_variable_operator_write_node_t *) pm_arena_alloc(arena, sizeof(pm_local_variable_operator_write_node_t), PRISM_ALIGNOF(pm_local_variable_operator_write_node_t)); + + *node = (pm_local_variable_operator_write_node_t) { + .base = { .type = PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name_loc = name_loc, + .binary_operator_loc = binary_operator_loc, + .value = value, + .name = name, + .binary_operator = binary_operator, + .depth = depth + }; + + return node; +} + +/** + * Allocate and initialize a new LocalVariableOrWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @param name The name field. + * @param depth The depth field. + * @return The newly allocated and initialized node. + */ +static inline pm_local_variable_or_write_node_t * +pm_local_variable_or_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value, pm_constant_id_t name, uint32_t depth) { + pm_local_variable_or_write_node_t *node = (pm_local_variable_or_write_node_t *) pm_arena_alloc(arena, sizeof(pm_local_variable_or_write_node_t), PRISM_ALIGNOF(pm_local_variable_or_write_node_t)); + + *node = (pm_local_variable_or_write_node_t) { + .base = { .type = PM_LOCAL_VARIABLE_OR_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value, + .name = name, + .depth = depth + }; + + return node; +} + +/** + * Allocate and initialize a new LocalVariableReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the local variable, which is an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifiers)\. + * @param depth The number of visible scopes that should be searched to find the origin of this local variable\. + * @return The newly allocated and initialized node. + */ +static inline pm_local_variable_read_node_t * +pm_local_variable_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, uint32_t depth) { + pm_local_variable_read_node_t *node = (pm_local_variable_read_node_t *) pm_arena_alloc(arena, sizeof(pm_local_variable_read_node_t), PRISM_ALIGNOF(pm_local_variable_read_node_t)); + + *node = (pm_local_variable_read_node_t) { + .base = { .type = PM_LOCAL_VARIABLE_READ_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .depth = depth + }; + + return node; +} + +/** + * Allocate and initialize a new LocalVariableTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param depth The depth field. + * @return The newly allocated and initialized node. + */ +static inline pm_local_variable_target_node_t * +pm_local_variable_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, uint32_t depth) { + pm_local_variable_target_node_t *node = (pm_local_variable_target_node_t *) pm_arena_alloc(arena, sizeof(pm_local_variable_target_node_t), PRISM_ALIGNOF(pm_local_variable_target_node_t)); + + *node = (pm_local_variable_target_node_t) { + .base = { .type = PM_LOCAL_VARIABLE_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .depth = depth + }; + + return node; +} + +/** + * Allocate and initialize a new LocalVariableWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name of the local variable, which is an [identifier](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#identifiers)\. + * @param depth The number of semantic scopes we have to traverse to find the declaration of this variable\. + * @param name_loc The Location of the variable name\. + * @param value The value to write to the local variable\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc The Location of the \`=\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_local_variable_write_node_t * +pm_local_variable_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, uint32_t depth, pm_location_t name_loc, struct pm_node *value, pm_location_t operator_loc) { + pm_local_variable_write_node_t *node = (pm_local_variable_write_node_t *) pm_arena_alloc(arena, sizeof(pm_local_variable_write_node_t), PRISM_ALIGNOF(pm_local_variable_write_node_t)); + + *node = (pm_local_variable_write_node_t) { + .base = { .type = PM_LOCAL_VARIABLE_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .depth = depth, + .name_loc = name_loc, + .value = value, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new MatchLastLineNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param content_loc The content_loc field. + * @param closing_loc The closing_loc field. + * @param unescaped The unescaped field. + * @return The newly allocated and initialized node. + */ +static inline pm_match_last_line_node_t * +pm_match_last_line_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_location_t content_loc, pm_location_t closing_loc, pm_string_t unescaped) { + pm_match_last_line_node_t *node = (pm_match_last_line_node_t *) pm_arena_alloc(arena, sizeof(pm_match_last_line_node_t), PRISM_ALIGNOF(pm_match_last_line_node_t)); + + *node = (pm_match_last_line_node_t) { + .base = { .type = PM_MATCH_LAST_LINE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .content_loc = content_loc, + .closing_loc = closing_loc, + .unescaped = unescaped + }; + + return node; +} + +/** + * Allocate and initialize a new MatchPredicateNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param value The value field. + * @param pattern The pattern field. + * @param operator_loc The operator_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_match_predicate_node_t * +pm_match_predicate_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *value, struct pm_node *pattern, pm_location_t operator_loc) { + pm_match_predicate_node_t *node = (pm_match_predicate_node_t *) pm_arena_alloc(arena, sizeof(pm_match_predicate_node_t), PRISM_ALIGNOF(pm_match_predicate_node_t)); + + *node = (pm_match_predicate_node_t) { + .base = { .type = PM_MATCH_PREDICATE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .value = value, + .pattern = pattern, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new MatchRequiredNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param value Represents the left\-hand side of the operator\. + * @param pattern Represents the right\-hand side of the operator\. The type of the node depends on the expression\. + * @param operator_loc The Location of the operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_match_required_node_t * +pm_match_required_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *value, struct pm_node *pattern, pm_location_t operator_loc) { + pm_match_required_node_t *node = (pm_match_required_node_t *) pm_arena_alloc(arena, sizeof(pm_match_required_node_t), PRISM_ALIGNOF(pm_match_required_node_t)); + + *node = (pm_match_required_node_t) { + .base = { .type = PM_MATCH_REQUIRED_NODE, .flags = flags, .node_id = node_id, .location = location }, + .value = value, + .pattern = pattern, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new MatchWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param call The call field. + * @param targets The targets field. + * @return The newly allocated and initialized node. + */ +static inline pm_match_write_node_t * +pm_match_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_call_node *call, pm_node_list_t targets) { + pm_match_write_node_t *node = (pm_match_write_node_t *) pm_arena_alloc(arena, sizeof(pm_match_write_node_t), PRISM_ALIGNOF(pm_match_write_node_t)); + + *node = (pm_match_write_node_t) { + .base = { .type = PM_MATCH_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .call = call, + .targets = targets + }; + + return node; +} + +/** + * Allocate and initialize a new MissingNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_missing_node_t * +pm_missing_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_missing_node_t *node = (pm_missing_node_t *) pm_arena_alloc(arena, sizeof(pm_missing_node_t), PRISM_ALIGNOF(pm_missing_node_t)); + + *node = (pm_missing_node_t) { + .base = { .type = PM_MISSING_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new ModuleNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param locals The locals field. + * @param module_keyword_loc The module_keyword_loc field. + * @param constant_path The constant_path field. + * @param body The body field. + * @param end_keyword_loc The end_keyword_loc field. + * @param name The name field. + * @return The newly allocated and initialized node. + */ +static inline pm_module_node_t * +pm_module_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_list_t locals, pm_location_t module_keyword_loc, struct pm_node *constant_path, struct pm_node *body, pm_location_t end_keyword_loc, pm_constant_id_t name) { + pm_module_node_t *node = (pm_module_node_t *) pm_arena_alloc(arena, sizeof(pm_module_node_t), PRISM_ALIGNOF(pm_module_node_t)); + + *node = (pm_module_node_t) { + .base = { .type = PM_MODULE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .locals = locals, + .module_keyword_loc = module_keyword_loc, + .constant_path = constant_path, + .body = body, + .end_keyword_loc = end_keyword_loc, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new MultiTargetNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param lefts Represents the targets expressions before a splat node\. + * @param rest Represents a splat node in the target expression\. + * @param rights Represents the targets expressions after a splat node\. + * @param lparen_loc The Location of the opening parenthesis\. + * @param rparen_loc The Location of the closing parenthesis\. + * @return The newly allocated and initialized node. + */ +static inline pm_multi_target_node_t * +pm_multi_target_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t lefts, struct pm_node *rest, pm_node_list_t rights, pm_location_t lparen_loc, pm_location_t rparen_loc) { + pm_multi_target_node_t *node = (pm_multi_target_node_t *) pm_arena_alloc(arena, sizeof(pm_multi_target_node_t), PRISM_ALIGNOF(pm_multi_target_node_t)); + + *node = (pm_multi_target_node_t) { + .base = { .type = PM_MULTI_TARGET_NODE, .flags = flags, .node_id = node_id, .location = location }, + .lefts = lefts, + .rest = rest, + .rights = rights, + .lparen_loc = lparen_loc, + .rparen_loc = rparen_loc + }; + + return node; +} + +/** + * Allocate and initialize a new MultiWriteNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param lefts Represents the targets expressions before a splat node\. + * @param rest Represents a splat node in the target expression\. + * @param rights Represents the targets expressions after a splat node\. + * @param lparen_loc The Location of the opening parenthesis\. + * @param rparen_loc The Location of the closing parenthesis\. + * @param operator_loc The Location of the operator\. + * @param value The value to write to the targets\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @return The newly allocated and initialized node. + */ +static inline pm_multi_write_node_t * +pm_multi_write_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t lefts, struct pm_node *rest, pm_node_list_t rights, pm_location_t lparen_loc, pm_location_t rparen_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_multi_write_node_t *node = (pm_multi_write_node_t *) pm_arena_alloc(arena, sizeof(pm_multi_write_node_t), PRISM_ALIGNOF(pm_multi_write_node_t)); + + *node = (pm_multi_write_node_t) { + .base = { .type = PM_MULTI_WRITE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .lefts = lefts, + .rest = rest, + .rights = rights, + .lparen_loc = lparen_loc, + .rparen_loc = rparen_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new NextNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param arguments The arguments field. + * @param keyword_loc The keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_next_node_t * +pm_next_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_arguments_node *arguments, pm_location_t keyword_loc) { + pm_next_node_t *node = (pm_next_node_t *) pm_arena_alloc(arena, sizeof(pm_next_node_t), PRISM_ALIGNOF(pm_next_node_t)); + + *node = (pm_next_node_t) { + .base = { .type = PM_NEXT_NODE, .flags = flags, .node_id = node_id, .location = location }, + .arguments = arguments, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new NilNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_nil_node_t * +pm_nil_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_nil_node_t *node = (pm_nil_node_t *) pm_arena_alloc(arena, sizeof(pm_nil_node_t), PRISM_ALIGNOF(pm_nil_node_t)); + + *node = (pm_nil_node_t) { + .base = { .type = PM_NIL_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new NoBlockParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param operator_loc The operator_loc field. + * @param keyword_loc The keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_no_block_parameter_node_t * +pm_no_block_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t operator_loc, pm_location_t keyword_loc) { + pm_no_block_parameter_node_t *node = (pm_no_block_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_no_block_parameter_node_t), PRISM_ALIGNOF(pm_no_block_parameter_node_t)); + + *node = (pm_no_block_parameter_node_t) { + .base = { .type = PM_NO_BLOCK_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .operator_loc = operator_loc, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new NoKeywordsParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param operator_loc The operator_loc field. + * @param keyword_loc The keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_no_keywords_parameter_node_t * +pm_no_keywords_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t operator_loc, pm_location_t keyword_loc) { + pm_no_keywords_parameter_node_t *node = (pm_no_keywords_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_no_keywords_parameter_node_t), PRISM_ALIGNOF(pm_no_keywords_parameter_node_t)); + + *node = (pm_no_keywords_parameter_node_t) { + .base = { .type = PM_NO_KEYWORDS_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .operator_loc = operator_loc, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new NumberedParametersNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param maximum The maximum field. + * @return The newly allocated and initialized node. + */ +static inline pm_numbered_parameters_node_t * +pm_numbered_parameters_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, uint8_t maximum) { + pm_numbered_parameters_node_t *node = (pm_numbered_parameters_node_t *) pm_arena_alloc(arena, sizeof(pm_numbered_parameters_node_t), PRISM_ALIGNOF(pm_numbered_parameters_node_t)); + + *node = (pm_numbered_parameters_node_t) { + .base = { .type = PM_NUMBERED_PARAMETERS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .maximum = maximum + }; + + return node; +} + +/** + * Allocate and initialize a new NumberedReferenceReadNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param number The (1\-indexed, from the left) number of the capture group\. Numbered references that are too large result in this value being \`0\`\. + * @return The newly allocated and initialized node. + */ +static inline pm_numbered_reference_read_node_t * +pm_numbered_reference_read_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, uint32_t number) { + pm_numbered_reference_read_node_t *node = (pm_numbered_reference_read_node_t *) pm_arena_alloc(arena, sizeof(pm_numbered_reference_read_node_t), PRISM_ALIGNOF(pm_numbered_reference_read_node_t)); + + *node = (pm_numbered_reference_read_node_t) { + .base = { .type = PM_NUMBERED_REFERENCE_READ_NODE, .flags = flags, .node_id = node_id, .location = location }, + .number = number + }; + + return node; +} + +/** + * Allocate and initialize a new OptionalKeywordParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_optional_keyword_parameter_node_t * +pm_optional_keyword_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, struct pm_node *value) { + pm_optional_keyword_parameter_node_t *node = (pm_optional_keyword_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_optional_keyword_parameter_node_t), PRISM_ALIGNOF(pm_optional_keyword_parameter_node_t)); + + *node = (pm_optional_keyword_parameter_node_t) { + .base = { .type = PM_OPTIONAL_KEYWORD_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new OptionalParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @param value The value field. + * @return The newly allocated and initialized node. + */ +static inline pm_optional_parameter_node_t * +pm_optional_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc, struct pm_node *value) { + pm_optional_parameter_node_t *node = (pm_optional_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_optional_parameter_node_t), PRISM_ALIGNOF(pm_optional_parameter_node_t)); + + *node = (pm_optional_parameter_node_t) { + .base = { .type = PM_OPTIONAL_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc, + .value = value + }; + + return node; +} + +/** + * Allocate and initialize a new OrNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param left Represents the left side of the expression\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param right Represents the right side of the expression\. + * @param operator_loc The Location of the \`or\` keyword or the \`||\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_or_node_t * +pm_or_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *left, struct pm_node *right, pm_location_t operator_loc) { + pm_or_node_t *node = (pm_or_node_t *) pm_arena_alloc(arena, sizeof(pm_or_node_t), PRISM_ALIGNOF(pm_or_node_t)); + + *node = (pm_or_node_t) { + .base = { .type = PM_OR_NODE, .flags = flags, .node_id = node_id, .location = location }, + .left = left, + .right = right, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ParametersNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param requireds The requireds field. + * @param optionals The optionals field. + * @param rest The rest field. + * @param posts The posts field. + * @param keywords The keywords field. + * @param keyword_rest The keyword_rest field. + * @param block The block field. + * @return The newly allocated and initialized node. + */ +static inline pm_parameters_node_t * +pm_parameters_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t requireds, pm_node_list_t optionals, struct pm_node *rest, pm_node_list_t posts, pm_node_list_t keywords, struct pm_node *keyword_rest, struct pm_node *block) { + pm_parameters_node_t *node = (pm_parameters_node_t *) pm_arena_alloc(arena, sizeof(pm_parameters_node_t), PRISM_ALIGNOF(pm_parameters_node_t)); + + *node = (pm_parameters_node_t) { + .base = { .type = PM_PARAMETERS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .requireds = requireds, + .optionals = optionals, + .rest = rest, + .posts = posts, + .keywords = keywords, + .keyword_rest = keyword_rest, + .block = block + }; + + return node; +} + +/** + * Allocate and initialize a new ParenthesesNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param body The body field. + * @param opening_loc The opening_loc field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_parentheses_node_t * +pm_parentheses_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *body, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_parentheses_node_t *node = (pm_parentheses_node_t *) pm_arena_alloc(arena, sizeof(pm_parentheses_node_t), PRISM_ALIGNOF(pm_parentheses_node_t)); + + *node = (pm_parentheses_node_t) { + .base = { .type = PM_PARENTHESES_NODE, .flags = flags, .node_id = node_id, .location = location }, + .body = body, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new PinnedExpressionNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param expression The expression used in the pinned expression + * @param operator_loc The Location of the \`^\` operator + * @param lparen_loc The Location of the opening parenthesis\. + * @param rparen_loc The Location of the closing parenthesis\. + * @return The newly allocated and initialized node. + */ +static inline pm_pinned_expression_node_t * +pm_pinned_expression_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *expression, pm_location_t operator_loc, pm_location_t lparen_loc, pm_location_t rparen_loc) { + pm_pinned_expression_node_t *node = (pm_pinned_expression_node_t *) pm_arena_alloc(arena, sizeof(pm_pinned_expression_node_t), PRISM_ALIGNOF(pm_pinned_expression_node_t)); + + *node = (pm_pinned_expression_node_t) { + .base = { .type = PM_PINNED_EXPRESSION_NODE, .flags = flags, .node_id = node_id, .location = location }, + .expression = expression, + .operator_loc = operator_loc, + .lparen_loc = lparen_loc, + .rparen_loc = rparen_loc + }; + + return node; +} + +/** + * Allocate and initialize a new PinnedVariableNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param variable The variable used in the pinned expression + * @param operator_loc The Location of the \`^\` operator + * @return The newly allocated and initialized node. + */ +static inline pm_pinned_variable_node_t * +pm_pinned_variable_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *variable, pm_location_t operator_loc) { + pm_pinned_variable_node_t *node = (pm_pinned_variable_node_t *) pm_arena_alloc(arena, sizeof(pm_pinned_variable_node_t), PRISM_ALIGNOF(pm_pinned_variable_node_t)); + + *node = (pm_pinned_variable_node_t) { + .base = { .type = PM_PINNED_VARIABLE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .variable = variable, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new PostExecutionNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param statements The statements field. + * @param keyword_loc The keyword_loc field. + * @param opening_loc The opening_loc field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_post_execution_node_t * +pm_post_execution_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_statements_node *statements, pm_location_t keyword_loc, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_post_execution_node_t *node = (pm_post_execution_node_t *) pm_arena_alloc(arena, sizeof(pm_post_execution_node_t), PRISM_ALIGNOF(pm_post_execution_node_t)); + + *node = (pm_post_execution_node_t) { + .base = { .type = PM_POST_EXECUTION_NODE, .flags = flags, .node_id = node_id, .location = location }, + .statements = statements, + .keyword_loc = keyword_loc, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new PreExecutionNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param statements The statements field. + * @param keyword_loc The keyword_loc field. + * @param opening_loc The opening_loc field. + * @param closing_loc The closing_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_pre_execution_node_t * +pm_pre_execution_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_statements_node *statements, pm_location_t keyword_loc, pm_location_t opening_loc, pm_location_t closing_loc) { + pm_pre_execution_node_t *node = (pm_pre_execution_node_t *) pm_arena_alloc(arena, sizeof(pm_pre_execution_node_t), PRISM_ALIGNOF(pm_pre_execution_node_t)); + + *node = (pm_pre_execution_node_t) { + .base = { .type = PM_PRE_EXECUTION_NODE, .flags = flags, .node_id = node_id, .location = location }, + .statements = statements, + .keyword_loc = keyword_loc, + .opening_loc = opening_loc, + .closing_loc = closing_loc + }; + + return node; +} + +/** + * Allocate and initialize a new ProgramNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param locals The locals field. + * @param statements The statements field. + * @return The newly allocated and initialized node. + */ +static inline pm_program_node_t * +pm_program_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_list_t locals, struct pm_statements_node *statements) { + pm_program_node_t *node = (pm_program_node_t *) pm_arena_alloc(arena, sizeof(pm_program_node_t), PRISM_ALIGNOF(pm_program_node_t)); + + *node = (pm_program_node_t) { + .base = { .type = PM_PROGRAM_NODE, .flags = flags, .node_id = node_id, .location = location }, + .locals = locals, + .statements = statements + }; + + return node; +} + +/** + * Allocate and initialize a new RangeNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param left The left\-hand side of the range, if present\. It can be either \`nil\` or any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param right The right\-hand side of the range, if present\. It can be either \`nil\` or any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param operator_loc The Location of the \`\.\.\` or \`\.\.\.\` operator\. + * @return The newly allocated and initialized node. + */ +static inline pm_range_node_t * +pm_range_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *left, struct pm_node *right, pm_location_t operator_loc) { + pm_range_node_t *node = (pm_range_node_t *) pm_arena_alloc(arena, sizeof(pm_range_node_t), PRISM_ALIGNOF(pm_range_node_t)); + + *node = (pm_range_node_t) { + .base = { .type = PM_RANGE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .left = left, + .right = right, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new RationalNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param numerator The numerator of the rational number\. + * @param denominator The denominator of the rational number\. + * @return The newly allocated and initialized node. + */ +static inline pm_rational_node_t * +pm_rational_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_integer_t numerator, pm_integer_t denominator) { + pm_rational_node_t *node = (pm_rational_node_t *) pm_arena_alloc(arena, sizeof(pm_rational_node_t), PRISM_ALIGNOF(pm_rational_node_t)); + + *node = (pm_rational_node_t) { + .base = { .type = PM_RATIONAL_NODE, .flags = flags, .node_id = node_id, .location = location }, + .numerator = numerator, + .denominator = denominator + }; + + return node; +} + +/** + * Allocate and initialize a new RedoNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_redo_node_t * +pm_redo_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_redo_node_t *node = (pm_redo_node_t *) pm_arena_alloc(arena, sizeof(pm_redo_node_t), PRISM_ALIGNOF(pm_redo_node_t)); + + *node = (pm_redo_node_t) { + .base = { .type = PM_REDO_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new RegularExpressionNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param content_loc The content_loc field. + * @param closing_loc The closing_loc field. + * @param unescaped The unescaped field. + * @return The newly allocated and initialized node. + */ +static inline pm_regular_expression_node_t * +pm_regular_expression_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_location_t content_loc, pm_location_t closing_loc, pm_string_t unescaped) { + pm_regular_expression_node_t *node = (pm_regular_expression_node_t *) pm_arena_alloc(arena, sizeof(pm_regular_expression_node_t), PRISM_ALIGNOF(pm_regular_expression_node_t)); + + *node = (pm_regular_expression_node_t) { + .base = { .type = PM_REGULAR_EXPRESSION_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .content_loc = content_loc, + .closing_loc = closing_loc, + .unescaped = unescaped + }; + + return node; +} + +/** + * Allocate and initialize a new RequiredKeywordParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_required_keyword_parameter_node_t * +pm_required_keyword_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc) { + pm_required_keyword_parameter_node_t *node = (pm_required_keyword_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_required_keyword_parameter_node_t), PRISM_ALIGNOF(pm_required_keyword_parameter_node_t)); + + *node = (pm_required_keyword_parameter_node_t) { + .base = { .type = PM_REQUIRED_KEYWORD_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc + }; + + return node; +} + +/** + * Allocate and initialize a new RequiredParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @return The newly allocated and initialized node. + */ +static inline pm_required_parameter_node_t * +pm_required_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name) { + pm_required_parameter_node_t *node = (pm_required_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_required_parameter_node_t), PRISM_ALIGNOF(pm_required_parameter_node_t)); + + *node = (pm_required_parameter_node_t) { + .base = { .type = PM_REQUIRED_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new RescueModifierNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param expression The expression field. + * @param keyword_loc The keyword_loc field. + * @param rescue_expression The rescue_expression field. + * @return The newly allocated and initialized node. + */ +static inline pm_rescue_modifier_node_t * +pm_rescue_modifier_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *expression, pm_location_t keyword_loc, struct pm_node *rescue_expression) { + pm_rescue_modifier_node_t *node = (pm_rescue_modifier_node_t *) pm_arena_alloc(arena, sizeof(pm_rescue_modifier_node_t), PRISM_ALIGNOF(pm_rescue_modifier_node_t)); + + *node = (pm_rescue_modifier_node_t) { + .base = { .type = PM_RESCUE_MODIFIER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .expression = expression, + .keyword_loc = keyword_loc, + .rescue_expression = rescue_expression + }; + + return node; +} + +/** + * Allocate and initialize a new RescueNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The keyword_loc field. + * @param exceptions The exceptions field. + * @param operator_loc The operator_loc field. + * @param reference The reference field. + * @param then_keyword_loc The then_keyword_loc field. + * @param statements The statements field. + * @param subsequent The subsequent field. + * @return The newly allocated and initialized node. + */ +static inline pm_rescue_node_t * +pm_rescue_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, pm_node_list_t exceptions, pm_location_t operator_loc, struct pm_node *reference, pm_location_t then_keyword_loc, struct pm_statements_node *statements, struct pm_rescue_node *subsequent) { + pm_rescue_node_t *node = (pm_rescue_node_t *) pm_arena_alloc(arena, sizeof(pm_rescue_node_t), PRISM_ALIGNOF(pm_rescue_node_t)); + + *node = (pm_rescue_node_t) { + .base = { .type = PM_RESCUE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .exceptions = exceptions, + .operator_loc = operator_loc, + .reference = reference, + .then_keyword_loc = then_keyword_loc, + .statements = statements, + .subsequent = subsequent + }; + + return node; +} + +/** + * Allocate and initialize a new RestParameterNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param name The name field. + * @param name_loc The name_loc field. + * @param operator_loc The operator_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_rest_parameter_node_t * +pm_rest_parameter_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_t name, pm_location_t name_loc, pm_location_t operator_loc) { + pm_rest_parameter_node_t *node = (pm_rest_parameter_node_t *) pm_arena_alloc(arena, sizeof(pm_rest_parameter_node_t), PRISM_ALIGNOF(pm_rest_parameter_node_t)); + + *node = (pm_rest_parameter_node_t) { + .base = { .type = PM_REST_PARAMETER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .name = name, + .name_loc = name_loc, + .operator_loc = operator_loc + }; + + return node; +} + +/** + * Allocate and initialize a new RetryNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_retry_node_t * +pm_retry_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_retry_node_t *node = (pm_retry_node_t *) pm_arena_alloc(arena, sizeof(pm_retry_node_t), PRISM_ALIGNOF(pm_retry_node_t)); + + *node = (pm_retry_node_t) { + .base = { .type = PM_RETRY_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new ReturnNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The keyword_loc field. + * @param arguments The arguments field. + * @return The newly allocated and initialized node. + */ +static inline pm_return_node_t * +pm_return_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, struct pm_arguments_node *arguments) { + pm_return_node_t *node = (pm_return_node_t *) pm_arena_alloc(arena, sizeof(pm_return_node_t), PRISM_ALIGNOF(pm_return_node_t)); + + *node = (pm_return_node_t) { + .base = { .type = PM_RETURN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .arguments = arguments + }; + + return node; +} + +/** + * Allocate and initialize a new SelfNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_self_node_t * +pm_self_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_self_node_t *node = (pm_self_node_t *) pm_arena_alloc(arena, sizeof(pm_self_node_t), PRISM_ALIGNOF(pm_self_node_t)); + + *node = (pm_self_node_t) { + .base = { .type = PM_SELF_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new ShareableConstantNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param write The constant write that should be modified with the shareability state\. + * @return The newly allocated and initialized node. + */ +static inline pm_shareable_constant_node_t * +pm_shareable_constant_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, struct pm_node *write) { + pm_shareable_constant_node_t *node = (pm_shareable_constant_node_t *) pm_arena_alloc(arena, sizeof(pm_shareable_constant_node_t), PRISM_ALIGNOF(pm_shareable_constant_node_t)); + + *node = (pm_shareable_constant_node_t) { + .base = { .type = PM_SHAREABLE_CONSTANT_NODE, .flags = flags, .node_id = node_id, .location = location }, + .write = write + }; + + return node; +} + +/** + * Allocate and initialize a new SingletonClassNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param locals The locals field. + * @param class_keyword_loc The class_keyword_loc field. + * @param operator_loc The operator_loc field. + * @param expression The expression field. + * @param body The body field. + * @param end_keyword_loc The end_keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_singleton_class_node_t * +pm_singleton_class_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_constant_id_list_t locals, pm_location_t class_keyword_loc, pm_location_t operator_loc, struct pm_node *expression, struct pm_node *body, pm_location_t end_keyword_loc) { + pm_singleton_class_node_t *node = (pm_singleton_class_node_t *) pm_arena_alloc(arena, sizeof(pm_singleton_class_node_t), PRISM_ALIGNOF(pm_singleton_class_node_t)); + + *node = (pm_singleton_class_node_t) { + .base = { .type = PM_SINGLETON_CLASS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .locals = locals, + .class_keyword_loc = class_keyword_loc, + .operator_loc = operator_loc, + .expression = expression, + .body = body, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new SourceEncodingNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_source_encoding_node_t * +pm_source_encoding_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_source_encoding_node_t *node = (pm_source_encoding_node_t *) pm_arena_alloc(arena, sizeof(pm_source_encoding_node_t), PRISM_ALIGNOF(pm_source_encoding_node_t)); + + *node = (pm_source_encoding_node_t) { + .base = { .type = PM_SOURCE_ENCODING_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new SourceFileNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param filepath Represents the file path being parsed\. This corresponds directly to the \`filepath\` option given to the various \`Prism\.parse\*\` APIs\. + * @return The newly allocated and initialized node. + */ +static inline pm_source_file_node_t * +pm_source_file_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_string_t filepath) { + pm_source_file_node_t *node = (pm_source_file_node_t *) pm_arena_alloc(arena, sizeof(pm_source_file_node_t), PRISM_ALIGNOF(pm_source_file_node_t)); + + *node = (pm_source_file_node_t) { + .base = { .type = PM_SOURCE_FILE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .filepath = filepath + }; + + return node; +} + +/** + * Allocate and initialize a new SourceLineNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_source_line_node_t * +pm_source_line_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_source_line_node_t *node = (pm_source_line_node_t *) pm_arena_alloc(arena, sizeof(pm_source_line_node_t), PRISM_ALIGNOF(pm_source_line_node_t)); + + *node = (pm_source_line_node_t) { + .base = { .type = PM_SOURCE_LINE_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new SplatNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param operator_loc The operator_loc field. + * @param expression The expression field. + * @return The newly allocated and initialized node. + */ +static inline pm_splat_node_t * +pm_splat_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t operator_loc, struct pm_node *expression) { + pm_splat_node_t *node = (pm_splat_node_t *) pm_arena_alloc(arena, sizeof(pm_splat_node_t), PRISM_ALIGNOF(pm_splat_node_t)); + + *node = (pm_splat_node_t) { + .base = { .type = PM_SPLAT_NODE, .flags = flags, .node_id = node_id, .location = location }, + .operator_loc = operator_loc, + .expression = expression + }; + + return node; +} + +/** + * Allocate and initialize a new StatementsNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param body The body field. + * @return The newly allocated and initialized node. + */ +static inline pm_statements_node_t * +pm_statements_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t body) { + pm_statements_node_t *node = (pm_statements_node_t *) pm_arena_alloc(arena, sizeof(pm_statements_node_t), PRISM_ALIGNOF(pm_statements_node_t)); + + *node = (pm_statements_node_t) { + .base = { .type = PM_STATEMENTS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .body = body + }; + + return node; +} + +/** + * Allocate and initialize a new StringNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param content_loc The content_loc field. + * @param closing_loc The closing_loc field. + * @param unescaped The unescaped field. + * @return The newly allocated and initialized node. + */ +static inline pm_string_node_t * +pm_string_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_location_t content_loc, pm_location_t closing_loc, pm_string_t unescaped) { + pm_string_node_t *node = (pm_string_node_t *) pm_arena_alloc(arena, sizeof(pm_string_node_t), PRISM_ALIGNOF(pm_string_node_t)); + + *node = (pm_string_node_t) { + .base = { .type = PM_STRING_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .content_loc = content_loc, + .closing_loc = closing_loc, + .unescaped = unescaped + }; + + return node; +} + +/** + * Allocate and initialize a new SuperNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The keyword_loc field. + * @param lparen_loc The lparen_loc field. + * @param arguments Can be only \`nil\` when there are empty parentheses, like \`super()\`\. + * @param rparen_loc The rparen_loc field. + * @param block The block field. + * @return The newly allocated and initialized node. + */ +static inline pm_super_node_t * +pm_super_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, pm_location_t lparen_loc, struct pm_arguments_node *arguments, pm_location_t rparen_loc, struct pm_node *block) { + pm_super_node_t *node = (pm_super_node_t *) pm_arena_alloc(arena, sizeof(pm_super_node_t), PRISM_ALIGNOF(pm_super_node_t)); + + *node = (pm_super_node_t) { + .base = { .type = PM_SUPER_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .lparen_loc = lparen_loc, + .arguments = arguments, + .rparen_loc = rparen_loc, + .block = block + }; + + return node; +} + +/** + * Allocate and initialize a new SymbolNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param value_loc The value_loc field. + * @param closing_loc The closing_loc field. + * @param unescaped The unescaped field. + * @return The newly allocated and initialized node. + */ +static inline pm_symbol_node_t * +pm_symbol_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_location_t value_loc, pm_location_t closing_loc, pm_string_t unescaped) { + pm_symbol_node_t *node = (pm_symbol_node_t *) pm_arena_alloc(arena, sizeof(pm_symbol_node_t), PRISM_ALIGNOF(pm_symbol_node_t)); + + *node = (pm_symbol_node_t) { + .base = { .type = PM_SYMBOL_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .value_loc = value_loc, + .closing_loc = closing_loc, + .unescaped = unescaped + }; + + return node; +} + +/** + * Allocate and initialize a new TrueNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @return The newly allocated and initialized node. + */ +static inline pm_true_node_t * +pm_true_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location) { + pm_true_node_t *node = (pm_true_node_t *) pm_arena_alloc(arena, sizeof(pm_true_node_t), PRISM_ALIGNOF(pm_true_node_t)); + + *node = (pm_true_node_t) { + .base = { .type = PM_TRUE_NODE, .flags = flags, .node_id = node_id, .location = location } + }; + + return node; +} + +/** + * Allocate and initialize a new UndefNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param names The names field. + * @param keyword_loc The keyword_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_undef_node_t * +pm_undef_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_node_list_t names, pm_location_t keyword_loc) { + pm_undef_node_t *node = (pm_undef_node_t *) pm_arena_alloc(arena, sizeof(pm_undef_node_t), PRISM_ALIGNOF(pm_undef_node_t)); + + *node = (pm_undef_node_t) { + .base = { .type = PM_UNDEF_NODE, .flags = flags, .node_id = node_id, .location = location }, + .names = names, + .keyword_loc = keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new UnlessNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The Location of the \`unless\` keyword\. + * @param predicate The condition to be evaluated for the unless expression\. It can be any [non\-void expression](https://github\.com/ruby/prism/blob/main/docs/parsing\_rules\.md\#non\-void\-expression)\. + * @param then_keyword_loc The Location of the \`then\` keyword, if present\. + * @param statements The body of statements that will executed if the unless condition is + * @param else_clause The else clause of the unless expression, if present\. + * @param end_keyword_loc The Location of the \`end\` keyword, if present\. + * @return The newly allocated and initialized node. + */ +static inline pm_unless_node_t * +pm_unless_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, struct pm_node *predicate, pm_location_t then_keyword_loc, struct pm_statements_node *statements, struct pm_else_node *else_clause, pm_location_t end_keyword_loc) { + pm_unless_node_t *node = (pm_unless_node_t *) pm_arena_alloc(arena, sizeof(pm_unless_node_t), PRISM_ALIGNOF(pm_unless_node_t)); + + *node = (pm_unless_node_t) { + .base = { .type = PM_UNLESS_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .predicate = predicate, + .then_keyword_loc = then_keyword_loc, + .statements = statements, + .else_clause = else_clause, + .end_keyword_loc = end_keyword_loc + }; + + return node; +} + +/** + * Allocate and initialize a new UntilNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The keyword_loc field. + * @param do_keyword_loc The do_keyword_loc field. + * @param closing_loc The closing_loc field. + * @param predicate The predicate field. + * @param statements The statements field. + * @return The newly allocated and initialized node. + */ +static inline pm_until_node_t * +pm_until_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, pm_location_t do_keyword_loc, pm_location_t closing_loc, struct pm_node *predicate, struct pm_statements_node *statements) { + pm_until_node_t *node = (pm_until_node_t *) pm_arena_alloc(arena, sizeof(pm_until_node_t), PRISM_ALIGNOF(pm_until_node_t)); + + *node = (pm_until_node_t) { + .base = { .type = PM_UNTIL_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .do_keyword_loc = do_keyword_loc, + .closing_loc = closing_loc, + .predicate = predicate, + .statements = statements + }; + + return node; +} + +/** + * Allocate and initialize a new WhenNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The keyword_loc field. + * @param conditions The conditions field. + * @param then_keyword_loc The then_keyword_loc field. + * @param statements The statements field. + * @return The newly allocated and initialized node. + */ +static inline pm_when_node_t * +pm_when_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, pm_node_list_t conditions, pm_location_t then_keyword_loc, struct pm_statements_node *statements) { + pm_when_node_t *node = (pm_when_node_t *) pm_arena_alloc(arena, sizeof(pm_when_node_t), PRISM_ALIGNOF(pm_when_node_t)); + + *node = (pm_when_node_t) { + .base = { .type = PM_WHEN_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .conditions = conditions, + .then_keyword_loc = then_keyword_loc, + .statements = statements + }; + + return node; +} + +/** + * Allocate and initialize a new WhileNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The keyword_loc field. + * @param do_keyword_loc The do_keyword_loc field. + * @param closing_loc The closing_loc field. + * @param predicate The predicate field. + * @param statements The statements field. + * @return The newly allocated and initialized node. + */ +static inline pm_while_node_t * +pm_while_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, pm_location_t do_keyword_loc, pm_location_t closing_loc, struct pm_node *predicate, struct pm_statements_node *statements) { + pm_while_node_t *node = (pm_while_node_t *) pm_arena_alloc(arena, sizeof(pm_while_node_t), PRISM_ALIGNOF(pm_while_node_t)); + + *node = (pm_while_node_t) { + .base = { .type = PM_WHILE_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .do_keyword_loc = do_keyword_loc, + .closing_loc = closing_loc, + .predicate = predicate, + .statements = statements + }; + + return node; +} + +/** + * Allocate and initialize a new XStringNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param opening_loc The opening_loc field. + * @param content_loc The content_loc field. + * @param closing_loc The closing_loc field. + * @param unescaped The unescaped field. + * @return The newly allocated and initialized node. + */ +static inline pm_x_string_node_t * +pm_x_string_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t opening_loc, pm_location_t content_loc, pm_location_t closing_loc, pm_string_t unescaped) { + pm_x_string_node_t *node = (pm_x_string_node_t *) pm_arena_alloc(arena, sizeof(pm_x_string_node_t), PRISM_ALIGNOF(pm_x_string_node_t)); + + *node = (pm_x_string_node_t) { + .base = { .type = PM_X_STRING_NODE, .flags = flags, .node_id = node_id, .location = location }, + .opening_loc = opening_loc, + .content_loc = content_loc, + .closing_loc = closing_loc, + .unescaped = unescaped + }; + + return node; +} + +/** + * Allocate and initialize a new YieldNode node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. + * @param keyword_loc The keyword_loc field. + * @param lparen_loc The lparen_loc field. + * @param arguments The arguments field. + * @param rparen_loc The rparen_loc field. + * @return The newly allocated and initialized node. + */ +static inline pm_yield_node_t * +pm_yield_node_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location, pm_location_t keyword_loc, pm_location_t lparen_loc, struct pm_arguments_node *arguments, pm_location_t rparen_loc) { + pm_yield_node_t *node = (pm_yield_node_t *) pm_arena_alloc(arena, sizeof(pm_yield_node_t), PRISM_ALIGNOF(pm_yield_node_t)); + + *node = (pm_yield_node_t) { + .base = { .type = PM_YIELD_NODE, .flags = flags, .node_id = node_id, .location = location }, + .keyword_loc = keyword_loc, + .lparen_loc = lparen_loc, + .arguments = arguments, + .rparen_loc = rparen_loc + }; + + return node; +} + +#endif diff --git a/prism/prism.c b/prism/prism.c index b6bc90ebd77234..6f21c97bc3b48f 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -1,4 +1,5 @@ #include "prism.h" +#include "prism/node_new.h" /** * The prism version and the serialization format. @@ -2018,26 +2019,17 @@ pm_integer_arena_move(pm_arena_t *arena, pm_integer_t *integer) { } } -#define PM_NODE_ALLOC(parser_, type_) (type_ *) pm_arena_zalloc((parser_)->arena, sizeof(type_), PRISM_ALIGNOF(type_)) -#define PM_NODE_INIT(parser_, type_, flags_, location_) (pm_node_t) { \ - .type = (type_), \ - .flags = (flags_), \ - .node_id = ++(parser_)->node_id, \ - .location = location_ \ -} - /** * Allocate a new MissingNode node. */ static pm_missing_node_t * pm_missing_node_create(pm_parser_t *parser, uint32_t start, uint32_t length) { - pm_missing_node_t *node = PM_NODE_ALLOC(parser, pm_missing_node_t); - - *node = (pm_missing_node_t) { - .base = PM_NODE_INIT(parser, PM_MISSING_NODE, 0, ((pm_location_t) { .start = start, .length = length })) - }; - - return node; + return pm_missing_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = length }) + ); } /** @@ -2046,16 +2038,16 @@ pm_missing_node_create(pm_parser_t *parser, uint32_t start, uint32_t length) { static pm_alias_global_variable_node_t * pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) { assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS); - pm_alias_global_variable_node_t *node = PM_NODE_ALLOC(parser, pm_alias_global_variable_node_t); - - *node = (pm_alias_global_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_ALIAS_GLOBAL_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name)), - .new_name = new_name, - .old_name = old_name, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_alias_global_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name), + new_name, + old_name, + TOK2LOC(parser, keyword) + ); } /** @@ -2064,16 +2056,16 @@ pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyw static pm_alias_method_node_t * pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) { assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS); - pm_alias_method_node_t *node = PM_NODE_ALLOC(parser, pm_alias_method_node_t); - - *node = (pm_alias_method_node_t) { - .base = PM_NODE_INIT(parser, PM_ALIAS_METHOD_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name)), - .new_name = new_name, - .old_name = old_name, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_alias_method_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name), + new_name, + old_name, + TOK2LOC(parser, keyword) + ); } /** @@ -2081,16 +2073,15 @@ pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_n */ static pm_alternation_pattern_node_t * pm_alternation_pattern_node_create(pm_parser_t *parser, pm_node_t *left, pm_node_t *right, const pm_token_t *operator) { - pm_alternation_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_alternation_pattern_node_t); - - *node = (pm_alternation_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ALTERNATION_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_alternation_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -2100,16 +2091,15 @@ static pm_and_node_t * pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); - pm_and_node_t *node = PM_NODE_ALLOC(parser, pm_and_node_t); - - *node = (pm_and_node_t) { - .base = PM_NODE_INIT(parser, PM_AND_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .operator_loc = TOK2LOC(parser, operator), - .right = right - }; - - return node; + return pm_and_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -2117,14 +2107,13 @@ pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *opera */ static pm_arguments_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_ARGUMENTS_NODE, 0, PM_LOCATION_INIT_UNSET), - .arguments = { 0 } - }; - - return node; + return pm_arguments_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -2164,25 +2153,27 @@ pm_arguments_node_arguments_append(pm_arena_t *arena, pm_arguments_node_t *node, */ static pm_array_node_t * 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); - if (opening == NULL) { - *node = (pm_array_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_UNSET), - .opening_loc = { 0 }, - .closing_loc = { 0 }, - .elements = { 0 } - }; + return pm_array_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } else { - *node = (pm_array_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, opening), - .elements = { 0 } - }; + return pm_array_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, opening) + ); } - - return node; } /** @@ -2224,17 +2215,18 @@ pm_array_node_close_set(const pm_parser_t *parser, pm_array_node_t *node, const */ static pm_array_pattern_node_t * pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *nodes) { - pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(nodes->nodes[0], nodes->nodes[nodes->size - 1])), - .constant = NULL, - .rest = NULL, - .requireds = { 0 }, - .posts = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + pm_array_pattern_node_t *node = pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(nodes->nodes[0], nodes->nodes[nodes->size - 1]), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); // For now we're going to just copy over each pointer manually. This could be // much more efficient, as we could instead resize the node list. @@ -2260,19 +2252,18 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node */ static pm_array_pattern_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODE(rest)), - .constant = NULL, - .rest = rest, - .requireds = { 0 }, - .posts = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(rest), + NULL, + ((pm_node_list_t) { 0 }), + rest, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -2281,19 +2272,18 @@ pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) { */ static pm_array_pattern_node_t * pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant, const pm_token_t *opening, const pm_token_t *closing) { - pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODE_TOKEN(parser, constant, closing)), - .constant = constant, - .rest = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .requireds = { 0 }, - .posts = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE_TOKEN(parser, constant, closing), + constant, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -2302,19 +2292,18 @@ pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant, */ static pm_array_pattern_node_t * pm_array_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .constant = NULL, - .rest = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .requireds = { 0 }, - .posts = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } static inline void @@ -2327,7 +2316,6 @@ pm_array_pattern_node_requireds_append(pm_arena_t *arena, pm_array_pattern_node_ */ static pm_assoc_node_t * pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *operator, pm_node_t *value) { - pm_assoc_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_node_t); uint32_t end; if (value != NULL && PM_NODE_END(value) > PM_NODE_END(key)) { @@ -2355,14 +2343,15 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper flags = key->flags & value->flags & PM_NODE_FLAG_STATIC_LITERAL; } - *node = (pm_assoc_node_t) { - .base = PM_NODE_INIT(parser, PM_ASSOC_NODE, flags, ((pm_location_t) { .start = PM_NODE_START(key), .length = U32(end - PM_NODE_START(key)) })), - .key = key, - .operator_loc = NTOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_assoc_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = PM_NODE_START(key), .length = U32(end - PM_NODE_START(key)) }), + key, + value, + NTOK2LOC(parser, operator) + ); } /** @@ -2371,15 +2360,15 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper static pm_assoc_splat_node_t * pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token_t *operator) { assert(operator->type == PM_TOKEN_USTAR_STAR); - pm_assoc_splat_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_splat_node_t); - - *node = (pm_assoc_splat_node_t) { - .base = PM_NODE_INIT(parser, PM_ASSOC_SPLAT_NODE, 0, (value == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, value)), - .value = value, - .operator_loc = TOK2LOC(parser, operator) - }; - return node; + return pm_assoc_splat_node_new( + parser->arena, + ++parser->node_id, + 0, + (value == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, value), + value, + TOK2LOC(parser, operator) + ); } /** @@ -2388,14 +2377,14 @@ pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token static pm_back_reference_read_node_t * pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_BACK_REFERENCE); - pm_back_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_back_reference_read_node_t); - - *node = (pm_back_reference_read_node_t) { - .base = PM_NODE_INIT(parser, PM_BACK_REFERENCE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - return node; + return pm_back_reference_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -2403,19 +2392,21 @@ pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) */ static pm_begin_node_t * pm_begin_node_create(pm_parser_t *parser, const pm_token_t *begin_keyword, pm_statements_node_t *statements) { - pm_begin_node_t *node = PM_NODE_ALLOC(parser, pm_begin_node_t); - uint32_t start = begin_keyword == NULL ? 0 : PM_TOKEN_START(parser, begin_keyword); uint32_t end = statements == NULL ? (begin_keyword == NULL ? 0 : PM_TOKEN_END(parser, begin_keyword)) : PM_NODE_END(statements); - *node = (pm_begin_node_t) { - .base = PM_NODE_INIT(parser, PM_BEGIN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .begin_keyword_loc = NTOK2LOC(parser, begin_keyword), - .statements = statements, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_begin_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, begin_keyword), + statements, + NULL, + NULL, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -2470,15 +2461,15 @@ pm_begin_node_end_keyword_set(const pm_parser_t *parser, pm_begin_node_t *node, static pm_block_argument_node_t * pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) { assert(operator->type == PM_TOKEN_UAMPERSAND); - pm_block_argument_node_t *node = PM_NODE_ALLOC(parser, pm_block_argument_node_t); - *node = (pm_block_argument_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_ARGUMENT_NODE, 0, (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression)), - .expression = expression, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_block_argument_node_new( + parser->arena, + ++parser->node_id, + 0, + (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression), + expression, + TOK2LOC(parser, operator) + ); } /** @@ -2486,18 +2477,17 @@ pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, p */ static pm_block_node_t * pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *opening, pm_node_t *parameters, pm_node_t *body, const pm_token_t *closing) { - pm_block_node_t *node = PM_NODE_ALLOC(parser, pm_block_node_t); - - *node = (pm_block_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .locals = *locals, - .parameters = parameters, - .body = body, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_block_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + *locals, + parameters, + body, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -2506,16 +2496,16 @@ pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p static pm_block_parameter_node_t * pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator) { assert(operator->type == PM_TOKEN_UAMPERSAND || operator->type == PM_TOKEN_AMPERSAND); - pm_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameter_node_t); - *node = (pm_block_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_block_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -2523,8 +2513,6 @@ pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, cons */ static pm_block_parameters_node_t * pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *parameters, const pm_token_t *opening) { - pm_block_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameters_node_t); - uint32_t start; if (opening != NULL) { start = PM_TOKEN_START(parser, opening); @@ -2543,15 +2531,16 @@ pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *param end = 0; } - *node = (pm_block_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETERS_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .parameters = parameters, - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = { 0 }, - .locals = { 0 } - }; - - return node; + return pm_block_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + parameters, + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, opening), + ((pm_location_t) { 0 }) + ); } /** @@ -2569,14 +2558,13 @@ pm_block_parameters_node_closing_set(const pm_parser_t *parser, pm_block_paramet */ static pm_block_local_variable_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_BLOCK_LOCAL_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_block_local_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -2599,15 +2587,15 @@ pm_block_parameters_node_append_local(pm_arena_t *arena, pm_block_parameters_nod static pm_break_node_t * pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_BREAK); - pm_break_node_t *node = PM_NODE_ALLOC(parser, pm_break_node_t); - - *node = (pm_break_node_t) { - .base = PM_NODE_INIT(parser, PM_BREAK_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .arguments = arguments, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_break_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + arguments, + TOK2LOC(parser, keyword) + ); } // There are certain flags that we want to use internally but don't want to @@ -2626,22 +2614,21 @@ static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = ((PM_CALL_NODE_FLAGS_LAS */ static pm_call_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_CALL_NODE, flags, PM_LOCATION_INIT_UNSET), - .receiver = NULL, - .call_operator_loc = { 0 }, - .message_loc = { 0 }, - .opening_loc = { 0 }, - .arguments = NULL, - .closing_loc = { 0 }, - .equal_loc = { 0 }, - .block = NULL, - .name = 0 - }; - - return node; + return pm_call_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_UNSET, + NULL, + ((pm_location_t) { 0 }), + 0, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + NULL, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + NULL + ); } /** @@ -2938,18 +2925,20 @@ static pm_call_and_write_node_t * pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_call_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_and_write_node_t); - - *node = (pm_call_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_AND_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_and_write_node_t *node = pm_call_and_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); @@ -2988,22 +2977,25 @@ pm_index_arguments_check(pm_parser_t *parser, const pm_arguments_node_t *argumen static pm_index_and_write_node_t * pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_index_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_and_write_node_t); 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_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_AND_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_index_and_write_node_t *node = pm_index_and_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + TOK2LOC(parser, operator), + value + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3017,19 +3009,21 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons static pm_call_operator_write_node_t * pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); - pm_call_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_operator_write_node_t); - - *node = (pm_call_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_OPERATOR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_operator_write_node_t *node = pm_call_operator_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); @@ -3044,23 +3038,25 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, */ static pm_index_operator_write_node_t * pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_index_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_operator_write_node_t); - 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_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_OPERATOR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_index_operator_write_node_t *node = pm_index_operator_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + TOK2LOC(parser, operator), + value + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3075,18 +3071,20 @@ static pm_call_or_write_node_t * pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_call_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_or_write_node_t); - - *node = (pm_call_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_OR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_or_write_node_t *node = pm_call_or_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); @@ -3102,22 +3100,25 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const static pm_index_or_write_node_t * pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_index_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_or_write_node_t); 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_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_OR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_index_or_write_node_t *node = pm_index_or_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + TOK2LOC(parser, operator), + value + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3131,15 +3132,16 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const */ static pm_call_target_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_CALL_TARGET_NODE, FL(target), PM_LOCATION_INIT_NODE(target)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .name = target->name, - .message_loc = target->message_loc - }; + pm_call_target_node_t *node = pm_call_target_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODE(target), + target->receiver, + target->call_operator_loc, + target->name, + 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 @@ -3161,19 +3163,20 @@ 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_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) { - .base = PM_NODE_INIT(parser, PM_INDEX_TARGET_NODE, FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, PM_LOCATION_INIT_NODE(target)), - .receiver = target->receiver, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - }; + pm_index_target_node_t *node = pm_index_target_node_new( + parser->arena, + ++parser->node_id, + FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, + PM_LOCATION_INIT_NODE(target), + target->receiver, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3186,16 +3189,15 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { */ static pm_capture_pattern_node_t * pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_variable_target_node_t *target, const pm_token_t *operator) { - pm_capture_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_capture_pattern_node_t); - - *node = (pm_capture_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_CAPTURE_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(value, target)), - .value = value, - .target = target, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_capture_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, target), + value, + target, + TOK2LOC(parser, operator) + ); } /** @@ -3203,18 +3205,17 @@ pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_v */ static pm_case_node_t * pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) { - pm_case_node_t *node = PM_NODE_ALLOC(parser, pm_case_node_t); - - *node = (pm_case_node_t) { - .base = PM_NODE_INIT(parser, PM_CASE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, case_keyword, end_keyword == NULL ? case_keyword : end_keyword)), - .predicate = predicate, - .else_clause = NULL, - .case_keyword_loc = TOK2LOC(parser, case_keyword), - .end_keyword_loc = NTOK2LOC(parser, end_keyword), - .conditions = { 0 } - }; - - return node; + return pm_case_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, case_keyword, end_keyword == NULL ? case_keyword : end_keyword), + predicate, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, case_keyword), + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3251,18 +3252,17 @@ pm_case_node_end_keyword_loc_set(const pm_parser_t *parser, pm_case_node_t *node */ static pm_case_match_node_t * pm_case_match_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate) { - pm_case_match_node_t *node = PM_NODE_ALLOC(parser, pm_case_match_node_t); - - *node = (pm_case_match_node_t) { - .base = PM_NODE_INIT(parser, PM_CASE_MATCH_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, case_keyword)), - .predicate = predicate, - .else_clause = NULL, - .case_keyword_loc = TOK2LOC(parser, case_keyword), - .end_keyword_loc = { 0 }, - .conditions = { 0 } - }; - - return node; + return pm_case_match_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, case_keyword), + predicate, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, case_keyword), + ((pm_location_t) { 0 }) + ); } /** @@ -3299,21 +3299,20 @@ pm_case_match_node_end_keyword_loc_set(const pm_parser_t *parser, pm_case_match_ */ static pm_class_node_t * pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, pm_node_t *constant_path, const pm_token_t *name, const pm_token_t *inheritance_operator, pm_node_t *superclass, pm_node_t *body, const pm_token_t *end_keyword) { - pm_class_node_t *node = PM_NODE_ALLOC(parser, pm_class_node_t); - - *node = (pm_class_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword)), - .locals = *locals, - .class_keyword_loc = TOK2LOC(parser, class_keyword), - .constant_path = constant_path, - .inheritance_operator_loc = NTOK2LOC(parser, inheritance_operator), - .superclass = superclass, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_class_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword), + *locals, + TOK2LOC(parser, class_keyword), + constant_path, + NTOK2LOC(parser, inheritance_operator), + superclass, + body, + TOK2LOC(parser, end_keyword), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -3322,17 +3321,17 @@ pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p static pm_class_variable_and_write_node_t * pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_class_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3340,18 +3339,17 @@ pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_r */ static pm_class_variable_operator_write_node_t * pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - 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) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_class_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3360,17 +3358,17 @@ pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_varia static pm_class_variable_or_write_node_t * pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_class_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3379,14 +3377,14 @@ pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_re static pm_class_variable_read_node_t * pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_CLASS_VARIABLE); - pm_class_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_read_node_t); - - *node = (pm_class_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - return node; + return pm_class_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -3408,18 +3406,16 @@ 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) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(read_node, value)), - .name = read_node->name, - .name_loc = read_node->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_class_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(read_node, value), + read_node->name, + read_node->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -3428,16 +3424,16 @@ pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_ static pm_constant_path_and_write_node_t * pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_path_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3445,17 +3441,16 @@ pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_nod */ static pm_constant_path_operator_write_node_t * pm_constant_path_operator_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_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_operator_write_node_t); - - *node = (pm_constant_path_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_constant_path_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3464,16 +3459,16 @@ pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_pat static pm_constant_path_or_write_node_t * pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_path_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3482,22 +3477,22 @@ pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node static pm_constant_path_node_t * pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_token_t *delimiter, const pm_token_t *name_token) { pm_assert_value_expression(parser, parent); - pm_constant_path_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_node_t); pm_constant_id_t name = PM_CONSTANT_ID_UNSET; if (name_token->type == PM_TOKEN_CONSTANT) { name = pm_parser_constant_id_token(parser, name_token); } - *node = (pm_constant_path_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_NODE, 0, (parent == NULL) ? PM_LOCATION_INIT_TOKENS(parser, delimiter, name_token) : PM_LOCATION_INIT_NODE_TOKEN(parser, parent, name_token)), - .parent = parent, - .name = name, - .delimiter_loc = TOK2LOC(parser, delimiter), - .name_loc = TOK2LOC(parser, name_token) - }; - - return node; + return pm_constant_path_node_new( + parser->arena, + ++parser->node_id, + 0, + (parent == NULL) ? PM_LOCATION_INIT_TOKENS(parser, delimiter, name_token) : PM_LOCATION_INIT_NODE_TOKEN(parser, parent, name_token), + parent, + name, + TOK2LOC(parser, delimiter), + TOK2LOC(parser, name_token) + ); } /** @@ -3505,17 +3500,15 @@ 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) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_constant_path_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3524,17 +3517,17 @@ pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t static pm_constant_and_write_node_t * pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_constant_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_and_write_node_t); - - *node = (pm_constant_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3542,18 +3535,17 @@ pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t * */ static pm_constant_operator_write_node_t * pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_operator_write_node_t); - - *node = (pm_constant_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_constant_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3562,17 +3554,17 @@ pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_nod static pm_constant_or_write_node_t * pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_constant_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_or_write_node_t); - - *node = (pm_constant_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3581,14 +3573,14 @@ pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *t static pm_constant_read_node_t * pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_CONSTANT || name->type == 0); - pm_constant_read_node_t *node = PM_NODE_ALLOC(parser, pm_constant_read_node_t); - - *node = (pm_constant_read_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - return node; + return pm_constant_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -3596,18 +3588,16 @@ 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) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_constant_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -3673,29 +3663,28 @@ pm_def_node_create( const pm_token_t *equal, const pm_token_t *end_keyword ) { - pm_def_node_t *node = PM_NODE_ALLOC(parser, pm_def_node_t); - if (receiver != NULL) { pm_def_node_receiver_check(parser, receiver); } - *node = (pm_def_node_t) { - .base = PM_NODE_INIT(parser, PM_DEF_NODE, 0, (end_keyword == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, def_keyword, body) : PM_LOCATION_INIT_TOKENS(parser, def_keyword, end_keyword)), - .name = name, - .name_loc = TOK2LOC(parser, name_loc), - .receiver = receiver, - .parameters = parameters, - .body = body, - .locals = *locals, - .def_keyword_loc = TOK2LOC(parser, def_keyword), - .operator_loc = NTOK2LOC(parser, operator), - .lparen_loc = NTOK2LOC(parser, lparen), - .rparen_loc = NTOK2LOC(parser, rparen), - .equal_loc = NTOK2LOC(parser, equal), - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_def_node_new( + parser->arena, + ++parser->node_id, + 0, + (end_keyword == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, def_keyword, body) : PM_LOCATION_INIT_TOKENS(parser, def_keyword, end_keyword), + name, + TOK2LOC(parser, name_loc), + receiver, + parameters, + body, + *locals, + TOK2LOC(parser, def_keyword), + NTOK2LOC(parser, operator), + NTOK2LOC(parser, lparen), + NTOK2LOC(parser, rparen), + NTOK2LOC(parser, equal), + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3703,17 +3692,16 @@ pm_def_node_create( */ 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_token_t *keyword) { - pm_defined_node_t *node = PM_NODE_ALLOC(parser, pm_defined_node_t); - - *node = (pm_defined_node_t) { - .base = PM_NODE_INIT(parser, PM_DEFINED_NODE, 0, (rparen == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, value) : PM_LOCATION_INIT_TOKENS(parser, keyword, rparen)), - .lparen_loc = NTOK2LOC(parser, lparen), - .value = value, - .rparen_loc = NTOK2LOC(parser, rparen), - .keyword_loc = TOK2LOC(parser, keyword) - }; - - return node; + return pm_defined_node_new( + parser->arena, + ++parser->node_id, + 0, + (rparen == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, value) : PM_LOCATION_INIT_TOKENS(parser, keyword, rparen), + NTOK2LOC(parser, lparen), + value, + NTOK2LOC(parser, rparen), + TOK2LOC(parser, keyword) + ); } /** @@ -3721,16 +3709,15 @@ 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); - - *node = (pm_else_node_t) { - .base = PM_NODE_INIT(parser, PM_ELSE_NODE, 0, ((end_keyword == NULL) && (statements != NULL)) ? PM_LOCATION_INIT_TOKEN_NODE(parser, else_keyword, statements) : PM_LOCATION_INIT_TOKENS(parser, else_keyword, end_keyword)), - .else_keyword_loc = TOK2LOC(parser, else_keyword), - .statements = statements, - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_else_node_new( + parser->arena, + ++parser->node_id, + 0, + ((end_keyword == NULL) && (statements != NULL)) ? PM_LOCATION_INIT_TOKEN_NODE(parser, else_keyword, statements) : PM_LOCATION_INIT_TOKENS(parser, else_keyword, end_keyword), + TOK2LOC(parser, else_keyword), + statements, + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3738,16 +3725,15 @@ pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_stat */ static pm_embedded_statements_node_t * pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_embedded_statements_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_statements_node_t); - - *node = (pm_embedded_statements_node_t) { - .base = PM_NODE_INIT(parser, PM_EMBEDDED_STATEMENTS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .statements = statements, - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_embedded_statements_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + statements, + TOK2LOC(parser, closing) + ); } /** @@ -3755,15 +3741,14 @@ pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *openin */ static pm_embedded_variable_node_t * pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) { - pm_embedded_variable_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_variable_node_t); - - *node = (pm_embedded_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_EMBEDDED_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable)), - .operator_loc = TOK2LOC(parser, operator), - .variable = variable - }; - - return node; + return pm_embedded_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable), + TOK2LOC(parser, operator), + variable + ); } /** @@ -3771,16 +3756,15 @@ pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator */ static pm_ensure_node_t * pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) { - pm_ensure_node_t *node = PM_NODE_ALLOC(parser, pm_ensure_node_t); - - *node = (pm_ensure_node_t) { - .base = PM_NODE_INIT(parser, PM_ENSURE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, ensure_keyword, end_keyword)), - .ensure_keyword_loc = TOK2LOC(parser, ensure_keyword), - .statements = statements, - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_ensure_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, ensure_keyword, end_keyword), + TOK2LOC(parser, ensure_keyword), + statements, + TOK2LOC(parser, end_keyword) + ); } /** @@ -3789,13 +3773,13 @@ pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_ static pm_false_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_FALSE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_false_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -3804,8 +3788,6 @@ pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_find_pattern_node_t * pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { - pm_find_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_find_pattern_node_t); - pm_node_t *left = nodes->nodes[0]; assert(PM_NODE_TYPE_P(left, PM_SPLAT_NODE)); pm_splat_node_t *left_splat_node = (pm_splat_node_t *) left; @@ -3826,15 +3808,19 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { #else pm_node_t *right_splat_node = right; #endif - *node = (pm_find_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_FIND_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .constant = NULL, - .left = left_splat_node, - .right = right_splat_node, - .requireds = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + + pm_find_pattern_node_t *node = pm_find_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + NULL, + left_splat_node, + ((pm_node_list_t) { 0 }), + right_splat_node, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); // For now we're going to just copy over each pointer manually. This could be // much more efficient, as we could instead resize the node list to only point @@ -3926,14 +3912,14 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { static pm_float_node_t * pm_float_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT); - pm_float_node_t *node = PM_NODE_ALLOC(parser, pm_float_node_t); - *node = (pm_float_node_t) { - .base = PM_NODE_INIT(parser, PM_FLOAT_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .value = pm_double_parse(parser, token) - }; - - return node; + return pm_float_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_double_parse(parser, token) + ); } /** @@ -3943,17 +3929,17 @@ static pm_imaginary_node_t * pm_float_node_imaginary_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_float_node_create(parser, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_float_node_create(parser, &((pm_token_t) { .type = PM_TOKEN_FLOAT, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -3963,12 +3949,14 @@ static pm_rational_node_t * pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_RATIONAL); - pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t); - *node = (pm_rational_node_t) { - .base = PM_NODE_INIT(parser, PM_RATIONAL_NODE, PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numerator = { 0 }, - .denominator = { 0 } - }; + pm_rational_node_t *node = pm_rational_node_new( + parser->arena, + ++parser->node_id, + PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }), + ((pm_integer_t) { 0 }) + ); const uint8_t *start = token->start; const uint8_t *end = token->end - 1; // r @@ -4018,17 +4006,17 @@ static pm_imaginary_node_t * pm_float_node_rational_imaginary_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_RATIONAL_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_float_node_rational_create(parser, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_float_node_rational_create(parser, &((pm_token_t) { .type = PM_TOKEN_FLOAT_RATIONAL, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4045,20 +4033,19 @@ pm_for_node_create( const pm_token_t *do_keyword, const pm_token_t *end_keyword ) { - pm_for_node_t *node = PM_NODE_ALLOC(parser, pm_for_node_t); - - *node = (pm_for_node_t) { - .base = PM_NODE_INIT(parser, PM_FOR_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, for_keyword, end_keyword)), - .index = index, - .collection = collection, - .statements = statements, - .for_keyword_loc = TOK2LOC(parser, for_keyword), - .in_keyword_loc = TOK2LOC(parser, in_keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_for_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, for_keyword, end_keyword), + index, + collection, + statements, + TOK2LOC(parser, for_keyword), + TOK2LOC(parser, in_keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, end_keyword) + ); } /** @@ -4067,13 +4054,13 @@ pm_for_node_create( static pm_forwarding_arguments_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_ARGUMENTS_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_forwarding_arguments_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4082,13 +4069,13 @@ pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token static pm_forwarding_parameter_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_forwarding_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4098,19 +4085,19 @@ static pm_forwarding_super_node_t * pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm_arguments_t *arguments) { assert(arguments->block == NULL || PM_NODE_TYPE_P(arguments->block, PM_BLOCK_NODE)); assert(token->type == PM_TOKEN_KEYWORD_SUPER); - pm_forwarding_super_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_super_node_t); pm_block_node_t *block = NULL; if (arguments->block != NULL) { block = (pm_block_node_t *) arguments->block; } - *node = (pm_forwarding_super_node_t) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_SUPER_NODE, 0, (block == NULL) ? PM_LOCATION_INIT_TOKEN(parser, token) : PM_LOCATION_INIT_TOKEN_NODE(parser, token, block)), - .block = block - }; - - return node; + return pm_forwarding_super_node_new( + parser->arena, + ++parser->node_id, + 0, + (block == NULL) ? PM_LOCATION_INIT_TOKEN(parser, token) : PM_LOCATION_INIT_TOKEN_NODE(parser, token, block), + block + ); } /** @@ -4119,18 +4106,17 @@ pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm */ static pm_hash_pattern_node_t * pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t); - - *node = (pm_hash_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .constant = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .elements = { 0 }, - .rest = NULL - }; - - return node; + return pm_hash_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -4138,8 +4124,6 @@ pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening */ static pm_hash_pattern_node_t * pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *elements, pm_node_t *rest) { - pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t); - uint32_t start; uint32_t end; @@ -4157,14 +4141,17 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme end = PM_NODE_END(rest); } - *node = (pm_hash_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .constant = NULL, - .elements = { 0 }, - .rest = rest, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + pm_hash_pattern_node_t *node = pm_hash_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NULL, + ((pm_node_list_t) { 0 }), + rest, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); pm_node_list_concat(parser->arena, &node->elements, elements); return node; @@ -4196,17 +4183,17 @@ pm_global_variable_write_name(pm_parser_t *parser, const pm_node_t *target) { static pm_global_variable_and_write_node_t * pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_global_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4214,18 +4201,17 @@ pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_global_variable_operator_write_node_t * pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { - 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) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_global_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -4234,17 +4220,17 @@ pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *ta static pm_global_variable_or_write_node_t * pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_global_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4252,14 +4238,13 @@ pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_global_variable_read_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_global_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -4267,14 +4252,13 @@ pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) */ static pm_global_variable_read_node_t * pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant_id_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) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_UNSET), - .name = name - }; - - return node; + return pm_global_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + name + ); } /** @@ -4282,18 +4266,16 @@ 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) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_global_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -4301,17 +4283,16 @@ pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, con */ static pm_global_variable_write_node_t * pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name, pm_node_t *value) { - pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t); - - *node = (pm_global_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, 0, PM_LOCATION_INIT_UNSET), - .name = name, - .name_loc = { 0 }, - .operator_loc = { 0 }, - .value = value - }; - - return node; + return pm_global_variable_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + name, + ((pm_location_t) { 0 }), + value, + ((pm_location_t) { 0 }) + ); } /** @@ -4320,16 +4301,16 @@ pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constan static pm_hash_node_t * pm_hash_node_create(pm_parser_t *parser, const pm_token_t *opening) { assert(opening != NULL); - pm_hash_node_t *node = PM_NODE_ALLOC(parser, pm_hash_node_t); - - *node = (pm_hash_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = { 0 }, - .elements = { 0 } - }; - return node; + return pm_hash_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -4371,7 +4352,6 @@ pm_if_node_create(pm_parser_t *parser, const pm_token_t *end_keyword ) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); uint32_t start = PM_TOKEN_START(parser, if_keyword); uint32_t end; @@ -4386,17 +4366,18 @@ pm_if_node_create(pm_parser_t *parser, end = PM_NODE_END(predicate); } - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .if_keyword_loc = TOK2LOC(parser, if_keyword), - .predicate = predicate, - .then_keyword_loc = NTOK2LOC(parser, then_keyword), - .statements = statements, - .subsequent = subsequent, - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + TOK2LOC(parser, if_keyword), + predicate, + NTOK2LOC(parser, then_keyword), + statements, + subsequent, + NTOK2LOC(parser, end_keyword) + ); } /** @@ -4405,22 +4386,22 @@ pm_if_node_create(pm_parser_t *parser, static pm_if_node_t * pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *if_keyword, pm_node_t *predicate) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(statement, predicate)), - .if_keyword_loc = TOK2LOC(parser, if_keyword), - .predicate = predicate, - .then_keyword_loc = { 0 }, - .statements = statements, - .subsequent = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(statement, predicate), + TOK2LOC(parser, if_keyword), + predicate, + ((pm_location_t) { 0 }), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -4438,20 +4419,18 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to pm_statements_node_body_append(parser, else_statements, false_expression, true); pm_else_node_t *else_node = pm_else_node_create(parser, colon, else_statements, NULL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); - - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(predicate, false_expression)), - .if_keyword_loc = { 0 }, - .predicate = predicate, - .then_keyword_loc = TOK2LOC(parser, qmark), - .statements = if_statements, - .subsequent = UP(else_node), - .end_keyword_loc = { 0 } - }; - - return node; - + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(predicate, false_expression), + ((pm_location_t) { 0 }), + predicate, + TOK2LOC(parser, qmark), + if_statements, + UP(else_node), + ((pm_location_t) { 0 }) + ); } static inline void @@ -4471,14 +4450,13 @@ pm_else_node_end_keyword_loc_set(const pm_parser_t *parser, pm_else_node_t *node */ static pm_implicit_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_IMPLICIT_NODE, 0, PM_LOCATION_INIT_NODE(value)), - .value = value - }; - - return node; + return pm_implicit_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(value), + value + ); } /** @@ -4488,13 +4466,12 @@ static pm_implicit_rest_node_t * pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_COMMA); - pm_implicit_rest_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_rest_node_t); - - *node = (pm_implicit_rest_node_t) { - .base = PM_NODE_INIT(parser, PM_IMPLICIT_REST_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_implicit_rest_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4503,12 +4480,14 @@ pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) { static pm_integer_node_t * pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER); - pm_integer_node_t *node = PM_NODE_ALLOC(parser, pm_integer_node_t); - *node = (pm_integer_node_t) { - .base = PM_NODE_INIT(parser, PM_INTEGER_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .value = { 0 } - }; + pm_integer_node_t *node = pm_integer_node_new( + parser->arena, + ++parser->node_id, + base | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }) + ); pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; switch (base) { @@ -4532,17 +4511,17 @@ static pm_imaginary_node_t * pm_integer_node_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_integer_node_create(parser, base, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_integer_node_create(parser, base, &((pm_token_t) { .type = PM_TOKEN_INTEGER, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4553,12 +4532,14 @@ static pm_rational_node_t * pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_RATIONAL); - pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t); - *node = (pm_rational_node_t) { - .base = PM_NODE_INIT(parser, PM_RATIONAL_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numerator = { 0 }, - .denominator = { .value = 1, 0 } - }; + pm_rational_node_t *node = pm_rational_node_new( + parser->arena, + ++parser->node_id, + base | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }), + ((pm_integer_t) { .value = 1 }) + ); pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; switch (base) { @@ -4583,17 +4564,17 @@ static pm_imaginary_node_t * pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_RATIONAL_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_integer_node_rational_create(parser, base, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + 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; + ); } /** @@ -4601,8 +4582,6 @@ pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t b */ static pm_in_node_t * pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t *statements, const pm_token_t *in_keyword, const pm_token_t *then_keyword) { - pm_in_node_t *node = PM_NODE_ALLOC(parser, pm_in_node_t); - uint32_t start = PM_TOKEN_START(parser, in_keyword); uint32_t end; @@ -4614,15 +4593,16 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t end = PM_NODE_END(pattern); } - *node = (pm_in_node_t) { - .base = PM_NODE_INIT(parser, PM_IN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .pattern = pattern, - .statements = statements, - .in_loc = TOK2LOC(parser, in_keyword), - .then_loc = NTOK2LOC(parser, then_keyword) - }; - - return node; + return pm_in_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + pattern, + statements, + TOK2LOC(parser, in_keyword), + NTOK2LOC(parser, then_keyword) + ); } /** @@ -4631,17 +4611,17 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t static pm_instance_variable_and_write_node_t * pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_instance_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4649,18 +4629,17 @@ pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_vari */ static pm_instance_variable_operator_write_node_t * pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - 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) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_instance_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -4669,17 +4648,17 @@ pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance static pm_instance_variable_or_write_node_t * pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_instance_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4688,14 +4667,14 @@ pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_varia static pm_instance_variable_read_node_t * pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_INSTANCE_VARIABLE); - pm_instance_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_read_node_t); - - *node = (pm_instance_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - return node; + return pm_instance_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -4704,18 +4683,16 @@ 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) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(read_node, value)), - .name = read_node->name, - .name_loc = read_node->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_instance_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(read_node, value), + read_node->name, + read_node->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -4767,16 +4744,15 @@ pm_interpolated_node_append(pm_arena_t *arena, pm_node_t *node, pm_node_list_t * */ static pm_interpolated_regular_expression_node_t * pm_interpolated_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening) { - pm_interpolated_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_regular_expression_node_t); - - *node = (pm_interpolated_regular_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_REGULAR_EXPRESSION_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, opening), - .parts = { 0 } - }; - - return node; + return pm_interpolated_regular_expression_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening) + ); } static inline void @@ -4918,7 +4894,6 @@ pm_interpolated_string_node_append(pm_arena_t *arena, pm_interpolated_string_nod */ static pm_interpolated_string_node_t * pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) { - pm_interpolated_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_string_node_t); pm_node_flags_t flags = PM_NODE_FLAG_STATIC_LITERAL; switch (parser->frozen_string_literal) { @@ -4933,12 +4908,15 @@ pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *openin uint32_t start = opening == NULL ? 0 : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? 0 : PM_TOKEN_END(parser, closing); - *node = (pm_interpolated_string_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_STRING_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = NTOK2LOC(parser, closing), - .parts = { 0 } - }; + pm_interpolated_string_node_t *node = pm_interpolated_string_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, closing) + ); if (parts != NULL) { pm_node_t *part; @@ -4983,17 +4961,18 @@ pm_interpolated_symbol_node_closing_loc_set(const pm_parser_t *parser, pm_interp */ static pm_interpolated_symbol_node_t * pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) { - pm_interpolated_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_symbol_node_t); - uint32_t start = opening == NULL ? 0 : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? 0 : PM_TOKEN_END(parser, closing); - *node = (pm_interpolated_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = NTOK2LOC(parser, closing), - .parts = { 0 } - }; + pm_interpolated_symbol_node_t *node = pm_interpolated_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, closing) + ); if (parts != NULL) { pm_node_t *part; @@ -5010,16 +4989,15 @@ pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *openin */ static pm_interpolated_x_string_node_t * pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_interpolated_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_x_string_node_t); - - *node = (pm_interpolated_x_string_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_X_STRING_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .parts = { 0 } - }; - - return node; + return pm_interpolated_x_string_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, closing) + ); } static inline void @@ -5039,13 +5017,12 @@ pm_interpolated_xstring_node_closing_set(const pm_parser_t *parser, pm_interpola */ static pm_it_local_variable_read_node_t * pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) { - 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) { - .base = PM_NODE_INIT(parser, PM_IT_LOCAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - }; - - return node; + return pm_it_local_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name) + ); } /** @@ -5053,13 +5030,12 @@ pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *nam */ static pm_it_parameters_node_t * pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_it_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_it_parameters_node_t); - - *node = (pm_it_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_IT_PARAMETERS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - }; - - return node; + return pm_it_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing) + ); } /** @@ -5067,14 +5043,13 @@ pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, con */ static pm_keyword_hash_node_t * 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 = PM_NODE_INIT(parser, PM_KEYWORD_HASH_NODE, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS, PM_LOCATION_INIT_UNSET), - .elements = { 0 } - }; - - return node; + return pm_keyword_hash_node_new( + parser->arena, + ++parser->node_id, + PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -5100,15 +5075,14 @@ pm_keyword_hash_node_elements_append(pm_arena_t *arena, pm_keyword_hash_node_t * */ static pm_required_keyword_parameter_node_t * pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_required_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_keyword_parameter_node_t); - - *node = (pm_required_keyword_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REQUIRED_KEYWORD_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_raw(parser, name->start, name->end - 1), - .name_loc = TOK2LOC(parser, name), - }; - - return node; + return pm_required_keyword_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_raw(parser, name->start, name->end - 1), + TOK2LOC(parser, name) + ); } /** @@ -5116,16 +5090,15 @@ pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t */ static pm_optional_keyword_parameter_node_t * pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, pm_node_t *value) { - pm_optional_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_keyword_parameter_node_t); - - *node = (pm_optional_keyword_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_OPTIONAL_KEYWORD_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, name, value)), - .name = pm_parser_constant_id_raw(parser, name->start, name->end - 1), - .name_loc = TOK2LOC(parser, name), - .value = value - }; - - return node; + return pm_optional_keyword_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, name, value), + pm_parser_constant_id_raw(parser, name->start, name->end - 1), + TOK2LOC(parser, name), + value + ); } /** @@ -5133,16 +5106,15 @@ pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t */ static pm_keyword_rest_parameter_node_t * pm_keyword_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) { - pm_keyword_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_rest_parameter_node_t); - - *node = (pm_keyword_rest_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_KEYWORD_REST_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_keyword_rest_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -5158,19 +5130,18 @@ pm_lambda_node_create( pm_node_t *parameters, pm_node_t *body ) { - pm_lambda_node_t *node = PM_NODE_ALLOC(parser, pm_lambda_node_t); - - *node = (pm_lambda_node_t) { - .base = PM_NODE_INIT(parser, PM_LAMBDA_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, closing)), - .locals = *locals, - .operator_loc = TOK2LOC(parser, operator), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .parameters = parameters, - .body = body - }; - - return node; + return pm_lambda_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, closing), + *locals, + TOK2LOC(parser, operator), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing), + parameters, + body + ); } /** @@ -5180,18 +5151,18 @@ static pm_local_variable_and_write_node_t * pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_IT_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE)); assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + depth + ); } /** @@ -5199,19 +5170,18 @@ pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_local_variable_operator_write_node_t * pm_local_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { - 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) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .depth = depth - }; - - return node; + return pm_local_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + depth + ); } /** @@ -5221,18 +5191,18 @@ static pm_local_variable_or_write_node_t * pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_IT_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE)); assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - 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) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + depth + ); } /** @@ -5242,15 +5212,14 @@ static pm_local_variable_read_node_t * pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_token_t *name, pm_constant_id_t name_id, uint32_t depth, bool missing) { if (!missing) pm_locals_read(&pm_parser_scope_find(parser, depth)->locals, name_id); - pm_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_read_node_t); - - *node = (pm_local_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = name_id, - .depth = depth - }; - - return node; + return pm_local_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + name_id, + depth + ); } /** @@ -5277,19 +5246,17 @@ 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) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_WRITE_NODE, flags, ((pm_location_t) { .start = name_loc->start, .length = PM_NODE_END(value) - name_loc->start })), - .name = name, - .depth = depth, - .value = value, - .name_loc = *name_loc, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_local_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + ((pm_location_t) { .start = name_loc->start, .length = PM_NODE_END(value) - name_loc->start }), + name, + depth, + *name_loc, + value, + TOK2LOC(parser, operator) + ); } /** @@ -5332,15 +5299,15 @@ pm_refute_numbered_parameter(pm_parser_t *parser, uint32_t start, uint32_t lengt static pm_local_variable_target_node_t * pm_local_variable_target_node_create(pm_parser_t *parser, const pm_location_t *location, pm_constant_id_t name, uint32_t depth) { pm_refute_numbered_parameter(parser, location->start, location->length); - pm_local_variable_target_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_target_node_t); - - *node = (pm_local_variable_target_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_TARGET_NODE, 0, ((pm_location_t) { .start = location->start, .length = location->length })), - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_target_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = location->start, .length = location->length }), + name, + depth + ); } /** @@ -5350,16 +5317,15 @@ static pm_match_predicate_node_t * pm_match_predicate_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) { pm_assert_value_expression(parser, value); - pm_match_predicate_node_t *node = PM_NODE_ALLOC(parser, pm_match_predicate_node_t); - - *node = (pm_match_predicate_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_PREDICATE_NODE, 0, PM_LOCATION_INIT_NODES(value, pattern)), - .value = value, - .pattern = pattern, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_match_predicate_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, pattern), + value, + pattern, + TOK2LOC(parser, operator) + ); } /** @@ -5369,16 +5335,15 @@ static pm_match_required_node_t * pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) { pm_assert_value_expression(parser, value); - pm_match_required_node_t *node = PM_NODE_ALLOC(parser, pm_match_required_node_t); - - *node = (pm_match_required_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_REQUIRED_NODE, 0, PM_LOCATION_INIT_NODES(value, pattern)), - .value = value, - .pattern = pattern, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_match_required_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, pattern), + value, + pattern, + TOK2LOC(parser, operator) + ); } /** @@ -5386,15 +5351,14 @@ pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t * */ static pm_match_write_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_MATCH_WRITE_NODE, 0, PM_LOCATION_INIT_NODE(call)), - .call = call, - .targets = { 0 } - }; - - return node; + return pm_match_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(call), + call, + ((pm_node_list_t) { 0 }) + ); } /** @@ -5402,19 +5366,18 @@ pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) { */ static pm_module_node_t * pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *module_keyword, pm_node_t *constant_path, const pm_token_t *name, pm_node_t *body, const pm_token_t *end_keyword) { - pm_module_node_t *node = PM_NODE_ALLOC(parser, pm_module_node_t); - - *node = (pm_module_node_t) { - .base = PM_NODE_INIT(parser, PM_MODULE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, module_keyword, end_keyword)), - .locals = (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals), - .module_keyword_loc = TOK2LOC(parser, module_keyword), - .constant_path = constant_path, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_module_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, module_keyword, end_keyword), + (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals), + TOK2LOC(parser, module_keyword), + constant_path, + body, + TOK2LOC(parser, end_keyword), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -5422,18 +5385,17 @@ pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const */ static pm_multi_target_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_MULTI_TARGET_NODE, 0, PM_LOCATION_INIT_UNSET), - .lefts = { 0 }, - .rest = NULL, - .rights = { 0 }, - .lparen_loc = { 0 }, - .rparen_loc = { 0 } - }; - - return node; + return pm_multi_target_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -5494,24 +5456,21 @@ pm_multi_target_node_closing_set(const pm_parser_t *parser, pm_multi_target_node */ 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) { - .base = PM_NODE_INIT(parser, PM_MULTI_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .lefts = target->lefts, - .rest = target->rest, - .rights = target->rights, - .lparen_loc = target->lparen_loc, - .rparen_loc = target->rparen_loc, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - // The target is no longer necessary because we've reused its children. - // It is arena-allocated so no explicit free is needed. - - return node; + /* The target is no longer necessary because we have reused its children. It + * is arena-allocated so no explicit free is needed. */ + return pm_multi_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target->lefts, + target->rest, + target->rights, + target->lparen_loc, + target->rparen_loc, + TOK2LOC(parser, operator), + value + ); } /** @@ -5520,15 +5479,15 @@ pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, static pm_next_node_t * pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_NEXT); - pm_next_node_t *node = PM_NODE_ALLOC(parser, pm_next_node_t); - *node = (pm_next_node_t) { - .base = PM_NODE_INIT(parser, PM_NEXT_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .keyword_loc = TOK2LOC(parser, keyword), - .arguments = arguments - }; - - return node; + return pm_next_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + arguments, + TOK2LOC(parser, keyword) + ); } /** @@ -5537,13 +5496,13 @@ pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments static pm_nil_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_NIL_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_nil_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -5553,15 +5512,15 @@ static pm_no_block_parameter_node_t * pm_no_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) { assert(operator->type == PM_TOKEN_AMPERSAND || operator->type == PM_TOKEN_UAMPERSAND); assert(keyword->type == PM_TOKEN_KEYWORD_NIL); - pm_no_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_block_parameter_node_t); - - *node = (pm_no_block_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_NO_BLOCK_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, keyword)), - .operator_loc = TOK2LOC(parser, operator), - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_no_block_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, keyword), + TOK2LOC(parser, operator), + TOK2LOC(parser, keyword) + ); } /** @@ -5571,15 +5530,15 @@ static pm_no_keywords_parameter_node_t * pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) { assert(operator->type == PM_TOKEN_USTAR_STAR || operator->type == PM_TOKEN_STAR_STAR); assert(keyword->type == PM_TOKEN_KEYWORD_NIL); - pm_no_keywords_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_keywords_parameter_node_t); - - *node = (pm_no_keywords_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_NO_KEYWORDS_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, keyword)), - .operator_loc = TOK2LOC(parser, operator), - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_no_keywords_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, keyword), + TOK2LOC(parser, operator), + TOK2LOC(parser, keyword) + ); } /** @@ -5587,14 +5546,13 @@ pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *oper */ static pm_numbered_parameters_node_t * pm_numbered_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing, uint8_t maximum) { - pm_numbered_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_parameters_node_t); - - *node = (pm_numbered_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_NUMBERED_PARAMETERS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .maximum = maximum - }; - - return node; + return pm_numbered_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + maximum + ); } /** @@ -5652,14 +5610,14 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to static pm_numbered_reference_read_node_t * pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_NUMBERED_REFERENCE); - pm_numbered_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_reference_read_node_t); - - *node = (pm_numbered_reference_read_node_t) { - .base = PM_NODE_INIT(parser, PM_NUMBERED_REFERENCE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .number = pm_numbered_reference_read_node_number(parser, name) - }; - return node; + return pm_numbered_reference_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_numbered_reference_read_node_number(parser, name) + ); } /** @@ -5667,17 +5625,16 @@ pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *na */ static pm_optional_parameter_node_t * pm_optional_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator, pm_node_t *value) { - pm_optional_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_parameter_node_t); - - *node = (pm_optional_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_OPTIONAL_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, name, value)), - .name = pm_parser_constant_id_token(parser, name), - .name_loc = TOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_optional_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, name, value), + pm_parser_constant_id_token(parser, name), + TOK2LOC(parser, name), + TOK2LOC(parser, operator), + value + ); } /** @@ -5687,16 +5644,15 @@ static pm_or_node_t * pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); - pm_or_node_t *node = PM_NODE_ALLOC(parser, pm_or_node_t); - - *node = (pm_or_node_t) { - .base = PM_NODE_INIT(parser, PM_OR_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_or_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -5704,20 +5660,19 @@ pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operat */ static pm_parameters_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_PARAMETERS_NODE, 0, PM_LOCATION_INIT_UNSET), - .rest = NULL, - .keyword_rest = NULL, - .block = NULL, - .requireds = { 0 }, - .optionals = { 0 }, - .posts = { 0 }, - .keywords = { 0 } - }; - - return node; + return pm_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_node_list_t) { 0 }), + NULL, + NULL + ); } /** @@ -5804,15 +5759,14 @@ pm_parameters_node_block_set(pm_parameters_node_t *params, pm_node_t *param) { */ static pm_program_node_t * pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_statements_node_t *statements) { - pm_program_node_t *node = PM_NODE_ALLOC(parser, pm_program_node_t); - - *node = (pm_program_node_t) { - .base = PM_NODE_INIT(parser, PM_PROGRAM_NODE, 0, PM_LOCATION_INIT_NODE(statements)), - .locals = *locals, - .statements = statements - }; - - return node; + return pm_program_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(statements), + *locals, + statements + ); } /** @@ -5820,16 +5774,15 @@ pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_st */ static pm_parentheses_node_t * pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_node_t *body, const pm_token_t *closing, pm_node_flags_t flags) { - pm_parentheses_node_t *node = PM_NODE_ALLOC(parser, pm_parentheses_node_t); - - *node = (pm_parentheses_node_t) { - .base = PM_NODE_INIT(parser, PM_PARENTHESES_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .body = body, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_parentheses_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + body, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5837,17 +5790,16 @@ pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_no */ static pm_pinned_expression_node_t * pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *operator, const pm_token_t *lparen, const pm_token_t *rparen) { - pm_pinned_expression_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_expression_node_t); - - *node = (pm_pinned_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_PINNED_EXPRESSION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, rparen)), - .expression = expression, - .operator_loc = TOK2LOC(parser, operator), - .lparen_loc = TOK2LOC(parser, lparen), - .rparen_loc = TOK2LOC(parser, rparen) - }; - - return node; + return pm_pinned_expression_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, rparen), + expression, + TOK2LOC(parser, operator), + TOK2LOC(parser, lparen), + TOK2LOC(parser, rparen) + ); } /** @@ -5855,15 +5807,14 @@ pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, con */ static pm_pinned_variable_node_t * pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) { - pm_pinned_variable_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_variable_node_t); - - *node = (pm_pinned_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_PINNED_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable)), - .variable = variable, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_pinned_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable), + variable, + TOK2LOC(parser, operator) + ); } /** @@ -5871,17 +5822,16 @@ pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, */ static pm_post_execution_node_t * pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_post_execution_node_t *node = PM_NODE_ALLOC(parser, pm_post_execution_node_t); - - *node = (pm_post_execution_node_t) { - .base = PM_NODE_INIT(parser, PM_POST_EXECUTION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .statements = statements, - .keyword_loc = TOK2LOC(parser, keyword), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_post_execution_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + statements, + TOK2LOC(parser, keyword), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5889,17 +5839,16 @@ pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, co */ static pm_pre_execution_node_t * pm_pre_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_pre_execution_node_t *node = PM_NODE_ALLOC(parser, pm_pre_execution_node_t); - - *node = (pm_pre_execution_node_t) { - .base = PM_NODE_INIT(parser, PM_PRE_EXECUTION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .statements = statements, - .keyword_loc = TOK2LOC(parser, keyword), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_pre_execution_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + statements, + TOK2LOC(parser, keyword), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5909,8 +5858,6 @@ static pm_range_node_t * pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); pm_assert_value_expression(parser, right); - - pm_range_node_t *node = PM_NODE_ALLOC(parser, pm_range_node_t); pm_node_flags_t flags = 0; // Indicate that this node is an exclusive range if the operator is `...`. @@ -5931,14 +5878,15 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope uint32_t start = left == NULL ? PM_TOKEN_START(parser, operator) : PM_NODE_START(left); uint32_t end = right == NULL ? PM_TOKEN_END(parser, operator) : PM_NODE_END(right); - *node = (pm_range_node_t) { - .base = PM_NODE_INIT(parser, PM_RANGE_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_range_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -5947,13 +5895,13 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope static pm_redo_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_REDO_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_redo_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -5962,18 +5910,16 @@ 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) { - .base = PM_NODE_INIT(parser, PM_REGULAR_EXPRESSION_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = TOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_regular_expression_node_new( + parser->arena, + ++parser->node_id, + pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + TOK2LOC(parser, content), + TOK2LOC(parser, closing), + *unescaped + ); } /** @@ -5989,14 +5935,13 @@ pm_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening */ static pm_required_parameter_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_REQUIRED_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - - return node; + return pm_required_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -6004,16 +5949,15 @@ pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) */ static pm_rescue_modifier_node_t * pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *keyword, pm_node_t *rescue_expression) { - pm_rescue_modifier_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_modifier_node_t); - - *node = (pm_rescue_modifier_node_t) { - .base = PM_NODE_INIT(parser, PM_RESCUE_MODIFIER_NODE, 0, PM_LOCATION_INIT_NODES(expression, rescue_expression)), - .expression = expression, - .keyword_loc = TOK2LOC(parser, keyword), - .rescue_expression = rescue_expression - }; - - return node; + return pm_rescue_modifier_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(expression, rescue_expression), + expression, + TOK2LOC(parser, keyword), + rescue_expression + ); } /** @@ -6021,20 +5965,19 @@ pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const */ static pm_rescue_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_RESCUE_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, keyword)), - .keyword_loc = TOK2LOC(parser, keyword), - .operator_loc = { 0 }, - .then_keyword_loc = { 0 }, - .reference = NULL, - .statements = NULL, - .subsequent = NULL, - .exceptions = { 0 } - }; - - return node; + return pm_rescue_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, keyword), + TOK2LOC(parser, keyword), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + NULL, + ((pm_location_t) { 0 }), + NULL, + NULL + ); } static inline void @@ -6085,16 +6028,15 @@ pm_rescue_node_exceptions_append(pm_arena_t *arena, pm_rescue_node_t *node, pm_n */ static pm_rest_parameter_node_t * pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) { - pm_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_rest_parameter_node_t); - - *node = (pm_rest_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REST_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_rest_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -6103,13 +6045,13 @@ pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, c static pm_retry_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_RETRY_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_retry_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6117,15 +6059,14 @@ pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_return_node_t * pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { - pm_return_node_t *node = PM_NODE_ALLOC(parser, pm_return_node_t); - - *node = (pm_return_node_t) { - .base = PM_NODE_INIT(parser, PM_RETURN_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .keyword_loc = TOK2LOC(parser, keyword), - .arguments = arguments - }; - - return node; + return pm_return_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + TOK2LOC(parser, keyword), + arguments + ); } /** @@ -6134,13 +6075,13 @@ pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argumen static pm_self_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_SELF_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_self_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6148,14 +6089,13 @@ pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_shareable_constant_node_t * pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shareable_constant_value_t value) { - pm_shareable_constant_node_t *node = PM_NODE_ALLOC(parser, pm_shareable_constant_node_t); - - *node = (pm_shareable_constant_node_t) { - .base = PM_NODE_INIT(parser, PM_SHAREABLE_CONSTANT_NODE, (pm_node_flags_t) value, PM_LOCATION_INIT_NODE(write)), - .write = write - }; - - return node; + return pm_shareable_constant_node_new( + parser->arena, + ++parser->node_id, + (pm_node_flags_t) value, + PM_LOCATION_INIT_NODE(write), + write + ); } /** @@ -6163,19 +6103,18 @@ pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shar */ static pm_singleton_class_node_t * pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, const pm_token_t *operator, pm_node_t *expression, pm_node_t *body, const pm_token_t *end_keyword) { - pm_singleton_class_node_t *node = PM_NODE_ALLOC(parser, pm_singleton_class_node_t); - - *node = (pm_singleton_class_node_t) { - .base = PM_NODE_INIT(parser, PM_SINGLETON_CLASS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword)), - .locals = *locals, - .class_keyword_loc = TOK2LOC(parser, class_keyword), - .operator_loc = TOK2LOC(parser, operator), - .expression = expression, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_singleton_class_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword), + *locals, + TOK2LOC(parser, class_keyword), + TOK2LOC(parser, operator), + expression, + body, + TOK2LOC(parser, end_keyword) + ); } /** @@ -6184,13 +6123,13 @@ pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *local static pm_source_encoding_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_SOURCE_ENCODING_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_source_encoding_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6198,7 +6137,6 @@ pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_source_file_node_t* pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) { - pm_source_file_node_t *node = PM_NODE_ALLOC(parser, pm_source_file_node_t); assert(file_keyword->type == PM_TOKEN_KEYWORD___FILE__); pm_node_flags_t flags = 0; @@ -6212,12 +6150,13 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) break; } - *node = (pm_source_file_node_t) { - .base = PM_NODE_INIT(parser, PM_SOURCE_FILE_NODE, flags, PM_LOCATION_INIT_TOKEN(parser, file_keyword)), - .filepath = parser->filepath - }; - - return node; + return pm_source_file_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKEN(parser, file_keyword), + parser->filepath + ); } /** @@ -6226,13 +6165,13 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) static pm_source_line_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_SOURCE_LINE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_source_line_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6240,15 +6179,14 @@ pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_splat_node_t * pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) { - pm_splat_node_t *node = PM_NODE_ALLOC(parser, pm_splat_node_t); - - *node = (pm_splat_node_t) { - .base = PM_NODE_INIT(parser, PM_SPLAT_NODE, 0, (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression)), - .operator_loc = TOK2LOC(parser, operator), - .expression = expression - }; - - return node; + return pm_splat_node_new( + parser->arena, + ++parser->node_id, + 0, + (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression), + TOK2LOC(parser, operator), + expression + ); } /** @@ -6256,14 +6194,13 @@ pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t */ static pm_statements_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_STATEMENTS_NODE, 0, PM_LOCATION_INIT_UNSET), - .body = { 0 } - }; - - return node; + return pm_statements_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -6331,7 +6268,6 @@ pm_statements_node_body_prepend(pm_arena_t *arena, pm_statements_node_t *node, p */ static inline pm_string_node_t * pm_string_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 *string) { - pm_string_node_t *node = PM_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -6346,15 +6282,16 @@ pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, uint32_t start = PM_TOKEN_START(parser, opening == NULL ? content : opening); uint32_t end = PM_TOKEN_END(parser, closing == NULL ? content : closing); - *node = (pm_string_node_t) { - .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = NTOK2LOC(parser, closing), - .unescaped = *string - }; - - return node; + return pm_string_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + TOK2LOC(parser, content), + NTOK2LOC(parser, closing), + *string + ); } /** @@ -6382,21 +6319,21 @@ pm_string_node_create_current_string(pm_parser_t *parser, const pm_token_t *open static pm_super_node_t * pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_SUPER); - pm_super_node_t *node = PM_NODE_ALLOC(parser, pm_super_node_t); const pm_location_t *end = pm_arguments_end(arguments); assert(end != NULL && "unreachable"); - *node = (pm_super_node_t) { - .base = PM_NODE_INIT(parser, PM_SUPER_NODE, 0, ((pm_location_t) { .start = PM_TOKEN_START(parser, keyword), .length = PM_LOCATION_END(end) - PM_TOKEN_START(parser, keyword) })), - .keyword_loc = TOK2LOC(parser, keyword), - .lparen_loc = arguments->opening_loc, - .arguments = arguments->arguments, - .rparen_loc = arguments->closing_loc, - .block = arguments->block - }; - - return node; + return pm_super_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = PM_TOKEN_START(parser, keyword), .length = PM_LOCATION_END(end) - PM_TOKEN_START(parser, keyword) }), + TOK2LOC(parser, keyword), + arguments->opening_loc, + arguments->arguments, + arguments->closing_loc, + arguments->block + ); } /** @@ -6615,20 +6552,19 @@ parse_and_validate_regular_expression_encoding(pm_parser_t *parser, const pm_str */ 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); - uint32_t start = opening == NULL ? PM_TOKEN_START(parser, value) : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? PM_TOKEN_END(parser, value) : PM_TOKEN_END(parser, closing); - *node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .value_loc = NTOK2LOC(parser, value), - .closing_loc = NTOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL | flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + NTOK2LOC(parser, value), + NTOK2LOC(parser, closing), + *unescaped + ); } /** @@ -6672,13 +6608,16 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_symbol_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, PM_LOCATION_INIT_UNSET), - .value_loc = { 0 }, - .unescaped = { 0 } - }; + pm_symbol_node_t *node = pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, + PM_LOCATION_INIT_UNSET, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_string_t) { 0 }) + ); pm_string_constant_init(&node->unescaped, content, strlen(content)); return node; @@ -6718,15 +6657,16 @@ pm_symbol_node_label_p(const pm_parser_t *parser, const pm_node_t *node) { */ static pm_symbol_node_t * pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_token_t *opening, const pm_token_t *closing) { - pm_symbol_node_t *new_node = PM_NODE_ALLOC(parser, pm_symbol_node_t); - - *new_node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .value_loc = node->content_loc, - .closing_loc = TOK2LOC(parser, closing), - .unescaped = node->unescaped - }; + pm_symbol_node_t *new_node = pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + node->content_loc, + TOK2LOC(parser, closing), + node->unescaped + ); pm_token_t content = { .type = PM_TOKEN_IDENTIFIER, @@ -6736,8 +6676,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_node_flag_set(UP(new_node), parse_symbol_encoding(parser, &content, &node->unescaped, true)); - // The old node is arena-allocated so no explicit free is needed. - + /* The old node is arena-allocated so no explicit free is needed. */ return new_node; } @@ -6746,7 +6685,6 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const */ static pm_string_node_t * pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { - pm_string_node_t *new_node = PM_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -6758,16 +6696,18 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { break; } - *new_node = (pm_string_node_t) { - .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, PM_LOCATION_INIT_NODE(node)), - .opening_loc = node->opening_loc, - .content_loc = node->value_loc, - .closing_loc = node->closing_loc, - .unescaped = node->unescaped - }; - - // The old node is arena-allocated so no explicit free is needed. + pm_string_node_t *new_node = pm_string_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODE(node), + node->opening_loc, + node->value_loc, + node->closing_loc, + node->unescaped + ); + /* The old node is arena-allocated so no explicit free is needed. */ return new_node; } @@ -6777,13 +6717,13 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { static pm_true_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_true_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6791,13 +6731,12 @@ pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) { */ 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) { - .base = PM_NODE_INIT(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_UNSET) - }; - - return node; + return pm_true_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_UNSET + ); } /** @@ -6806,15 +6745,15 @@ pm_true_node_synthesized_create(pm_parser_t *parser) { static pm_undef_node_t * pm_undef_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_UNDEF); - pm_undef_node_t *node = PM_NODE_ALLOC(parser, pm_undef_node_t); - *node = (pm_undef_node_t) { - .base = PM_NODE_INIT(parser, PM_UNDEF_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .keyword_loc = TOK2LOC(parser, token), - .names = { 0 } - }; - - return node; + return pm_undef_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, token) + ); } /** @@ -6832,21 +6771,20 @@ pm_undef_node_append(pm_arena_t *arena, 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); pm_node_t *end = statements == NULL ? predicate : UP(statements); - *node = (pm_unless_node_t) { - .base = PM_NODE_INIT(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, end)), - .keyword_loc = TOK2LOC(parser, keyword), - .predicate = predicate, - .then_keyword_loc = NTOK2LOC(parser, then_keyword), - .statements = statements, - .else_clause = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_unless_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, end), + TOK2LOC(parser, keyword), + predicate, + NTOK2LOC(parser, then_keyword), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -6855,22 +6793,22 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t static pm_unless_node_t * pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *unless_keyword, pm_node_t *predicate) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t); pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); - *node = (pm_unless_node_t) { - .base = PM_NODE_INIT(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(statement, predicate)), - .keyword_loc = TOK2LOC(parser, unless_keyword), - .predicate = predicate, - .then_keyword_loc = { 0 }, - .statements = statements, - .else_clause = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_unless_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(statement, predicate), + TOK2LOC(parser, unless_keyword), + predicate, + ((pm_location_t) { 0 }), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } static inline void @@ -6907,19 +6845,19 @@ pm_loop_modifier_block_exits(pm_parser_t *parser, pm_statements_node_t *statemen */ static pm_until_node_t * pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *do_keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - *node = (pm_until_node_t) { - .base = PM_NODE_INIT(parser, PM_UNTIL_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .closing_loc = TOK2LOC(parser, closing), - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_until_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + TOK2LOC(parser, keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, closing), + predicate, + statements + ); } /** @@ -6927,20 +6865,20 @@ pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to */ static pm_until_node_t * pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); pm_loop_modifier_block_exits(parser, statements); - *node = (pm_until_node_t) { - .base = PM_NODE_INIT(parser, PM_UNTIL_NODE, flags, PM_LOCATION_INIT_NODES(statements, predicate)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_until_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODES(statements, predicate), + TOK2LOC(parser, keyword), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -6948,17 +6886,16 @@ pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm */ static pm_when_node_t * 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) { - .base = PM_NODE_INIT(parser, PM_WHEN_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, keyword)), - .keyword_loc = TOK2LOC(parser, keyword), - .statements = NULL, - .then_keyword_loc = { 0 }, - .conditions = { 0 } - }; - - return node; + return pm_when_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, keyword), + TOK2LOC(parser, keyword), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + NULL + ); } /** @@ -6996,19 +6933,19 @@ pm_when_node_statements_set(pm_when_node_t *node, pm_statements_node_t *statemen */ static pm_while_node_t * pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *do_keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .closing_loc = TOK2LOC(parser, closing), - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + TOK2LOC(parser, keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, closing), + predicate, + statements + ); } /** @@ -7016,20 +6953,20 @@ pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to */ static pm_while_node_t * pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); pm_loop_modifier_block_exits(parser, statements); - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, flags, PM_LOCATION_INIT_NODES(statements, predicate)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODES(statements, predicate), + TOK2LOC(parser, keyword), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -7037,18 +6974,17 @@ pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm */ static pm_while_node_t * pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_statements_node_t *statements) { - pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); - - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, 0, PM_LOCATION_INIT_UNSET), - .keyword_loc = { 0 }, - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -7057,17 +6993,16 @@ pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_s */ static pm_x_string_node_t * pm_xstring_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_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_x_string_node_t); - - *node = (pm_x_string_node_t) { - .base = PM_NODE_INIT(parser, PM_X_STRING_NODE, PM_STRING_FLAGS_FROZEN, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = TOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_x_string_node_new( + parser->arena, + ++parser->node_id, + PM_STRING_FLAGS_FROZEN, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + TOK2LOC(parser, content), + TOK2LOC(parser, closing), + *unescaped + ); } /** @@ -7083,8 +7018,6 @@ pm_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_ */ static pm_yield_node_t * pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_location_t *lparen_loc, pm_arguments_node_t *arguments, const pm_location_t *rparen_loc) { - pm_yield_node_t *node = PM_NODE_ALLOC(parser, pm_yield_node_t); - uint32_t start = PM_TOKEN_START(parser, keyword); uint32_t end; @@ -7098,15 +7031,16 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo end = PM_TOKEN_END(parser, keyword); } - *node = (pm_yield_node_t) { - .base = PM_NODE_INIT(parser, PM_YIELD_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .keyword_loc = TOK2LOC(parser, keyword), - .lparen_loc = *lparen_loc, - .arguments = arguments, - .rparen_loc = *rparen_loc - }; - - return node; + return pm_yield_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + TOK2LOC(parser, keyword), + *lparen_loc, + arguments, + *rparen_loc + ); } /** diff --git a/prism/srcs.mk b/prism/srcs.mk index 022662a00b5f30..ca3f86d3162621 100644 --- a/prism/srcs.mk +++ b/prism/srcs.mk @@ -44,6 +44,13 @@ $(srcdir)/prism/diagnostic.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATE realclean-prism-srcs:: $(RM) $(srcdir)/prism/diagnostic.h +main incs: $(srcdir)/prism/node_new.h +$(srcdir)/prism/node_new.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/include/prism/node_new.h.erb + $(Q) $(BASERUBY) $(PRISM_TEMPLATE) include/prism/node_new.h $@ + +realclean-prism-srcs:: + $(RM) $(srcdir)/prism/node_new.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 $@ diff --git a/prism/templates/include/prism/node_new.h.erb b/prism/templates/include/prism/node_new.h.erb new file mode 100644 index 00000000000000..56c214e00634b1 --- /dev/null +++ b/prism/templates/include/prism/node_new.h.erb @@ -0,0 +1,42 @@ +/** + * @file node_new.h + * + * Static inline functions for allocating and initializing AST nodes. + * + * -- + */ +#ifndef PRISM_NODE_NEW_H +#define PRISM_NODE_NEW_H + +#include "prism/node.h" + +<%- nodes.each do |node| -%> +<%- params = node.fields.map(&:c_param) -%> +/** + * Allocate and initialize a new <%= node.name %> node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. +<%- node.fields.each do |field| -%> + * @param <%= field.name %> <%= field.comment ? Prism::Template::Doxygen.verbatim(field.comment.lines.first.strip) : "The #{field.name} field." %> +<%- end -%> + * @return The newly allocated and initialized node. + */ +static inline pm_<%= node.human %>_t * +pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { + pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); + + *node = (pm_<%= node.human %>_t) { + .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %> +<%- node.fields.each_with_index do |field, index| -%> + .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %> +<%- end -%> + }; + + return node; +} + +<%- end -%> +#endif diff --git a/prism/templates/template.rb b/prism/templates/template.rb index e571c58bf298a8..70fa17c83d59b9 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -105,6 +105,11 @@ def should_be_serialized? # Some node fields can be specialized if they point to a specific kind of # node and not just a generic node. class NodeKindField < Field + # The C type to use for this field as a function parameter. + def c_param + "struct #{c_type} *#{name}" + end + def initialize(kind:, **options) @kind = kind super(**options) @@ -210,6 +215,10 @@ def check_field_kind # This represents a field on a node that is a list of nodes. We pass them as # references and store them directly on the struct. class NodeListField < NodeKindField + def c_param + "pm_node_list_t #{name}" + end + def element_rbs_class if specific_kind "#{specific_kind}" @@ -250,6 +259,10 @@ def check_field_kind # This represents a field on a node that is the ID of a string interned # through the parser's constant pool. class ConstantField < Field + def c_param + "pm_constant_id_t #{name}" + end + def rbs_class "Symbol" end @@ -266,6 +279,10 @@ def java_type # This represents a field on a node that is the ID of a string interned # through the parser's constant pool and can be optionally null. class OptionalConstantField < Field + def c_param + "pm_constant_id_t #{name}" + end + def rbs_class "Symbol?" end @@ -282,6 +299,10 @@ def java_type # This represents a field on a node that is a list of IDs that are associated # with strings interned through the parser's constant pool. class ConstantListField < Field + def c_param + "pm_constant_id_list_t #{name}" + end + def rbs_class "Array[Symbol]" end @@ -297,6 +318,10 @@ def java_type # This represents a field on a node that is a string. class StringField < Field + def c_param + "pm_string_t #{name}" + end + def rbs_class "String" end @@ -312,6 +337,10 @@ def java_type # This represents a field on a node that is a location. class LocationField < Field + def c_param + "pm_location_t #{name}" + end + def semantic_field? false end @@ -331,6 +360,10 @@ def java_type # This represents a field on a node that is a location that is optional. class OptionalLocationField < Field + def c_param + "pm_location_t #{name}" + end + def semantic_field? false end @@ -350,6 +383,10 @@ def java_type # This represents an integer field. class UInt8Field < Field + def c_param + "uint8_t #{name}" + end + def rbs_class "Integer" end @@ -365,6 +402,10 @@ def java_type # This represents an integer field. class UInt32Field < Field + def c_param + "uint32_t #{name}" + end + def rbs_class "Integer" end @@ -381,6 +422,10 @@ def java_type # This represents an arbitrarily-sized integer. When it gets to Ruby it will # be an Integer. class IntegerField < Field + def c_param + "pm_integer_t #{name}" + end + def rbs_class "Integer" end @@ -397,6 +442,10 @@ def java_type # This represents a double-precision floating point number. When it gets to # Ruby it will be a Float. class DoubleField < Field + def c_param + "double #{name}" + end + def rbs_class "Float" end @@ -636,6 +685,7 @@ def locals "ext/prism/api_node.c", "include/prism/ast.h", "include/prism/diagnostic.h", + "include/prism/node_new.h", "javascript/src/deserialize.js", "javascript/src/nodes.js", "javascript/src/visitor.js",