Add unary operators

This commit is contained in:
Sofia 2026-03-16 16:53:52 +02:00
parent f3870e2e1a
commit 0fca17defb
2 changed files with 81 additions and 34 deletions

View File

@ -284,6 +284,7 @@ pub enum AccessModifier {
#[derive(Debug, Clone)]
pub enum Expression {
ValueRef(String),
UnOp(UnaryOperator, Box<Node<Expression>>),
BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>),
FunctionDefinition(Vec<Node<String>>, Block),
FunctionCall(Box<Node<Expression>>, Node<ExpressionList>),
@ -318,6 +319,24 @@ impl Parse for ExpressionList {
#[derive(Debug, Clone)]
pub struct PrimaryExpression(Node<Expression>);
#[derive(Debug, Clone, Copy)]
pub enum UnaryOperator {
Negation,
}
impl Parse for UnaryOperator {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
if let Some(token) = stream.next() {
match token {
Token::Symbol('-') => Ok(UnaryOperator::Negation),
_ => Err(stream.expected_err("unop")),
}
} else {
Err(stream.expected_err("unop"))
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum BinaryOperator {
And,
@ -347,10 +366,49 @@ impl BinaryOperator {
}
}
impl Parse for BinaryOperator {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
if let Some(token) = stream.next() {
match (token, stream.peek()) {
(Token::Word(word), _) => match word.as_str() {
"and" => Ok(BinaryOperator::And),
"or" => Ok(BinaryOperator::Or),
_ => Err(stream.expected_err("binop")),
},
(Token::Symbol('<'), Some(Token::Symbol('='))) => {
stream.next();
Ok(BinaryOperator::LessThanOrEqual)
}
(Token::Symbol('>'), Some(Token::Symbol('='))) => {
stream.next();
Ok(BinaryOperator::GreaterThanOrEqual)
}
(Token::Symbol('='), Some(Token::Symbol('='))) => {
stream.next();
Ok(BinaryOperator::Equal)
}
(Token::Symbol('<'), _) => Ok(BinaryOperator::LessThan),
(Token::Symbol('>'), _) => Ok(BinaryOperator::GreaterThan),
(Token::Symbol('+'), _) => Ok(BinaryOperator::Add),
(Token::Symbol('-'), _) => Ok(BinaryOperator::Sub),
_ => Err(stream.expected_err("binop")),
}
} else {
Err(stream.expected_err("binop"))
}
}
}
impl Parse for PrimaryExpression {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
let pre = Metadata::pre(&mut stream, "expression")?;
let mut unary_operators = Vec::new();
while let Ok(unop) = stream.parse::<UnaryOperator>() {
unary_operators.push(unop);
}
let peeked = stream.peek();
let mut expression = if peeked == Some(Token::Keyword(Keyword::Function)) {
let function = stream.parse::<Node<Function>>()?;
@ -377,6 +435,16 @@ impl Parse for PrimaryExpression {
);
}
for unop in unary_operators.into_iter().rev() {
expression = Expression::UnOp(
unop,
Box::new(Node {
kind: expression,
meta: Metadata::produce(&mut stream, pre.clone()),
}),
);
}
Ok(PrimaryExpression(Node {
kind: expression,
meta: Metadata::produce(&mut stream, pre),
@ -421,39 +489,6 @@ fn parse_binop_rhs(
Ok(lhs.0)
}
impl Parse for BinaryOperator {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
if let Some(token) = stream.next() {
match (token, stream.peek()) {
(Token::Word(word), _) => match word.as_str() {
"and" => Ok(BinaryOperator::And),
"or" => Ok(BinaryOperator::Or),
_ => Err(stream.expected_err("binop")),
},
(Token::Symbol('<'), Some(Token::Symbol('='))) => {
stream.next();
Ok(BinaryOperator::LessThanOrEqual)
}
(Token::Symbol('>'), Some(Token::Symbol('='))) => {
stream.next();
Ok(BinaryOperator::GreaterThanOrEqual)
}
(Token::Symbol('='), Some(Token::Symbol('='))) => {
stream.next();
Ok(BinaryOperator::Equal)
}
(Token::Symbol('<'), _) => Ok(BinaryOperator::LessThan),
(Token::Symbol('>'), _) => Ok(BinaryOperator::GreaterThan),
(Token::Symbol('+'), _) => Ok(BinaryOperator::Add),
(Token::Symbol('-'), _) => Ok(BinaryOperator::Sub),
_ => Err(stream.expected_err("binop")),
}
} else {
Err(stream.expected_err("binop"))
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Literal {
Number(LuaNumber),

View File

@ -1,7 +1,7 @@
use std::collections::{HashMap, HashSet};
use crate::{
ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement},
ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator},
vm::{Constant, Instruction, VMNumber},
};
@ -258,6 +258,7 @@ impl Expression {
constants.extend(rhs.kind.find_constants(scope));
constants
}
Expression::UnOp(_, expr) => expr.kind.find_constants(scope),
Expression::FunctionDefinition(_, block) => block.find_constants(scope),
Expression::FunctionCall(expr, params) => {
let mut constants = HashSet::new();
@ -371,6 +372,17 @@ impl Expression {
};
(instructions, vec![reg])
}
Expression::UnOp(op, expr) => {
let mut instructions = Vec::new();
let (instr, registers) = expr.kind.compile(state, scope, Some(1));
instructions.extend(instr);
for reg in &registers {
match op {
UnaryOperator::Negation => instructions.push(Instruction::Unm(*reg, *reg)),
}
}
(instructions, registers)
}
Expression::FunctionDefinition(params, block) => {
let mut inner_scope = Scope::default();
for param in params {