Skip to content

Commit

Permalink
Merge pull request #374 from CohenArthur/feature/improve-parser
Browse files Browse the repository at this point in the history
Improve parser logic and performance
  • Loading branch information
CohenArthur authored Nov 29, 2021
2 parents 47c57e6 + 5d3fecc commit 775639a
Show file tree
Hide file tree
Showing 42 changed files with 1,298 additions and 2,378 deletions.
14 changes: 5 additions & 9 deletions interpreter/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ mod prompt;
use prompt::Prompt;
use std::path::PathBuf;

use jinko::{CheckedType, TypeCheck, TypeCtx};
use jinko::{
Construct, Context, Error, FromObjectInstance, Instruction, JkConstant, ObjectInstance,
constructs, Context, Error, FromObjectInstance, Instruction, JkConstant, ObjectInstance,
};
use jinko::{CheckedType, TypeCheck, TypeCtx};

use linefeed::{DefaultTerminal, Interface, ReadResult};
use crate::{Args, InteractResult};

use crate::args::Args;
use crate::InteractResult;
use linefeed::{DefaultTerminal, Interface, ReadResult};

struct ReplInstance(ObjectInstance);

Expand Down Expand Up @@ -49,7 +48,7 @@ impl<'args> Repl<'args> {
fn parse_instruction(input: &str) -> Result<Option<Box<dyn Instruction>>, Error> {
match input.is_empty() {
true => Ok(None),
false => match Construct::instruction(input) {
false => match constructs::expr(input) {
Ok((_, value)) => Ok(Some(value)),
Err(e) => Err(Error::from(e)),
},
Expand Down Expand Up @@ -83,9 +82,6 @@ impl<'args> Repl<'args> {
ep.instructions().iter().for_each(|inst| {
inst.execute(ctx);
});
if let Some(last) = ep.last() {
last.execute(ctx);
}

ctx.emit_errors();
}
Expand Down
14 changes: 7 additions & 7 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ impl Context {
entry_point.instructions().iter().for_each(|inst| {
inst.resolve_type(&mut ctx);
});
entry_point.last().map(|l| l.resolve_type(&mut ctx));

self.included.clear();
match self.error_handler.has_errors() {
Expand All @@ -295,17 +294,18 @@ impl Context {

self.type_check(&ep)?;

ep.instructions().iter().for_each(|inst| {
inst.execute(self);
});

let res = ep.last().map(|last| last.execute(self));
let res = ep
.instructions()
.iter()
.map(|inst| inst.execute(self))
.last()
.flatten();

self.emit_errors();

match self.error_handler.has_errors() {
true => Err(Error::new(ErrKind::Context)),
false => Ok(res.flatten()),
false => Ok(res),
}
}

Expand Down
14 changes: 5 additions & 9 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ pub fn execute(
mod tests {
use super::*;
use crate::jinko;
use crate::parser::Construct;
use crate::parser::constructs;
use crate::{JkInt, ToObjectInstance};

fn init_ctx() -> Context {
Expand All @@ -181,11 +181,9 @@ mod tests {
fn t_void_int() {
let mut i = init_ctx();

let dec = Construct::instruction("ext func no_arg() -> int;")
.unwrap()
.1;
let dec = constructs::expr("ext func no_arg() -> int;").unwrap().1;
let dec = dec.downcast_ref::<FunctionDec>().unwrap();
let call = Construct::instruction("no_arg()").unwrap().1;
let call = constructs::expr("no_arg()").unwrap().1;
let call = call.downcast_ref::<FunctionCall>().unwrap();

assert_eq!(
Expand All @@ -198,11 +196,9 @@ mod tests {
fn t_void_void() {
let mut i = init_ctx();

let dec = Construct::instruction("ext func print_something();")
.unwrap()
.1;
let dec = constructs::expr("ext func print_something();").unwrap().1;
let dec = dec.downcast_ref::<FunctionDec>().unwrap();
let call = Construct::instruction("print_something()").unwrap().1;
let call = constructs::expr("print_something()").unwrap().1;
let call = call.downcast_ref::<FunctionCall>().unwrap();

assert_eq!(execute(&dec, &call, &mut i), Ok(None));
Expand Down
22 changes: 8 additions & 14 deletions src/instance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,29 +169,23 @@ pub trait FromObjectInstance {
#[cfg(test)]
mod tests {
use super::*;
use crate::{parser::Construct, Context, JkInt};
use crate::{parser::constructs, Context, JkInt};

fn setup() -> Context {
let mut ctx = Context::new();

let inst = Construct::instruction("type Point(x: int, y: int); ")
.unwrap()
.1;
let inst = constructs::expr("type Point(x: int, y: int); ").unwrap().1;
inst.execute(&mut ctx);

let inst = Construct::instruction("type Vec2(f: Point, s: Point); ")
let inst = constructs::expr("type Vec2(f: Point, s: Point); ")
.unwrap()
.1;
inst.execute(&mut ctx);

let inst = Construct::instruction("p = Point { x = 1, y = 2}")
.unwrap()
.1;
let inst = constructs::expr("p = Point ( x : 1, y : 2)").unwrap().1;
inst.execute(&mut ctx);

let inst = Construct::instruction("v = Vec2 { f = p, s = p}")
.unwrap()
.1;
let inst = constructs::expr("v = Vec2 ( f : p, s : p)").unwrap().1;
inst.execute(&mut ctx);

ctx
Expand All @@ -201,10 +195,10 @@ mod tests {
fn t_one_deep_access() {
let mut ctx = setup();

let inst = Construct::instruction("p").unwrap().1;
let inst = constructs::expr("p").unwrap().1;
let p = inst.execute(&mut ctx).unwrap();

let inst = Construct::instruction("v").unwrap().1;
let inst = constructs::expr("v").unwrap().1;
let v = inst.execute(&mut ctx).unwrap();
let v_f = v.get_field("f").unwrap();
let v_s = v.get_field("s").unwrap();
Expand All @@ -217,7 +211,7 @@ mod tests {
fn t_two_deep_access() {
let mut ctx = setup();

let inst = Construct::instruction("v").unwrap().1;
let inst = constructs::expr("v").unwrap().1;
let v = inst.execute(&mut ctx).unwrap();
let v_f = v.get_field("f").unwrap();
let v_s = v.get_field("s").unwrap();
Expand Down
201 changes: 155 additions & 46 deletions src/instruction/binary_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,52 +148,6 @@ mod tests {
use crate::ToObjectInstance;
use crate::{jinko, jinko_fail};

fn binop_assert(l_num: i64, r_num: i64, op_string: &str, res: i64) {
let l = Box::new(JkInt::from(l_num));
let r = Box::new(JkInt::from(r_num));
let op = Operator::new(op_string);

let binop = BinaryOp::new(l, r, op);

let mut i = Context::new();

assert_eq!(
binop.execute(&mut i).unwrap(),
JkInt::from(res).to_instance(),
);
assert!(!i.error_handler.has_errors());
}

#[test]
fn t_binop_add_same() {
binop_assert(12, 12, "+", 24);
}

#[test]
fn t_binop_add_l_diff() {
binop_assert(12, 2, "+", 14);
}

#[test]
fn t_binop_add_r_diff() {
binop_assert(2, 99, "+", 101);
}

#[test]
fn t_binop_mul_same() {
binop_assert(12, 12, "*", 144);
}

#[test]
fn t_binop_mul_l_diff() {
binop_assert(12, 2, "*", 24);
}

#[test]
fn t_binop_mul_r_diff() {
binop_assert(2, 99, "*", 198);
}

#[test]
fn t_binop_rhs_execute() {
let r_bin = BinaryOp::new(
Expand Down Expand Up @@ -240,6 +194,48 @@ mod tests {
assert!(!i.error_handler.has_errors());
}

fn assert_bool(input: &str, value: bool) {
use crate::JkBool;

let boxed_output = crate::parser::constructs::expr(input).unwrap().1;
let output = boxed_output.downcast_ref::<BinaryOp>().unwrap();

let mut i = Context::new();

assert_eq!(
output.execute(&mut i).unwrap(),
JkBool::from(value).to_instance()
);
}

#[test]
#[allow(clippy::eq_op)]
fn comparison_simple_int() {
assert_bool("1 < 4", 1 < 4);
assert_bool("4 < 1", 4 < 1);
assert_bool("1 <= 4", 1 <= 4);
assert_bool("4 <= 1", 4 <= 1);
assert_bool("1 == 1", 1 == 1);
assert_bool("4 != 1", 4 != 1);
}

#[test]
fn comparison_simple_float() {
assert_bool("1.0 < 4.0", 1.0 < 4.0);
assert_bool("4.0 < 1.0", 4.0 < 1.0);
assert_bool("1.0 <= 4.0", 1.0 <= 4.0);
assert_bool("4.0 <= 1.0", 4.0 <= 1.0);
}

#[test]
#[ignore]
fn comparison_precedence() {
assert_bool(
"1 + 4 * 2 - 1 + 2 * (14 + (2 - 17) * 1) - 12 + 3 / 2 < 45",
1 + 4 * 2 - 1 + 2 * (14 + (2 - 17) * 1) - 12 + 3 / 2 < 45,
);
}

#[test]
fn tc_binop_valid() {
jinko! {
Expand All @@ -263,4 +259,117 @@ mod tests {
t2 = 1.0 + "hey";
};
}

macro_rules! binop_assert {
($expr:expr) => {{
let mut ctx = Context::new();
let expr = crate::parser::constructs::expr(stringify!($expr))
.unwrap()
.1;

assert_eq!(
expr.execute(&mut ctx).unwrap(),
JkInt::from($expr).to_instance()
);
}};
}

#[test]
fn t_binop_add_same() {
binop_assert!(12 + 12);
}

#[test]
fn t_binop_add_l_diff() {
binop_assert!(12 + 2);
}

#[test]
fn t_binop_add_r_diff() {
binop_assert!(2 + 99);
}

#[test]
fn t_binop_mul_same() {
binop_assert!(12 * 12);
}

#[test]
fn t_binop_mul_l_diff() {
binop_assert!(12 * 2);
}

#[test]
fn t_binop_mul_r_diff() {
binop_assert!(2 * 99);
}

#[test]
fn binop_parentheses_execute() {
binop_assert!(4 * (3 + 4))
}

#[test]
fn binop_easy() {
binop_assert!(5 + 7)
}

fn binop_execute_execute_natural_order() {
binop_assert!(4 + 7 + 3);
}

#[test]
fn binop_execute_execute_mult_priority() {
binop_assert!(4 + 2 * 3);
}

#[test]
fn binop_execute_execute_mult_natural_priority() {
binop_assert!(2 * 3 + 4);
}

#[test]
fn binop_execute_valid_add() {
binop_assert!(1 + 2);
}

#[test]
fn binop_execute_valid_mul() {
binop_assert!(1 * 2);
}

#[test]
fn binop_execute_valid_normal_priority() {
binop_assert!(1 * 2 + 3);
}

#[test]
fn binop_execute_valid_back_priority() {
binop_assert!(3 + 1 * 2);
}

#[test]
fn binop_execute_valid_parentheses_priority() {
binop_assert!((3 + 1) * 2);
}

#[test]
fn binop_execute_valid_parentheses_priority_reverse() {
binop_assert!(2 * (3 + 1));
}

#[test]
fn binop_execute_valid_complex_expr() {
binop_assert!(1 + 4 * 2 - 1 + 2);
}

#[test]
fn binop_execute_valid_multi_expr() {
binop_assert!(3 + 4 * 2 + 5);
}

#[test]
fn binop_execute_valid_extremely_complex_expr() {
binop_assert!(1 + 4 * 2 - 1 + 2 * (14 + (2 - 17) * 1) - 12 + 3 / 2);
}
}
Loading

0 comments on commit 775639a

Please sign in to comment.