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)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
ValueRef(String),
|
ValueRef(String),
|
||||||
|
UnOp(UnaryOperator, Box<Node<Expression>>),
|
||||||
BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>),
|
BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>),
|
||||||
FunctionDefinition(Vec<Node<String>>, Block),
|
FunctionDefinition(Vec<Node<String>>, Block),
|
||||||
FunctionCall(Box<Node<Expression>>, Node<ExpressionList>),
|
FunctionCall(Box<Node<Expression>>, Node<ExpressionList>),
|
||||||
@ -318,6 +319,24 @@ impl Parse for ExpressionList {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PrimaryExpression(Node<Expression>);
|
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)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum BinaryOperator {
|
pub enum BinaryOperator {
|
||||||
And,
|
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 {
|
impl Parse for PrimaryExpression {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
||||||
let pre = Metadata::pre(&mut stream, "expression")?;
|
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 peeked = stream.peek();
|
||||||
let mut expression = if peeked == Some(Token::Keyword(Keyword::Function)) {
|
let mut expression = if peeked == Some(Token::Keyword(Keyword::Function)) {
|
||||||
let function = stream.parse::<Node<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 {
|
Ok(PrimaryExpression(Node {
|
||||||
kind: expression,
|
kind: expression,
|
||||||
meta: Metadata::produce(&mut stream, pre),
|
meta: Metadata::produce(&mut stream, pre),
|
||||||
@ -421,39 +489,6 @@ fn parse_binop_rhs(
|
|||||||
Ok(lhs.0)
|
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)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
Number(LuaNumber),
|
Number(LuaNumber),
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement},
|
ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator},
|
||||||
vm::{Constant, Instruction, VMNumber},
|
vm::{Constant, Instruction, VMNumber},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -258,6 +258,7 @@ impl Expression {
|
|||||||
constants.extend(rhs.kind.find_constants(scope));
|
constants.extend(rhs.kind.find_constants(scope));
|
||||||
constants
|
constants
|
||||||
}
|
}
|
||||||
|
Expression::UnOp(_, expr) => expr.kind.find_constants(scope),
|
||||||
Expression::FunctionDefinition(_, block) => block.find_constants(scope),
|
Expression::FunctionDefinition(_, block) => block.find_constants(scope),
|
||||||
Expression::FunctionCall(expr, params) => {
|
Expression::FunctionCall(expr, params) => {
|
||||||
let mut constants = HashSet::new();
|
let mut constants = HashSet::new();
|
||||||
@ -371,6 +372,17 @@ impl Expression {
|
|||||||
};
|
};
|
||||||
(instructions, vec![reg])
|
(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) => {
|
Expression::FunctionDefinition(params, block) => {
|
||||||
let mut inner_scope = Scope::default();
|
let mut inner_scope = Scope::default();
|
||||||
for param in params {
|
for param in params {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user