pub mod diagnostics;
pub mod fragment;
pub mod identifiers;
pub mod literals;
pub mod resugared;
pub mod span;
pub mod utils;
pub mod visitors;
use crate::{ast::diagnostics::Context, symbol::Symbol};
use diagnostics::Diagnostic;
use fragment::Fragment;
use hax_rust_engine_macros::*;
pub use identifiers::*;
use literals::*;
use resugared::*;
use span::Span;
#[derive_group_for_ast]
pub enum GenericValue {
Ty(Ty),
Expr(Expr),
Lifetime,
}
#[derive_group_for_ast]
pub enum PrimitiveTy {
Bool,
Int(IntKind),
Float(FloatKind),
Char,
Str,
}
#[derive_group_for_ast]
pub struct Region;
#[derive_group_for_ast]
pub struct Ty(pub(crate) Box<TyKind>);
impl Ty {
pub fn bool() -> Self {
Self(Box::new(TyKind::Primitive(PrimitiveTy::Bool)))
}
pub fn int(size: IntSize, signedness: Signedness) -> Self {
Self(Box::new(TyKind::Primitive(PrimitiveTy::Int(IntKind {
size,
signedness,
}))))
}
pub fn is_int(&self) -> bool {
let Self(b) = self;
matches!(
&**b,
TyKind::Primitive(PrimitiveTy::Int(IntKind {
size: _,
signedness: _,
}))
)
}
pub fn prop() -> Self {
Self(Box::new(TyKind::App {
head: crate::names::hax_lib::prop::Prop,
args: vec![],
}))
}
}
#[derive_group_for_ast]
pub enum TyKind {
Primitive(PrimitiveTy),
App {
head: GlobalId,
args: Vec<GenericValue>,
},
Arrow {
inputs: Vec<Ty>,
output: Ty,
},
Ref {
inner: Ty,
mutable: bool,
region: Region,
},
Param(LocalId),
Slice(Ty),
Array {
ty: Ty,
length: Box<Expr>,
},
RawPointer,
AssociatedType {
impl_: ImplExpr,
item: GlobalId,
},
Opaque(GlobalId),
Dyn(Vec<DynTraitGoal>),
Resugared(ResugaredTyKind),
Error(ErrorNode),
}
#[derive_group_for_ast]
pub struct ErrorNode {
pub fragment: Box<Fragment>,
pub diagnostics: Vec<Diagnostic>,
}
impl ErrorNode {
pub fn assertion_failure(
fragment: impl Into<Fragment> + HasMetadata,
context: Context,
message: impl Into<String>,
) -> Self {
let span = fragment.span();
let fragment = fragment.into();
ErrorNode {
diagnostics: vec![Diagnostic::new(
fragment.clone(),
diagnostics::DiagnosticInfo {
context,
span,
kind: hax_types::diagnostics::Kind::AssertionFailure {
details: message.into(),
},
},
)],
fragment: Box::new(fragment),
}
}
}
#[derive_group_for_ast]
pub struct DynTraitGoal {
pub trait_: GlobalId,
pub non_self_args: Vec<GenericValue>,
}
#[derive_group_for_ast]
pub struct Metadata {
pub span: Span,
pub attributes: Attributes,
}
#[derive_group_for_ast]
pub struct Expr {
pub kind: Box<ExprKind>,
pub ty: Ty,
pub meta: Metadata,
}
#[derive_group_for_ast]
pub struct Pat {
pub kind: Box<PatKind>,
pub ty: Ty,
pub meta: Metadata,
}
#[derive_group_for_ast]
pub struct Arm {
pub pat: Pat,
pub body: Expr,
pub guard: Option<Guard>,
pub meta: Metadata,
}
#[derive_group_for_ast]
pub struct Guard {
pub kind: GuardKind,
pub meta: Metadata,
}
#[derive_group_for_ast]
pub enum BorrowKind {
Shared,
Unique,
Mut,
}
#[derive_group_for_ast]
pub enum BindingMode {
ByValue,
ByRef(BorrowKind),
}
#[derive_group_for_ast]
pub enum PatKind {
Wild,
Ascription {
pat: Pat,
ty: SpannedTy,
},
Or {
sub_pats: Vec<Pat>,
},
Array {
args: Vec<Pat>,
},
Deref {
sub_pat: Pat,
},
Constant {
lit: Literal,
},
Binding {
mutable: bool,
var: LocalId,
mode: BindingMode,
sub_pat: Option<Pat>,
},
Construct {
constructor: GlobalId,
is_record: bool,
is_struct: bool,
fields: Vec<(GlobalId, Pat)>,
},
Resugared(ResugaredPatKind),
Error(ErrorNode),
}
#[derive_group_for_ast]
pub enum GuardKind {
IfLet {
lhs: Pat,
rhs: Expr,
},
}
#[derive_group_for_ast]
#[allow(missing_docs)]
pub enum Lhs {
LocalVar {
var: LocalId,
ty: Ty,
},
VecRef {
e: Box<Lhs>,
ty: Ty,
},
ArbitraryExpr(Box<Expr>),
FieldAccessor {
e: Box<Lhs>,
ty: Ty,
field: GlobalId,
},
ArrayAccessor {
e: Box<Lhs>,
ty: Ty,
index: Expr,
},
}
#[derive_group_for_ast]
pub struct ImplExpr {
pub kind: Box<ImplExprKind>,
pub goal: TraitGoal,
}
#[derive_group_for_ast]
pub enum ImplExprKind {
Self_,
Concrete(TraitGoal),
LocalBound {
id: Symbol,
},
Parent {
impl_: ImplExpr,
ident: ImplIdent,
},
Projection {
impl_: ImplExpr,
item: GlobalId,
ident: ImplIdent,
},
ImplApp {
impl_: ImplExpr,
args: Vec<ImplExpr>,
},
Dyn,
Builtin(TraitGoal),
Error(ErrorNode),
}
#[derive_group_for_ast]
pub struct ImplItem {
pub meta: Metadata,
pub generics: Generics,
pub kind: ImplItemKind,
pub ident: GlobalId,
}
#[derive_group_for_ast]
pub enum ImplItemKind {
Type {
ty: Ty,
parent_bounds: Vec<(ImplExpr, ImplIdent)>,
},
Fn {
body: Expr,
params: Vec<Param>,
},
Resugared(ResugaredImplItemKind),
Error(ErrorNode),
}
#[derive_group_for_ast]
pub struct TraitItem {
pub meta: Metadata,
pub kind: TraitItemKind,
pub generics: Generics,
pub ident: GlobalId,
}
#[derive_group_for_ast]
pub enum TraitItemKind {
Type(Vec<ImplIdent>),
Fn(Ty),
Default {
params: Vec<Param>,
body: Expr,
},
Resugared(ResugaredTraitItemKind),
Error(ErrorNode),
}
#[derive_group_for_ast]
pub enum QuoteContent {
Verbatim(String),
Expr(Expr),
Pattern(Pat),
Ty(Ty),
}
#[derive_group_for_ast]
pub struct Quote(pub Vec<QuoteContent>);
#[derive_group_for_ast]
pub struct ItemQuoteOrigin {
pub item_kind: ItemQuoteOriginKind,
pub item_ident: GlobalId,
pub position: ItemQuoteOriginPosition,
}
#[derive_group_for_ast]
pub enum ItemQuoteOriginKind {
Fn,
TyAlias,
Type,
MacroInvocation,
Trait,
Impl,
Alias,
Use,
Quote,
HaxError,
NotImplementedYet,
}
#[derive_group_for_ast]
pub enum ItemQuoteOriginPosition {
Before,
After,
Replace,
}
#[derive_group_for_ast]
pub enum LoopKind {
UnconditionalLoop,
WhileLoop {
condition: Expr,
},
ForLoop {
pat: Pat,
iterator: Expr,
},
ForIndexLoop {
start: Expr,
end: Expr,
var: LocalId,
var_ty: Ty,
},
}
#[derive_group_for_ast]
pub enum ControlFlowKind {
BreakOnly,
BreakOrReturn,
}
#[derive_group_for_ast]
pub struct LoopState {
pub init: Expr,
pub body_pat: Pat,
}
#[derive_group_for_ast]
pub enum ExprKind {
If {
condition: Expr,
then: Expr,
else_: Option<Expr>,
},
App {
head: Expr,
args: Vec<Expr>,
generic_args: Vec<GenericValue>,
bounds_impls: Vec<ImplExpr>,
trait_: Option<(ImplExpr, Vec<GenericValue>)>,
},
Literal(Literal),
Array(Vec<Expr>),
Construct {
constructor: GlobalId,
is_record: bool,
is_struct: bool,
fields: Vec<(GlobalId, Expr)>,
base: Option<Expr>,
},
Match {
scrutinee: Expr,
arms: Vec<Arm>,
},
Borrow {
mutable: bool,
inner: Expr,
},
AddressOf {
mutable: bool,
inner: Expr,
},
Let {
lhs: Pat,
rhs: Expr,
body: Expr,
},
GlobalId(GlobalId),
LocalId(LocalId),
Ascription {
e: Expr,
ty: Ty,
},
Assign {
lhs: Lhs,
value: Expr,
},
Loop {
body: Expr,
kind: Box<LoopKind>,
state: Option<LoopState>,
control_flow: Option<ControlFlowKind>,
label: Option<Symbol>,
},
Break {
value: Expr,
label: Option<Symbol>,
state: Option<Expr>,
},
Return {
value: Expr,
},
Continue {
label: Option<Symbol>,
state: Option<Expr>,
},
Closure {
params: Vec<Pat>,
body: Expr,
captures: Vec<Expr>,
},
Block {
body: Expr,
safety_mode: SafetyKind,
},
Quote {
contents: Quote,
},
Resugared(ResugaredExprKind),
Error(ErrorNode),
}
#[derive_group_for_ast]
pub enum GenericParamKind {
Lifetime,
Type,
Const {
ty: Ty,
},
}
#[derive_group_for_ast]
pub struct TraitGoal {
pub trait_: GlobalId,
pub args: Vec<GenericValue>,
}
#[derive_group_for_ast]
pub struct ImplIdent {
pub goal: TraitGoal,
pub name: Symbol,
}
#[derive_group_for_ast]
pub struct ProjectionPredicate {
pub impl_: ImplExpr,
pub assoc_item: GlobalId,
pub ty: Ty,
}
#[derive_group_for_ast]
pub enum GenericConstraint {
Lifetime(String), TypeClass(ImplIdent),
Equality(ProjectionPredicate),
}
#[derive_group_for_ast]
pub struct GenericParam {
pub ident: LocalId,
pub meta: Metadata,
pub kind: GenericParamKind,
}
#[derive_group_for_ast]
pub struct Generics {
pub params: Vec<GenericParam>,
pub constraints: Vec<GenericConstraint>,
}
#[derive_group_for_ast]
pub enum SafetyKind {
Safe,
Unsafe,
}
#[derive_group_for_ast]
pub struct Attribute {
pub kind: AttributeKind,
pub span: Span,
}
#[derive_group_for_ast]
pub enum AttributeKind {
Tool {
path: String,
tokens: String,
},
DocComment {
kind: DocCommentKind,
body: String,
},
Hax(hax_lib_macros_types::AttrPayload),
}
#[derive_group_for_ast]
pub enum DocCommentKind {
Line,
Block,
}
pub type Attributes = Vec<Attribute>;
#[derive_group_for_ast]
pub struct SpannedTy {
pub span: Span,
pub ty: Ty,
}
#[derive_group_for_ast]
pub struct Param {
pub pat: Pat,
pub ty: Ty,
pub ty_span: Option<Span>,
pub attributes: Attributes,
}
#[derive_group_for_ast]
pub struct Variant {
pub name: GlobalId,
pub arguments: Vec<(GlobalId, Ty, Attributes)>,
pub is_record: bool,
pub attributes: Attributes,
}
#[derive_group_for_ast]
pub enum ItemKind {
Fn {
name: GlobalId,
generics: Generics,
body: Expr,
params: Vec<Param>,
safety: SafetyKind,
},
TyAlias {
name: GlobalId,
generics: Generics,
ty: Ty,
},
Type {
name: GlobalId,
generics: Generics,
variants: Vec<Variant>,
is_struct: bool,
},
Trait {
name: GlobalId,
generics: Generics,
items: Vec<TraitItem>,
safety: SafetyKind,
},
Impl {
generics: Generics,
self_ty: Ty,
of_trait: (GlobalId, Vec<GenericValue>),
items: Vec<ImplItem>,
parent_bounds: Vec<(ImplExpr, ImplIdent)>,
},
Alias {
name: GlobalId,
item: GlobalId,
},
Use {
path: Vec<String>,
is_external: bool,
rename: Option<String>,
},
Quote {
quote: Quote,
origin: ItemQuoteOrigin,
},
RustModule,
Error(ErrorNode),
Resugared(ResugaredItemKind),
NotImplementedYet,
}
#[derive_group_for_ast]
pub struct Item {
pub ident: GlobalId,
pub kind: ItemKind,
pub meta: Metadata,
}
impl Item {
pub fn is_opaque(&self) -> bool {
self.meta.attributes.iter().any(|a| {
matches!(
a.kind,
AttributeKind::Hax(hax_lib_macros_types::AttrPayload::Erased)
)
})
}
}
#[derive_group_for_ast]
pub struct Module {
pub ident: GlobalId,
pub items: Vec<Item>,
pub meta: Metadata,
}
impl Generics {
pub fn type_class_constraints(&self) -> impl Iterator<Item = &ImplIdent> {
self.constraints.iter().filter_map(|c| match c {
GenericConstraint::TypeClass(impl_id) => Some(impl_id),
_ => None,
})
}
pub fn equality_constraints(&self) -> impl Iterator<Item = &ProjectionPredicate> {
self.constraints.iter().filter_map(|c| match c {
GenericConstraint::Equality(pp) => Some(pp),
_ => None,
})
}
}
pub mod traits {
use super::*;
pub trait HasMetadata {
fn metadata(&self) -> &Metadata;
fn metadata_mut(&mut self) -> &mut Metadata;
}
pub trait HasSpan {
fn span(&self) -> Span;
fn span_mut(&mut self) -> &mut Span;
}
pub trait Typed {
fn ty(&self) -> &Ty;
}
impl<T: HasMetadata> HasSpan for T {
fn span(&self) -> Span {
self.metadata().span
}
fn span_mut(&mut self) -> &mut Span {
&mut self.metadata_mut().span
}
}
pub trait HasKind {
type Kind;
fn kind(&self) -> &Self::Kind;
fn kind_mut(&mut self) -> &mut Self::Kind;
}
macro_rules! derive_has_metadata {
($($ty:ty),*) => {
$(impl HasMetadata for $ty {
fn metadata(&self) -> &Metadata {
&self.meta
}
fn metadata_mut(&mut self) -> &mut Metadata {
&mut self.meta
}
})*
};
}
macro_rules! derive_has_kind {
($($ty:ty => $kind:ty),*) => {
$(impl HasKind for $ty {
type Kind = $kind;
fn kind(&self) -> &Self::Kind {
&self.kind
}
fn kind_mut(&mut self) -> &mut Self::Kind {
&mut self.kind
}
})*
};
}
derive_has_metadata!(
Item,
Expr,
Pat,
Guard,
Arm,
ImplItem,
TraitItem,
GenericParam
);
derive_has_kind!(
Item => ItemKind, Expr => ExprKind, Pat => PatKind, Guard => GuardKind,
GenericParam => GenericParamKind, ImplItem => ImplItemKind, TraitItem => TraitItemKind, ImplExpr => ImplExprKind
);
impl HasSpan for Attribute {
fn span(&self) -> Span {
self.span
}
fn span_mut(&mut self) -> &mut Span {
&mut self.span
}
}
impl Typed for Expr {
fn ty(&self) -> &Ty {
&self.ty
}
}
impl Typed for Pat {
fn ty(&self) -> &Ty {
&self.ty
}
}
impl Typed for SpannedTy {
fn ty(&self) -> &Ty {
&self.ty
}
}
impl HasSpan for SpannedTy {
fn span(&self) -> Span {
self.span
}
fn span_mut(&mut self) -> &mut Span {
&mut self.span
}
}
impl ExprKind {
pub fn into_expr(self, span: Span, ty: Ty, attributes: Vec<Attribute>) -> Expr {
Expr {
kind: Box::new(self),
ty,
meta: Metadata { span, attributes },
}
}
}
impl HasKind for Ty {
type Kind = TyKind;
fn kind(&self) -> &Self::Kind {
&self.0
}
fn kind_mut(&mut self) -> &mut Self::Kind {
&mut self.0
}
}
pub trait FallibleAstNode {
fn set_error(&mut self, error_node: ErrorNode);
fn get_error(&self) -> Option<&ErrorNode>;
}
macro_rules! derive_error_node {
($($ty:ident => $kind:ident),*) => {$(
impl FallibleAstNode for $ty {
fn set_error(&mut self, mut error_node: ErrorNode) {
if let Some(base) = self.get_error().cloned() {
error_node.diagnostics.extend_from_slice(&base.diagnostics);
}
*self.kind_mut() = $kind::Error(error_node)
}
fn get_error(&self) -> Option<&ErrorNode> {
match &self.kind() {
$kind::Error(error_node) => Some(error_node),
_ => None,
}
}
}
)*};
}
derive_error_node!(Item => ItemKind, Pat => PatKind, Expr => ExprKind, Ty => TyKind);
}
pub use traits::*;