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

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/runtime/cst/green/cache.rb,
sig/ibex/runtime/cst/green/cache.rbs

Overview

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

Constant Summary collapse

DEFAULT_NODE_ARITY_LIMIT =

Signature:

  • Integer

Returns:

  • (Integer)
3
DEFAULT_NODE_DESCENDANT_LIMIT =

Signature:

  • Integer

Returns:

  • (Integer)
32
EMPTY_TRIVIA =

Returns:

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

Parameters:

  • enabled: (Boolean) (defaults to: true)
  • node_arity_limit: (Integer) (defaults to: DEFAULT_NODE_ARITY_LIMIT)
  • node_descendant_limit: (Integer) (defaults to: DEFAULT_NODE_DESCENDANT_LIMIT)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ibex/runtime/cst/green/cache.rb', line 24

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

#clearvoid

This method returns an undefined value.

RBS:

  • () -> void



119
120
121
122
123
# File 'lib/ibex/runtime/cst/green/cache.rb', line 119

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

#find_token(bucket, kind, text, leading, trailing, flags, expected_kind) ⇒ GreenToken?

RBS:

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

Parameters:

  • bucket (Array[GreenToken], nil)
  • kind (Integer)
  • text (String)
  • leading (Array[GreenTrivia])
  • trailing (Array[GreenTrivia])
  • flags (Integer)
  • expected_kind (Integer, nil)

Returns:



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ibex/runtime/cst/green/cache.rb', line 135

def find_token(bucket, kind, text, leading, trailing, flags, expected_kind)
  return unless bucket

  bucket.find do |token|
    token.kind == kind &&
      token.text == text &&
      token.leading == leading &&
      token.trailing == trailing &&
      token.flags == flags &&
      token.expected_kind == expected_kind
  end
end

#intern_node(node) ⇒ GreenNode

RBS:

  • (GreenNode node) -> GreenNode

Parameters:

Returns:



109
110
111
112
113
114
115
116
# File 'lib/ibex/runtime/cst/green/cache.rb', line 109

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) ⇒ GreenToken

RBS:

  • (GreenToken token) -> GreenToken

Parameters:

Returns:



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ibex/runtime/cst/green/cache.rb', line 60

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) ⇒ GreenToken

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

Parameters:

  • kind: (Integer)
  • text: (String)
  • leading: (Array[GreenTrivia]) (defaults to: EMPTY_TRIVIA)
  • trailing: (Array[GreenTrivia]) (defaults to: EMPTY_TRIVIA)
  • flags: (Integer) (defaults to: 0)
  • expected_kind: (Integer, nil) (defaults to: nil)

Returns:



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ibex/runtime/cst/green/cache.rb', line 80

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:) ⇒ GreenTrivia

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

RBS:

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

Parameters:

  • kind: (Integer)
  • text: (String)

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/ibex/runtime/cst/green/cache.rb', line 41

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

#token_signature(kind, text, leading, trailing, flags, expected_kind) ⇒ Integer

RBS:

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

Parameters:

  • kind (Integer)
  • text (String)
  • leading (Array[GreenTrivia])
  • trailing (Array[GreenTrivia])
  • flags (Integer)
  • expected_kind (Integer, nil)

Returns:

  • (Integer)


129
130
131
# File 'lib/ibex/runtime/cst/green/cache.rb', line 129

def token_signature(kind, text, leading, trailing, flags, expected_kind)
  kind.hash ^ text.hash ^ leading.hash ^ trailing.hash ^ flags.hash ^ expected_kind.hash
end