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

View File

@ -11,6 +11,8 @@ fn main() -> u32 {
second: 3,
};
value.second = 17;
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 escape_next = false;
while cursor.first().is_some()
&& (cursor.first() != Some(*character) || escape_next)
{
while cursor.first().is_some() && (cursor.first() != Some(*character) || escape_next) {
if cursor.first() == Some('\\') && !escape_next {
cursor.next(); // Consume backslash and always add next character
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;
if let Some(second) = cursor.second() {
if cursor.first() == Some('x')
&& HEXADECIMAL_NUMERICS
.contains(&second.to_lowercase().next().unwrap_or('.'))
&& HEXADECIMAL_NUMERICS.contains(&second.to_lowercase().next().unwrap_or('.'))
{
cursor.next();
value = NumberType::Hexadecimal(String::new());
@ -464,9 +461,7 @@ impl AddAssign<char> for NumberType {
fn add_assign(&mut self, rhs: char) {
*self = match self {
NumberType::Decimal(val) => NumberType::Decimal(val.to_owned() + &rhs.to_string()),
NumberType::Hexadecimal(val) => {
NumberType::Hexadecimal(val.to_owned() + &rhs.to_string())
}
NumberType::Hexadecimal(val) => NumberType::Hexadecimal(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()),
};

View File

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

View File

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

View File

@ -366,6 +366,15 @@ impl ast::Expression {
Box::new(expr.process(module_id)),
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(
Box::new(expression.process(module_id)),