updated compiler with support for more operators.
(only the unary operators from this are implemented for now)
This commit is contained in:
@@ -510,7 +510,7 @@ impl CodeGenerator {
|
|||||||
code.push("\tpop zero".to_string());
|
code.push("\tpop zero".to_string());
|
||||||
}
|
}
|
||||||
// Comparison operators - return 1 (true) or 0 (false)
|
// Comparison operators - return 1 (true) or 0 (false)
|
||||||
BinaryOperator::Eq => {
|
BinaryOperator::Equal => {
|
||||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||||
code.push(format!("\tlli 1, {}", result_reg));
|
code.push(format!("\tlli 1, {}", result_reg));
|
||||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||||
@@ -518,7 +518,7 @@ impl CodeGenerator {
|
|||||||
code.push(format!("\tlli 0, {}", result_reg));
|
code.push(format!("\tlli 0, {}", result_reg));
|
||||||
code.push(format!("{}:", end_label));
|
code.push(format!("{}:", end_label));
|
||||||
}
|
}
|
||||||
BinaryOperator::Ne => {
|
BinaryOperator::NotEqual => {
|
||||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||||
code.push(format!("\tlli 1, {}", result_reg));
|
code.push(format!("\tlli 1, {}", result_reg));
|
||||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||||
@@ -526,7 +526,7 @@ impl CodeGenerator {
|
|||||||
code.push(format!("\tlli 0, {}", result_reg));
|
code.push(format!("\tlli 0, {}", result_reg));
|
||||||
code.push(format!("{}:", end_label));
|
code.push(format!("{}:", end_label));
|
||||||
}
|
}
|
||||||
BinaryOperator::Lt => {
|
BinaryOperator::LessThan => {
|
||||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||||
code.push(format!("\tlli 1, {}", result_reg));
|
code.push(format!("\tlli 1, {}", result_reg));
|
||||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||||
@@ -534,7 +534,7 @@ impl CodeGenerator {
|
|||||||
code.push(format!("\tlli 0, {}", result_reg));
|
code.push(format!("\tlli 0, {}", result_reg));
|
||||||
code.push(format!("{}:", end_label));
|
code.push(format!("{}:", end_label));
|
||||||
}
|
}
|
||||||
BinaryOperator::Le => {
|
BinaryOperator::LessOrEqual => {
|
||||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||||
code.push(format!("\tlli 1, {}", result_reg));
|
code.push(format!("\tlli 1, {}", result_reg));
|
||||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||||
@@ -542,7 +542,7 @@ impl CodeGenerator {
|
|||||||
code.push(format!("\tlli 0, {}", result_reg));
|
code.push(format!("\tlli 0, {}", result_reg));
|
||||||
code.push(format!("{}:", end_label));
|
code.push(format!("{}:", end_label));
|
||||||
}
|
}
|
||||||
BinaryOperator::Gt => {
|
BinaryOperator::GreaterThan => {
|
||||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||||
code.push(format!("\tlli 1, {}", result_reg));
|
code.push(format!("\tlli 1, {}", result_reg));
|
||||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||||
@@ -550,7 +550,7 @@ impl CodeGenerator {
|
|||||||
code.push(format!("\tlli 0, {}", result_reg));
|
code.push(format!("\tlli 0, {}", result_reg));
|
||||||
code.push(format!("{}:", end_label));
|
code.push(format!("{}:", end_label));
|
||||||
}
|
}
|
||||||
BinaryOperator::Ge => {
|
BinaryOperator::GreaterOrEqual => {
|
||||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||||
code.push(format!("\tlli 1, {}", result_reg));
|
code.push(format!("\tlli 1, {}", result_reg));
|
||||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||||
@@ -581,13 +581,6 @@ impl CodeGenerator {
|
|||||||
arg_regs.push(arg_reg);
|
arg_regs.push(arg_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save caller-saved registers and track which ones we saved
|
|
||||||
// old method, inefficient.
|
|
||||||
// let saved_regs = self.allocator.get_caller_saved_registers();
|
|
||||||
// for reg in &saved_regs {
|
|
||||||
// code.push(format!("\tpush {}", reg));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Save caller-saved registers and track which ones we saved
|
// Save caller-saved registers and track which ones we saved
|
||||||
let saved_regs = self.allocator.get_caller_saved_registers();
|
let saved_regs = self.allocator.get_caller_saved_registers();
|
||||||
for reg in &saved_regs {
|
for reg in &saved_regs {
|
||||||
@@ -604,9 +597,6 @@ impl CodeGenerator {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if GLOBAL_METHODS.contains_key(name.name.as_str()) {
|
|
||||||
// code.push(format!("\tcall {}",
|
|
||||||
// GLOBAL_METHODS[name.name.as_str()])); } else
|
|
||||||
if self.symbols.contains(&name.name) {
|
if self.symbols.contains(&name.name) {
|
||||||
// Call local function
|
// Call local function
|
||||||
code.push(format!("\tcall {}", name));
|
code.push(format!("\tcall {}", name));
|
||||||
@@ -644,11 +634,6 @@ impl CodeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore caller-saved registers in reverse order (LIFO)
|
|
||||||
// for reg in saved_regs.iter().rev() {
|
|
||||||
// code.push(format!("\tpop {}", reg));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Free argument registers
|
// Free argument registers
|
||||||
for reg in arg_regs {
|
for reg in arg_regs {
|
||||||
self.allocator.free_temp(reg);
|
self.allocator.free_temp(reg);
|
||||||
@@ -677,7 +662,9 @@ impl CodeGenerator {
|
|||||||
UnaryOperator::Dereference => {
|
UnaryOperator::Dereference => {
|
||||||
code.push(format!("\tldw {}, {}", operand_reg, result_reg));
|
code.push(format!("\tldw {}, {}", operand_reg, result_reg));
|
||||||
}
|
}
|
||||||
UnaryOperator::Reference => {
|
UnaryOperator::AddressOf => {
|
||||||
|
// ensure the referenced variable is on the stack and return its
|
||||||
|
// address.
|
||||||
let (offset, alloc_code) =
|
let (offset, alloc_code) =
|
||||||
self.allocator.free_register(&operand_reg)?;
|
self.allocator.free_register(&operand_reg)?;
|
||||||
code.extend(alloc_code);
|
code.extend(alloc_code);
|
||||||
@@ -687,6 +674,28 @@ impl CodeGenerator {
|
|||||||
result_reg
|
result_reg
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
UnaryOperator::SizeOf => {
|
||||||
|
if let Ok(id) = operand.type_id() {
|
||||||
|
let size = id.size();
|
||||||
|
code.push(format!("\tmov {}, {}", size, result_reg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnaryOperator::CastAs => {} /* this should be removed once the */
|
||||||
|
// semantic analyser can handle it!
|
||||||
|
UnaryOperator::Increment => {
|
||||||
|
// prefix increment
|
||||||
|
code.push(format!("\tmov {}, {}", operand_reg, result_reg));
|
||||||
|
code.push(format!("\taddi {}, {}, 1", operand_reg, operand_reg));
|
||||||
|
}
|
||||||
|
UnaryOperator::Decrement => {
|
||||||
|
// prefix decrement
|
||||||
|
code.push(format!("\tmov {}, {}", operand_reg, result_reg));
|
||||||
|
code.push(format!("\tsubi {}, {}, 1", operand_reg, operand_reg));
|
||||||
|
}
|
||||||
|
UnaryOperator::BitwiseNot => {
|
||||||
|
code.push(format!("\tnot {}, {}", operand_reg, result_reg));
|
||||||
|
}
|
||||||
|
UnaryOperator::LogicalNot => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.allocator.free_temp(operand_reg);
|
self.allocator.free_temp(operand_reg);
|
||||||
@@ -694,6 +703,8 @@ impl CodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expression::Empty => Ok((Register::Null, code)),
|
Expression::Empty => Ok((Register::Null, code)),
|
||||||
|
|
||||||
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ impl RegisterAllocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is a true temporary - safe to free
|
// This is a true temporary - safe to free
|
||||||
if reg != Register::Zero {
|
if !matches!(reg, Register::Zero | Register::Null) {
|
||||||
self.in_use.insert(reg, false);
|
self.in_use.insert(reg, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ impl RegisterAllocator {
|
|||||||
// Check if this variable is in a register
|
// Check if this variable is in a register
|
||||||
if let Some(location) = self.variable_locations.get(var).cloned() {
|
if let Some(location) = self.variable_locations.get(var).cloned() {
|
||||||
if let Some(reg) = location.register
|
if let Some(reg) = location.register
|
||||||
&& reg != Register::Zero
|
&& !matches!(reg, Register::Zero | Register::Null)
|
||||||
{
|
{
|
||||||
self.register_contents.remove(®);
|
self.register_contents.remove(®);
|
||||||
self.in_use.insert(reg, false);
|
self.in_use.insert(reg, false);
|
||||||
|
|||||||
+557
-277
File diff suppressed because it is too large
Load Diff
@@ -353,12 +353,12 @@ impl Parser {
|
|||||||
let mut expr = self.parse_additive()?;
|
let mut expr = self.parse_additive()?;
|
||||||
|
|
||||||
while let Some(op) = match self.peek_next()? {
|
while let Some(op) = match self.peek_next()? {
|
||||||
Token::EqualEqual => Some(BinaryOperator::Eq),
|
Token::EqualEqual => Some(BinaryOperator::Equal),
|
||||||
Token::BangEqual => Some(BinaryOperator::Ne),
|
Token::BangEqual => Some(BinaryOperator::NotEqual),
|
||||||
Token::Less => Some(BinaryOperator::Lt),
|
Token::Less => Some(BinaryOperator::LessThan),
|
||||||
Token::Greater => Some(BinaryOperator::Gt),
|
Token::Greater => Some(BinaryOperator::GreaterThan),
|
||||||
Token::LessEqual => Some(BinaryOperator::Le),
|
Token::LessEqual => Some(BinaryOperator::LessOrEqual),
|
||||||
Token::GreaterEqual => Some(BinaryOperator::Ge),
|
Token::GreaterEqual => Some(BinaryOperator::GreaterOrEqual),
|
||||||
_ => None,
|
_ => None,
|
||||||
} {
|
} {
|
||||||
self.next()?;
|
self.next()?;
|
||||||
@@ -412,11 +412,27 @@ impl Parser {
|
|||||||
|
|
||||||
fn parse_unary(&mut self) -> ParseResult<Expression, CompilerError> {
|
fn parse_unary(&mut self) -> ParseResult<Expression, CompilerError> {
|
||||||
let op = match self.peek_next()? {
|
let op = match self.peek_next()? {
|
||||||
|
// prefix inc/dec
|
||||||
|
Token::PlusPlus => UnaryOperator::Increment,
|
||||||
|
Token::MinusMinus => UnaryOperator::Decrement,
|
||||||
|
|
||||||
|
// arithmetic
|
||||||
Token::Plus => UnaryOperator::Plus,
|
Token::Plus => UnaryOperator::Plus,
|
||||||
Token::Minus => UnaryOperator::Minus,
|
Token::Minus => UnaryOperator::Minus,
|
||||||
|
|
||||||
|
// pointer
|
||||||
Token::Star => UnaryOperator::Dereference,
|
Token::Star => UnaryOperator::Dereference,
|
||||||
Token::Amphersand => UnaryOperator::Reference,
|
Token::Ampersand => UnaryOperator::AddressOf,
|
||||||
_ => return ParseResult::Accept(self.parse_primary()?),
|
|
||||||
|
// boolean
|
||||||
|
Token::Bang => UnaryOperator::LogicalNot,
|
||||||
|
Token::Tilde => UnaryOperator::BitwiseNot,
|
||||||
|
|
||||||
|
Token::SizeOf => UnaryOperator::SizeOf,
|
||||||
|
_ => {
|
||||||
|
let expr = self.parse_primary()?;
|
||||||
|
return self.parse_postfix(expr);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.next()?;
|
self.next()?;
|
||||||
@@ -428,6 +444,99 @@ impl Parser {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_postfix(
|
||||||
|
&mut self,
|
||||||
|
mut expr: Expression,
|
||||||
|
) -> ParseResult<Expression, CompilerError> {
|
||||||
|
loop {
|
||||||
|
match self.peek_next()? {
|
||||||
|
// Type cast: expr as Type
|
||||||
|
Token::As => {
|
||||||
|
self.next()?; // consume 'as'
|
||||||
|
let target_type = self.parse_type()?;
|
||||||
|
expr = Expression::TypeCast {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
target_type,
|
||||||
|
type_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postfix increment/decrement
|
||||||
|
Token::PlusPlus => {
|
||||||
|
self.next()?;
|
||||||
|
expr = Expression::UnaryPostfix {
|
||||||
|
op: UnaryOperator::Increment,
|
||||||
|
operand: Box::new(expr),
|
||||||
|
type_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Token::MinusMinus => {
|
||||||
|
self.next()?;
|
||||||
|
expr = Expression::UnaryPostfix {
|
||||||
|
op: UnaryOperator::Decrement,
|
||||||
|
operand: Box::new(expr),
|
||||||
|
type_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Array indexing: expr[index]
|
||||||
|
Token::LeftBracket => {
|
||||||
|
self.next()?; // consume '['
|
||||||
|
let index = Box::new(self.parse_expression()?);
|
||||||
|
|
||||||
|
let _ = expect_tt!(self.next()?, RightBracket)?;
|
||||||
|
|
||||||
|
expr = Expression::IndexAccess {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
index,
|
||||||
|
type_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function call: expr(args...)
|
||||||
|
Token::LeftParen => {
|
||||||
|
self.next()?; // consume '('
|
||||||
|
let mut args = Vec::new();
|
||||||
|
|
||||||
|
if !matches!(self.peek_next()?, Token::RightParen) {
|
||||||
|
loop {
|
||||||
|
args.push(self.parse_expression()?);
|
||||||
|
if !matches!(self.peek_next()?, Token::Comma) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.next()?; // consume comma
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = expect_tt!(self.next()?, RightParen)?;
|
||||||
|
|
||||||
|
if let Expression::Variable { name, .. } = expr {
|
||||||
|
expr = Expression::Call {
|
||||||
|
func: Call { name, args },
|
||||||
|
type_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member access: expr.member (if you support structs)
|
||||||
|
Token::Dot => {
|
||||||
|
self.next()?;
|
||||||
|
let field_name = expect_value!(self.next()?, Identifier)?;
|
||||||
|
expr = Expression::MemberAccess {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
field_name,
|
||||||
|
type_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// No more postfix operations
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseResult::Accept(expr)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_primary(&mut self) -> ParseResult<Expression, CompilerError> {
|
fn parse_primary(&mut self) -> ParseResult<Expression, CompilerError> {
|
||||||
match self.peek_next()? {
|
match self.peek_next()? {
|
||||||
Token::Integer(value) => {
|
Token::Integer(value) => {
|
||||||
@@ -441,39 +550,37 @@ impl Parser {
|
|||||||
self.next()?;
|
self.next()?;
|
||||||
ParseResult::Accept(Expression::StringLiteral(value))
|
ParseResult::Accept(Expression::StringLiteral(value))
|
||||||
}
|
}
|
||||||
Token::Identifier(_) => {
|
Token::Char(value) => {
|
||||||
let name = expect_value!(self.next()?, Identifier)?;
|
self.next()?;
|
||||||
|
ParseResult::Accept(Expression::CharLiteral(value))
|
||||||
|
}
|
||||||
|
|
||||||
if matches!(self.peek_next()?, Token::LeftParen) {
|
Token::Identifier(name) => {
|
||||||
// Function call
|
self.next()?;
|
||||||
self.next()?;
|
ParseResult::Accept(Expression::Variable {
|
||||||
let mut args = Vec::new();
|
name,
|
||||||
|
expr_type: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Token::LeftBracket => {
|
||||||
|
self.next()?; // consume '['
|
||||||
|
let mut elements = Vec::new();
|
||||||
|
|
||||||
if !matches!(self.peek_next()?, Token::RightParen) {
|
if !matches!(self.peek_next()?, Token::RightBracket) {
|
||||||
args.push(self.parse_expression()?);
|
loop {
|
||||||
|
elements.push(self.parse_expression()?);
|
||||||
while matches!(self.peek_next()?, Token::Comma) {
|
if !matches!(self.peek_next()?, Token::Comma) {
|
||||||
self.next()?;
|
break;
|
||||||
args.push(self.parse_expression()?);
|
|
||||||
}
|
}
|
||||||
|
self.next()?; // consume comma
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = expect_tt!(self.next()?, RightParen)?;
|
|
||||||
|
|
||||||
ParseResult::Accept(Expression::Call {
|
|
||||||
func: Call {
|
|
||||||
name: name.clone(),
|
|
||||||
args,
|
|
||||||
},
|
|
||||||
|
|
||||||
type_id: None,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
ParseResult::Accept(Expression::Variable {
|
|
||||||
name,
|
|
||||||
expr_type: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expect_tt!(self.next()?, RightBracket)?;
|
||||||
|
ParseResult::Accept(Expression::ArrayLiteral {
|
||||||
|
elements,
|
||||||
|
type_id: None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Token::LeftParen => {
|
Token::LeftParen => {
|
||||||
self.next()?;
|
self.next()?;
|
||||||
|
|||||||
+133
-21
@@ -65,6 +65,26 @@ pub enum TypeId {
|
|||||||
Struct { name: Name, fields: Vec<TypeId> },
|
Struct { name: Name, fields: Vec<TypeId> },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypeId {
|
||||||
|
pub fn size(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
Self::U8 => 1,
|
||||||
|
Self::U16 => 2,
|
||||||
|
Self::U32 => 4,
|
||||||
|
Self::I8 => 1,
|
||||||
|
Self::I16 => 2,
|
||||||
|
Self::I32 => 4,
|
||||||
|
Self::Bool => 1,
|
||||||
|
Self::Char => 1,
|
||||||
|
Self::Void => 0,
|
||||||
|
Self::Ptr(t) => t.size(),
|
||||||
|
Self::Ref(t) => t.size(),
|
||||||
|
Self::Array(t, size) => t.size() * size,
|
||||||
|
Self::Struct { fields, .. } => fields.iter().map(|t| t.size()).sum(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for TypeId {
|
impl fmt::Display for TypeId {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@@ -169,10 +189,38 @@ pub enum Expression {
|
|||||||
// Post-Semantic Analysis
|
// Post-Semantic Analysis
|
||||||
type_id: Option<TypeId>,
|
type_id: Option<TypeId>,
|
||||||
},
|
},
|
||||||
|
UnaryPostfix {
|
||||||
|
op: UnaryOperator,
|
||||||
|
operand: Box<Expression>,
|
||||||
|
|
||||||
|
// Post-Semantic Analysis
|
||||||
|
type_id: Option<TypeId>,
|
||||||
|
},
|
||||||
Variable {
|
Variable {
|
||||||
name: Name,
|
name: Name,
|
||||||
expr_type: Option<TypeId>,
|
expr_type: Option<TypeId>,
|
||||||
},
|
},
|
||||||
|
TypeCast {
|
||||||
|
expr: Box<Expression>,
|
||||||
|
target_type: TypeId,
|
||||||
|
|
||||||
|
// Post-Semantic Analysis
|
||||||
|
type_id: Option<TypeId>,
|
||||||
|
},
|
||||||
|
IndexAccess {
|
||||||
|
expr: Box<Expression>,
|
||||||
|
index: Box<Expression>,
|
||||||
|
|
||||||
|
// Post-Semantic Analysis
|
||||||
|
type_id: Option<TypeId>,
|
||||||
|
},
|
||||||
|
MemberAccess {
|
||||||
|
expr: Box<Expression>,
|
||||||
|
field_name: Name,
|
||||||
|
|
||||||
|
// Post-Semantic Analysis
|
||||||
|
type_id: Option<TypeId>,
|
||||||
|
},
|
||||||
Call {
|
Call {
|
||||||
func: Call,
|
func: Call,
|
||||||
|
|
||||||
@@ -187,6 +235,10 @@ pub enum Expression {
|
|||||||
},
|
},
|
||||||
StringLiteral(String),
|
StringLiteral(String),
|
||||||
CharLiteral(char),
|
CharLiteral(char),
|
||||||
|
ArrayLiteral {
|
||||||
|
elements: Vec<Expression>,
|
||||||
|
type_id: Option<TypeId>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -204,8 +256,17 @@ impl Expression {
|
|||||||
Expression::Call { .. } => false,
|
Expression::Call { .. } => false,
|
||||||
Expression::Binary { left, right, .. } => left.is_pure() && right.is_pure(),
|
Expression::Binary { left, right, .. } => left.is_pure() && right.is_pure(),
|
||||||
Expression::Unary { operand, .. } => operand.is_pure(),
|
Expression::Unary { operand, .. } => operand.is_pure(),
|
||||||
|
Expression::UnaryPostfix { operand, .. } => operand.is_pure(),
|
||||||
Expression::Empty => true,
|
Expression::Empty => true,
|
||||||
Expression::Variable { .. } => true,
|
Expression::Variable { .. } => true,
|
||||||
|
Expression::TypeCast { expr, .. } => expr.is_pure(),
|
||||||
|
Expression::IndexAccess { expr, index, .. } => {
|
||||||
|
expr.is_pure() && index.is_pure()
|
||||||
|
}
|
||||||
|
Expression::MemberAccess { expr, .. } => expr.is_pure(),
|
||||||
|
Expression::ArrayLiteral { elements, type_id } => {
|
||||||
|
elements.iter().all(|element| element.is_pure())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,10 +286,24 @@ impl Expression {
|
|||||||
Expression::Unary { type_id, .. } => {
|
Expression::Unary { type_id, .. } => {
|
||||||
type_id.clone().ok_or(CompilerError::UnknownType)
|
type_id.clone().ok_or(CompilerError::UnknownType)
|
||||||
}
|
}
|
||||||
|
Expression::UnaryPostfix { type_id, .. } => {
|
||||||
|
type_id.clone().ok_or(CompilerError::UnknownType)
|
||||||
|
}
|
||||||
Expression::Empty => Ok(TypeId::Void),
|
Expression::Empty => Ok(TypeId::Void),
|
||||||
Expression::Variable { expr_type, .. } => {
|
Expression::Variable { expr_type, .. } => {
|
||||||
expr_type.clone().ok_or(CompilerError::UnknownType)
|
expr_type.clone().ok_or(CompilerError::UnknownType)
|
||||||
}
|
}
|
||||||
|
Expression::TypeCast { type_id, .. } => {
|
||||||
|
type_id.clone().ok_or(CompilerError::UnknownType)
|
||||||
|
}
|
||||||
|
Expression::IndexAccess { expr, .. } => expr.type_id(),
|
||||||
|
Expression::MemberAccess { expr, .. } => expr.type_id(),
|
||||||
|
Expression::ArrayLiteral { elements, .. } => {
|
||||||
|
let element_type = elements
|
||||||
|
.first()
|
||||||
|
.map_or(TypeId::Void, |e| e.type_id().unwrap_or(TypeId::Void));
|
||||||
|
Ok(TypeId::Array(Box::new(element_type), elements.len()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,31 +311,56 @@ impl Expression {
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum BinaryOperator {
|
pub enum BinaryOperator {
|
||||||
|
// arithmetic
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
Mul,
|
Mul,
|
||||||
Div,
|
Div,
|
||||||
Eq,
|
Mod,
|
||||||
Ne,
|
|
||||||
Lt,
|
// comparison
|
||||||
Gt,
|
Equal,
|
||||||
Le,
|
NotEqual,
|
||||||
Ge,
|
LessThan,
|
||||||
|
GreaterThan,
|
||||||
|
LessOrEqual,
|
||||||
|
GreaterOrEqual,
|
||||||
|
|
||||||
|
// bitwise
|
||||||
|
BitwiseAnd,
|
||||||
|
BitwiseOr,
|
||||||
|
BitwiseXor,
|
||||||
|
|
||||||
|
// logical
|
||||||
|
LogicalAnd,
|
||||||
|
LogicalOr,
|
||||||
|
|
||||||
|
// shift
|
||||||
|
LeftShift,
|
||||||
|
RightShift,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BinaryOperator {
|
impl fmt::Display for BinaryOperator {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
BinaryOperator::Add => write!(f, "+"),
|
Self::Add => write!(f, "+"),
|
||||||
BinaryOperator::Sub => write!(f, "-"),
|
Self::Sub => write!(f, "-"),
|
||||||
BinaryOperator::Mul => write!(f, "*"),
|
Self::Mul => write!(f, "*"),
|
||||||
BinaryOperator::Div => write!(f, "/"),
|
Self::Div => write!(f, "/"),
|
||||||
BinaryOperator::Eq => write!(f, "=="),
|
Self::Mod => write!(f, "%"),
|
||||||
BinaryOperator::Ne => write!(f, "!="),
|
Self::Equal => write!(f, "=="),
|
||||||
BinaryOperator::Lt => write!(f, "<"),
|
Self::NotEqual => write!(f, "!="),
|
||||||
BinaryOperator::Gt => write!(f, ">"),
|
Self::LessThan => write!(f, "<"),
|
||||||
BinaryOperator::Le => write!(f, "<="),
|
Self::GreaterThan => write!(f, ">"),
|
||||||
BinaryOperator::Ge => write!(f, ">="),
|
Self::LessOrEqual => write!(f, "<="),
|
||||||
|
Self::GreaterOrEqual => write!(f, ">="),
|
||||||
|
Self::BitwiseAnd => write!(f, "&"),
|
||||||
|
Self::BitwiseOr => write!(f, "|"),
|
||||||
|
Self::BitwiseXor => write!(f, "^"),
|
||||||
|
Self::LogicalAnd => write!(f, "&&"),
|
||||||
|
Self::LogicalOr => write!(f, "||"),
|
||||||
|
Self::LeftShift => write!(f, "<<"),
|
||||||
|
Self::RightShift => write!(f, ">>"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,17 +369,29 @@ impl fmt::Display for BinaryOperator {
|
|||||||
pub enum UnaryOperator {
|
pub enum UnaryOperator {
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
Reference,
|
AddressOf,
|
||||||
Dereference,
|
Dereference,
|
||||||
|
CastAs,
|
||||||
|
BitwiseNot,
|
||||||
|
LogicalNot,
|
||||||
|
Increment,
|
||||||
|
Decrement,
|
||||||
|
SizeOf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for UnaryOperator {
|
impl fmt::Display for UnaryOperator {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
UnaryOperator::Plus => write!(f, "+"),
|
Self::Increment => write!(f, "++"),
|
||||||
UnaryOperator::Minus => write!(f, "-"),
|
Self::Decrement => write!(f, "--"),
|
||||||
UnaryOperator::Dereference => write!(f, "*"),
|
Self::Plus => write!(f, "+"),
|
||||||
UnaryOperator::Reference => write!(f, "&"),
|
Self::Minus => write!(f, "-"),
|
||||||
|
Self::Dereference => write!(f, "*"),
|
||||||
|
Self::AddressOf => write!(f, "&"),
|
||||||
|
Self::CastAs => write!(f, "as"),
|
||||||
|
Self::BitwiseNot => write!(f, "~"),
|
||||||
|
Self::LogicalNot => write!(f, "!"),
|
||||||
|
Self::SizeOf => write!(f, "sizeof"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user