compiler, language, runtime: Separate Parser Type From Instances
In P4, parsers are considered types. Those parsers are instantiated. The instantiated parsers are values. Previously, gp4 treated a parser type and a parser value as identical. This PR makes that difference clear _and_ sets the stage for the future. TODO: Make the same distinction between control and action types and values. Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -39,14 +39,14 @@ extension ParserAssignmentStatement: EvaluatableStatement {
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserStateDirectTransition: EvaluatableParserState {
|
||||
extension ParserStateDirectTransitionValue: EvaluatableParserState {
|
||||
public func execute(
|
||||
program: Common.ProgramExecution
|
||||
) -> (any EvaluatableParserState, Common.ProgramExecution) {
|
||||
var program = program.enter_scope()
|
||||
|
||||
let (control_flow, next_execution) = program.evaluator.ExecuteStatements(
|
||||
statements, inExecution: program)
|
||||
self.state.statements, inExecution: program)
|
||||
|
||||
switch control_flow {
|
||||
case .Next: program = next_execution
|
||||
@@ -59,17 +59,7 @@ extension ParserStateDirectTransition: EvaluatableParserState {
|
||||
)
|
||||
}
|
||||
|
||||
let res = program.scopes.lookup(identifier: get_next_state())
|
||||
|
||||
if case .Ok(let value) = res {
|
||||
if value.type().baseType().eq(rhs: self) {
|
||||
return (value.dataValue() as! EvaluatableParserState, program.exit_scope())
|
||||
}
|
||||
}
|
||||
|
||||
program = program.setError(error: res.error()!).exit_scope()
|
||||
|
||||
return (self, program.exit_scope())
|
||||
return (self.next_state as! EvaluatableParserState, program.exit_scope())
|
||||
}
|
||||
|
||||
public func done() -> Bool {
|
||||
@@ -77,11 +67,11 @@ extension ParserStateDirectTransition: EvaluatableParserState {
|
||||
}
|
||||
|
||||
public func state() -> P4Lang.ParserState {
|
||||
return self
|
||||
return self.state
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserStateNoTransition: EvaluatableParserState {
|
||||
extension ParserStateNoTransitionValue: EvaluatableParserState {
|
||||
public func execute(
|
||||
program: Common.ProgramExecution
|
||||
) -> (any EvaluatableParserState, Common.ProgramExecution) {
|
||||
@@ -93,18 +83,18 @@ extension ParserStateNoTransition: EvaluatableParserState {
|
||||
}
|
||||
|
||||
public func state() -> P4Lang.ParserState {
|
||||
return self
|
||||
return self.state
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserStateSelectTransition: EvaluatableParserState {
|
||||
extension ParserStateSelectTransitionValue: EvaluatableParserState {
|
||||
public func execute(
|
||||
program: Common.ProgramExecution
|
||||
) -> (any EvaluatableParserState, Common.ProgramExecution) {
|
||||
var program = program.enter_scope()
|
||||
|
||||
let (control_flow, next_execution) = program.evaluator.ExecuteStatements(
|
||||
statements, inExecution: program)
|
||||
self.state.statements, inExecution: program)
|
||||
switch control_flow {
|
||||
case .Next: program = next_execution
|
||||
case .Error: return (reject, next_execution.exit_scope())
|
||||
@@ -116,10 +106,9 @@ extension ParserStateSelectTransition: EvaluatableParserState {
|
||||
)
|
||||
}
|
||||
|
||||
//switch self.selectExpression.evaluate(execution: program) {
|
||||
switch program.evaluator.EvaluateExpression(self.selectExpression, inExecution: program) {
|
||||
switch program.evaluator.EvaluateExpression(self.te, inExecution: program) {
|
||||
case (.Ok(let value), let program):
|
||||
if value.type().baseType().eq(rhs: self) {
|
||||
if AnyParserState.eq(rhs: value.type().baseType()) {
|
||||
return (value.dataValue() as! EvaluatableParserState, program.exit_scope())
|
||||
} else {
|
||||
return (
|
||||
@@ -137,11 +126,11 @@ extension ParserStateSelectTransition: EvaluatableParserState {
|
||||
}
|
||||
|
||||
public func state() -> P4Lang.ParserState {
|
||||
return self
|
||||
return self.state
|
||||
}
|
||||
}
|
||||
|
||||
extension Parser: LibraryCallable {
|
||||
extension ParserValue: LibraryCallable {
|
||||
public typealias T = InstantiatedParserState
|
||||
public func call(
|
||||
execution: Common.ProgramExecution, arguments: ArgumentList
|
||||
@@ -149,10 +138,10 @@ extension Parser: LibraryCallable {
|
||||
var execution = execution.enter_scope()
|
||||
|
||||
execution = execution.declare(
|
||||
identifier: AsInstantiatedParserState(accept.state()).state,
|
||||
identifier: accept.state().getName(),
|
||||
withValue: P4Value(accept, P4QualifiedType.ReadOnly(accept.type())))
|
||||
execution = execution.declare(
|
||||
identifier: AsInstantiatedParserState(reject.state()).state,
|
||||
identifier: reject.state().getName(),
|
||||
withValue: P4Value(reject, P4QualifiedType.ReadOnly(reject.type())))
|
||||
|
||||
// Add initial values to the global scope
|
||||
@@ -161,13 +150,20 @@ extension Parser: LibraryCallable {
|
||||
}
|
||||
|
||||
// First, add every state to the scope!
|
||||
for state in self.states.states {
|
||||
for state in self.tipe.states.states {
|
||||
guard let instantiated_state = state.instantiate(state.getName()) else {
|
||||
return (
|
||||
reject,
|
||||
execution.setError(error: Error(withMessage: "Could not instantiate \(state.getName())"))
|
||||
)
|
||||
}
|
||||
execution = execution.declare(
|
||||
identifier: state.state, withValue: P4Value(state))
|
||||
identifier: state.getName(), withValue: P4Value(instantiated_state))
|
||||
}
|
||||
|
||||
guard let _current_state = self.findStartState(),
|
||||
var current_state = _current_state as? EvaluatableParserState
|
||||
guard let _current_state = self.tipe.findStartState(),
|
||||
var current_state = _current_state.instantiate(Identifier(name: "start"))
|
||||
as? EvaluatableParserState
|
||||
else {
|
||||
return (
|
||||
reject, execution.setError(error: Error(withMessage: "Could not find the start state"))
|
||||
@@ -181,12 +177,12 @@ extension Parser: LibraryCallable {
|
||||
while !current_state.done() && !current_execution.hasError() {
|
||||
(current_state, current_execution) = current_state.execute(program: current_execution)
|
||||
}
|
||||
return (.Ok(P4Value(AsInstantiatedParserState(current_state.state()))), current_execution)
|
||||
return (.Ok(P4Value((current_state))), current_execution)
|
||||
}
|
||||
|
||||
return
|
||||
switch Call(
|
||||
body: call_body, withArguments: arguments, withParameters: parameters,
|
||||
body: call_body, withArguments: arguments, withParameters: self.tipe.parameters,
|
||||
inExecution: execution)
|
||||
{
|
||||
case (.Ok(let value), let updated_execution):
|
||||
|
||||
Reference in New Issue
Block a user