// p4rse, Copyright 2026, Will Hawkins
//
// This file is part of p4rse.
//
// This file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
open class ProgramExecution: CustomStringConvertible {
public var scopes: VarValueScopes = VarValueScopes()
let initialValues: VarValueScopes?
var error: Error?
var debug: DebugLevel = DebugLevel.Error
init(copy: ProgramExecution) {
self.scopes = copy.scopes
self.initialValues = copy.initialValues
self.error = copy.error
self.debug = copy.debug
}
public init() {
initialValues = .none
}
public init(withGlobalValues values: VarValueScopes) {
initialValues = values
}
open var description: String {
return "Runtime:\nScopes: \(scopes)"
}
public func hasError() -> Bool {
return self.error != nil
}
public func getError() -> Error? {
return self.error
}
public func setError(error: Error) -> ProgramExecution {
let npe = ProgramExecution(copy: self)
npe.error = error
return npe
}
public func getDebugLevel() -> DebugLevel {
return self.debug
}
public func setDebugLevel(_ dl: DebugLevel) -> ProgramExecution {
let pe = ProgramExecution(copy: self)
pe.debug = dl
return pe
}
open func isDone() -> Bool {
return false
}
open func setDone() -> ProgramExecution {
// For a bare ProgramExecution, setDone is a noop.
return self
}
public func enter_scope() -> ProgramExecution {
let new_pe = ProgramExecution(copy: self)
new_pe.scopes = new_pe.scopes.enter()
return new_pe
}
public func exit_scope() -> ProgramExecution {
let new_pe = ProgramExecution(copy: self)
new_pe.scopes = new_pe.scopes.exit()
return new_pe
}
public func replaceScopes(_ new_scopes: VarValueScopes) -> ProgramExecution {
let new_pe = ProgramExecution(copy: self)
new_pe.scopes = new_scopes
return new_pe
}
public func declare(identifier: Identifier, withValue value: P4Value) -> ProgramExecution {
let new_pe = ProgramExecution(copy: self)
let new_scopes = new_pe.scopes.declare(identifier: identifier, withValue: value)
new_pe.scopes = new_scopes
return new_pe
}
public func initial_values() -> VarValueScopes? {
return self.initialValues
}
}
/// A scope that resolves variable identifiers to their values.
public typealias VarValueScope = Scope
/// Scopes that resolves variable identifiers to their values.
public typealias VarValueScopes = Scopes
/// Indicate the control flow result of a particular statement.
public enum ControlFlow {
case Next
case Continue
case Break
case Return(P4Value?)
case Error
}