Add unary operators
This commit is contained in:
parent
f3870e2e1a
commit
0fca17defb
101
src/ast.rs
101
src/ast.rs
@ -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),
|
||||
|
||||
@ -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 ®isters {
|
||||
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 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user