From 5b46e973d48ab1bbe12242c51a0ac1f2be30acea Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 23:04:35 +0300 Subject: [PATCH] Add types to number-literals --- README.md | 5 +- reid/src/ast/mod.rs | 22 ++++++ reid/src/ast/parse.rs | 123 ++++++++++++++++++++++++---------- reid/src/ast/process.rs | 21 ++++++ reid/src/mir/typeinference.rs | 10 ++- 5 files changed, 144 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 48ce1b8..fa85e49 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,12 @@ Currently missing big features (TODOs) are: - ~~Built-in Int/Float division and modulo~~ (DONE) - ~~Loops~~ (DONE) - ~~Intrinsic functions~~ (DONE) +- ~~Ability to specify types in literals~~ (DONE) - Debug Information (PARTIALLY DONE) -- Ability to specify types in literals and variable definitions - Not-Unary +- Importing types from other modules +- Importable binops? +- Ability to specify types in variable definitions Big features that I want later but are not necessary: - Associated functions diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs index 19779b1..524baa0 100644 --- a/reid/src/ast/mod.rs +++ b/reid/src/ast/mod.rs @@ -45,6 +45,28 @@ pub enum Literal { Bool(bool), String(String), Char(char), + Specific(SpecificLiteral), +} + +#[derive(Debug, Clone)] +pub enum SpecificLiteral { + I8(i8), + I16(i16), + I32(i32), + I64(i64), + I128(i128), + U8(u8), + U16(u16), + U32(u32), + U64(u64), + U128(u128), + F16(f32), + F32(f32), + F32B(f32), + F64(f64), + F80(f64), + F128(f64), + F128PPC(f64), } #[derive(Debug, Clone)] diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index 32da973..2720c28 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -96,6 +96,46 @@ impl Parse for UnaryOperator { } } +fn specific_int_lit(value: u128, stream: &mut TokenStream) -> Result { + use ExpressionKind as Kind; + + let specific_lit = if let Ok(ty) = stream.parse::() { + Some(match ty.0 { + TypeKind::I8 => SpecificLiteral::I8(value as i8), + TypeKind::I16 => SpecificLiteral::I16(value as i16), + TypeKind::I32 => SpecificLiteral::I32(value as i32), + TypeKind::I64 => SpecificLiteral::I64(value as i64), + TypeKind::I128 => SpecificLiteral::I128(value as i128), + TypeKind::U8 => SpecificLiteral::U8(value as u8), + TypeKind::U16 => SpecificLiteral::U16(value as u16), + TypeKind::U32 => SpecificLiteral::U32(value as u32), + TypeKind::U64 => SpecificLiteral::U64(value as u64), + TypeKind::U128 => SpecificLiteral::U128(value as u128), + TypeKind::F16 => SpecificLiteral::F16(value as f32), + TypeKind::F32 => SpecificLiteral::F32(value as f32), + TypeKind::F32B => SpecificLiteral::F32B(value as f32), + TypeKind::F64 => SpecificLiteral::F64(value as f64), + TypeKind::F128 => SpecificLiteral::F128(value as f64), + TypeKind::F80 => SpecificLiteral::F80(value as f64), + TypeKind::F128PPC => SpecificLiteral::F128PPC(value as f64), + _ => return Err(stream.expected_err("integer-compatible type")?), + }) + } else { + None + }; + Ok(if let Some(lit) = specific_lit { + Expression( + Kind::Literal(Literal::Specific(lit)), + stream.get_range().unwrap(), + ) + } else { + Expression( + Kind::Literal(Literal::Integer(value)), + stream.get_range().unwrap(), + ) + }) +} + #[derive(Debug)] pub struct PrimaryExpression(Expression); @@ -154,32 +194,26 @@ impl Parse for PrimaryExpression { } } Token::BinaryValue(v) => { - stream.next(); // Consume octal - Expression( - Kind::Literal(Literal::Integer( - u128::from_str_radix(&v, 2).expect("Binary is not parseable as u128!"), - )), - stream.get_range().unwrap(), - ) + stream.next(); // Consume binary + specific_int_lit( + u128::from_str_radix(&v, 2).expect("Binary is not parseable as u128!"), + &mut stream, + )? } Token::OctalValue(v) => { stream.next(); // Consume octal - Expression( - Kind::Literal(Literal::Integer( - u128::from_str_radix(&v, 8).expect("Octal is not parseable as u128!"), - )), - stream.get_range().unwrap(), - ) + specific_int_lit( + u128::from_str_radix(&v, 8).expect("Octal is not parseable as u128!"), + &mut stream, + )? } Token::HexadecimalValue(v) => { stream.next(); // Consume hexadecimal - Expression( - Kind::Literal(Literal::Integer( - u128::from_str_radix(&v, 16) - .expect("Hexadecimal is not parseable as u128!"), - )), - stream.get_range().unwrap(), - ) + specific_int_lit( + u128::from_str_radix(&v, 16) + .expect("Hexadecimal is not parseable as u128!"), + &mut stream, + )? } Token::DecimalValue(v) => { stream.next(); // Consume decimal @@ -189,22 +223,41 @@ impl Parse for PrimaryExpression { stream.next(); // Consume dot stream.next(); // Consume fractional - Expression( - Kind::Literal(Literal::Decimal( - format!("{}.{}", v, fractional) - .parse() - .expect("Decimal is not parseable as f64!"), - )), - stream.get_range().unwrap(), - ) + let value = format!("{}.{}", v, fractional) + .parse() + .expect("Decimal is not parseable as f64!"); + + let specific_lit = if let Ok(ty) = stream.parse::() { + Some(match ty.0 { + TypeKind::F16 => SpecificLiteral::F16(value as f32), + TypeKind::F32B => SpecificLiteral::F32B(value as f32), + TypeKind::F32 => SpecificLiteral::F32(value as f32), + TypeKind::F64 => SpecificLiteral::F64(value), + TypeKind::F80 => SpecificLiteral::F80(value), + TypeKind::F128 => SpecificLiteral::F128(value), + TypeKind::F128PPC => SpecificLiteral::F128PPC(value), + _ => return Err(stream.expected_err("float-compatible type")?), + }) + } else { + None + }; + if let Some(lit) = specific_lit { + Expression( + Kind::Literal(Literal::Specific(lit)), + stream.get_range().unwrap(), + ) + } else { + Expression( + Kind::Literal(Literal::Decimal(value)), + stream.get_range().unwrap(), + ) + } } else { - Expression( - Kind::Literal(Literal::Integer( - u128::from_str_radix(&v, 10) - .expect("Integer is not parseable as u128!"), - )), - stream.get_range().unwrap(), - ) + specific_int_lit( + u128::from_str_radix(&v, 10) + .expect("Integer is not parseable as u128!"), + &mut stream, + )? } } Token::StringLit(v) => { diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 6abfa4f..c27a6e5 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -8,6 +8,8 @@ use crate::{ }, }; +use super::TypeKind; + impl mir::Context { pub fn from(modules: Vec, base: PathBuf) -> mir::Context { let mut map = ModuleMap::new(); @@ -417,6 +419,25 @@ impl ast::Literal { ast::Literal::String(val) => mir::Literal::String(val.clone()), ast::Literal::Decimal(v) => mir::Literal::Vague(mir::VagueLiteral::Decimal(*v)), ast::Literal::Char(inner) => mir::Literal::Char(*inner), + ast::Literal::Specific(specific_literal) => match specific_literal { + ast::SpecificLiteral::I8(val) => mir::Literal::I8(*val), + ast::SpecificLiteral::I16(val) => mir::Literal::I16(*val), + ast::SpecificLiteral::I32(val) => mir::Literal::I32(*val), + ast::SpecificLiteral::I64(val) => mir::Literal::I64(*val), + ast::SpecificLiteral::I128(val) => mir::Literal::I128(*val), + ast::SpecificLiteral::U8(val) => mir::Literal::U8(*val), + ast::SpecificLiteral::U16(val) => mir::Literal::U16(*val), + ast::SpecificLiteral::U32(val) => mir::Literal::U32(*val), + ast::SpecificLiteral::U64(val) => mir::Literal::U64(*val), + ast::SpecificLiteral::U128(val) => mir::Literal::U128(*val), + ast::SpecificLiteral::F16(val) => mir::Literal::F16(*val), + ast::SpecificLiteral::F32(val) => mir::Literal::F32(*val), + ast::SpecificLiteral::F32B(val) => mir::Literal::F32B(*val), + ast::SpecificLiteral::F64(val) => mir::Literal::F64(*val), + ast::SpecificLiteral::F80(val) => mir::Literal::F80(*val), + ast::SpecificLiteral::F128(val) => mir::Literal::F128(*val), + ast::SpecificLiteral::F128PPC(val) => mir::Literal::F128PPC(*val), + }, } } } diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index aff4e19..d67bf98 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -326,7 +326,15 @@ impl Expression { { Ok(binop) } else { - let typeref = lhs_ref.narrow(&rhs_ref).unwrap(); + let typeref = state.or_else( + lhs_ref.narrow(&rhs_ref).ok_or(ErrorKind::InvalidBinop( + *op, + lhs_ref.resolve_deep().unwrap(), + rhs_ref.resolve_deep().unwrap(), + )), + type_refs.from_type(&Vague(Unknown)).unwrap(), + self.1, + ); Ok(type_refs .from_type( &typeref