From 709ff28febd38f0e91722e2095eeeba685122041 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Fri, 6 Mar 2020 15:26:03 +0100 Subject: [PATCH 1/3] feat: adds bitwise primitive types --- crates/mun_codegen/src/ir/body.rs | 37 +++++- crates/mun_codegen/src/ir/ty.rs | 30 ++++- crates/mun_hir/src/buildin_type.rs | 153 ++++++++++++++++++++++ crates/mun_hir/src/code_model.rs | 18 +-- crates/mun_hir/src/lib.rs | 4 +- crates/mun_hir/src/name.rs | 32 ++++- crates/mun_hir/src/name_resolution.rs | 2 +- crates/mun_hir/src/ty.rs | 10 +- crates/mun_hir/src/ty/infer.rs | 5 +- crates/mun_hir/src/ty/lower.rs | 8 +- crates/mun_hir/src/ty/op.rs | 6 +- crates/mun_hir/src/ty/primitives.rs | 176 ++++++++++++++++++++++++++ 12 files changed, 432 insertions(+), 49 deletions(-) create mode 100644 crates/mun_hir/src/buildin_type.rs create mode 100644 crates/mun_hir/src/ty/primitives.rs diff --git a/crates/mun_codegen/src/ir/body.rs b/crates/mun_codegen/src/ir/body.rs index 3bef260ce..b20b55958 100644 --- a/crates/mun_codegen/src/ir/body.rs +++ b/crates/mun_codegen/src/ir/body.rs @@ -441,8 +441,8 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { let lhs_type = self.infer[lhs].clone(); let rhs_type = self.infer[rhs].clone(); match lhs_type.as_simple() { - Some(TypeCtor::Float) => self.gen_binary_op_float(lhs, rhs, op), - Some(TypeCtor::Int) => self.gen_binary_op_int(lhs, rhs, op), + Some(TypeCtor::Float(_ty)) => self.gen_binary_op_float(lhs, rhs, op), + Some(TypeCtor::Int(ty)) => self.gen_binary_op_int(lhs, rhs, op, ty.signedness), _ => unimplemented!( "unimplemented operation {0}op{1}", lhs_type.display(self.db), @@ -516,6 +516,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { lhs_expr: ExprId, rhs_expr: ExprId, op: BinaryOp, + signedness: hir::Signedness, ) -> Option { let lhs = self .gen_expr(lhs_expr) @@ -536,19 +537,43 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { CmpOp::Ord { ordering: Ordering::Less, strict: false, - } => ("lesseq", IntPredicate::SLE), + } => ( + "lesseq", + match signedness { + hir::Signedness::Signed => IntPredicate::SLE, + hir::Signedness::Unsigned => IntPredicate::ULE, + }, + ), CmpOp::Ord { ordering: Ordering::Less, strict: true, - } => ("less", IntPredicate::SLT), + } => ( + "less", + match signedness { + hir::Signedness::Signed => IntPredicate::SLT, + hir::Signedness::Unsigned => IntPredicate::ULT, + }, + ), CmpOp::Ord { ordering: Ordering::Greater, strict: false, - } => ("greatereq", IntPredicate::SGE), + } => ( + "greatereq", + match signedness { + hir::Signedness::Signed => IntPredicate::SGE, + hir::Signedness::Unsigned => IntPredicate::UGE, + }, + ), CmpOp::Ord { ordering: Ordering::Greater, strict: true, - } => ("greater", IntPredicate::SGT), + } => ( + "greater", + match signedness { + hir::Signedness::Signed => IntPredicate::SGT, + hir::Signedness::Unsigned => IntPredicate::UGT, + }, + ), }; Some( self.builder diff --git a/crates/mun_codegen/src/ir/ty.rs b/crates/mun_codegen/src/ir/ty.rs index 280fe0595..2735dd098 100644 --- a/crates/mun_codegen/src/ir/ty.rs +++ b/crates/mun_codegen/src/ir/ty.rs @@ -3,19 +3,33 @@ use crate::{ type_info::{TypeGroup, TypeInfo}, IrDatabase, }; -use hir::{ApplicationTy, CallableDef, Ty, TypeCtor}; +use hir::{ApplicationTy, CallableDef, FloatBitness, FloatTy, IntBitness, IntTy, Ty, TypeCtor}; use inkwell::types::{AnyTypeEnum, BasicType, BasicTypeEnum, StructType}; use inkwell::AddressSpace; /// Given a mun type, construct an LLVM IR type +#[rustfmt::skip] pub(crate) fn ir_query(db: &impl IrDatabase, ty: Ty) -> AnyTypeEnum { let context = db.context(); match ty { Ty::Empty => AnyTypeEnum::StructType(context.struct_type(&[], false)), Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Float => AnyTypeEnum::FloatType(context.f64_type()), - TypeCtor::Int => AnyTypeEnum::IntType(context.i64_type()), - TypeCtor::Bool => AnyTypeEnum::IntType(context.bool_type()), + // Float primitives + TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }) => AnyTypeEnum::FloatType(context.f32_type()), + TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }) => AnyTypeEnum::FloatType(context.f64_type()), + TypeCtor::Float(FloatTy { bitness: FloatBitness::Undefined }) => AnyTypeEnum::FloatType(context.f64_type()), + + // Int primitives + TypeCtor::Int(IntTy { bitness: IntBitness::Undefined, .. }) => AnyTypeEnum::IntType(context.i64_type()), + TypeCtor::Int(IntTy { bitness: IntBitness::X8, .. }) => AnyTypeEnum::IntType(context.i8_type()), + TypeCtor::Int(IntTy { bitness: IntBitness::X16, .. }) => AnyTypeEnum::IntType(context.i16_type()), + TypeCtor::Int(IntTy { bitness: IntBitness::X32, .. }) => AnyTypeEnum::IntType(context.i32_type()), + TypeCtor::Int(IntTy { bitness: IntBitness::X64, .. }) => AnyTypeEnum::IntType(context.i64_type()), + TypeCtor::Int(IntTy { bitness: IntBitness::Xsize, .. }) => AnyTypeEnum::IntType(context.i64_type()), + + // Boolean + TypeCtor::Bool => AnyTypeEnum::IntType(context.bool_type()), + TypeCtor::FnDef(def @ CallableDef::Function(_)) => { let ty = db.callable_sig(def); let params: Vec = ty @@ -61,8 +75,12 @@ pub fn struct_ty_query(db: &impl IrDatabase, s: hir::Struct) -> StructType { pub fn type_info_query(db: &impl IrDatabase, ty: Ty) -> TypeInfo { match ty { Ty::Apply(ctor) => match ctor.ctor { - TypeCtor::Float => TypeInfo::new("core::float", TypeGroup::FundamentalTypes), - TypeCtor::Int => TypeInfo::new("core::int", TypeGroup::FundamentalTypes), + TypeCtor::Float(ty) => { + TypeInfo::new(format!("core::{}", ty), TypeGroup::FundamentalTypes) + } + TypeCtor::Int(ty) => { + TypeInfo::new(format!("core::{}", ty), TypeGroup::FundamentalTypes) + } TypeCtor::Bool => TypeInfo::new("core::bool", TypeGroup::FundamentalTypes), TypeCtor::Struct(s) => TypeInfo::new(s.name(db).to_string(), TypeGroup::StructTypes(s)), _ => unreachable!("{:?} unhandled", ctor), diff --git a/crates/mun_hir/src/buildin_type.rs b/crates/mun_hir/src/buildin_type.rs new file mode 100644 index 000000000..c5b69540b --- /dev/null +++ b/crates/mun_hir/src/buildin_type.rs @@ -0,0 +1,153 @@ +use crate::name::{name, Name}; +use std::fmt; + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum Signedness { + Signed, + Unsigned, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum IntBitness { + Xsize, + X8, + X16, + X32, + X64, + Undefined, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum FloatBitness { + X32, + X64, + Undefined, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct BuiltinInt { + pub signedness: Signedness, + pub bitness: IntBitness, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct BuiltinFloat { + pub bitness: FloatBitness, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum BuiltinType { + Float(BuiltinFloat), + Int(BuiltinInt), + Bool, +} + +impl BuiltinType { + #[rustfmt::skip] + pub const ALL: &'static [(Name, BuiltinType)] = &[ + (name![bool], BuiltinType::Bool), + + (name![int], BuiltinType::Int(BuiltinInt::INT)), + (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)), + (name![i8], BuiltinType::Int(BuiltinInt::I8)), + (name![i16], BuiltinType::Int(BuiltinInt::I16)), + (name![i32], BuiltinType::Int(BuiltinInt::I32)), + (name![i64], BuiltinType::Int(BuiltinInt::I64)), + + (name![uint], BuiltinType::Int(BuiltinInt::UINT)), + (name![usize], BuiltinType::Int(BuiltinInt::USIZE)), + (name![u8], BuiltinType::Int(BuiltinInt::U8)), + (name![u16], BuiltinType::Int(BuiltinInt::U16)), + (name![u32], BuiltinType::Int(BuiltinInt::U32)), + (name![u64], BuiltinType::Int(BuiltinInt::U64)), + + (name![float], BuiltinType::Float(BuiltinFloat::FLOAT)), + (name![f32], BuiltinType::Float(BuiltinFloat::F32)), + (name![f64], BuiltinType::Float(BuiltinFloat::F64)), + ]; +} + +impl fmt::Display for BuiltinType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let type_name = match self { + BuiltinType::Bool => "bool", + BuiltinType::Int(BuiltinInt { + signedness, + bitness, + }) => match (signedness, bitness) { + (Signedness::Signed, IntBitness::Xsize) => "isize", + (Signedness::Signed, IntBitness::X8) => "i8", + (Signedness::Signed, IntBitness::X16) => "i16", + (Signedness::Signed, IntBitness::X32) => "i32", + (Signedness::Signed, IntBitness::X64) => "i64", + (Signedness::Signed, IntBitness::Undefined) => "int", + + (Signedness::Unsigned, IntBitness::Xsize) => "usize", + (Signedness::Unsigned, IntBitness::X8) => "u8", + (Signedness::Unsigned, IntBitness::X16) => "u16", + (Signedness::Unsigned, IntBitness::X32) => "u32", + (Signedness::Unsigned, IntBitness::X64) => "u64", + (Signedness::Unsigned, IntBitness::Undefined) => "uint", + }, + BuiltinType::Float(BuiltinFloat { bitness }) => match bitness { + FloatBitness::X32 => "f32", + FloatBitness::X64 => "f64", + FloatBitness::Undefined => "float", + }, + }; + f.write_str(type_name) + } +} + +#[rustfmt::skip] +impl BuiltinInt { + pub const INT : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Undefined }; + pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize }; + pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 }; + pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 }; + pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 }; + pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 }; + + pub const UINT : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Undefined }; + pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }; + pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }; + pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }; + pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }; + pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }; + + + pub fn from_suffix(suffix: &str) -> Option { + let res = match suffix { + "isize" => Self::ISIZE, + "i8" => Self::I8, + "i16" => Self::I16, + "i32" => Self::I32, + "i64" => Self::I64, + + "usize" => Self::USIZE, + "u8" => Self::U8, + "u16" => Self::U16, + "u32" => Self::U32, + "u64" => Self::U64, + + _ => return None, + }; + Some(res) + } +} + +#[rustfmt::skip] +impl BuiltinFloat { + pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 }; + pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 }; + pub const FLOAT: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::Undefined }; + + pub fn from_suffix(suffix: &str) -> Option { + let res = match suffix { + "f32" => BuiltinFloat::F32, + "f64" => BuiltinFloat::F64, + _ => return None, + }; + Some(res) + } +} diff --git a/crates/mun_hir/src/code_model.rs b/crates/mun_hir/src/code_model.rs index 958269871..b380117c0 100644 --- a/crates/mun_hir/src/code_model.rs +++ b/crates/mun_hir/src/code_model.rs @@ -2,13 +2,13 @@ pub(crate) mod src; use self::src::HasSource; use crate::adt::{StructData, StructFieldId}; +use crate::buildin_type::BuiltinType; use crate::code_model::diagnostics::ModuleDefinitionDiagnostic; use crate::diagnostics::DiagnosticSink; use crate::expr::validator::ExprValidator; use crate::expr::{Body, BodySourceMap}; use crate::ids::AstItemDef; use crate::ids::LocationCtx; -use crate::name::*; use crate::name_resolution::Namespace; use crate::raw::{DefKind, RawFileItem}; use crate::resolve::{Resolution, Resolver}; @@ -338,22 +338,6 @@ impl Function { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum BuiltinType { - Float, - Int, - Boolean, -} - -impl BuiltinType { - #[rustfmt::skip] - pub(crate) const ALL: &'static [(Name, BuiltinType)] = &[ - (FLOAT, BuiltinType::Float), - (INT, BuiltinType::Int), - (BOOLEAN, BuiltinType::Boolean), - ]; -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Struct { pub(crate) id: StructId, diff --git a/crates/mun_hir/src/lib.rs b/crates/mun_hir/src/lib.rs index 2fcf97665..19e875e4a 100644 --- a/crates/mun_hir/src/lib.rs +++ b/crates/mun_hir/src/lib.rs @@ -10,6 +10,7 @@ mod macros; #[macro_use] mod arena; mod adt; +mod buildin_type; mod code_model; mod db; pub mod diagnostics; @@ -40,6 +41,7 @@ pub use relative_path::{RelativePath, RelativePathBuf}; pub use crate::{ arena::{ArenaId, RawId}, + buildin_type::{FloatBitness, IntBitness, Signedness}, db::{ DefDatabase, DefDatabaseStorage, HirDatabase, HirDatabaseStorage, SourceDatabase, SourceDatabaseStorage, @@ -56,7 +58,7 @@ pub use crate::{ path::{Path, PathKind}, raw::RawItems, resolve::{Resolution, Resolver}, - ty::{lower::CallableDef, ApplicationTy, InferenceResult, Ty, TypeCtor}, + ty::{lower::CallableDef, ApplicationTy, FloatTy, InferenceResult, IntTy, Ty, TypeCtor}, }; use crate::{ diff --git a/crates/mun_hir/src/name.rs b/crates/mun_hir/src/name.rs index 9df501272..b9013eba4 100644 --- a/crates/mun_hir/src/name.rs +++ b/crates/mun_hir/src/name.rs @@ -34,8 +34,8 @@ impl Name { } /// Shortcut to create inline plain text name - const fn new_inline_ascii(len: usize, text: &[u8]) -> Name { - Name::new_text(SmolStr::new_inline_from_ascii(len, text)) + const fn new_inline_ascii(text: &[u8]) -> Name { + Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text)) } /// Resolve a name from the text of token. @@ -88,6 +88,28 @@ impl AsName for ast::FieldKind { } } -pub(crate) const FLOAT: Name = Name::new_inline_ascii(5, b"float"); -pub(crate) const INT: Name = Name::new_inline_ascii(3, b"int"); -pub(crate) const BOOLEAN: Name = Name::new_inline_ascii(4, b"bool"); +pub mod known { + macro_rules! known_names { + ($($ident:ident),* $(,)?) => { + $( + #[allow(bad_style)] + pub const $ident: super::Name = + super::Name::new_inline_ascii(stringify!($ident).as_bytes()); + )* + }; + } + + known_names!( + // Primitives + int, isize, i8, i16, i32, i64, uint, usize, u8, u16, u32, u64, float, f32, f64, bool, + ); + + #[macro_export] + macro_rules! name { + ($ident:ident) => { + $crate::name::known::$ident + }; + } +} + +pub use crate::name; diff --git a/crates/mun_hir/src/name_resolution.rs b/crates/mun_hir/src/name_resolution.rs index 8f3c804cb..744532861 100644 --- a/crates/mun_hir/src/name_resolution.rs +++ b/crates/mun_hir/src/name_resolution.rs @@ -1,7 +1,7 @@ mod per_ns; pub use self::per_ns::{Namespace, PerNs}; -use crate::{code_model::BuiltinType, FileId, HirDatabase, ModuleDef, Name}; +use crate::{buildin_type::BuiltinType, FileId, HirDatabase, ModuleDef, Name}; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; use std::sync::Arc; diff --git a/crates/mun_hir/src/ty.rs b/crates/mun_hir/src/ty.rs index 6f3f84cf3..19d5b2d7d 100644 --- a/crates/mun_hir/src/ty.rs +++ b/crates/mun_hir/src/ty.rs @@ -1,6 +1,7 @@ mod infer; pub(super) mod lower; mod op; +mod primitives; use crate::display::{HirDisplay, HirFormatter}; use crate::ty::infer::TypeVarId; @@ -9,6 +10,7 @@ use crate::{HirDatabase, Struct}; pub(crate) use infer::infer_query; pub use infer::InferenceResult; pub(crate) use lower::{callable_item_sig, fn_sig_for_fn, type_for_def, CallableDef, TypableDef}; +pub use primitives::{FloatTy, IntTy}; use std::fmt; use std::sync::Arc; @@ -47,10 +49,10 @@ pub struct ApplicationTy { #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum TypeCtor { /// The primitive floating point type. Written as `float`. - Float, + Float(FloatTy), /// The primitive integral type. Written as `int`. - Int, + Int(IntTy), /// The primitive boolean type. Written as `bool`. Bool, @@ -188,8 +190,8 @@ impl HirDisplay for Ty { impl HirDisplay for ApplicationTy { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { match self.ctor { - TypeCtor::Float => write!(f, "float"), - TypeCtor::Int => write!(f, "int"), + TypeCtor::Float(ty) => write!(f, "{}", ty), + TypeCtor::Int(ty) => write!(f, "{}", ty), TypeCtor::Bool => write!(f, "bool"), TypeCtor::Struct(def) => write!(f, "{}", def.name(f.db)), TypeCtor::Never => write!(f, "never"), diff --git a/crates/mun_hir/src/ty/infer.rs b/crates/mun_hir/src/ty/infer.rs index 822790426..69d6a5b5b 100644 --- a/crates/mun_hir/src/ty/infer.rs +++ b/crates/mun_hir/src/ty/infer.rs @@ -23,6 +23,7 @@ use std::sync::Arc; mod place_expr; mod type_variable; +use crate::ty::primitives::{FloatTy, IntTy}; pub use type_variable::TypeVarId; #[macro_export] @@ -322,8 +323,8 @@ impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { Expr::Literal(lit) => match lit { Literal::String(_) => Ty::Unknown, Literal::Bool(_) => Ty::simple(TypeCtor::Bool), - Literal::Int(_) => Ty::simple(TypeCtor::Int), - Literal::Float(_) => Ty::simple(TypeCtor::Float), + Literal::Int(_) => Ty::simple(TypeCtor::Int(IntTy::int())), + Literal::Float(_) => Ty::simple(TypeCtor::Float(FloatTy::float())), }, Expr::Return { expr } => { if let Some(expr) = expr { diff --git a/crates/mun_hir/src/ty/lower.rs b/crates/mun_hir/src/ty/lower.rs index 5c8ca8b33..fee87c242 100644 --- a/crates/mun_hir/src/ty/lower.rs +++ b/crates/mun_hir/src/ty/lower.rs @@ -1,7 +1,7 @@ pub(crate) use self::diagnostics::LowerDiagnostic; use crate::adt::StructKind; use crate::arena::map::ArenaMap; -use crate::code_model::BuiltinType; +use crate::buildin_type::BuiltinType; use crate::diagnostics::DiagnosticSink; use crate::name_resolution::Namespace; use crate::resolve::{Resolution, Resolver}; @@ -207,9 +207,9 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace /// Build the declared type of a static. fn type_for_builtin(def: BuiltinType) -> Ty { Ty::simple(match def { - BuiltinType::Float => TypeCtor::Float, - BuiltinType::Int => TypeCtor::Int, - BuiltinType::Boolean => TypeCtor::Bool, + BuiltinType::Float(f) => TypeCtor::Float(f.into()), + BuiltinType::Int(i) => TypeCtor::Int(i.into()), + BuiltinType::Bool => TypeCtor::Bool, }) } diff --git a/crates/mun_hir/src/ty/op.rs b/crates/mun_hir/src/ty/op.rs index c7daef9aa..52dc963aa 100644 --- a/crates/mun_hir/src/ty/op.rs +++ b/crates/mun_hir/src/ty/op.rs @@ -7,7 +7,7 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Bool), BinaryOp::Assignment { op: None } | BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty { Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Int | TypeCtor::Float | TypeCtor::Bool => lhs_ty, + TypeCtor::Int(_) | TypeCtor::Float(_) | TypeCtor::Bool => lhs_ty, _ => Ty::Unknown, }, _ => Ty::Unknown, @@ -16,7 +16,7 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | BinaryOp::Assignment { op: Some(_) } | BinaryOp::ArithOp(_) => match lhs_ty { Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Int | TypeCtor::Float => lhs_ty, + TypeCtor::Int(_) | TypeCtor::Float(_) => lhs_ty, _ => Ty::Unknown, }, _ => Ty::Unknown, @@ -30,7 +30,7 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { match op { BinaryOp::ArithOp(_) => match rhs_ty { Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { - TypeCtor::Int | TypeCtor::Float => rhs_ty, + TypeCtor::Int(_) | TypeCtor::Float(_) => rhs_ty, _ => Ty::Unknown, }, _ => Ty::Unknown, diff --git a/crates/mun_hir/src/ty/primitives.rs b/crates/mun_hir/src/ty/primitives.rs new file mode 100644 index 000000000..ed6266257 --- /dev/null +++ b/crates/mun_hir/src/ty/primitives.rs @@ -0,0 +1,176 @@ +use crate::buildin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness}; +use std::fmt::{self}; + +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct IntTy { + pub signedness: Signedness, + pub bitness: IntBitness, +} + +impl fmt::Debug for IntTy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Display for IntTy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.ty_to_string()) + } +} + +impl IntTy { + pub fn int() -> IntTy { + IntTy { + signedness: Signedness::Signed, + bitness: IntBitness::Undefined, + } + } + + pub fn isize() -> IntTy { + IntTy { + signedness: Signedness::Signed, + bitness: IntBitness::Xsize, + } + } + + pub fn i8() -> IntTy { + IntTy { + signedness: Signedness::Signed, + bitness: IntBitness::X8, + } + } + + pub fn i16() -> IntTy { + IntTy { + signedness: Signedness::Signed, + bitness: IntBitness::X16, + } + } + + pub fn i32() -> IntTy { + IntTy { + signedness: Signedness::Signed, + bitness: IntBitness::X32, + } + } + + pub fn i64() -> IntTy { + IntTy { + signedness: Signedness::Signed, + bitness: IntBitness::X64, + } + } + + pub fn usize() -> IntTy { + IntTy { + signedness: Signedness::Unsigned, + bitness: IntBitness::Xsize, + } + } + + pub fn u8() -> IntTy { + IntTy { + signedness: Signedness::Unsigned, + bitness: IntBitness::X8, + } + } + + pub fn u16() -> IntTy { + IntTy { + signedness: Signedness::Unsigned, + bitness: IntBitness::X16, + } + } + + pub fn u32() -> IntTy { + IntTy { + signedness: Signedness::Unsigned, + bitness: IntBitness::X32, + } + } + + pub fn u64() -> IntTy { + IntTy { + signedness: Signedness::Unsigned, + bitness: IntBitness::X64, + } + } + + pub fn ty_to_string(self) -> &'static str { + match (self.signedness, self.bitness) { + (Signedness::Signed, IntBitness::Undefined) => "int", + (Signedness::Signed, IntBitness::Xsize) => "isize", + (Signedness::Signed, IntBitness::X8) => "i8", + (Signedness::Signed, IntBitness::X16) => "i16", + (Signedness::Signed, IntBitness::X32) => "i32", + (Signedness::Signed, IntBitness::X64) => "i64", + (Signedness::Unsigned, IntBitness::Undefined) => "uint", + (Signedness::Unsigned, IntBitness::Xsize) => "usize", + (Signedness::Unsigned, IntBitness::X8) => "u8", + (Signedness::Unsigned, IntBitness::X16) => "u16", + (Signedness::Unsigned, IntBitness::X32) => "u32", + (Signedness::Unsigned, IntBitness::X64) => "u64", + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct FloatTy { + pub bitness: FloatBitness, +} + +impl fmt::Debug for FloatTy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Display for FloatTy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.ty_to_string()) + } +} + +impl FloatTy { + pub fn float() -> FloatTy { + FloatTy { + bitness: FloatBitness::Undefined, + } + } + + pub fn f32() -> FloatTy { + FloatTy { + bitness: FloatBitness::X32, + } + } + + pub fn f64() -> FloatTy { + FloatTy { + bitness: FloatBitness::X64, + } + } + + pub fn ty_to_string(self) -> &'static str { + match self.bitness { + FloatBitness::X32 => "f32", + FloatBitness::X64 => "f64", + FloatBitness::Undefined => "float", + } + } +} + +impl From for IntTy { + fn from(t: BuiltinInt) -> Self { + IntTy { + signedness: t.signedness, + bitness: t.bitness, + } + } +} + +impl From for FloatTy { + fn from(t: BuiltinFloat) -> Self { + FloatTy { bitness: t.bitness } + } +} From 631b2c855382b3b184f0dbcebb641d5c49f359aa Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Fri, 6 Mar 2020 15:37:01 +0100 Subject: [PATCH 2/3] feat: added tests to validate primitive types --- .../src/snapshots/test__primitive_types.snap | 19 ++++++++++++++ crates/mun_codegen/src/test.rs | 10 +++++++ crates/mun_hir/src/buildin_type.rs | 26 +++++++++---------- .../src/ty/snapshots/tests__primitives.snap | 25 ++++++++++++++++++ crates/mun_hir/src/ty/tests.rs | 11 ++++++++ 5 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 crates/mun_codegen/src/snapshots/test__primitive_types.snap create mode 100644 crates/mun_hir/src/ty/snapshots/tests__primitives.snap diff --git a/crates/mun_codegen/src/snapshots/test__primitive_types.snap b/crates/mun_codegen/src/snapshots/test__primitive_types.snap new file mode 100644 index 000000000..30073b80e --- /dev/null +++ b/crates/mun_codegen/src/snapshots/test__primitive_types.snap @@ -0,0 +1,19 @@ +--- +source: crates/mun_codegen/src/test.rs +expression: "fn add(a: u8, b: u8): u8 { a+b }\n fn less(a: u8, b: u8): bool { a Option { diff --git a/crates/mun_hir/src/ty/snapshots/tests__primitives.snap b/crates/mun_hir/src/ty/snapshots/tests__primitives.snap new file mode 100644 index 000000000..24d54fd2e --- /dev/null +++ b/crates/mun_hir/src/ty/snapshots/tests__primitives.snap @@ -0,0 +1,25 @@ +--- +source: crates/mun_hir/src/ty/tests.rs +expression: "fn unsigned_primitives(a: u8, b: u16, c: u32, d: u64, e: usize, f: uint) : u8 { a }\nfn signed_primitives(a: i8, b: i16, c: i32, d: i64, e: isize, f: int) : i8 { a }\nfn float_primitives(a: f32, b: f64, c: float) : f32 { a }" +--- +[23; 24) 'a': u8 +[30; 31) 'b': u16 +[38; 39) 'c': u32 +[46; 47) 'd': u64 +[54; 55) 'e': usize +[64; 65) 'f': uint +[78; 83) '{ a }': u8 +[80; 81) 'a': u8 +[105; 106) 'a': i8 +[112; 113) 'b': i16 +[120; 121) 'c': i32 +[128; 129) 'd': i64 +[136; 137) 'e': isize +[146; 147) 'f': int +[159; 164) '{ a }': i8 +[161; 162) 'a': i8 +[185; 186) 'a': f32 +[193; 194) 'b': f64 +[201; 202) 'c': float +[217; 222) '{ a }': f32 +[219; 220) 'a': f32 diff --git a/crates/mun_hir/src/ty/tests.rs b/crates/mun_hir/src/ty/tests.rs index 32e19c149..933167668 100644 --- a/crates/mun_hir/src/ty/tests.rs +++ b/crates/mun_hir/src/ty/tests.rs @@ -250,6 +250,17 @@ fn struct_field_index() { ) } +#[test] +fn primitives() { + infer_snapshot( + r#" + fn unsigned_primitives(a: u8, b: u16, c: u32, d: u64, e: usize, f: uint) : u8 { a } + fn signed_primitives(a: i8, b: i16, c: i32, d: i64, e: isize, f: int) : i8 { a } + fn float_primitives(a: f32, b: f64, c: float) : f32 { a } + "#, + ) +} + fn infer_snapshot(text: &str) { let text = text.trim().replace("\n ", "\n"); insta::assert_snapshot!(insta::_macro_support::AutoName, infer(&text), &text); From c7ed4ff1ddf66acb65ae7ea948b0de24541e7a0a Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Fri, 6 Mar 2020 16:50:17 +0100 Subject: [PATCH 3/3] misc: renamed buildin to builtin --- crates/mun_hir/src/{buildin_type.rs => builtin_type.rs} | 0 crates/mun_hir/src/code_model.rs | 2 +- crates/mun_hir/src/lib.rs | 4 ++-- crates/mun_hir/src/name_resolution.rs | 2 +- crates/mun_hir/src/ty/lower.rs | 2 +- crates/mun_hir/src/ty/primitives.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename crates/mun_hir/src/{buildin_type.rs => builtin_type.rs} (100%) diff --git a/crates/mun_hir/src/buildin_type.rs b/crates/mun_hir/src/builtin_type.rs similarity index 100% rename from crates/mun_hir/src/buildin_type.rs rename to crates/mun_hir/src/builtin_type.rs diff --git a/crates/mun_hir/src/code_model.rs b/crates/mun_hir/src/code_model.rs index b380117c0..8320a60a3 100644 --- a/crates/mun_hir/src/code_model.rs +++ b/crates/mun_hir/src/code_model.rs @@ -2,7 +2,7 @@ pub(crate) mod src; use self::src::HasSource; use crate::adt::{StructData, StructFieldId}; -use crate::buildin_type::BuiltinType; +use crate::builtin_type::BuiltinType; use crate::code_model::diagnostics::ModuleDefinitionDiagnostic; use crate::diagnostics::DiagnosticSink; use crate::expr::validator::ExprValidator; diff --git a/crates/mun_hir/src/lib.rs b/crates/mun_hir/src/lib.rs index 19e875e4a..001ef2826 100644 --- a/crates/mun_hir/src/lib.rs +++ b/crates/mun_hir/src/lib.rs @@ -10,7 +10,7 @@ mod macros; #[macro_use] mod arena; mod adt; -mod buildin_type; +mod builtin_type; mod code_model; mod db; pub mod diagnostics; @@ -41,7 +41,7 @@ pub use relative_path::{RelativePath, RelativePathBuf}; pub use crate::{ arena::{ArenaId, RawId}, - buildin_type::{FloatBitness, IntBitness, Signedness}, + builtin_type::{FloatBitness, IntBitness, Signedness}, db::{ DefDatabase, DefDatabaseStorage, HirDatabase, HirDatabaseStorage, SourceDatabase, SourceDatabaseStorage, diff --git a/crates/mun_hir/src/name_resolution.rs b/crates/mun_hir/src/name_resolution.rs index 744532861..15a1a4aa7 100644 --- a/crates/mun_hir/src/name_resolution.rs +++ b/crates/mun_hir/src/name_resolution.rs @@ -1,7 +1,7 @@ mod per_ns; pub use self::per_ns::{Namespace, PerNs}; -use crate::{buildin_type::BuiltinType, FileId, HirDatabase, ModuleDef, Name}; +use crate::{builtin_type::BuiltinType, FileId, HirDatabase, ModuleDef, Name}; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; use std::sync::Arc; diff --git a/crates/mun_hir/src/ty/lower.rs b/crates/mun_hir/src/ty/lower.rs index fee87c242..48fbf0960 100644 --- a/crates/mun_hir/src/ty/lower.rs +++ b/crates/mun_hir/src/ty/lower.rs @@ -1,7 +1,7 @@ pub(crate) use self::diagnostics::LowerDiagnostic; use crate::adt::StructKind; use crate::arena::map::ArenaMap; -use crate::buildin_type::BuiltinType; +use crate::builtin_type::BuiltinType; use crate::diagnostics::DiagnosticSink; use crate::name_resolution::Namespace; use crate::resolve::{Resolution, Resolver}; diff --git a/crates/mun_hir/src/ty/primitives.rs b/crates/mun_hir/src/ty/primitives.rs index ed6266257..afdad558f 100644 --- a/crates/mun_hir/src/ty/primitives.rs +++ b/crates/mun_hir/src/ty/primitives.rs @@ -1,4 +1,4 @@ -use crate::buildin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness}; +use crate::builtin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness}; use std::fmt::{self}; #[derive(Copy, Clone, Eq, PartialEq, Hash)]