Add Not-Unary

This commit is contained in:
Sofia 2025-07-25 23:40:10 +03:00
parent bf878c02a7
commit 12e2851a8b
6 changed files with 45 additions and 99 deletions

View File

@ -47,13 +47,13 @@ Currently missing big features (TODOs) are:
- ~~Intrinsic functions~~ (DONE) - ~~Intrinsic functions~~ (DONE)
- ~~Ability to specify types in literals and variable definitions~~ (DONE) - ~~Ability to specify types in literals and variable definitions~~ (DONE)
- ~~Debug Information~~ (DONE) - ~~Debug Information~~ (DONE)
- Fix struct initialization (wrong order and missing fields allowed now) - ~~Fix struct initialization (wrong order and missing fields allowed now)~~
- Not-Unary - ~~Not-Unary~~
- Importing types from other modules - Importing types from other modules
- Importable binops? - Importable binops?
- Associated functions (for e.g. sizeof)
Big features that I want later but are not necessary: Big features that I want later but are not necessary:
- Associated functions (for e.g. sizeof)
- ~~User-defined binary operations~~ (DONE) - ~~User-defined binary operations~~ (DONE)
- ~~Asymmetric binary operations (e.g. string + u32)~~ (DONE) - ~~Asymmetric binary operations (e.g. string + u32)~~ (DONE)
- Error handling - Error handling

View File

@ -11,6 +11,8 @@ fn main() -> u32 {
second: 3, second: 3,
}; };
value.second = 17;
return value.second; return value.second;
} }

View File

@ -298,9 +298,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
'\"' | '\'' => { '\"' | '\'' => {
let mut value = String::new(); let mut value = String::new();
let mut escape_next = false; let mut escape_next = false;
while cursor.first().is_some() while cursor.first().is_some() && (cursor.first() != Some(*character) || escape_next) {
&& (cursor.first() != Some(*character) || escape_next)
{
if cursor.first() == Some('\\') && !escape_next { if cursor.first() == Some('\\') && !escape_next {
cursor.next(); // Consume backslash and always add next character cursor.next(); // Consume backslash and always add next character
escape_next = true; escape_next = true;
@ -366,8 +364,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
let mut numerics = DECIMAL_NUMERICS; let mut numerics = DECIMAL_NUMERICS;
if let Some(second) = cursor.second() { if let Some(second) = cursor.second() {
if cursor.first() == Some('x') if cursor.first() == Some('x')
&& HEXADECIMAL_NUMERICS && HEXADECIMAL_NUMERICS.contains(&second.to_lowercase().next().unwrap_or('.'))
.contains(&second.to_lowercase().next().unwrap_or('.'))
{ {
cursor.next(); cursor.next();
value = NumberType::Hexadecimal(String::new()); value = NumberType::Hexadecimal(String::new());
@ -464,9 +461,7 @@ impl AddAssign<char> for NumberType {
fn add_assign(&mut self, rhs: char) { fn add_assign(&mut self, rhs: char) {
*self = match self { *self = match self {
NumberType::Decimal(val) => NumberType::Decimal(val.to_owned() + &rhs.to_string()), NumberType::Decimal(val) => NumberType::Decimal(val.to_owned() + &rhs.to_string()),
NumberType::Hexadecimal(val) => { NumberType::Hexadecimal(val) => NumberType::Hexadecimal(val.to_owned() + &rhs.to_string()),
NumberType::Hexadecimal(val.to_owned() + &rhs.to_string())
}
NumberType::Octal(val) => NumberType::Octal(val.to_owned() + &rhs.to_string()), NumberType::Octal(val) => NumberType::Octal(val.to_owned() + &rhs.to_string()),
NumberType::Binary(val) => NumberType::Binary(val.to_owned() + &rhs.to_string()), NumberType::Binary(val) => NumberType::Binary(val.to_owned() + &rhs.to_string()),
}; };

View File

@ -101,6 +101,7 @@ pub enum ExpressionKind {
pub enum UnaryOperator { pub enum UnaryOperator {
Plus, Plus,
Minus, Minus,
Not,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]

View File

@ -87,6 +87,7 @@ impl Parse for UnaryOperator {
match token { match token {
Token::Plus => Ok(UnaryOperator::Plus), Token::Plus => Ok(UnaryOperator::Plus),
Token::Minus => Ok(UnaryOperator::Minus), Token::Minus => Ok(UnaryOperator::Minus),
Token::Exclamation => Ok(UnaryOperator::Not),
_ => Err(stream.expected_err("unary operator")?), _ => Err(stream.expected_err("unary operator")?),
} }
} else { } else {
@ -174,20 +175,11 @@ impl Parse for PrimaryExpression {
use ExpressionKind as Kind; use ExpressionKind as Kind;
let mut expr = if let Ok(exp) = stream.parse() { let mut expr = if let Ok(exp) = stream.parse() {
Expression( Expression(Kind::FunctionCall(Box::new(exp)), stream.get_range().unwrap())
Kind::FunctionCall(Box::new(exp)),
stream.get_range().unwrap(),
)
} else if let Ok(block) = stream.parse() { } else if let Ok(block) = stream.parse() {
Expression( Expression(Kind::BlockExpr(Box::new(block)), stream.get_range().unwrap())
Kind::BlockExpr(Box::new(block)),
stream.get_range().unwrap(),
)
} else if let Some(Token::If) = stream.peek() { } else if let Some(Token::If) = stream.peek() {
Expression( Expression(Kind::IfExpr(Box::new(stream.parse()?)), stream.get_range().unwrap())
Kind::IfExpr(Box::new(stream.parse()?)),
stream.get_range().unwrap(),
)
} else if let (Some(Token::Et), Some(Token::MutKeyword)) = (stream.peek(), stream.peek2()) { } else if let (Some(Token::Et), Some(Token::MutKeyword)) = (stream.peek(), stream.peek2()) {
stream.next(); // Consume Et stream.next(); // Consume Et
stream.next(); // Consume mut stream.next(); // Consume mut
@ -195,15 +187,11 @@ impl Parse for PrimaryExpression {
return Err(stream.expected_err("identifier")?); return Err(stream.expected_err("identifier")?);
}; };
Expression(Kind::Borrow(name, true), stream.get_range().unwrap()) Expression(Kind::Borrow(name, true), stream.get_range().unwrap())
} else if let (Some(Token::Et), Some(Token::Identifier(name))) = } else if let (Some(Token::Et), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) {
(stream.peek(), stream.peek2())
{
stream.next(); // Consume Et stream.next(); // Consume Et
stream.next(); // Consume identifier stream.next(); // Consume identifier
Expression(Kind::Borrow(name, false), stream.get_range().unwrap()) Expression(Kind::Borrow(name, false), stream.get_range().unwrap())
} else if let (Some(Token::Star), Some(Token::Identifier(name))) = } else if let (Some(Token::Star), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) {
(stream.peek(), stream.peek2())
{
stream.next(); // Consume Et stream.next(); // Consume Et
stream.next(); // Consume identifier stream.next(); // Consume identifier
Expression(Kind::Deref(name), stream.get_range().unwrap()) Expression(Kind::Deref(name), stream.get_range().unwrap())
@ -225,49 +213,35 @@ impl Parse for PrimaryExpression {
} }
Token::BinaryValue(v) => { Token::BinaryValue(v) => {
stream.next(); // Consume binary stream.next(); // Consume binary
let value = let value = u128::from_str_radix(&v, 2).expect("Value is not parseable as u128!");
u128::from_str_radix(&v, 2).expect("Value is not parseable as u128!");
if let Ok(expr) = specific_int_lit(value, &mut stream) { if let Ok(expr) = specific_int_lit(value, &mut stream) {
expr expr
} else { } else {
Expression( Expression(Kind::Literal(Literal::Integer(value)), stream.get_range().unwrap())
Kind::Literal(Literal::Integer(value)),
stream.get_range().unwrap(),
)
} }
} }
Token::OctalValue(v) => { Token::OctalValue(v) => {
stream.next(); // Consume octal stream.next(); // Consume octal
let value = let value = u128::from_str_radix(&v, 8).expect("Value is not parseable as u128!");
u128::from_str_radix(&v, 8).expect("Value is not parseable as u128!");
if let Ok(expr) = specific_int_lit(value, &mut stream) { if let Ok(expr) = specific_int_lit(value, &mut stream) {
expr expr
} else { } else {
Expression( Expression(Kind::Literal(Literal::Integer(value)), stream.get_range().unwrap())
Kind::Literal(Literal::Integer(value)),
stream.get_range().unwrap(),
)
} }
} }
Token::HexadecimalValue(v) => { Token::HexadecimalValue(v) => {
stream.next(); // Consume hexadecimal stream.next(); // Consume hexadecimal
let value = let value = u128::from_str_radix(&v, 16).expect("Value is not parseable as u128!");
u128::from_str_radix(&v, 16).expect("Value is not parseable as u128!");
if let Ok(expr) = specific_int_lit(value, &mut stream) { if let Ok(expr) = specific_int_lit(value, &mut stream) {
expr expr
} else { } else {
Expression( Expression(Kind::Literal(Literal::Integer(value)), stream.get_range().unwrap())
Kind::Literal(Literal::Integer(value)),
stream.get_range().unwrap(),
)
} }
} }
Token::DecimalValue(v) => { Token::DecimalValue(v) => {
stream.next(); // Consume decimal stream.next(); // Consume decimal
if let (Some(Token::Dot), Some(Token::DecimalValue(fractional))) = if let (Some(Token::Dot), Some(Token::DecimalValue(fractional))) = (stream.peek(), stream.peek2()) {
(stream.peek(), stream.peek2())
{
stream.next(); // Consume dot stream.next(); // Consume dot
stream.next(); // Consume fractional stream.next(); // Consume fractional
@ -278,30 +252,20 @@ impl Parse for PrimaryExpression {
if let Ok(expr) = specific_float_lit(value, &mut stream) { if let Ok(expr) = specific_float_lit(value, &mut stream) {
expr expr
} else { } else {
Expression( Expression(Kind::Literal(Literal::Decimal(value)), stream.get_range().unwrap())
Kind::Literal(Literal::Decimal(value)),
stream.get_range().unwrap(),
)
} }
} else { } else {
let value = let value = u128::from_str_radix(&v, 10).expect("Value is not parseable as u128!");
u128::from_str_radix(&v, 10).expect("Value is not parseable as u128!");
if let Ok(expr) = specific_int_lit(value, &mut stream) { if let Ok(expr) = specific_int_lit(value, &mut stream) {
expr expr
} else { } else {
Expression( Expression(Kind::Literal(Literal::Integer(value)), stream.get_range().unwrap())
Kind::Literal(Literal::Integer(value)),
stream.get_range().unwrap(),
)
} }
} }
} }
Token::StringLit(v) => { Token::StringLit(v) => {
stream.next(); // Consume stream.next(); // Consume
Expression( Expression(Kind::Literal(Literal::String(v.clone())), stream.get_range().unwrap())
Kind::Literal(Literal::String(v.clone())),
stream.get_range().unwrap(),
)
} }
Token::CharLit(v) => { Token::CharLit(v) => {
stream.next(); // Consume stream.next(); // Consume
@ -319,17 +283,11 @@ impl Parse for PrimaryExpression {
} }
Token::True => { Token::True => {
stream.next(); // Consume stream.next(); // Consume
Expression( Expression(Kind::Literal(Literal::Bool(true)), stream.get_range().unwrap())
Kind::Literal(Literal::Bool(true)),
stream.get_range().unwrap(),
)
} }
Token::False => { Token::False => {
stream.next(); // Consume stream.next(); // Consume
Expression( Expression(Kind::Literal(Literal::Bool(false)), stream.get_range().unwrap())
Kind::Literal(Literal::Bool(false)),
stream.get_range().unwrap(),
)
} }
Token::ParenOpen => { Token::ParenOpen => {
stream.next(); // Consume stream.next(); // Consume
@ -343,16 +301,14 @@ impl Parse for PrimaryExpression {
if let Some(Token::Semi) = stream.peek() { if let Some(Token::Semi) = stream.peek() {
stream.next(); // Consume colon stream.next(); // Consume colon
let Some(Token::DecimalValue(val)) = stream.next() else { let Some(Token::DecimalValue(val)) = stream.next() else {
return Err(stream return Err(stream.expecting_err("decimal value describing array length")?);
.expecting_err("decimal value describing array length")?);
}; };
stream.expect(Token::BracketClose)?; stream.expect(Token::BracketClose)?;
Expression( Expression(
Kind::ArrayShort( Kind::ArrayShort(
Box::new(exp), Box::new(exp),
u64::from_str_radix(&val, 10).expect( u64::from_str_radix(&val, 10)
"Unable to parse array length to 64-bit decimal value", .expect("Unable to parse array length to 64-bit decimal value"),
),
), ),
stream.get_range().unwrap(), stream.get_range().unwrap(),
) )
@ -514,11 +470,7 @@ impl Parse for FunctionCallExpression {
stream.expect(Token::ParenClose)?; stream.expect(Token::ParenClose)?;
Ok(FunctionCallExpression( Ok(FunctionCallExpression(name, args, stream.get_range().unwrap()))
name,
args,
stream.get_range().unwrap(),
))
} else { } else {
Err(stream.expected_err("identifier")?) Err(stream.expected_err("identifier")?)
} }
@ -535,12 +487,7 @@ impl Parse for IfExpression {
} else { } else {
None None
}; };
Ok(IfExpression( Ok(IfExpression(cond, then_b, else_b, stream.get_range().unwrap()))
cond,
then_b,
else_b,
stream.get_range().unwrap(),
))
} }
} }
@ -700,11 +647,7 @@ impl Parse for Block {
statements.push(statement); statements.push(statement);
} }
stream.expect(Token::BraceClose)?; stream.expect(Token::BraceClose)?;
Ok(Block( Ok(Block(statements, return_stmt, stream.get_range_prev().unwrap()))
statements,
return_stmt,
stream.get_range_prev().unwrap(),
))
} }
} }
@ -809,9 +752,7 @@ impl Parse for BlockLevelStatement {
use BlockLevelStatement as Stmt; use BlockLevelStatement as Stmt;
Ok(match stream.peek() { Ok(match stream.peek() {
Some(Token::LetKeyword) => Stmt::Let(stream.parse()?), Some(Token::LetKeyword) => Stmt::Let(stream.parse()?),
Some(Token::ImportKeyword) => Stmt::Import { Some(Token::ImportKeyword) => Stmt::Import { _i: stream.parse()? },
_i: stream.parse()?,
},
Some(Token::ReturnKeyword) => { Some(Token::ReturnKeyword) => {
stream.next(); stream.next();
let exp = stream.parse().ok(); let exp = stream.parse().ok();
@ -924,9 +865,7 @@ impl Parse for TopLevelStatement {
stream.expect(Token::Semi)?; stream.expect(Token::Semi)?;
extern_fn extern_fn
} }
Some(Token::FnKeyword) | Some(Token::PubKeyword) => { Some(Token::FnKeyword) | Some(Token::PubKeyword) => Stmt::FunctionDefinition(stream.parse()?),
Stmt::FunctionDefinition(stream.parse()?)
}
Some(Token::Struct) => { Some(Token::Struct) => {
let StructDefinition(name, fields, range) = stream.parse::<StructDefinition>()?; let StructDefinition(name, fields, range) = stream.parse::<StructDefinition>()?;
Stmt::TypeDefinition(TypeDefinition { Stmt::TypeDefinition(TypeDefinition {

View File

@ -366,6 +366,15 @@ impl ast::Expression {
Box::new(expr.process(module_id)), Box::new(expr.process(module_id)),
mir::TypeKind::Vague(mir::VagueType::Unknown), mir::TypeKind::Vague(mir::VagueType::Unknown),
), ),
ast::UnaryOperator::Not => mir::ExprKind::BinOp(
mir::BinaryOperator::Cmp(mir::CmpOperator::EQ),
Box::new(expr.process(module_id)),
Box::new(mir::Expression(
mir::ExprKind::Literal(mir::Literal::Bool(false)),
expr.1.as_meta(module_id),
)),
mir::TypeKind::Bool,
),
}, },
ast::ExpressionKind::CastTo(expression, ty) => mir::ExprKind::CastTo( ast::ExpressionKind::CastTo(expression, ty) => mir::ExprKind::CastTo(
Box::new(expression.process(module_id)), Box::new(expression.process(module_id)),