Class: Ibex::Runtime::CST::NodeCache

Inherits:
Object
  • Object
show all
Defined in:
lib/json5/generated_parser.rb

Overview

Session-owned hash-consing cache for immutable Green elements.

Constant Summary collapse

DEFAULT_NODE_ARITY_LIMIT =

Signature:

  • Integer

3
DEFAULT_NODE_DESCENDANT_LIMIT =

Signature:

  • Integer

32
EMPTY_TRIVIA =

Signature:

  • Array[GreenTrivia]

empty_trivia.freeze

Instance Method Summary collapse

Constructor Details

#initialize(enabled: true, node_arity_limit: DEFAULT_NODE_ARITY_LIMIT, node_descendant_limit: DEFAULT_NODE_DESCENDANT_LIMIT) ⇒ NodeCache

Returns a new instance of NodeCache.

RBS:

  • (?enabled: bool, ?node_arity_limit: Integer, ?node_descendant_limit: Integer) -> void

Raises:

  • (ArgumentError)


504
505
506
507
508
509
510
511
512
513
514
515
516
517
# File 'lib/json5/generated_parser.rb', line 504

def initialize(
  enabled: true, node_arity_limit: DEFAULT_NODE_ARITY_LIMIT,
  node_descendant_limit: DEFAULT_NODE_DESCENDANT_LIMIT
)
  raise ArgumentError, "node_arity_limit must be non-negative" if node_arity_limit.negative?
  raise ArgumentError, "node_descendant_limit must be positive" unless node_descendant_limit.positive?

  @enabled = enabled
  @node_arity_limit = node_arity_limit
  @node_descendant_limit = node_descendant_limit
  @trivia = {}
  @tokens = {}
  @nodes = {}
end

Instance Method Details

#clearObject

RBS:

  • () -> void



599
600
601
602
603
# File 'lib/json5/generated_parser.rb', line 599

def clear
  @trivia.clear
  @tokens.clear
  @nodes.clear
end

#intern_node(node) ⇒ Object

RBS:

  • (GreenNode node) -> GreenNode



589
590
591
592
593
594
595
596
# File 'lib/json5/generated_parser.rb', line 589

def intern_node(node)
  return node unless @enabled
  return node if node.children.length > @node_arity_limit
  return node if node.descendant_count > @node_descendant_limit
  return node unless node.flags.nobits?(Flags::HAS_ANNOTATION)

  @nodes[node] ||= node
end

#intern_token(token) ⇒ Object

RBS:

  • (GreenToken token) -> GreenToken



540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
# File 'lib/json5/generated_parser.rb', line 540

def intern_token(token)
  return token unless @enabled
  return token unless token.flags.nobits?(Flags::HAS_ANNOTATION)

  signature = token_signature(
    token.kind, token.text, token.leading, token.trailing, token.flags, token.expected_kind
  )
  bucket = @tokens[signature]
  existing = find_token(
    bucket, token.kind, token.text, token.leading, token.trailing, token.flags, token.expected_kind
  )
  return existing if existing

  (@tokens[signature] ||= []) << token
  token
end

#intern_token_fields(kind:, text:, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0, expected_kind: nil) ⇒ Object

Intern a token before constructing it, avoiding discarded duplicate immutable values.

RBS:

  • (kind: Integer, text: String, ?leading: Array[GreenTrivia], ?trailing: Array[GreenTrivia], ?flags: Integer, ?expected_kind: Integer?) -> GreenToken



560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
# File 'lib/json5/generated_parser.rb', line 560

def intern_token_fields(
  kind:, text:, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0, expected_kind: nil
)
  unless @enabled && flags.nobits?(Flags::HAS_ANNOTATION)
    return GreenToken.new(
      kind: kind, text: text, leading: leading, trailing: trailing,
      flags: flags, expected_kind: expected_kind
    )
  end

  comparable_text = if text.encoding == Encoding::BINARY || text.ascii_only?
                      text
                    else
                      text.b.freeze
                    end
  signature = token_signature(kind, comparable_text, leading, trailing, flags, expected_kind)
  bucket = @tokens[signature]
  existing = find_token(bucket, kind, comparable_text, leading, trailing, flags, expected_kind)
  return existing if existing

  token = GreenToken.new(
    kind: kind, text: comparable_text, leading: leading, trailing: trailing,
    flags: flags, expected_kind: expected_kind
  )
  (@tokens[signature] ||= []) << token
  token
end

#intern_trivia_fields(kind:, text:) ⇒ Object

Intern trivia before constructing it, using byte-equivalent text within this session.

RBS:

  • (kind: Integer, text: String) -> GreenTrivia



521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
# File 'lib/json5/generated_parser.rb', line 521

def intern_trivia_fields(kind:, text:)
  return GreenTrivia.new(kind: kind, text: text) unless @enabled

  comparable_text = if text.encoding == Encoding::BINARY || text.ascii_only?
                      text
                    else
                      text.b.freeze
                    end
  signature = kind.hash ^ comparable_text.hash
  bucket = @trivia[signature]
  existing = bucket&.find { |trivia| trivia.kind == kind && trivia.text == comparable_text }
  return existing if existing

  trivia = GreenTrivia.new(kind: kind, text: comparable_text)
  (@trivia[signature] ||= []) << trivia
  trivia
end