Add and/or/sub
This commit is contained in:
parent
763d818c51
commit
d04ddd95d0
@ -21,3 +21,4 @@ print(add(10)(15))
|
|||||||
print(add(10)(15))
|
print(add(10)(15))
|
||||||
print(b)
|
print(b)
|
||||||
print(min(11, 9))
|
print(min(11, 9))
|
||||||
|
print(10 > 5 or 11 < 10)
|
||||||
12
src/ast.rs
12
src/ast.rs
@ -320,23 +320,29 @@ pub struct PrimaryExpression(Node<Expression>);
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum BinaryOperator {
|
pub enum BinaryOperator {
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
LessThan,
|
LessThan,
|
||||||
LessThanOrEqual,
|
LessThanOrEqual,
|
||||||
GreaterThan,
|
GreaterThan,
|
||||||
GreaterThanOrEqual,
|
GreaterThanOrEqual,
|
||||||
Equal,
|
Equal,
|
||||||
Add,
|
Add,
|
||||||
|
Sub,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryOperator {
|
impl BinaryOperator {
|
||||||
pub fn precedence(&self) -> u32 {
|
pub fn precedence(&self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
|
BinaryOperator::Or => 0,
|
||||||
|
BinaryOperator::And => 1,
|
||||||
BinaryOperator::LessThan => 10,
|
BinaryOperator::LessThan => 10,
|
||||||
BinaryOperator::LessThanOrEqual => 10,
|
BinaryOperator::LessThanOrEqual => 10,
|
||||||
BinaryOperator::GreaterThan => 10,
|
BinaryOperator::GreaterThan => 10,
|
||||||
BinaryOperator::GreaterThanOrEqual => 10,
|
BinaryOperator::GreaterThanOrEqual => 10,
|
||||||
BinaryOperator::Equal => 10,
|
BinaryOperator::Equal => 10,
|
||||||
BinaryOperator::Add => 20,
|
BinaryOperator::Add => 20,
|
||||||
|
BinaryOperator::Sub => 20,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,6 +425,11 @@ impl Parse for BinaryOperator {
|
|||||||
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
|
||||||
if let Some(token) = stream.next() {
|
if let Some(token) = stream.next() {
|
||||||
match (token, stream.peek()) {
|
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('='))) => {
|
(Token::Symbol('<'), Some(Token::Symbol('='))) => {
|
||||||
stream.next();
|
stream.next();
|
||||||
Ok(BinaryOperator::LessThanOrEqual)
|
Ok(BinaryOperator::LessThanOrEqual)
|
||||||
@ -434,6 +445,7 @@ impl Parse for BinaryOperator {
|
|||||||
(Token::Symbol('<'), _) => Ok(BinaryOperator::LessThan),
|
(Token::Symbol('<'), _) => Ok(BinaryOperator::LessThan),
|
||||||
(Token::Symbol('>'), _) => Ok(BinaryOperator::GreaterThan),
|
(Token::Symbol('>'), _) => Ok(BinaryOperator::GreaterThan),
|
||||||
(Token::Symbol('+'), _) => Ok(BinaryOperator::Add),
|
(Token::Symbol('+'), _) => Ok(BinaryOperator::Add),
|
||||||
|
(Token::Symbol('-'), _) => Ok(BinaryOperator::Sub),
|
||||||
_ => Err(stream.expected_err("binop")),
|
_ => Err(stream.expected_err("binop")),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -350,6 +350,25 @@ impl Expression {
|
|||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
BinaryOperator::Sub => {
|
||||||
|
let temp = scope.register_counter.next();
|
||||||
|
instructions.push(Instruction::Unm(temp, *rhs.get(0).unwrap()));
|
||||||
|
instructions.push(Instruction::Add(reg, *lhs.get(0).unwrap(), temp));
|
||||||
|
}
|
||||||
|
BinaryOperator::And => {
|
||||||
|
instructions.push(Instruction::And(
|
||||||
|
reg,
|
||||||
|
*rhs.get(0).unwrap(),
|
||||||
|
*lhs.get(0).unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
BinaryOperator::Or => {
|
||||||
|
instructions.push(Instruction::Or(
|
||||||
|
reg,
|
||||||
|
*rhs.get(0).unwrap(),
|
||||||
|
*lhs.get(0).unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
(instructions, vec![reg])
|
(instructions, vec![reg])
|
||||||
}
|
}
|
||||||
@ -364,15 +383,11 @@ impl Expression {
|
|||||||
inner_scope.highest_upvalue = scope.highest_upvalue + scope.register_counter.0;
|
inner_scope.highest_upvalue = scope.highest_upvalue + scope.register_counter.0;
|
||||||
inner_scope.upvalues = scope.upvalues.clone();
|
inner_scope.upvalues = scope.upvalues.clone();
|
||||||
|
|
||||||
dbg!(&scope.locals);
|
|
||||||
for (name, reg) in &scope.locals {
|
for (name, reg) in &scope.locals {
|
||||||
let new_reg = *reg + scope.highest_upvalue + 1;
|
let new_reg = *reg + scope.highest_upvalue + 1;
|
||||||
inner_scope.upvalues.insert(name.clone(), new_reg);
|
inner_scope.upvalues.insert(name.clone(), new_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg!(&inner_scope.highest_upvalue);
|
|
||||||
dbg!(&inner_scope.upvalues);
|
|
||||||
|
|
||||||
let instructions = block.compile(state, &mut inner_scope);
|
let instructions = block.compile(state, &mut inner_scope);
|
||||||
state.prototypes.push(instructions);
|
state.prototypes.push(instructions);
|
||||||
|
|
||||||
|
|||||||
89
src/vm.rs
89
src/vm.rs
@ -40,12 +40,18 @@ pub enum Instruction {
|
|||||||
SetUpVal(u16, u16),
|
SetUpVal(u16, u16),
|
||||||
/// R(A) := R(B) + R(C)
|
/// R(A) := R(B) + R(C)
|
||||||
Add(u16, u16, u16),
|
Add(u16, u16, u16),
|
||||||
|
/// R(A) := -R(B)
|
||||||
|
Unm(u16, u16),
|
||||||
/// R(A) := R(B) == R(C)
|
/// R(A) := R(B) == R(C)
|
||||||
Equal(u16, u16, u16),
|
Equal(u16, u16, u16),
|
||||||
/// R(A) := R(B) < R(C)
|
/// R(A) := R(B) < R(C)
|
||||||
LessThan(u16, u16, u16),
|
LessThan(u16, u16, u16),
|
||||||
/// R(A) := R(B) <= R(C)
|
/// R(A) := R(B) <= R(C)
|
||||||
LessThanOrEqual(u16, u16, u16),
|
LessThanOrEqual(u16, u16, u16),
|
||||||
|
/// R(A) := R(B) or R(C)
|
||||||
|
Or(u16, u16, u16),
|
||||||
|
/// R(A) := R(B) and R(C)
|
||||||
|
And(u16, u16, u16),
|
||||||
/// PC += sAx
|
/// PC += sAx
|
||||||
Jmp(i32),
|
Jmp(i32),
|
||||||
/// if (R(B) <=> C) then R(A) := R(B) else PC++
|
/// if (R(B) <=> C) then R(A) := R(B) else PC++
|
||||||
@ -83,6 +89,9 @@ impl Debug for Instruction {
|
|||||||
}
|
}
|
||||||
Instruction::Add(arg0, arg1, arg2) => write!(f, "ADD {} {} {}", arg0, arg1, arg2),
|
Instruction::Add(arg0, arg1, arg2) => write!(f, "ADD {} {} {}", arg0, arg1, arg2),
|
||||||
Instruction::LoadNil(arg0, arg1) => write!(f, "LOADNIL {} {}", arg0, arg1),
|
Instruction::LoadNil(arg0, arg1) => write!(f, "LOADNIL {} {}", arg0, arg1),
|
||||||
|
Instruction::Unm(arg0, arg1) => write!(f, "UNM {} {}", arg0, arg1),
|
||||||
|
Instruction::Or(arg0, arg1, arg2) => write!(f, "OR {} {} {}", arg0, arg1, arg2),
|
||||||
|
Instruction::And(arg0, arg1, arg2) => write!(f, "AND {} {} {}", arg0, arg1, arg2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,6 +149,50 @@ impl Value {
|
|||||||
_ => Value::Nil,
|
_ => Value::Nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unm(&self) -> Value {
|
||||||
|
match self {
|
||||||
|
Value::Number(lhs) => {
|
||||||
|
let res = -LuaNumber::from_bits(*lhs);
|
||||||
|
Value::Number((res as u64 as f64).to_bits())
|
||||||
|
}
|
||||||
|
_ => Value::Nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn and(&self, other: &Value) -> Value {
|
||||||
|
match (self, other) {
|
||||||
|
(Value::Nil, _) | (_, Value::Nil) => Value::Nil,
|
||||||
|
(Value::Number(lhs), Value::Number(rhs)) => {
|
||||||
|
let res = LuaNumber::from_bits(*lhs) > 0. && LuaNumber::from_bits(*rhs) > 0.;
|
||||||
|
Value::Number((res as u64 as f64).to_bits())
|
||||||
|
}
|
||||||
|
(Value::Number(value), _) | (_, Value::Number(value)) => {
|
||||||
|
let res = LuaNumber::from_bits(*value) > 0.;
|
||||||
|
Value::Number((res as u64 as f64).to_bits())
|
||||||
|
}
|
||||||
|
_ => Value::Nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn or(&self, other: &Value) -> Value {
|
||||||
|
match (self, other) {
|
||||||
|
(Value::Nil, value) | (value, Value::Nil) => value.clone(),
|
||||||
|
(Value::Number(lhs), Value::Number(rhs)) => {
|
||||||
|
let res = LuaNumber::from_bits(*lhs) > 0. || LuaNumber::from_bits(*rhs) > 0.;
|
||||||
|
Value::Number((res as u64 as f64).to_bits())
|
||||||
|
}
|
||||||
|
(Value::Number(value), other) => {
|
||||||
|
if LuaNumber::from_bits(*value) > 0. {
|
||||||
|
Value::Number(*value)
|
||||||
|
} else {
|
||||||
|
other.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(value, _) => value.clone(),
|
||||||
|
_ => Value::Nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Value {
|
impl Debug for Value {
|
||||||
@ -508,6 +561,42 @@ impl ClosureRunner {
|
|||||||
.unwrap_or(Value::Nil);
|
.unwrap_or(Value::Nil);
|
||||||
self.set_stack(*res, lhs.lte(&rhs));
|
self.set_stack(*res, lhs.lte(&rhs));
|
||||||
}
|
}
|
||||||
|
Instruction::Unm(res, reg) => {
|
||||||
|
self.set_stack(
|
||||||
|
*res,
|
||||||
|
self.stack
|
||||||
|
.get(reg)
|
||||||
|
.map(|v| v.borrow().clone())
|
||||||
|
.unwrap_or(Value::Nil)
|
||||||
|
.unm(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Instruction::Or(res, lhs, rhs) => {
|
||||||
|
let lhs = self
|
||||||
|
.stack
|
||||||
|
.get(lhs)
|
||||||
|
.map(|v| v.borrow().clone())
|
||||||
|
.unwrap_or(Value::Nil);
|
||||||
|
let rhs = self
|
||||||
|
.stack
|
||||||
|
.get(rhs)
|
||||||
|
.map(|v| v.borrow().clone())
|
||||||
|
.unwrap_or(Value::Nil);
|
||||||
|
self.set_stack(*res, lhs.or(&rhs));
|
||||||
|
}
|
||||||
|
Instruction::And(res, lhs, rhs) => {
|
||||||
|
let lhs = self
|
||||||
|
.stack
|
||||||
|
.get(lhs)
|
||||||
|
.map(|v| v.borrow().clone())
|
||||||
|
.unwrap_or(Value::Nil);
|
||||||
|
let rhs = self
|
||||||
|
.stack
|
||||||
|
.get(rhs)
|
||||||
|
.map(|v| v.borrow().clone())
|
||||||
|
.unwrap_or(Value::Nil);
|
||||||
|
self.set_stack(*res, lhs.and(&rhs));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.program_counter += 1;
|
self.program_counter += 1;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user