conlang: Introduce as casting

Arbitrary primitive type conversion

Currently implemented as jankily as possible in the interpreter, but it works alright™️
This commit is contained in:
2024-07-26 05:26:08 -05:00
parent a8b8a91c79
commit e43847bbd4
10 changed files with 100 additions and 5 deletions

View File

@@ -365,6 +365,8 @@ pub enum ExprKind {
Binary(Binary),
/// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
Unary(Unary),
/// A [Cast] expression: [`Expr`] `as` [`Ty`]
Cast(Cast),
/// A [Member] access expression: [`Expr`] [`MemberKind`]\*
Member(Member),
/// An Array [Index] expression: a[10, 20, 30]
@@ -484,6 +486,12 @@ pub enum UnaryKind {
Tilde,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Cast {
pub head: Box<ExprKind>,
pub ty: Ty,
}
/// A [Member] access expression: [`Expr`] [`MemberKind`]\*
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Member {

View File

@@ -433,6 +433,7 @@ mod display {
ExprKind::Modify(v) => v.fmt(f),
ExprKind::Binary(v) => v.fmt(f),
ExprKind::Unary(v) => v.fmt(f),
ExprKind::Cast(v) => v.fmt(f),
ExprKind::Member(v) => v.fmt(f),
ExprKind::Index(v) => v.fmt(f),
ExprKind::Structor(v) => v.fmt(f),
@@ -548,6 +549,13 @@ mod display {
}
}
impl Display for Cast {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { head, ty } = self;
write!(f, "{head} as {ty}")
}
}
impl Display for Member {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { head, kind } = self;
@@ -764,6 +772,7 @@ mod convert {
Modify => ExprKind::Modify,
Binary => ExprKind::Binary,
Unary => ExprKind::Unary,
Cast => ExprKind::Cast,
Member => ExprKind::Member,
Index => ExprKind::Index,
Path => ExprKind::Path,

View File

@@ -276,6 +276,10 @@ pub trait Fold {
fn fold_unary_kind(&mut self, kind: UnaryKind) -> UnaryKind {
kind
}
fn fold_cast(&mut self, cast: Cast) -> Cast {
let Cast { head, ty } = cast;
Cast { head: Box::new(self.fold_expr_kind(*head)), ty: self.fold_ty(ty) }
}
fn fold_member(&mut self, m: Member) -> Member {
let Member { head, kind } = m;
Member { head: Box::new(self.fold_expr_kind(*head)), kind: self.fold_member_kind(kind) }
@@ -535,6 +539,7 @@ pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> Ex
ExprKind::Modify(m) => ExprKind::Modify(folder.fold_modify(m)),
ExprKind::Binary(b) => ExprKind::Binary(folder.fold_binary(b)),
ExprKind::Unary(u) => ExprKind::Unary(folder.fold_unary(u)),
ExprKind::Cast(c) => ExprKind::Cast(folder.fold_cast(c)),
ExprKind::Member(m) => ExprKind::Member(folder.fold_member(m)),
ExprKind::Index(i) => ExprKind::Index(folder.fold_index(i)),
ExprKind::Structor(s) => ExprKind::Structor(folder.fold_structor(s)),

View File

@@ -238,6 +238,11 @@ pub trait Visit<'a>: Sized {
self.visit_expr_kind(tail);
}
fn visit_unary_kind(&mut self, _kind: &'a UnaryKind) {}
fn visit_cast(&mut self, cast: &'a Cast) {
let Cast { head, ty } = cast;
self.visit_expr_kind(head);
self.visit_ty(ty);
}
fn visit_member(&mut self, m: &'a Member) {
let Member { head, kind } = m;
self.visit_expr_kind(head);
@@ -456,6 +461,7 @@ pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
ExprKind::Modify(m) => visitor.visit_modify(m),
ExprKind::Binary(b) => visitor.visit_binary(b),
ExprKind::Unary(u) => visitor.visit_unary(u),
ExprKind::Cast(c) => visitor.visit_cast(c),
ExprKind::Member(m) => visitor.visit_member(m),
ExprKind::Index(i) => visitor.visit_index(i),
ExprKind::Structor(s) => visitor.visit_structor(s),