mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-09 09:38:24 +00:00
feat: add casts
This commit is contained in:
parent
f25bd5729f
commit
e7037cfd33
|
@ -176,6 +176,7 @@ pub enum Expression {
|
||||||
Binary(Box<Self>, BinaryOp, Box<Self>),
|
Binary(Box<Self>, BinaryOp, Box<Self>),
|
||||||
Deref(Box<Self>, Span),
|
Deref(Box<Self>, Span),
|
||||||
AsRef(Box<Self>, bool, Span),
|
AsRef(Box<Self>, bool, Span),
|
||||||
|
Cast(PathExpr, Type, Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
|
@ -1020,6 +1020,103 @@ fn compile_rvalue<'ctx>(
|
||||||
);
|
);
|
||||||
compile_unary_op(ctx, fn_id, locals, *op, value)?
|
compile_unary_op(ctx, fn_id, locals, *op, value)?
|
||||||
}
|
}
|
||||||
|
ir::RValue::Cast(place, target_ty, span) => {
|
||||||
|
ctx.set_debug_loc(
|
||||||
|
ctx.builder
|
||||||
|
.get_current_debug_location()
|
||||||
|
.unwrap()
|
||||||
|
.get_scope(),
|
||||||
|
*span,
|
||||||
|
);
|
||||||
|
|
||||||
|
let target_ty = target_ty.clone();
|
||||||
|
let target_llvm_ty = compile_basic_type(ctx, &target_ty);
|
||||||
|
let (value, ty) = compile_load_place(ctx, fn_id, locals, place, false)?;
|
||||||
|
let current_ty = compile_basic_type(ctx, &ty);
|
||||||
|
|
||||||
|
if target_llvm_ty.is_pointer_type() {
|
||||||
|
// int to ptr
|
||||||
|
let target_llvm_ty = target_llvm_ty.into_pointer_type();
|
||||||
|
if current_ty.is_int_type() {
|
||||||
|
let value =
|
||||||
|
ctx.builder
|
||||||
|
.build_int_to_ptr(value.into_int_value(), target_llvm_ty, "")?;
|
||||||
|
(value.as_basic_value_enum(), target_ty)
|
||||||
|
} else if current_ty.is_pointer_type() {
|
||||||
|
(value, target_ty.clone())
|
||||||
|
} else {
|
||||||
|
unreachable!("cast from {:?} to ptr", current_ty)
|
||||||
|
}
|
||||||
|
} else if target_llvm_ty.is_int_type() {
|
||||||
|
let is_signed = target_ty.kind.is_signed_integer();
|
||||||
|
let target_llvm_ty = target_llvm_ty.into_int_type();
|
||||||
|
if current_ty.is_int_type() {
|
||||||
|
// int to int casts
|
||||||
|
let current_ty = current_ty.into_int_type();
|
||||||
|
|
||||||
|
match current_ty
|
||||||
|
.get_bit_width()
|
||||||
|
.cmp(&target_llvm_ty.get_bit_width())
|
||||||
|
{
|
||||||
|
std::cmp::Ordering::Greater => {
|
||||||
|
let value = ctx.builder.build_int_truncate(
|
||||||
|
value.into_int_value(),
|
||||||
|
target_llvm_ty,
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
(value.as_basic_value_enum(), target_ty)
|
||||||
|
}
|
||||||
|
std::cmp::Ordering::Equal => (value, target_ty.clone()),
|
||||||
|
std::cmp::Ordering::Less => {
|
||||||
|
if is_signed {
|
||||||
|
let value = ctx.builder.build_int_s_extend(
|
||||||
|
value.into_int_value(),
|
||||||
|
target_llvm_ty,
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
(value.as_basic_value_enum(), target_ty)
|
||||||
|
} else {
|
||||||
|
let value = ctx.builder.build_int_z_extend(
|
||||||
|
value.into_int_value(),
|
||||||
|
target_llvm_ty,
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
(value.as_basic_value_enum(), target_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if current_ty.is_float_type() {
|
||||||
|
// float to int casts
|
||||||
|
if is_signed {
|
||||||
|
let value = ctx.builder.build_float_to_signed_int(
|
||||||
|
value.into_float_value(),
|
||||||
|
target_llvm_ty,
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
(value.as_basic_value_enum(), target_ty)
|
||||||
|
} else {
|
||||||
|
let value = ctx.builder.build_float_to_unsigned_int(
|
||||||
|
value.into_float_value(),
|
||||||
|
target_llvm_ty,
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
(value.as_basic_value_enum(), target_ty)
|
||||||
|
}
|
||||||
|
} else if current_ty.is_pointer_type() {
|
||||||
|
// ptr to int
|
||||||
|
let value = ctx.builder.build_ptr_to_int(
|
||||||
|
value.into_pointer_value(),
|
||||||
|
target_llvm_ty,
|
||||||
|
"",
|
||||||
|
)?;
|
||||||
|
(value.as_basic_value_enum(), target_ty)
|
||||||
|
} else {
|
||||||
|
todo!("cast {:?} to int", current_ty)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
todo!("cast from {:?} to {:?}", current_ty, target_llvm_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -259,6 +259,14 @@ impl TypeKind {
|
||||||
matches!(self, Self::Int(_) | Self::Uint(_))
|
matches!(self, Self::Int(_) | Self::Uint(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn is_signed_integer(&self) -> bool {
|
||||||
|
matches!(self, Self::Int(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn is_float(&self) -> bool {
|
||||||
|
matches!(self, Self::Float(_))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_falsy_value(&self) -> ValueTree {
|
pub fn get_falsy_value(&self) -> ValueTree {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool => ValueTree::Leaf(ConstValue::Bool(false)),
|
Self::Bool => ValueTree::Leaf(ConstValue::Bool(false)),
|
||||||
|
@ -410,6 +418,7 @@ pub enum RValue {
|
||||||
BinOp(BinOp, Operand, Operand, Span),
|
BinOp(BinOp, Operand, Operand, Span),
|
||||||
LogicOp(LogicalOp, Operand, Operand, Span),
|
LogicOp(LogicalOp, Operand, Operand, Span),
|
||||||
UnOp(UnOp, Operand, Span),
|
UnOp(UnOp, Operand, Span),
|
||||||
|
Cast(Place, TypeInfo, Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
@ -516,15 +516,35 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) -> Result<(),
|
||||||
|
|
||||||
fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<TypeKind> {
|
fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<TypeKind> {
|
||||||
Some(match info {
|
Some(match info {
|
||||||
ast::Expression::Value(x) => match x {
|
ast::Expression::Value(val) => match val {
|
||||||
ast::ValueExpr::Bool { .. } => TypeKind::Bool,
|
ast::ValueExpr::Bool { .. } => TypeKind::Bool,
|
||||||
ast::ValueExpr::Char { .. } => TypeKind::Char,
|
ast::ValueExpr::Char { .. } => TypeKind::Char,
|
||||||
ast::ValueExpr::Int { .. } => return None,
|
ast::ValueExpr::Int { .. } => return None,
|
||||||
ast::ValueExpr::Float { .. } => return None,
|
ast::ValueExpr::Float { .. } => return None,
|
||||||
ast::ValueExpr::Str { .. } => todo!(),
|
ast::ValueExpr::Str { .. } => todo!(),
|
||||||
ast::ValueExpr::Path(path) => {
|
ast::ValueExpr::Path(path) => {
|
||||||
// todo: handle full path
|
let local = builder.get_local(&path.first.name)?;
|
||||||
builder.get_local(&path.first.name)?.ty.kind.clone()
|
let mut ty = local.ty.kind.clone();
|
||||||
|
|
||||||
|
for seg in &path.extra {
|
||||||
|
match seg {
|
||||||
|
ast::PathSegment::Field(field_name) => {
|
||||||
|
ty = match ty {
|
||||||
|
TypeKind::Struct(id, _struct_name) => {
|
||||||
|
let body = builder.ctx.body.structs.get(&id)?;
|
||||||
|
body.variants[*body.name_to_idx.get(&field_name.name)?]
|
||||||
|
.ty
|
||||||
|
.kind
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast::PathSegment::Index { .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ty
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ast::Expression::FnCall(info) => {
|
ast::Expression::FnCall(info) => {
|
||||||
|
@ -569,6 +589,11 @@ fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<T
|
||||||
.expect("struct not found");
|
.expect("struct not found");
|
||||||
ir::TypeKind::Struct(id, info.name.name.name.clone())
|
ir::TypeKind::Struct(id, info.name.name.name.clone())
|
||||||
}
|
}
|
||||||
|
ast::Expression::Cast(_, _new_ty, _) => {
|
||||||
|
// checks?
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,6 +730,15 @@ fn lower_expr(
|
||||||
|
|
||||||
(RValue::Use(Operand::Move(place), info.span), ty, info.span)
|
(RValue::Use(Operand::Move(place), info.span), ty, info.span)
|
||||||
}
|
}
|
||||||
|
ast::Expression::Cast(path, cast_ty, span) => {
|
||||||
|
let (place, _ty, _path_span) = lower_path(builder, path)?;
|
||||||
|
let new_ty = lower_type(&builder.ctx, cast_ty, builder.local_module)?;
|
||||||
|
let kind = new_ty.kind.clone();
|
||||||
|
|
||||||
|
// todo: some checks?
|
||||||
|
|
||||||
|
(RValue::Cast(place, new_ty, *span), kind, *span)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern {
|
||||||
"use" => Token::KeywordUse,
|
"use" => Token::KeywordUse,
|
||||||
"in" => Token::KeywordIn,
|
"in" => Token::KeywordIn,
|
||||||
"extern" => Token::KeywordExtern,
|
"extern" => Token::KeywordExtern,
|
||||||
|
"as" => Token::KeywordAs,
|
||||||
|
|
||||||
// literals
|
// literals
|
||||||
"identifier" => Token::Identifier(<String>),
|
"identifier" => Token::Identifier(<String>),
|
||||||
|
@ -308,7 +309,6 @@ pub(crate) Term: ast::Expression = {
|
||||||
#[precedence(level="0")]
|
#[precedence(level="0")]
|
||||||
<ValueExpr> => ast::Expression::Value(<>),
|
<ValueExpr> => ast::Expression::Value(<>),
|
||||||
<FnCallExpr> => ast::Expression::FnCall(<>),
|
<FnCallExpr> => ast::Expression::FnCall(<>),
|
||||||
"(" <StructInitExpr> ")" => ast::Expression::StructInit(<>),
|
|
||||||
#[precedence(level="2")] #[assoc(side="left")]
|
#[precedence(level="2")] #[assoc(side="left")]
|
||||||
"(" <Expression> ")",
|
"(" <Expression> ")",
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,6 @@ pub(crate) Expression: ast::Expression = {
|
||||||
op,
|
op,
|
||||||
Box::new(rhs)
|
Box::new(rhs)
|
||||||
),
|
),
|
||||||
|
|
||||||
#[precedence(level="2")] #[assoc(side="left")]
|
#[precedence(level="2")] #[assoc(side="left")]
|
||||||
<lhs:Expression> <op:BinaryFirstLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
<lhs:Expression> <op:BinaryFirstLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
||||||
Box::new(lhs),
|
Box::new(lhs),
|
||||||
|
@ -343,6 +342,9 @@ pub(crate) Expression: ast::Expression = {
|
||||||
op,
|
op,
|
||||||
Box::new(rhs)
|
Box::new(rhs)
|
||||||
),
|
),
|
||||||
|
#[precedence(level="5")] #[assoc(side="left")]
|
||||||
|
<lo:@L> <a:PathExpr> "as" <b: Type> <hi:@R> => ast::Expression::Cast(a, b, ast::Span::new(lo, hi)),
|
||||||
|
"(" <StructInitExpr> ")" => ast::Expression::StructInit(<>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub BinaryFirstLvlOp: ast::BinaryOp = {
|
pub BinaryFirstLvlOp: ast::BinaryOp = {
|
||||||
|
|
|
@ -55,6 +55,8 @@ pub enum Token {
|
||||||
KeywordIn,
|
KeywordIn,
|
||||||
#[token("extern")]
|
#[token("extern")]
|
||||||
KeywordExtern,
|
KeywordExtern,
|
||||||
|
#[token("as")]
|
||||||
|
KeywordAs,
|
||||||
|
|
||||||
// Modern way of allowing identifiers, read: https://unicode.org/reports/tr31/
|
// Modern way of allowing identifiers, read: https://unicode.org/reports/tr31/
|
||||||
#[regex(r"[\p{XID_Start}_]\p{XID_Continue}*", |lex| lex.slice().to_string())]
|
#[regex(r"[\p{XID_Start}_]\p{XID_Continue}*", |lex| lex.slice().to_string())]
|
||||||
|
|
Loading…
Reference in a new issue