Skip to content

Commit fddd63a

Browse files
committed
Implement missing conversions
1 parent 86b8d8e commit fddd63a

File tree

4 files changed

+241
-3
lines changed

4 files changed

+241
-3
lines changed

cobalt-ast/src/types/float.rs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ static F128: Float = Float(FPType::F128);
1818
#[derive(Debug, Display)]
1919
pub struct Float(FPType);
2020
impl Float {
21-
pub const KIND: NonZeroU64 = make_id(b"float");
2221
pub fn new(val: FPType) -> &'static Self {
2322
match val {
2423
FPType::F16 => &F16,
@@ -73,6 +72,91 @@ impl Type for Float {
7372
.into(),
7473
)
7574
}
75+
fn _can_iconv_to(&'static self, other: TypeRef, ctx: &CompCtx) -> bool {
76+
if let Some(ty) = other.downcast::<types::Float>() {
77+
ty.kind() >= self.kind()
78+
} else {
79+
false
80+
}
81+
}
82+
fn _iconv_to<'src, 'ctx>(
83+
&'static self,
84+
val: Value<'src, 'ctx>,
85+
target: (TypeRef, Option<SourceSpan>),
86+
ctx: &CompCtx<'src, 'ctx>,
87+
) -> Result<Value<'src, 'ctx>, CobaltError<'src>> {
88+
if let Some(ty) = target.0.downcast::<types::Float>() {
89+
if ty.kind() >= self.kind() {
90+
return Ok(Value::new(
91+
if let Some(BasicValueEnum::FloatValue(v)) = val.comp_val {
92+
if self.kind() == ty.kind() {
93+
Some(v.into())
94+
} else {
95+
Some(
96+
ctx.builder
97+
.build_float_ext(
98+
v,
99+
ty.llvm_type(ctx).unwrap().into_float_type(),
100+
"",
101+
)
102+
.into(),
103+
)
104+
}
105+
} else {
106+
None
107+
},
108+
val.inter_val,
109+
target.0,
110+
));
111+
}
112+
}
113+
Err(cant_econv(&val, target.0, target.1))
114+
}
115+
fn _econv_to<'src, 'ctx>(
116+
&'static self,
117+
val: Value<'src, 'ctx>,
118+
target: (TypeRef, Option<SourceSpan>),
119+
ctx: &CompCtx<'src, 'ctx>,
120+
) -> Result<Value<'src, 'ctx>, CobaltError<'src>> {
121+
if let Some(ty) = target.0.downcast::<types::Float>() {
122+
Ok(Value::new(
123+
if let Some(BasicValueEnum::FloatValue(v)) = val.comp_val {
124+
let ft = ty.llvm_type(ctx).unwrap().into_float_type();
125+
use std::cmp::Ordering;
126+
match ty.kind().cmp(&self.kind()) {
127+
Ordering::Greater => Some(ctx.builder.build_float_ext(v, ft, "").into()),
128+
Ordering::Less => Some(ctx.builder.build_float_trunc(v, ft, "").into()),
129+
Ordering::Equal => Some(v.into()),
130+
}
131+
} else {
132+
None
133+
},
134+
val.inter_val,
135+
target.0,
136+
))
137+
} else if let Some(ty) = target.0.downcast::<types::Int>() {
138+
Ok(Value::new(
139+
if let Some(BasicValueEnum::FloatValue(v)) = val.comp_val {
140+
let it = ty.llvm_type(ctx).unwrap().into_int_type();
141+
if ty.is_signed() {
142+
Some(ctx.builder.build_float_to_signed_int(v, it, "").into())
143+
} else {
144+
Some(ctx.builder.build_float_to_unsigned_int(v, it, "").into())
145+
}
146+
} else {
147+
None
148+
},
149+
if let Some(InterData::Float(v)) = val.inter_val {
150+
Some(InterData::Int(v as _))
151+
} else {
152+
None
153+
},
154+
target.0,
155+
))
156+
} else {
157+
Err(cant_econv(&val, target.0, target.1))
158+
}
159+
}
76160
fn pre_op<'src, 'ctx>(
77161
&'static self,
78162
val: Value<'src, 'ctx>,

cobalt-ast/src/types/int.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,125 @@ impl Type for Int {
105105
_ => Err(invalid_preop(&val, op, oloc)),
106106
}
107107
}
108+
fn _can_iconv_to(&'static self, other: TypeRef, ctx: &CompCtx) -> bool {
109+
if let Some(ty) = other.downcast::<types::Int>() {
110+
ty.bits() >= self.bits()
111+
} else {
112+
other.is::<types::Float>()
113+
}
114+
}
115+
fn _can_econv_to(&'static self, other: TypeRef, ctx: &CompCtx) -> bool {
116+
other.is::<types::Int>()
117+
|| other.is_and::<types::Pointer>(|p| {
118+
matches!(p.llvm_type(ctx), Some(BasicTypeEnum::PointerType(_)))
119+
})
120+
}
121+
fn _iconv_to<'src, 'ctx>(
122+
&'static self,
123+
val: Value<'src, 'ctx>,
124+
target: (TypeRef, Option<SourceSpan>),
125+
ctx: &CompCtx<'src, 'ctx>,
126+
) -> Result<Value<'src, 'ctx>, CobaltError<'src>> {
127+
if let Some(ty) = target.0.downcast::<types::Int>() {
128+
if ty.bits() >= self.bits() {
129+
Ok(Value::new(
130+
if ty.bits() == self.bits() {
131+
val.comp_val
132+
} else if let Some(BasicValueEnum::IntValue(v)) = val.comp_val {
133+
let ty = target.0.llvm_type(ctx).unwrap().into_int_type();
134+
if self.is_signed() {
135+
Some(ctx.builder.build_int_s_extend(v, ty, "").into())
136+
} else {
137+
Some(ctx.builder.build_int_z_extend(v, ty, "").into())
138+
}
139+
} else {
140+
None
141+
},
142+
if let Some(InterData::Int(v)) = val.inter_val {
143+
Some(InterData::Float(v as _))
144+
} else {
145+
None
146+
},
147+
target.0,
148+
))
149+
} else {
150+
Err(CobaltError::NarrowingIntConversion {
151+
sbits: self.bits(),
152+
dbits: ty.bits(),
153+
sloc: val.loc,
154+
dloc: target.1.unwrap_or(val.loc),
155+
})
156+
}
157+
} else if target.0.is::<types::Float>() {
158+
Ok(Value::new(
159+
if let Some(BasicValueEnum::IntValue(v)) = val.comp_val {
160+
let ty = target.0.llvm_type(ctx).unwrap().into_float_type();
161+
if self.is_signed() {
162+
Some(ctx.builder.build_signed_int_to_float(v, ty, "").into())
163+
} else {
164+
Some(ctx.builder.build_unsigned_int_to_float(v, ty, "").into())
165+
}
166+
} else {
167+
None
168+
},
169+
if let Some(InterData::Int(v)) = val.inter_val {
170+
Some(InterData::Float(v as _))
171+
} else {
172+
None
173+
},
174+
target.0,
175+
))
176+
} else {
177+
Err(cant_iconv(&val, target.0, target.1))
178+
}
179+
}
180+
fn _econv_to<'src, 'ctx>(
181+
&'static self,
182+
val: Value<'src, 'ctx>,
183+
target: (TypeRef, Option<SourceSpan>),
184+
ctx: &CompCtx<'src, 'ctx>,
185+
) -> Result<Value<'src, 'ctx>, CobaltError<'src>> {
186+
if let Some(ty) = target.0.downcast::<types::Int>() {
187+
Ok(Value::new(
188+
if let Some(BasicValueEnum::IntValue(v)) = val.comp_val {
189+
let it = target.0.llvm_type(ctx).unwrap().into_int_type();
190+
use std::cmp::Ordering;
191+
match ty.bits().cmp(&self.bits()) {
192+
Ordering::Greater => {
193+
if self.is_signed() {
194+
Some(ctx.builder.build_int_s_extend(v, it, "").into())
195+
} else {
196+
Some(ctx.builder.build_int_z_extend(v, it, "").into())
197+
}
198+
}
199+
Ordering::Less => Some(ctx.builder.build_int_truncate(v, it, "").into()),
200+
Ordering::Equal => Some(v.into()),
201+
}
202+
} else {
203+
None
204+
},
205+
if let Some(InterData::Int(v)) = val.inter_val {
206+
Some(InterData::Float(v as _))
207+
} else {
208+
None
209+
},
210+
target.0,
211+
))
212+
} else if target.0.is::<types::Pointer>() {
213+
Ok(Value::new(
214+
if let Some(BasicValueEnum::IntValue(v)) = val.comp_val {
215+
let ty = target.0.llvm_type(ctx).unwrap().into_pointer_type();
216+
Some(ctx.builder.build_int_to_ptr(v, ty, "").into())
217+
} else {
218+
None
219+
},
220+
None,
221+
target.0,
222+
))
223+
} else {
224+
Err(cant_iconv(&val, target.0, target.1))
225+
}
226+
}
108227
fn _has_bin_lhs(
109228
&'static self,
110229
other: TypeRef,

cobalt-ast/src/types/mem.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,6 @@ impl Type for Pointer {
904904
#[repr(transparent)]
905905
pub struct Mut(TypeRef);
906906
impl Mut {
907-
pub const KIND: NonZeroU64 = make_id(b"mut");
908907
#[ref_cast_custom]
909908
fn from_ref(base: &TypeRef) -> &Self;
910909
pub fn new(base: TypeRef) -> &'static Self {

cobalt-ast/src/types/meta.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use super::*;
33
#[display(fmt = "type")]
44
pub struct TypeData(());
55
impl TypeData {
6-
pub const KIND: NonZeroU64 = make_id(b"type");
76
pub fn new() -> &'static Self {
87
static SELF: TypeData = Self(());
98
&SELF
@@ -368,6 +367,15 @@ impl Type for Null {
368367
fn _can_iconv_to(&'static self, other: TypeRef, ctx: &CompCtx) -> bool {
369368
other.is::<TypeData>()
370369
}
370+
fn _can_econv_to(&'static self, other: TypeRef, ctx: &CompCtx) -> bool {
371+
matches!(
372+
other.kind(),
373+
types::Pointer::KIND | types::Int::KIND | types::Float::KIND
374+
)
375+
}
376+
fn _can_iconv_from(&'static self, other: TypeRef, ctx: &CompCtx) -> bool {
377+
true
378+
}
371379
fn _iconv_to<'src, 'ctx>(
372380
&'static self,
373381
val: Value<'src, 'ctx>,
@@ -380,6 +388,34 @@ impl Type for Null {
380388
Err(cant_iconv(&val, target.0, target.1))
381389
}
382390
}
391+
fn _econv_to<'src, 'ctx>(
392+
&'static self,
393+
val: Value<'src, 'ctx>,
394+
target: (TypeRef, Option<SourceSpan>),
395+
ctx: &CompCtx<'src, 'ctx>,
396+
) -> Result<Value<'src, 'ctx>, CobaltError<'src>> {
397+
match target.0.kind() {
398+
types::Int::KIND => Ok(Value::metaval(InterData::Int(0), target.0)),
399+
types::Float::KIND => Ok(Value::interpreted(
400+
target.0.llvm_type(ctx).unwrap().const_zero(),
401+
InterData::Float(0.),
402+
target.0,
403+
)),
404+
types::Pointer::KIND => Ok(Value::compiled(
405+
target.0.llvm_type(ctx).unwrap().const_zero(),
406+
target.0,
407+
)),
408+
_ => Err(cant_econv(&val, target.0, target.1)),
409+
}
410+
}
411+
fn _iconv_from<'src, 'ctx>(
412+
&'static self,
413+
val: Value<'src, 'ctx>,
414+
target: Option<SourceSpan>,
415+
ctx: &CompCtx<'src, 'ctx>,
416+
) -> Result<Value<'src, 'ctx>, CobaltError<'src>> {
417+
Ok(Value::null())
418+
}
383419
fn save(&self, _out: &mut dyn Write) -> io::Result<()> {
384420
Ok(())
385421
}

0 commit comments

Comments
 (0)