diff --git a/build.rs b/build.rs index 50fe205..266ae6b 100644 --- a/build.rs +++ b/build.rs @@ -77,7 +77,8 @@ fn generate_tests(f: &mut File, path_so_far: PathBuf) -> std::io::Result<()> { f, " let ir = syntax.type_infer().expect(\"example is typed correctly\");" )?; - writeln!(f, " let ir_result = ir.eval();")?; + writeln!(f, " let ir_evaluator = crate::ir::Evaluator::default();")?; + writeln!(f, " let ir_result = ir_evaluator.eval(ir.clone());")?; writeln!(f, " match (&syntax_result, &ir_result) {{")?; writeln!(f, " (Err(e1), Err(e2)) => assert_eq!(e1, e2),")?; writeln!(f, " (Ok((v1, o1)), Ok((v2, o2))) => {{")?; diff --git a/examples/basic/generated0004.ngr b/examples/basic/generated0004.ngr new file mode 100644 index 0000000..736e241 --- /dev/null +++ b/examples/basic/generated0004.ngr @@ -0,0 +1,150 @@ +d3347 = { + s3349 = v3348 = 17175152522826808410u64; + print s3349; + j3350 = -6926831316600240717i64; + g3351 = b3352 = print s3349; + g3351; + u3353 = v3348; + c3460 = p3354 = { + w3441 = u3355 = k3356 = v3357 = { + j3364 = b3358 = b3359 = { + e3363 = o3360 = a3361 = n3362 = v3348 * v3348; + print e3363; + a3361 + }; + v3365 = j3364; + o3376 = { + p3366 = 62081u16; + t3369 = { + k3367 = 3742184609455079849u64; + y3368 = print g3351; + k3367 + }; + e3371 = o3370 = p3366; + print s3349; + l3372 = 50u8; + g3373 = 1086766998u32; + u3374 = g3373; + p3375 = 13826883074707422152u64 + }; + h3379 = v3377 = h3378 = 1513207896u32; + x3382 = f3380 = i3381 = -72i8; + a3383 = g3351; + q3440 = q3384 = { + r3385 = v3365; + z3437 = n3386 = { + o3387 = -1428233008i32; + c3388 = s3349; + b3352; + c3389 = c3388; + a3383; + c3390 = 1056u16; + l3433 = { + b3392 = f3391 = -881200191i32; + print o3376; + print v3377; + h3395 = y3393 = j3394 = -2456592492064497053i64; + c3396 = c3388; + f3397 = 2442824079u32; + d3428 = { + n3400 = h3398 = m3399 = v3365; + j3401 = v3348; + t3402 = -10i8; + e3403 = g3404 = print r3385; + e3403; + d3425 = { + u3405 = 51313u16; + l3406 = 235u8; + l3407 = 7030u16; + i3413 = { + b3352; + v3408 = o3387; + i3409 = 42u8; + q3411 = { + u3410 = -70i8; + n3400 + }; + q3412 = print i3409; + x3382 + }; + z3414 = b3392; + j3417 = s3415 = o3416 = 7220082853233268797u64; + print i3381; + n3419 = a3418 = -1270109327i32; + o3420 = r3385; + o3421 = x3382; + j3422 = print i3381; + q3423 = -4497i16; + x3424 = -98995788i32; + f3391 + }; + { + x3426 = r3385 - 13032422114254415490u64; + e3427 = -51i8; + j3401 + } + }; + k3429 = c3396; + print j3350; + g3351; + f3430 = -12293i16; + v3431 = 4016608549u32; + t3432 = f3397; + f3391 - -716040069i32 + }; + r3434 = -12984i16; + s3435 = 293908485953501586u64; + { + print j3364; + h3436 = 7732092399687242928u64 + } + }; + u3438 = v3377 * 3168795739u32; + p3439 = -12313i16; + u3438 + }; + v3348 + }; + x3442 = -5279281110772475785i64; + y3443 = v3348; + b3444 = 2732851783u32; + l3456 = l3445 = { + v3446 = -27499i16; + i3447 = 3517560837u32; + z3448 = u3353 * u3355; + u3449 = x3442; + t3450 = u3353; + m3452 = n3451 = u3355; + b3453 = m3452; + x3455 = t3454 = 2134443760u32; + print b3444; + b3444 + }; + c3457 = l3456; + g3351; + m3458 = 1822439673528019141u64; + d3459 = l3456 + }; + k3462 = f3461 = 13u8; + g3351; + u3463 = -10083i16; + v3348 +}; +y3464 = { + y3465 = 163u8; + y3466 = -7760i16; + e3467 = d3347; + q3468 = 58708u16; + -426970972827051249i64 +}; +t3469 = 524885465u32; +function b3470 (y3471,c3472,u3473) 1606677228u32; +y3464; +-240502590i32; +v3474 = z3475 = { + t3476 = y3464; + p3477 = t3469; + i3478 = p3477; + a3480 = e3479 = t3476; + p3477 +}; \ No newline at end of file diff --git a/src/backend/eval.rs b/src/backend/eval.rs index fce0da9..227a48a 100644 --- a/src/backend/eval.rs +++ b/src/backend/eval.rs @@ -120,15 +120,6 @@ proptest::proptest! { #[test] fn static_backend(program in Program::arbitrary()) { use crate::eval::PrimOpError; - - let basic_result = program.eval().map(|(_,x)| x); - - // windows `printf` is going to terminate lines with "\r\n", so we need to adjust - // our test result here. - #[cfg(target_family="windows")] - let basic_result = basic_result.map(|x| x.replace('\n', "\r\n")); - - if !matches!(basic_result, Err(EvalError::PrimOp(PrimOpError::MathFailure(_)))) { use pretty::DocAllocator; let allocator = pretty::Arena::new(); let result = allocator.text("-------------") @@ -138,6 +129,28 @@ proptest::proptest! { result.render_raw(70, &mut pretty::IoWrite::new(std::io::stdout())) .expect("rendering works"); + + eprintln!("BEFORE EVAL"); + let ir_evaluator = crate::ir::Evaluator::default(); + let basic_result = ir_evaluator.eval(program.clone()).map(|(_,o)| o); + eprintln!("AFTER EVAL"); + + // windows `printf` is going to terminate lines with "\r\n", so we need to adjust + // our test result here. + #[cfg(target_family="windows")] + let basic_result = basic_result.map(|x| x.replace('\n', "\r\n")); + + if !matches!(basic_result, Err(EvalError::PrimOp(PrimOpError::MathFailure(_)))) { + //use pretty::DocAllocator; + //let allocator = pretty::Arena::new(); + //let result = allocator.text("-------------") + // .append(allocator.line()) + // .append(program.pretty(&allocator)) + // .append(allocator.line()); + //result.render_raw(70, &mut pretty::IoWrite::new(std::io::stdout())) + // .expect("rendering works"); + + eprintln!("BEFORE OM EVAL"); let compiled_result = Backend::::eval(program); proptest::prop_assert_eq!(basic_result, compiled_result); } @@ -159,7 +172,8 @@ proptest::proptest! { // .render_colored(70, pretty::termcolor::StandardStream::stdout(pretty::termcolor::ColorChoice::Auto)) // .expect("rendering works"); - let basic_result = program.eval().map(|(_,x)| x); + let ir_evaluator = crate::ir::Evaluator::default(); + let basic_result = ir_evaluator.eval(program.clone()).map(|(_,o)| o); if !matches!(basic_result, Err(EvalError::PrimOp(PrimOpError::MathFailure(_)))) { let compiled_result = Backend::::eval(program); diff --git a/src/backend/into_crane.rs b/src/backend/into_crane.rs index a92a90c..68f98f7 100644 --- a/src/backend/into_crane.rs +++ b/src/backend/into_crane.rs @@ -500,7 +500,7 @@ impl Backend { .into_iter() .unzip(); - match *function { + match function { ValueOrRef::Value(_, _, _) => { panic!("Can't use a value for a function") } @@ -568,10 +568,7 @@ impl Backend { Primitive::Negate => { assert_eq!(1, arguments.len()); - Ok(( - builder.ins().ineg(arguments[0]), - argument_types[0], - )) + Ok((builder.ins().ineg(arguments[0]), argument_types[0])) } Primitive::Print => { diff --git a/src/bin/ngrun.rs b/src/bin/ngrun.rs index 80a06bb..0cc42ec 100644 --- a/src/bin/ngrun.rs +++ b/src/bin/ngrun.rs @@ -102,7 +102,8 @@ fn main() { }; if cli.interpreter == Interpreter::IR { - match ir.eval() { + let evaluator = ngr::ir::Evaluator::default(); + match evaluator.eval(ir) { Err(e) => tracing::error!(error = %e, "Evaluation error"), Ok(v) => print_result(v), } diff --git a/src/eval/primtype.rs b/src/eval/primtype.rs index 19a8dd4..c714627 100644 --- a/src/eval/primtype.rs +++ b/src/eval/primtype.rs @@ -250,7 +250,7 @@ impl PrimitiveType { &[("+", 2), ("-", 2), ("*", 2), ("/", 2)] } PrimitiveType::I8 | PrimitiveType::I16 | PrimitiveType::I32 | PrimitiveType::I64 => { - &[("+", 2), ("-", 1), ("-", 2), ("*", 2), ("/", 2)] + &[("+", 2), ("negate", 1), ("-", 2), ("*", 2), ("/", 2)] } } } diff --git a/src/ir.rs b/src/ir.rs index 5308405..4b80658 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -21,3 +21,4 @@ mod strings; mod top_level; pub use ast::*; +pub use eval::Evaluator; diff --git a/src/ir/arbitrary.rs b/src/ir/arbitrary.rs index 072afc2..182c43b 100644 --- a/src/ir/arbitrary.rs +++ b/src/ir/arbitrary.rs @@ -359,11 +359,7 @@ fn generate_random_expression( Expression::Call( Location::manufactured(), out_type, - Box::new(ValueOrRef::Primitive( - Location::manufactured(), - primtype, - primop, - )), + ValueOrRef::Primitive(Location::manufactured(), primtype, primop), args, ) } @@ -393,11 +389,7 @@ fn generate_random_expression( Expression::Call( Location::manufactured(), Type::void(), - Box::new(ValueOrRef::Primitive( - Location::manufactured(), - Type::void(), - Primitive::Print, - )), + ValueOrRef::Primitive(Location::manufactured(), Type::void(), Primitive::Print), vec![ValueOrRef::Ref( Location::manufactured(), var_type.clone(), diff --git a/src/ir/ast.rs b/src/ir/ast.rs index 24ab128..9699fa3 100644 --- a/src/ir/ast.rs +++ b/src/ir/ast.rs @@ -114,7 +114,7 @@ pub enum Expression { ), FieldRef(Location, Type, Type, ValueOrRef, ArcIntern), Block(Location, Type, Vec>), - Call(Location, Type, Box>, Vec>), + Call(Location, Type, ValueOrRef, Vec>), Bind(Location, Variable, Type, Box>), } @@ -129,7 +129,7 @@ impl Expression { Expression::FieldRef(_, t, _, _, _) => t.clone(), Expression::Block(_, t, _) => t.clone(), Expression::Call(_, t, _, _) => t.clone(), - Expression::Bind(_, _, _, _) => Type::void(), + Expression::Bind(_, _, t, _) => t.clone(), } } diff --git a/src/ir/eval.rs b/src/ir/eval.rs index d74db44..aa88e21 100644 --- a/src/ir/eval.rs +++ b/src/ir/eval.rs @@ -3,60 +3,74 @@ use crate::eval::{EvalError, Value}; use crate::ir::{Expression, Program, TopLevel, Variable}; use crate::util::scoped_map::ScopedMap; use std::collections::HashMap; +use std::fmt::Display; type IRValue = Value>; type IREvalError = EvalError>; -impl> Program { +pub struct Evaluator { + env: ScopedMap>, + stdout: String, +} + +impl Default for Evaluator { + fn default() -> Self { + Evaluator { + env: ScopedMap::new(), + stdout: String::new(), + } + } +} + +impl Evaluator +where + T: Clone + Into, + Expression: Display, +{ /// Evaluate the program, returning either an error or the result of the final /// statement and the complete contents of the console output. /// /// The print outs will be newline separated, with one print out per line. - pub fn eval(&self) -> Result<(IRValue, String), IREvalError> { - let mut env: ScopedMap> = ScopedMap::new(); - let mut stdout = String::new(); + pub fn eval(mut self, program: Program) -> Result<(IRValue, String), IREvalError> { let mut last_value = Value::Void; - for stmt in self.items.iter() { + for stmt in program.items.into_iter() { match stmt { TopLevel::Function(name, args, _, body) => { let closure = Value::Closure( Some(name.clone()), - env.clone(), + self.env.clone(), args.iter().map(|(x, _)| x.clone()).collect(), body.clone(), ); - env.insert(name.clone(), closure.clone()); + self.env.insert(name.clone(), closure.clone()); last_value = closure; } TopLevel::Statement(expr) => { - last_value = expr.eval(&mut env, &mut stdout)?; + last_value = self.eval_expr(expr)?; } } } - Ok((last_value, stdout)) + Ok((last_value, self.stdout)) } -} -impl Expression -where - T: Clone + Into, -{ - fn eval( - &self, - env: &mut ScopedMap>, - stdout: &mut String, - ) -> Result, IREvalError> { - match self { - Expression::Atomic(x) => x.eval(env), + /// Get the current output of the evaluated program. + pub fn stdout(self) -> String { + self.stdout + } + + fn eval_expr(&mut self, expr: Expression) -> Result, IREvalError> { + println!("evaluating {}", expr); + match expr { + Expression::Atomic(x) => self.eval_atomic(x), Expression::Cast(_, t, valref) => { - let value = valref.eval(env)?; - let ty = t.clone().into(); + let value = self.eval_atomic(valref)?; + let ty = t.into(); match ty { Type::Primitive(pt) => Ok(pt.safe_cast(&value)?), @@ -68,15 +82,15 @@ where Expression::Construct(_, _, name, fields) => { let mut result_fields = HashMap::with_capacity(fields.len()); - for (name, subexpr) in fields.iter() { - result_fields.insert(name.clone(), subexpr.eval(env)?); + for (name, subexpr) in fields.into_iter() { + result_fields.insert(name.clone(), self.eval_atomic(subexpr)?); } Ok(Value::Structure(Some(name.clone()), result_fields)) } - Expression::FieldRef(loc, _, _, valref, field) => match valref.eval(env)? { - Value::Structure(oname, mut fields) => match fields.remove(field) { + Expression::FieldRef(loc, _, _, valref, field) => match self.eval_atomic(valref)? { + Value::Structure(oname, mut fields) => match fields.remove(&field) { None => Err(EvalError::NoFieldForValue( loc.clone(), Value::Structure(oname, fields), @@ -91,21 +105,21 @@ where Expression::Block(_, _, stmts) => { let mut result = Value::Void; - for stmt in stmts.iter() { - result = stmt.eval(env, stdout)?; + for stmt in stmts.into_iter() { + result = self.eval_expr(stmt)?; } Ok(result) } Expression::Bind(_, name, _, value) => { - let value = value.eval(env, stdout)?; - env.insert(name.clone(), value.clone()); + let value = self.eval_expr(*value)?; + self.env.insert(name.clone(), value.clone()); Ok(value) } Expression::Call(loc, _, fun, args) => { - let function = fun.eval(env)?; + let function = self.eval_atomic(fun)?; match function { Value::Closure(name, mut closure_env, arguments, body) => { @@ -120,20 +134,29 @@ where closure_env.new_scope(); for (name, value) in arguments.into_iter().zip(args) { - let value = value.eval(env)?; + let value = self.eval_atomic(value)?; closure_env.insert(name, value); } - let result = body.eval(&mut closure_env, stdout)?; + + let temp_ref = &mut closure_env; + + std::mem::swap(&mut self.env, temp_ref); + let result = self.eval_expr(body); + std::mem::swap(&mut self.env, temp_ref); closure_env.release_scope(); - Ok(result) + result } Value::Primitive(name) if name == "print" => { if let [ValueOrRef::Ref(loc, ty, name)] = &args[..] { - let value = ValueOrRef::Ref(loc.clone(), ty.clone(), name.clone()).eval(env)?; + let value = self.eval_atomic(ValueOrRef::Ref( + loc.clone(), + ty.clone(), + name.clone(), + ))?; let addendum = format!("{} = {}\n", name, value); - stdout.push_str(&addendum); + self.stdout.push_str(&addendum); Ok(Value::Void) } else { panic!("Non-reference/non-singleton argument to 'print'"); @@ -142,8 +165,8 @@ where Value::Primitive(name) => { let values = args - .iter() - .map(|x| x.eval(env)) + .into_iter() + .map(|x| self.eval_atomic(x)) .collect::>()?; println!("primitive {}: args {:?}", name, values); Value::calculate(name.as_str(), values).map_err(Into::into) @@ -154,25 +177,24 @@ where } } } -} -impl ValueOrRef { - fn eval(&self, env: &ScopedMap>) -> Result, IREvalError> { - match self { + fn eval_atomic(&self, value: ValueOrRef) -> Result, IREvalError> { + match value { ValueOrRef::Value(_, _, v) => match v { - super::Value::I8(_, v) => Ok(Value::I8(*v)), - super::Value::I16(_, v) => Ok(Value::I16(*v)), - super::Value::I32(_, v) => Ok(Value::I32(*v)), - super::Value::I64(_, v) => Ok(Value::I64(*v)), - super::Value::U8(_, v) => Ok(Value::U8(*v)), - super::Value::U16(_, v) => Ok(Value::U16(*v)), - super::Value::U32(_, v) => Ok(Value::U32(*v)), - super::Value::U64(_, v) => Ok(Value::U64(*v)), + super::Value::I8(_, v) => Ok(Value::I8(v)), + super::Value::I16(_, v) => Ok(Value::I16(v)), + super::Value::I32(_, v) => Ok(Value::I32(v)), + super::Value::I64(_, v) => Ok(Value::I64(v)), + super::Value::U8(_, v) => Ok(Value::U8(v)), + super::Value::U16(_, v) => Ok(Value::U16(v)), + super::Value::U32(_, v) => Ok(Value::U32(v)), + super::Value::U64(_, v) => Ok(Value::U64(v)), super::Value::Void => Ok(Value::Void), }, - ValueOrRef::Ref(loc, _, n) => env - .get(n) + ValueOrRef::Ref(loc, _, n) => self + .env + .get(&n) .cloned() .ok_or_else(|| EvalError::LookupFailed(loc.clone(), n.to_string())), @@ -185,8 +207,9 @@ impl ValueOrRef { fn two_plus_three() { let input = crate::syntax::Program::parse(0, "x = 2 + 3; print x;").expect("parse works"); let ir = input.type_infer().expect("test should be type-valid"); - let (_, output) = ir.eval().expect("runs successfully"); - assert_eq!("x = 5u64\n", &output); + let evaluator = Evaluator::default(); + let (_, result) = evaluator.eval(ir).expect("runs successfully"); + assert_eq!("x = 5u64\n", &result); } #[test] @@ -194,6 +217,7 @@ fn lotsa_math() { let input = crate::syntax::Program::parse(0, "x = 2 + 3 * 10 / 5 - 1; print x;").expect("parse works"); let ir = input.type_infer().expect("test should be type-valid"); - let (_, output) = ir.eval().expect("runs successfully"); - assert_eq!("x = 7u64\n", &output); + let evaluator = Evaluator::default(); + let (_, result) = evaluator.eval(ir).expect("runs successfully"); + assert_eq!("x = 7u64\n", &result); } diff --git a/src/syntax.rs b/src/syntax.rs index 26d0b36..6dd75d2 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -46,11 +46,9 @@ pub use crate::syntax::ast::*; pub use crate::syntax::location::Location; pub use crate::syntax::parser::{ProgramParser, TopLevelParser}; pub use crate::syntax::tokens::{LexerError, Token}; -#[cfg(test)] -use ::pretty::Arena; use lalrpop_util::ParseError; #[cfg(test)] -use proptest::{arbitrary::Arbitrary, prop_assert, prop_assert_eq}; +use proptest::{arbitrary::Arbitrary, prop_assert}; use std::ops::Range; #[cfg(test)] use std::str::FromStr; @@ -324,27 +322,6 @@ fn order_of_operations() { } proptest::proptest! { - #[test] - fn random_render_parses_equal(program: Program) { - let mut file_database = SimpleFiles::new(); - let writer = ::pretty::termcolor::StandardStream::stderr(::pretty::termcolor::ColorChoice::Auto); - let config = codespan_reporting::term::Config::default(); - let allocator = Arena::<()>::new(); - - let mut out_vector = vec![]; - prop_assert!(program.pretty(&allocator).render(80, &mut out_vector).is_ok()); - let string = std::str::from_utf8(&out_vector).expect("emitted valid string"); - let file_handle = file_database.add("test", string); - let file_db_info = file_database.get(file_handle).expect("find thing just inserted"); - let parsed = Program::parse(file_handle, file_db_info.source()); - - if let Err(e) = &parsed { - eprintln!("failed to parse:\n{}", string); - codespan_reporting::term::emit(&mut writer.lock(), &config, &file_database, &e.into()).unwrap(); - } - prop_assert_eq!(program, parsed.unwrap()); - } - #[test] fn random_syntaxes_validate(program: Program) { let (errors, _) = program.validate(); @@ -354,6 +331,8 @@ proptest::proptest! { #[test] fn generated_run_or_overflow(program in Program::arbitrary_with(GenerationEnvironment::new(false))) { use crate::eval::{EvalError, PrimOpError}; + println!("-----------\nprogram:\n{}\n", program); + println!("-----------\nresult:\n{:?}\n", program.eval()); prop_assert!(matches!(program.eval(), Ok(_) | Err(EvalError::PrimOp(PrimOpError::MathFailure(_))))); } } diff --git a/src/syntax/arbitrary.rs b/src/syntax/arbitrary.rs index 44bd323..e9ab301 100644 --- a/src/syntax/arbitrary.rs +++ b/src/syntax/arbitrary.rs @@ -15,7 +15,7 @@ impl ConstantType { match self { ConstantType::Void => &[], ConstantType::I8 | ConstantType::I16 | ConstantType::I32 | ConstantType::I64 => { - &[("+", 2), ("-", 1), ("-", 2), ("*", 2), ("/", 2)] + &[("+", 2), ("negate", 1), ("-", 2), ("*", 2), ("/", 2)] } ConstantType::U8 | ConstantType::U16 | ConstantType::U32 | ConstantType::U64 => { &[("+", 2), ("-", 2), ("*", 2), ("/", 2)] diff --git a/src/syntax/eval.rs b/src/syntax/eval.rs index f4635f7..d6185ec 100644 --- a/src/syntax/eval.rs +++ b/src/syntax/eval.rs @@ -146,7 +146,8 @@ impl Expression { Value::Primitive(name) if name == "print" => { if let [Expression::Reference(_, name)] = &args[..] { - let value = Expression::Reference(loc.clone(), name.clone()).eval(stdout, env)?; + let value = Expression::Reference(loc.clone(), name.clone()) + .eval(stdout, env)?; let value = match value { Value::Number(x) => Value::U64(x), x => x, @@ -156,7 +157,10 @@ impl Expression { stdout.push_str(&addendum); Ok(Value::Void) } else { - panic!("Non-reference/non-singleton argument to 'print': {:?}", args); + panic!( + "Non-reference/non-singleton argument to 'print': {:?}", + args + ); } } diff --git a/src/type_infer.rs b/src/type_infer.rs index 31916dd..475bf9f 100644 --- a/src/type_infer.rs +++ b/src/type_infer.rs @@ -44,7 +44,8 @@ proptest::proptest! { fn translation_maintains_semantics(input in syntax::Program::arbitrary_with(GenerationEnvironment::new(false))) { let syntax_result = input.eval().map(|(x,o)| (x.strip(), o)); let ir = input.type_infer().expect("arbitrary should generate type-safe programs"); - let ir_result = ir.eval().map(|(x,o)| (x.strip(), o)); + let ir_evaluator = crate::ir::Evaluator::default(); + let ir_result = ir_evaluator.eval(ir).map(|(x, o)| (x.strip(), o)); match (syntax_result, ir_result) { (Err(e1), Err(e2)) => proptest::prop_assert_eq!(e1, e2), (Ok((v1, o1)), Ok((v2, o2))) => { diff --git a/src/type_infer/convert.rs b/src/type_infer/convert.rs index fb69cba..02cb653 100644 --- a/src/type_infer/convert.rs +++ b/src/type_infer/convert.rs @@ -360,10 +360,8 @@ fn convert_expression( let arg_type = ir::TypeOrVar::new_located(loc.clone()); constraint_db.push(Constraint::NumericType(loc.clone(), arg_type.clone())); constraint_db.push(Constraint::IsSigned(loc.clone(), arg_type.clone())); - let funtype = ir::TypeOrVar::Function( - vec![arg_type.clone()], - Box::new(arg_type), - ); + let funtype = + ir::TypeOrVar::Function(vec![arg_type.clone()], Box::new(arg_type)); let result_value = ir::ValueOrRef::Primitive(loc, funtype.clone(), primop); (ir::Expression::Atomic(result_value), funtype) } @@ -409,8 +407,7 @@ fn convert_expression( }) .collect(); - let last_call = - ir::Expression::Call(loc.clone(), return_type.clone(), Box::new(fun), new_args); + let last_call = ir::Expression::Call(loc.clone(), return_type.clone(), fun, new_args); (finalize_expressions(prereqs, last_call), return_type) } diff --git a/src/type_infer/finalize.rs b/src/type_infer/finalize.rs index 7f12adb..624bbe8 100644 --- a/src/type_infer/finalize.rs +++ b/src/type_infer/finalize.rs @@ -91,7 +91,7 @@ fn finalize_expression( Expression::Call(loc, ty, fun, args) => Expression::Call( loc, finalize_type(ty, resolutions), - Box::new(finalize_val_or_ref(*fun, resolutions)), + finalize_val_or_ref(fun, resolutions), args.into_iter() .map(|x| finalize_val_or_ref(x, resolutions)) .collect(),