compiler, runtime, testing, common: Centralize Execution/Evaluation

Centralize the execution of statements and evaluation of expressions
so that the user can specify a debugging "callback" after every
execution/evaluation.

The callback can be used for myriad things, but it seems likely that
it will be useful for implementing:
1. Testing
2. Debugger

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-04-20 05:48:09 -04:00
parent c6f086f67f
commit d33066c543
13 changed files with 346 additions and 115 deletions
+41 -6
View File
@@ -15,25 +15,32 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
public typealias StatementInterloper = (EvaluatableStatement, ControlFlow, ProgramExecution) -> Void
public typealias ExpressionInterloper = (EvaluatableExpression, Result<P4Value>, ProgramExecution) -> Void
open class ProgramExecution: CustomStringConvertible {
public var scopes: VarValueScopes = VarValueScopes()
let initialValues: VarValueScopes?
var globalValues: VarValueScopes?
var error: Error?
var debug: DebugLevel = DebugLevel.Error
var statement_interloper: StatementInterloper?
var expression_interloper: ExpressionInterloper?
init(copy: ProgramExecution) {
self.scopes = copy.scopes
self.initialValues = copy.initialValues
self.globalValues = copy.globalValues
self.error = copy.error
self.debug = copy.debug
self.statement_interloper = copy.statement_interloper
self.expression_interloper = copy.expression_interloper
}
public init() {
initialValues = .none
globalValues = .none
}
public init(withGlobalValues values: VarValueScopes) {
initialValues = values
globalValues = values
}
open var description: String {
@@ -64,6 +71,26 @@ open class ProgramExecution: CustomStringConvertible {
return pe
}
public func getStatementInterloper() -> StatementInterloper? {
return self.statement_interloper
}
public func setStatementInterloper(_ interloper: @escaping StatementInterloper) -> ProgramExecution {
let pe = ProgramExecution(copy: self)
pe.statement_interloper = interloper
return pe
}
public func getExpressionInterloper() -> ExpressionInterloper? {
return self.expression_interloper
}
public func setExpressionInterloper(_ interloper: @escaping ExpressionInterloper) -> ProgramExecution {
let pe = ProgramExecution(copy: self)
pe.expression_interloper = interloper
return pe
}
open func isDone() -> Bool {
return false
}
@@ -101,9 +128,17 @@ open class ProgramExecution: CustomStringConvertible {
return new_pe
}
public func initial_values() -> VarValueScopes? {
return self.initialValues
public func getGlobalValues() -> VarValueScopes {
return self.globalValues ?? VarValueScopes()
}
public func setGlobalValues(_ global_values: VarValueScopes) -> ProgramExecution {
let new_pe = ProgramExecution(copy: self)
new_pe.globalValues = global_values
return new_pe
}
}
/// A scope that resolves variable identifiers to their values.
+2 -13
View File
@@ -117,24 +117,13 @@ public enum Result<OKT>: Equatable {
}
}
extension Result where OKT: CustomStringConvertible {
extension Result: CustomStringConvertible where OKT: CustomStringConvertible {
public var description: String {
switch self {
case Result.Error(let e):
return e.msg
case Result.Ok(let o):
return "\(o)"
}
}
}
extension Result: CustomStringConvertible {
public var description: String {
switch self {
case Result.Error(let e):
return e.msg
case Result.Ok(_):
return "Ok"
return "Ok: \(o)"
}
}
}