@@ -53,17 +53,28 @@ public func Call<T>(
|
|||||||
|
|
||||||
for (parameter, argument) in zip(params.parameters, args.arguments) {
|
for (parameter, argument) in zip(params.parameters, args.arguments) {
|
||||||
if let param_direction = parameter.type.direction(),
|
if let param_direction = parameter.type.direction(),
|
||||||
param_direction == Direction.InOut || param_direction == Direction.Out {
|
param_direction == Direction.InOut || param_direction == Direction.Out
|
||||||
|
{
|
||||||
// Let's make sure that it is an evaluatable l value!
|
// Let's make sure that it is an evaluatable l value!
|
||||||
guard let arg_lvalue = argument.argument as? EvaluatableLValueExpression else {
|
guard let arg_lvalue = argument.argument as? EvaluatableLValueExpression else {
|
||||||
return (.Error(Error(withMessage: "(in)out parameter argument is not lvalue")), updated_execution.exit_scope())
|
return (
|
||||||
|
.Error(Error(withMessage: "(in)out parameter argument is not lvalue")),
|
||||||
|
updated_execution.exit_scope()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard case .Ok(let arg_new_value) = updated_execution.scopes.lookup(identifier: parameter.name) else {
|
guard
|
||||||
return (.Error(Error(withMessage: "Could not get (in)out parameter value from scope")), updated_execution.exit_scope())
|
case .Ok(let arg_new_value) = updated_execution.scopes.lookup(identifier: parameter.name)
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
.Error(Error(withMessage: "Could not get (in)out parameter value from scope")),
|
||||||
|
updated_execution.exit_scope()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch arg_lvalue.set(to: arg_new_value, inScopes: inout_scopes, duringExecution: updated_execution) {
|
switch arg_lvalue.set(
|
||||||
|
to: arg_new_value, inScopes: inout_scopes, duringExecution: updated_execution)
|
||||||
|
{
|
||||||
case .Ok((let updated_scopes, _)): inout_scopes = updated_scopes
|
case .Ok((let updated_scopes, _)): inout_scopes = updated_scopes
|
||||||
case .Error(let e): return (.Error(e), updated_execution.exit_scope())
|
case .Error(let e): return (.Error(e), updated_execution.exit_scope())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ extension SelectExpression: EvaluatableExpression {
|
|||||||
switch self.selector.evaluate(execution: execution) {
|
switch self.selector.evaluate(execution: execution) {
|
||||||
case (.Ok(let selector_value), let updated_execution):
|
case (.Ok(let selector_value), let updated_execution):
|
||||||
for sce in self.case_expressions {
|
for sce in self.case_expressions {
|
||||||
if case (.Ok(let kse), let updated_execution) = sce.key.evaluate(execution: updated_execution),
|
if case (.Ok(let kse), let updated_execution) = sce.key.evaluate(
|
||||||
|
execution: updated_execution),
|
||||||
kse.eq(selector_value)
|
kse.eq(selector_value)
|
||||||
{
|
{
|
||||||
let result = sce.evaluate(execution: updated_execution)
|
let result = sce.evaluate(execution: updated_execution)
|
||||||
@@ -82,9 +83,22 @@ extension TypedIdentifier: EvaluatableLValueExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return switch type.assignableFromType(to.type()) {
|
return switch type.assignableFromType(to.type()) {
|
||||||
case TypeCheckResults.IncompatibleTypes: .Error( Error( withMessage: "Cannot assign value with type \(to.type()) to identifier \(self) with type \(type)"))
|
case TypeCheckResults.IncompatibleTypes:
|
||||||
case TypeCheckResults.ReadOnly: .Error( Error( withMessage: "Cannot assign value with type \(to.type()) to identifier \(self) that is read only"))
|
.Error(
|
||||||
case TypeCheckResults.WrongDirection: .Error( Error( withMessage: "Cannot assign value with type \(to.type()) to identifier \(self) that is in parameter"))
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to identifier \(self) with type \(type)"))
|
||||||
|
case TypeCheckResults.ReadOnly:
|
||||||
|
.Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to identifier \(self) that is read only"))
|
||||||
|
case TypeCheckResults.WrongDirection:
|
||||||
|
.Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to identifier \(self) that is in parameter")
|
||||||
|
)
|
||||||
case TypeCheckResults.Ok: .Ok(())
|
case TypeCheckResults.Ok: .Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,7 +267,8 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|||||||
let updated_execution = execution
|
let updated_execution = execution
|
||||||
let maybe_value = self.name.evaluate(execution: updated_execution)
|
let maybe_value = self.name.evaluate(execution: updated_execution)
|
||||||
guard case (.Ok(let value), let updated_execution) = maybe_value else {
|
guard case (.Ok(let value), let updated_execution) = maybe_value else {
|
||||||
return .Error(Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.0.error()!)"))
|
return .Error(
|
||||||
|
Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.0.error()!)"))
|
||||||
}
|
}
|
||||||
guard let array_value = value.dataValue() as? P4ArrayValue else {
|
guard let array_value = value.dataValue() as? P4ArrayValue else {
|
||||||
return Result.Error(Error(withMessage: "\(self.name) does not identify an array"))
|
return Result.Error(Error(withMessage: "\(self.name) does not identify an array"))
|
||||||
@@ -263,7 +278,8 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|||||||
let maybe_indexor_value = self.indexor.evaluate(execution: updated_execution)
|
let maybe_indexor_value = self.indexor.evaluate(execution: updated_execution)
|
||||||
guard case (.Ok(let indexor_value), let updated_execution) = maybe_indexor_value else {
|
guard case (.Ok(let indexor_value), let updated_execution) = maybe_indexor_value else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "\(self.indexor) cannot be evaluated: \(maybe_indexor_value.0.error()!)"))
|
Error(withMessage: "\(self.indexor) cannot be evaluated: \(maybe_indexor_value.0.error()!)")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
guard let indexor_int = indexor_value.dataValue() as? P4IntValue else {
|
guard let indexor_int = indexor_value.dataValue() as? P4IntValue else {
|
||||||
return Result.Error(Error(withMessage: "\(self.indexor) cannot be used to index an array"))
|
return Result.Error(Error(withMessage: "\(self.indexor) cannot be used to index an array"))
|
||||||
@@ -282,7 +298,8 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let array_lvalue = self.name as! EvaluatableLValueExpression
|
let array_lvalue = self.name as! EvaluatableLValueExpression
|
||||||
return array_lvalue.set(to: updated_array_value, inScopes: scopes, duringExecution: updated_execution)
|
return array_lvalue.set(
|
||||||
|
to: updated_array_value, inScopes: scopes, duringExecution: updated_execution)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func check(
|
public func check(
|
||||||
@@ -385,7 +402,8 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
|
|||||||
// We use recursion here -- ultimately finding our way to a TypedIdentifier that
|
// We use recursion here -- ultimately finding our way to a TypedIdentifier that
|
||||||
// will update the scope. Pretty cool!
|
// will update the scope. Pretty cool!
|
||||||
let struct_lvalue = self.strct as! EvaluatableLValueExpression
|
let struct_lvalue = self.strct as! EvaluatableLValueExpression
|
||||||
return struct_lvalue.set(to: new_struct_value, inScopes: scopes, duringExecution: updated_execution)
|
return struct_lvalue.set(
|
||||||
|
to: new_struct_value, inScopes: scopes, duringExecution: updated_execution)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func check(
|
public func check(
|
||||||
@@ -435,18 +453,27 @@ extension KeysetExpression: EvaluatableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension FunctionCall: EvaluatableExpression {
|
extension FunctionCall: EvaluatableExpression {
|
||||||
public func evaluate(execution: Common.ProgramExecution) -> (Common.Result<P4Value>, ProgramExecution) {
|
public func evaluate(
|
||||||
|
execution: Common.ProgramExecution
|
||||||
|
) -> (Common.Result<P4Value>, ProgramExecution) {
|
||||||
|
|
||||||
guard let body = self.callee.body else {
|
guard let body = self.callee.body else {
|
||||||
return (.Error(Error(withMessage: "No body for called function (\(self.callee.name))")), execution)
|
return (
|
||||||
|
.Error(Error(withMessage: "No body for called function (\(self.callee.name))")), execution
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_body: (ProgramExecution) -> (Result<P4Value>, ProgramExecution) = { (execution: ProgramExecution) in
|
let call_body: (ProgramExecution) -> (Result<P4Value>, ProgramExecution) = {
|
||||||
|
(execution: ProgramExecution) in
|
||||||
let (control_flow, updated_execution) = body.evaluate(execution: execution)
|
let (control_flow, updated_execution) = body.evaluate(execution: execution)
|
||||||
return switch control_flow {
|
return switch control_flow {
|
||||||
case ControlFlow.Return(.some(let value)): (.Ok(value), updated_execution)
|
case ControlFlow.Return(.some(let value)): (.Ok(value), updated_execution)
|
||||||
default:
|
default:
|
||||||
(.Error(Error(withMessage: "No value returned from called function (\(self.callee.name))")), execution)
|
(
|
||||||
|
.Error(
|
||||||
|
Error(withMessage: "No value returned from called function (\(self.callee.name))")),
|
||||||
|
execution
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,8 @@ extension Parser: LibraryCallable {
|
|||||||
|
|
||||||
return
|
return
|
||||||
switch Call(
|
switch Call(
|
||||||
body: call_body, withArguments: arguments, withParameters: parameters, inExecution: execution)
|
body: call_body, withArguments: arguments, withParameters: parameters,
|
||||||
|
inExecution: execution)
|
||||||
{
|
{
|
||||||
case (.Ok(let value), let updated_execution):
|
case (.Ok(let value), let updated_execution):
|
||||||
(value.dataValue() as! InstantiatedParserState, updated_execution)
|
(value.dataValue() as! InstantiatedParserState, updated_execution)
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ extension BlockStatement: EvaluatableStatement {
|
|||||||
|
|
||||||
extension VariableDeclarationStatement: EvaluatableStatement {
|
extension VariableDeclarationStatement: EvaluatableStatement {
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
guard case (.Ok(let initial_value), let execution) = self.initializer.evaluate(execution: execution) else {
|
guard
|
||||||
|
case (.Ok(let initial_value), let execution) = self.initializer.evaluate(execution: execution)
|
||||||
|
else {
|
||||||
return (
|
return (
|
||||||
ControlFlow.Error,
|
ControlFlow.Error,
|
||||||
execution.setError(error: Error(withMessage: "Could not evaluate \(self.initializer)"))
|
execution.setError(error: Error(withMessage: "Could not evaluate \(self.initializer)"))
|
||||||
@@ -55,7 +57,10 @@ extension VariableDeclarationStatement: EvaluatableStatement {
|
|||||||
|
|
||||||
extension ConditionalStatement: EvaluatableStatement {
|
extension ConditionalStatement: EvaluatableStatement {
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
guard case (.Ok(let evaluated_condition), let execution) = self.condition.evaluate(execution: execution) else {
|
guard
|
||||||
|
case (.Ok(let evaluated_condition), let execution) = self.condition.evaluate(
|
||||||
|
execution: execution)
|
||||||
|
else {
|
||||||
return (
|
return (
|
||||||
ControlFlow.Error,
|
ControlFlow.Error,
|
||||||
execution.setError(error: Error(withMessage: "Could not evaluate \(self.condition)"))
|
execution.setError(error: Error(withMessage: "Could not evaluate \(self.condition)"))
|
||||||
|
|||||||
Reference in New Issue
Block a user