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