Class: Carbon::Compiler::Metanostic::State

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/carbon/compiler/metanostic/state.rb

Overview

A “State” object. This manages the state of metanostic modes at any point in the program. This is useful for something like the diagnostic directives, in which ‘pop`/`push`/`set` operations need to be available for the metanostic modes. This manages the metanostic modes.

The Carbon::Compiler::Metanostics are first loaded using Defaults.defaults. They are then used to generate a “beginning” state or “blank” state. Their modes are extracted, resulting in a hash of ‘=> (Integer, Metanostic)`. Then, a “current” state is generated; this is the same hash type as the “beginning” state, and initially, the same contents. However, when the `push` operation occurs, a new “state” is added to the stack, and a new “current” state is generated, using the beginning state and the stack as a reference. Whenever a set occurs, it sets to the last state added to the stack, and a new current state is generated.

The point of all this is to have a hash at all times that accurately represents the set modes of all diagnostics.

Instance Method Summary collapse

Constructor Details

#initializeState

Initialize the state. It sets the defaults using Defaults.defaults, and generates the beginning state.



64
65
66
67
68
69
# File 'lib/carbon/compiler/metanostic/state.rb', line 64

def initialize
  @monitor = Monitor.new
  @defaults = Defaults.defaults
  @stack = Concurrent::Array.new([Concurrent::Hash.new])
  generate_beginning
end

Instance Method Details

#[](name) ⇒ (Integer, Metanostic)?

Indexes the state. Returns an array containing information about the mode and the metanostic for the corresponding name, otherwise it returns ‘nil`.

Parameters:

  • name (String)

    The name of the metanostic.

Returns:



37
# File 'lib/carbon/compiler/metanostic/state.rb', line 37

def_delegator :current, :[]

#current{String => (Integer, Metanostic)}

The current state. This is frozen and cached, since it is a derived value of the beginning state and the stack.

Returns:



146
147
148
149
150
# File 'lib/carbon/compiler/metanostic/state.rb', line 146

def current
  @_current ||= @monitor.synchronize do
    @stack.inject(@beginning) { |a, e| a.merge(e) }.freeze
  end
end

#each {|name, data| ... } ⇒ Enumerator

Iterates over each key-value pair in the current state.

Yields:

Yield Parameters:

  • name (String)

    The name, or key, of the key pair.

  • data ((Integer, Metanostic))

    The data, or value, of the key pair.

Returns:

  • (Enumerator)


60
# File 'lib/carbon/compiler/metanostic/state.rb', line 60

def_delegator :current, :each

#fetch(name, default = CANARY) ⇒ (Integer, Metanostic), Object

Fetches the Carbon::Compiler::Metanostic information with the name ‘name`. If no key exists with the given name, the method will attempt to do the following: if a block is given, yield to that; otherwise, if a default is given, return that; otherwise, throw a `KeyError`.

Parameters:

  • name (String)

    The name of the metanostic to look up.

Returns:

Raises:

  • (KeyError)

    If no block is given and no default is given and there is no key ‘name`.



51
# File 'lib/carbon/compiler/metanostic/state.rb', line 51

def_delegator :current, :fetch

#initialize_copy(state) ⇒ Object

Initializes a copy of the given state. This is called by ‘#clone` and `#dup`, and as such should not be used outside of either of these things.

Parameters:

  • state (State)

    The state to copy from.



76
77
78
79
80
81
# File 'lib/carbon/compiler/metanostic/state.rb', line 76

def initialize_copy(state)
  @defaults = state.defaults
  @stack = state.stack.map(&:clone)
  @monitor = Monitor.new
  @beginning = state.beginning
end

#popvoid

Note:

This may change the current state.

This method returns an undefined value.

Pops the last state from the stack. This could potentially change the state, since the last state may have a new diagnostic setting inside of it.



100
101
102
103
104
# File 'lib/carbon/compiler/metanostic/state.rb', line 100

def pop
  @monitor.synchronize do
    clear! if @stack.pop.any?
  end
end

#pushvoid

This method returns an undefined value.

Pushes to the stack. This pushes a clean state to the stack. This does not change the current state at all, since the new state is empty.



88
89
90
91
92
# File 'lib/carbon/compiler/metanostic/state.rb', line 88

def push
  @monitor.synchronize do
    @stack.push(Concurrent::Hash.new)
  end
end

#reset(name) ⇒ void

Note:

This changes the current state.

This method returns an undefined value.

This resets the given metanostic to its default metanostic mode. It does this by taking the definition from the beginning state and copying it to the last stack frame.

Parameters:

  • name (String)

    The name of the metanostic to reset.

Raises:

  • (KeyError)

    If the metanostic cannot be found.

  • (DiagnosticError)

    If the diagnostic could not be set to the given mode.

See Also:



138
139
140
# File 'lib/carbon/compiler/metanostic/state.rb', line 138

def reset(name)
  set(name, @beginning.fetch(name))
end

#set(name, mode) ⇒ void

Note:

This changes the current state.

This method returns an undefined value.

Sets the given metanostic name to the given metanostic value in the last state in the stack. If the metanostic is not found in any of the defaults, a ‘KeyError` is raised. If the new mode is not allowed for the given metanostic, a DiagnosticError is raised.

Raises:

  • (KeyError)

    If the metanostic cannot be found.

  • (DiagnosticError)

    If the diagnostic could not be set to the given mode.



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/carbon/compiler/metanostic/state.rb', line 116

def set(name, mode)
  @monitor.synchronize do
    mode = Mode.from(mode)
    metanostic = @defaults.fetch(name)
    unless metanostic.can_be?(mode)
      fail DiagnosticError,
        "Diagnostic #{name} cannot be #{Mode.to_s(mode)}"
    end
    @stack.last[metanostic.name] = [mode, metanostic]
    clear!
  end
end