Use BinOp type instead of strings
This commit is contained in:
parent
0ace370fc2
commit
d804efdc5e
@ -3,7 +3,7 @@ extern crate llvm_sys;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use self::llvm_sys::prelude::*;
|
||||
use parser::{AST, Statement, Function, Expression};
|
||||
use parser::{AST, Statement, Function, Expression, BinOp};
|
||||
|
||||
use llvm_wrap as LLVMWrap;
|
||||
|
||||
@ -128,6 +128,7 @@ impl CodeGen for Function {
|
||||
|
||||
impl CodeGen for Expression {
|
||||
fn codegen(&self, data: &mut CompilationData) -> LLVMValueRef {
|
||||
use self::BinOp::*;
|
||||
use self::Expression::*;
|
||||
|
||||
let int_type = LLVMWrap::Int64TypeInContext(data.context);
|
||||
@ -135,7 +136,7 @@ impl CodeGen for Expression {
|
||||
|
||||
match *self {
|
||||
Variable(ref name) => *data.variables.get(&**name).unwrap(),
|
||||
BinExp(ref op, ref left, ref right) if **op == "=" => {
|
||||
BinExp(Assign, ref left, ref right) => {
|
||||
if let Variable(ref name) = **left {
|
||||
let new_value = right.codegen(data);
|
||||
data.variables.insert((**name).clone(), new_value);
|
||||
@ -147,13 +148,13 @@ impl CodeGen for Expression {
|
||||
BinExp(ref op, ref left, ref right) => {
|
||||
let lhs = left.codegen(data);
|
||||
let rhs = right.codegen(data);
|
||||
let generator = match op.as_ref().as_ref() {
|
||||
"+" => LLVMWrap::BuildAdd,
|
||||
"-" => LLVMWrap::BuildSub,
|
||||
"*" => LLVMWrap::BuildMul,
|
||||
"/" => LLVMWrap::BuildUDiv,
|
||||
"%" => LLVMWrap::BuildSRem,
|
||||
_ => panic!("Bad operator {}", op),
|
||||
let generator = match *op {
|
||||
Add => LLVMWrap::BuildAdd,
|
||||
Sub => LLVMWrap::BuildSub,
|
||||
Mul => LLVMWrap::BuildMul,
|
||||
Div => LLVMWrap::BuildUDiv,
|
||||
Mod => LLVMWrap::BuildSRem,
|
||||
_ => panic!("Bad operator {:?}", op),
|
||||
};
|
||||
|
||||
generator(data.builder, lhs, rhs, "temp")
|
||||
|
67
src/eval.rs
67
src/eval.rs
@ -2,7 +2,7 @@ extern crate take_mut;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::VecDeque;
|
||||
use parser::{AST, Statement, Expression, Function, Callable};
|
||||
use parser::{AST, Statement, Expression, Function, Callable, BinOp};
|
||||
use std::rc::Rc;
|
||||
use std::io::{Write, Stdout, BufWriter};
|
||||
use std::convert::From;
|
||||
@ -125,10 +125,11 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_assignment(op: &str) -> bool {
|
||||
match op {
|
||||
"=" | "+=" | "-=" |
|
||||
"*=" | "/=" => true,
|
||||
fn is_assignment(op: &BinOp) -> bool {
|
||||
use self::BinOp::*;
|
||||
match *op {
|
||||
Assign | AddAssign | SubAssign |
|
||||
MulAssign | DivAssign => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -221,7 +222,7 @@ impl<'a> Evaluator<'a> {
|
||||
return (BinExp(op, left, right), side_effect);
|
||||
}
|
||||
|
||||
if *op == "=" {
|
||||
if let BinOp::Assign = op {
|
||||
return match *left {
|
||||
Variable(var) => {
|
||||
let reduced_value: ReducedValue = ReducedValue::from(*right);
|
||||
@ -232,17 +233,18 @@ impl<'a> Evaluator<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
if is_assignment(&*op) {
|
||||
let new_op = Rc::new(String::from(match &op[..] {
|
||||
"+=" => "+",
|
||||
"-=" => "-",
|
||||
"*=" => "*",
|
||||
"/=" => "/",
|
||||
if is_assignment(&op) {
|
||||
use self::BinOp::*;
|
||||
let new_op = match op {
|
||||
AddAssign => Add,
|
||||
SubAssign => Sub,
|
||||
MulAssign => Mul,
|
||||
DivAssign => Div,
|
||||
_ => unreachable!(),
|
||||
}));
|
||||
};
|
||||
|
||||
let reduction =
|
||||
BinExp(Rc::new(String::from("=")),
|
||||
BinExp(BinOp::Assign,
|
||||
Box::new(*left.clone()),
|
||||
Box::new(BinExp(new_op, left, right))
|
||||
);
|
||||
@ -316,26 +318,27 @@ impl<'a> Evaluator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn reduce_binop(&mut self, op: Rc<String>, left: Expression, right: Expression) -> Expression {
|
||||
fn reduce_binop(&mut self, op: BinOp, left: Expression, right: Expression) -> Expression {
|
||||
use self::BinOp::*;
|
||||
let truthy = Number(1.0);
|
||||
let falsy = Null;
|
||||
match (&op[..], left, right) {
|
||||
("+", Number(l), Number(r)) => Number(l + r),
|
||||
("+", StringLiteral(s1), StringLiteral(s2)) => StringLiteral(Rc::new(format!("{}{}", *s1, *s2))),
|
||||
("+", StringLiteral(s1), Number(r)) => StringLiteral(Rc::new(format!("{}{}", *s1, r))),
|
||||
("+", Number(l), StringLiteral(s1)) => StringLiteral(Rc::new(format!("{}{}", l, *s1))),
|
||||
("-", Number(l), Number(r)) => Number(l - r),
|
||||
("*", Number(l), Number(r)) => Number(l * r),
|
||||
("/", Number(l), Number(r)) if r != 0.0 => Number(l / r),
|
||||
("%", Number(l), Number(r)) => Number(l % r),
|
||||
("<", Number(l), Number(r)) => if l < r { truthy } else { falsy },
|
||||
("<=", Number(l), Number(r)) => if l <= r { truthy } else { falsy },
|
||||
(">", Number(l), Number(r)) => if l > r { truthy } else { falsy },
|
||||
(">=", Number(l), Number(r)) => if l >= r { truthy } else { falsy },
|
||||
("==", Number(l), Number(r)) => if l == r { truthy } else { falsy },
|
||||
("==", Null, Null) => truthy,
|
||||
("==", StringLiteral(s1), StringLiteral(s2)) => if s1 == s2 { truthy } else { falsy },
|
||||
("==", _, _) => falsy,
|
||||
match (op, left, right) {
|
||||
(Add, Number(l), Number(r)) => Number(l + r),
|
||||
(Add, StringLiteral(s1), StringLiteral(s2)) => StringLiteral(Rc::new(format!("{}{}", *s1, *s2))),
|
||||
(Add, StringLiteral(s1), Number(r)) => StringLiteral(Rc::new(format!("{}{}", *s1, r))),
|
||||
(Add, Number(l), StringLiteral(s1)) => StringLiteral(Rc::new(format!("{}{}", l, *s1))),
|
||||
(Sub, Number(l), Number(r)) => Number(l - r),
|
||||
(Mul, Number(l), Number(r)) => Number(l * r),
|
||||
(Div, Number(l), Number(r)) if r != 0.0 => Number(l / r),
|
||||
(Mod, Number(l), Number(r)) => Number(l % r),
|
||||
(Less, Number(l), Number(r)) => if l < r { truthy } else { falsy },
|
||||
(LessEq, Number(l), Number(r)) => if l <= r { truthy } else { falsy },
|
||||
(Greater, Number(l), Number(r)) => if l > r { truthy } else { falsy },
|
||||
(GreaterEq, Number(l), Number(r)) => if l >= r { truthy } else { falsy },
|
||||
(Equal, Number(l), Number(r)) => if l == r { truthy } else { falsy },
|
||||
(Equal, Null, Null) => truthy,
|
||||
(Equal, StringLiteral(s1), StringLiteral(s2)) => if s1 == s2 { truthy } else { falsy },
|
||||
(Equal, _, _) => falsy,
|
||||
_ => falsy,
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ pub enum Expression {
|
||||
StringLiteral(Rc<String>),
|
||||
Number(f64),
|
||||
Variable(Rc<String>),
|
||||
BinExp(Rc<String>, Box<Expression>, Box<Expression>),
|
||||
BinExp(BinOp, Box<Expression>, Box<Expression>),
|
||||
Call(Callable, Vec<Expression>),
|
||||
Conditional(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
|
||||
Lambda(Function),
|
||||
@ -94,7 +94,7 @@ impl fmt::Display for Expression {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Op {
|
||||
pub enum BinOp {
|
||||
Add,
|
||||
AddAssign,
|
||||
Sub,
|
||||
@ -113,10 +113,10 @@ pub enum Op {
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Op {
|
||||
fn from(s: &'a str) -> Op {
|
||||
use self::Op::*;
|
||||
match s {
|
||||
impl From<OpTok> for BinOp {
|
||||
fn from(token: OpTok) -> BinOp {
|
||||
use self::BinOp::*;
|
||||
match &token.0[..] {
|
||||
"+" => Add,
|
||||
"+=" => AddAssign,
|
||||
"-" => Sub,
|
||||
@ -132,7 +132,7 @@ impl<'a> From<&'a str> for Op {
|
||||
">=" => GreaterEq,
|
||||
"==" => Equal,
|
||||
"=" => Assign,
|
||||
op => Custom(op.to_string()),
|
||||
op => Custom(op.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -380,7 +380,7 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
lhs = Expression::BinExp(op.0, Box::new(lhs), Box::new(rhs));
|
||||
lhs = Expression::BinExp(op.into(), Box::new(lhs), Box::new(rhs));
|
||||
}
|
||||
Ok(lhs)
|
||||
}
|
||||
@ -569,17 +569,17 @@ mod tests {
|
||||
fn expression_parse_test() {
|
||||
parsetest!("a", &[ExprNode(Variable(ref s))], **s == "a");
|
||||
parsetest!("a + b",
|
||||
&[ExprNode(BinExp(ref plus, box Variable(ref a), box Variable(ref b)))],
|
||||
**plus == "+" && **a == "a" && **b == "b");
|
||||
&[ExprNode(BinExp(Op::Plus, box Variable(ref a), box Variable(ref b)))],
|
||||
**a == "a" && **b == "b");
|
||||
parsetest!("a + b * c",
|
||||
&[ExprNode(BinExp(ref plus, box Variable(ref a), box BinExp(ref mul, box Variable(ref b), box Variable(ref c))))],
|
||||
**plus == "+" && **mul == "*" && **a == "a" && **b == "b" && **c == "c");
|
||||
&[ExprNode(BinExp(Op::Plus, box Variable(ref a), box BinExp(Op::Mul, box Variable(ref b), box Variable(ref c))))],
|
||||
**a == "a" && **b == "b" && **c == "c");
|
||||
parsetest!("a * b + c",
|
||||
&[ExprNode(BinExp(ref plus, box BinExp(ref mul, box Variable(ref a), box Variable(ref b)), box Variable(ref c)))],
|
||||
**plus == "+" && **mul == "*" && **a == "a" && **b == "b" && **c == "c");
|
||||
&[ExprNode(BinExp(Op::Plus, box BinExp(Op::Mul, box Variable(ref a), box Variable(ref b)), box Variable(ref c)))],
|
||||
**a == "a" && **b == "b" && **c == "c");
|
||||
parsetest!("(a + b) * c",
|
||||
&[ExprNode(BinExp(ref mul, box BinExp(ref plus, box Variable(ref a), box Variable(ref b)), box Variable(ref c)))],
|
||||
**plus == "+" && **mul == "*" && **a == "a" && **b == "b" && **c == "c");
|
||||
&[ExprNode(BinExp(Op::Mul, box BinExp(Op::Plus, box Variable(ref a), box Variable(ref b)), box Variable(ref c)))],
|
||||
**a == "a" && **b == "b" && **c == "c");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user