Files
gp4/Sources/P4Lang/Expressions.swift
T
Will Hawkins b687454389 Refactor Expected Types During Compilation
By adding an expected type to the compilation context, it is
now possible for type checking to occur on keyset expressions
and return statements at the moment that they are being compiled.

Previously, it was necessary to tentatively compile them and then
typecheck afterward.

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
2026-04-10 00:59:11 -04:00

138 lines
4.0 KiB
Swift

// 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 <https://www.gnu.org/licenses/>.
import Common
public struct KeysetExpression {
public let key: EvaluatableExpression
public init(_ key: EvaluatableExpression) {
self.key = key
}
public func compatible(type: P4Type) -> Result<()> {
if let key_type = self.key.type() as? P4Set {
if !key_type.set_type().eq(rhs: type) {
return .Error(
Error(
withMessage:
"Key expression of type set of type \(key_type.set_type()) is not compatible with selector type \(type)"
))
}
} else if !self.key.type().eq(rhs: type) {
return .Error(
Error(
withMessage:
"Key expression of type \(self.key.type()) is not compatible with selector type \(type)"
))
}
return .Ok(())
}
}
public struct SelectCaseExpression {
public let key: KeysetExpression
public let next_state_identifier: Identifier
public let next_state: ParserState?
public init(withKey key: KeysetExpression, withNextState next_state_id: Identifier) {
self.key = key
self.next_state_identifier = next_state_id
self.next_state = .none
}
public init(
withKey key: KeysetExpression, withNextState next_state_id: Identifier,
withNextState next_state: ParserState?
) {
self.key = key
self.next_state_identifier = next_state_id
self.next_state = next_state
}
}
public struct SelectExpression {
public let selector: EvaluatableExpression
public let select_expressions: [SelectCaseExpression]
public init(
withSelector selector: EvaluatableExpression,
withSelectCaseExpressions sces: [SelectCaseExpression]
) {
self.selector = selector
self.select_expressions = sces
}
public func append_checked_sce(sce: SelectCaseExpression) -> SelectExpression {
var new_cses = self.select_expressions
new_cses.append(sce)
return SelectExpression(
withSelector: self.selector, withSelectCaseExpressions: new_cses)
}
}
public typealias NamedBinaryOperatorEvaluator = (String, P4Type, (P4Value, P4Value) -> P4Value)
public typealias BinaryOperatorEvaluator = (P4Value, P4Value) -> P4Value
public struct BinaryOperatorExpression {
public let evaluator: NamedBinaryOperatorEvaluator
public let left: EvaluatableExpression
public let right: EvaluatableExpression
public init(
withEvaluator evaluator: NamedBinaryOperatorEvaluator, withLhs lhs: EvaluatableExpression,
withRhs rhs: EvaluatableExpression
) {
self.evaluator = evaluator
self.left = lhs
self.right = rhs
}
}
public struct ArrayAccessExpression {
public let indexor: EvaluatableExpression
public let name: EvaluatableExpression
public let type: P4Array
public init(
withName name: EvaluatableExpression, withType type: P4Array,
withIndexor indexor: EvaluatableExpression
) {
self.name = name
self.type = type
self.indexor = indexor
}
}
public struct FieldAccessExpression {
public let field: P4StructFieldIdentifier
public let strct: EvaluatableExpression
public init(withStruct strct: EvaluatableExpression, withField field: P4StructFieldIdentifier) {
self.strct = strct
self.field = field
}
}
public struct FunctionCall {
public let callee: FunctionDeclaration
public let arguments: ArgumentList
public init(_ callee: FunctionDeclaration, withArguments arguments: ArgumentList) {
self.callee = callee
self.arguments = arguments
}
}