diff --git a/package/origlang-cli/src/args.rs b/package/origlang-cli/src/args.rs index c2cc612a..7dce5529 100644 --- a/package/origlang-cli/src/args.rs +++ b/package/origlang-cli/src/args.rs @@ -98,7 +98,6 @@ pub enum EmitPhase { LexerToken, Ast, TypedAst, - Ir0, Ir1, Ir2, } diff --git a/package/origlang-cli/src/task/emit.rs b/package/origlang-cli/src/task/emit.rs index be147bb2..71d903eb 100644 --- a/package/origlang-cli/src/task/emit.rs +++ b/package/origlang-cli/src/task/emit.rs @@ -73,15 +73,6 @@ impl Task for UnstableEmit { let the_lower = TheTranspiler::new(optimizer); - if self.phase == EmitPhase::Ir0 { - let ir_sequence = the_lower.optimizer().optimize(ir_sequence); - - println!("{ir_sequence:#?}"); - return Ok(()) - } - - let ir_sequence = the_lower.lower(ir_sequence); - if self.phase == EmitPhase::Ir1 { let ir_sequence: Vec = the_lower.optimizer().optimize(ir_sequence); diff --git a/package/origlang-cli/src/task/interpret.rs b/package/origlang-cli/src/task/interpret.rs index d79d433d..f92c2a20 100644 --- a/package/origlang-cli/src/task/interpret.rs +++ b/package/origlang-cli/src/task/interpret.rs @@ -33,8 +33,7 @@ impl Task for Interpret { let transpiler = TheTranspiler::new(&NoOptimization); let ir = root_ast.into_ir(); let ir = transpiler.lower(ir); - let ir = transpiler.lower(ir); - runtime.start(ir); + runtime.start(&ir); eprintln!("runtime.run: {:?}", i.elapsed()); Ok(()) } diff --git a/package/origlang-cli/src/task/repl.rs b/package/origlang-cli/src/task/repl.rs index cee2fc19..ce90980a 100644 --- a/package/origlang-cli/src/task/repl.rs +++ b/package/origlang-cli/src/task/repl.rs @@ -31,8 +31,6 @@ impl Repl { fn naive_lower(tra: TypedRootAst) -> Vec { let ir = tra.into_ir(); let trans = TheTranspiler::new(&NoOptimization); - let ir = trans.lower(ir); - trans.lower(ir) } @@ -64,7 +62,7 @@ impl Task for Repl { match parser.parse() { Ok(ast) => { let ast = checker.check(ast)?; - runtime.start(Self::naive_lower(ast)); + runtime.start(&Self::naive_lower(ast)); } Err(error_message) => { let error = error_message.kind; diff --git a/package/origlang-compiler-entrypoint/src/lib.rs b/package/origlang-compiler-entrypoint/src/lib.rs index d51270a5..e47a1712 100644 --- a/package/origlang-compiler-entrypoint/src/lib.rs +++ b/package/origlang-compiler-entrypoint/src/lib.rs @@ -11,7 +11,7 @@ use origlang_compiler::parser::{Parser, SimpleErrorWithPos}; use origlang_compiler::type_check::error::TypeCheckError; use origlang_compiler::type_check::TypeChecker; use origlang_diagnostics::{Diagnostic, DiagnosticSink}; -use origlang_ir::{IntoVerbatimSequencedIR, IR0, IR1, IR2}; +use origlang_ir::{IntoVerbatimSequencedIR, IR1, IR2}; use origlang_ir_optimizer::lower::{LowerStep, TheTranspiler}; use origlang_ir_optimizer::preset::{NoOptimization, OptimizationPreset}; @@ -63,7 +63,7 @@ impl TheCompiler { optimization_preset: &self.optimization_preset }; - let ir1_seq = the_transpiler.lower(ir0_seq); + let ir1_seq = ir0_seq; let (pre, post): (Vec<_>, Vec<_>) = self.scanner.ir1_scanner.iter().partition(|x| matches!(x, PreOrPost::Pre(..))); @@ -146,7 +146,6 @@ pub trait Scanner { } pub struct OptimizationPresetCollection { - pub ir0: Box>, pub ir1: Box>, pub ir2: Box>, } @@ -154,7 +153,6 @@ pub struct OptimizationPresetCollection { impl OptimizationPresetCollection { fn none() -> Self { Self { - ir0: Box::new(NoOptimization) as Box<_>, ir1: Box::new(NoOptimization) as Box<_>, ir2: Box::new(NoOptimization) as Box<_>, } @@ -171,6 +169,5 @@ macro_rules! delegate_optimization_to_field { }; } -delegate_optimization_to_field!(ir0, IR0); delegate_optimization_to_field!(ir1, IR1); delegate_optimization_to_field!(ir2, IR2); diff --git a/package/origlang-interop/src/lib.rs b/package/origlang-interop/src/lib.rs index d051e0bb..e5592aa8 100644 --- a/package/origlang-interop/src/lib.rs +++ b/package/origlang-interop/src/lib.rs @@ -121,9 +121,8 @@ pub fn run() { let lower = typed_root.into_ir(); let _ = Timer::new("runtime.ir.lower"); let lower = transpiler.lower(lower); - let lower = transpiler.lower(lower); let _ = Timer::new("runtime.start"); - runtime.start(lower); + runtime.start(&lower); } Ok(()) diff --git a/package/origlang-ir-optimizer/src/ir0.rs b/package/origlang-ir-optimizer/src/ir0.rs deleted file mode 100644 index 6c1faff5..00000000 --- a/package/origlang-ir-optimizer/src/ir0.rs +++ /dev/null @@ -1,12 +0,0 @@ -use origlang_ir::IR0; - -pub struct EliminateAfterExit(pub Vec); - -impl EliminateAfterExit { - #[must_use = "return value is optimized IR, dropping it will waste it"] - pub fn optimize(self) -> Vec { - let mut x = self.0.into_iter().take_while(|x| *x != IR0::Exit).collect::>(); - x.push(IR0::Exit); - x - } -} diff --git a/package/origlang-ir-optimizer/src/ir1.rs b/package/origlang-ir-optimizer/src/ir1.rs index 227bc8a9..a6a85bac 100644 --- a/package/origlang-ir-optimizer/src/ir1.rs +++ b/package/origlang-ir-optimizer/src/ir1.rs @@ -307,4 +307,15 @@ impl InlineSimpleBlock { other => other, } } -} \ No newline at end of file +} + +pub struct EliminateAfterExit(pub Vec); + +impl EliminateAfterExit { + #[must_use = "return value is optimized IR, dropping it will waste it"] + pub fn optimize(self) -> Vec { + let mut x = self.0.into_iter().take_while(|x| *x != IR1::Exit).collect::>(); + x.push(IR1::Exit); + x + } +} diff --git a/package/origlang-ir-optimizer/src/ir1/tests.rs b/package/origlang-ir-optimizer/src/ir1/tests.rs index 09f854c5..019c6189 100644 --- a/package/origlang-ir-optimizer/src/ir1/tests.rs +++ b/package/origlang-ir-optimizer/src/ir1/tests.rs @@ -1,7 +1,7 @@ use origlang_ast::after_parse::BinaryOperatorKind; use origlang_ir::IR1; use origlang_typesystem_model::{Type, TypedExpression, TypedIntLiteral}; -use crate::ir1::{FoldBinaryOperatorInvocationWithConstant, FoldIfWithConstantCondition, InlineSimpleBlock}; +use crate::ir1::{EliminateAfterExit, FoldBinaryOperatorInvocationWithConstant, FoldIfWithConstantCondition, InlineSimpleBlock}; #[test] fn fold_binary_operator_is_recursive() { @@ -84,3 +84,12 @@ fn inline_simple_block() { ]) } +#[test] +fn cut_down_after_exit() { + let opt_output = EliminateAfterExit(vec![ + IR1::Exit, + IR1::Output(TypedExpression::BooleanLiteral(false)) + ]).optimize(); + + assert_eq!(opt_output, [ IR1::Exit ]); +} diff --git a/package/origlang-ir-optimizer/src/lib.rs b/package/origlang-ir-optimizer/src/lib.rs index 59593691..3c05786b 100644 --- a/package/origlang-ir-optimizer/src/lib.rs +++ b/package/origlang-ir-optimizer/src/lib.rs @@ -1,7 +1,6 @@ #![deny(clippy::all, clippy::panicking_unwrap, clippy::panic)] #![warn(clippy::pedantic, clippy::nursery)] -pub mod ir0; pub mod ir1; pub mod preset; pub mod lower; diff --git a/package/origlang-ir-optimizer/src/lower.rs b/package/origlang-ir-optimizer/src/lower.rs index d7f1c1ec..cc995fa6 100644 --- a/package/origlang-ir-optimizer/src/lower.rs +++ b/package/origlang-ir-optimizer/src/lower.rs @@ -1,4 +1,4 @@ -use origlang_ir::{CompiledTypedExpression, IntoVerbatimSequencedIR, IR0, IR1, IR2}; +use origlang_ir::{CompiledTypedExpression, IntoVerbatimSequencedIR, IR1, IR2}; use origlang_typesystem_model::{TypedExpression, TypedStatement}; use crate::preset::OptimizationPreset; @@ -19,9 +19,9 @@ impl<'t> TheTranspiler<'t> { } } -pub trait EachStep: OptimizationPreset + OptimizationPreset + OptimizationPreset {} +pub trait EachStep: OptimizationPreset + OptimizationPreset {} -impl + OptimizationPreset + OptimizationPreset + ?Sized> EachStep for T {} +impl + OptimizationPreset + ?Sized> EachStep for T {} impl TheTranspiler<'_> { fn compile_typed_expression(&self, te: TypedExpression) -> CompiledTypedExpression { @@ -62,9 +62,7 @@ impl TheTranspiler<'_> { } fn compile_typed_statement(&self, ts: TypedStatement) -> Vec { - let opt_ir0 = self.optimization_preset.optimize(ts.into_ir()); - let ir1 = self.lower(opt_ir0); - let opt_ir1 = OptimizationPreset::::optimize(self.optimization_preset, ir1); + let opt_ir1 = OptimizationPreset::::optimize(self.optimization_preset, ts.into_ir()); let ir2 = self.lower(opt_ir1); OptimizationPreset::::optimize(self.optimization_preset, ir2) @@ -75,16 +73,6 @@ pub trait LowerStep { fn lower(&self, ir: Vec) -> Vec; } -impl LowerStep for TheTranspiler<'_> { - fn lower(&self, ir: Vec) -> Vec { - // TODO: this sequence is always terminated by IR0::Exit. Should be reflected on the type. - ir.into_iter().map(|x| match x { - IR0::Normal(ir1) => ir1, - IR0::Exit => IR1::Exit, - }).collect() - } -} - impl LowerStep for TheTranspiler<'_> { fn lower(&self, ir: Vec) -> Vec { ir.into_iter().map(|x| match x { diff --git a/package/origlang-ir-optimizer/src/preset.rs b/package/origlang-ir-optimizer/src/preset.rs index 5cf96174..8a6e1451 100644 --- a/package/origlang-ir-optimizer/src/preset.rs +++ b/package/origlang-ir-optimizer/src/preset.rs @@ -1,5 +1,5 @@ use tap::Pipe; -use origlang_ir::{IR0, IR1, IR2}; +use origlang_ir::{IR1, IR2}; pub trait OptimizationPreset { /// 最適化をする。 @@ -13,23 +13,13 @@ pub trait OptimizationPreset { /// Do not perform optimization at all. pub struct NoOptimization; -impl OptimizationPreset for NoOptimization { - #[allow(clippy::redundant_closure_for_method_calls)] - fn optimize(&self, seq: Vec) -> Vec { - #[allow(clippy::wildcard_imports)] - use crate::ir0::*; - - seq - .pipe(EliminateAfterExit).pipe(|x| x.optimize()) - } -} - impl OptimizationPreset for NoOptimization { fn optimize(&self, seq: Vec) -> Vec { #[allow(unused_imports)] use crate::ir1::*; seq + .pipe(EliminateAfterExit).pipe(|x| x.optimize()) } } @@ -42,17 +32,6 @@ impl OptimizationPreset for NoOptimization { /// Enables some basic optimization. pub struct SimpleOptimization; -impl OptimizationPreset for SimpleOptimization { - #[allow(clippy::redundant_closure_for_method_calls)] - fn optimize(&self, seq: Vec) -> Vec { - #[allow(clippy::wildcard_imports)] - use crate::ir0::*; - - seq - .pipe(EliminateAfterExit).pipe(|x| x.optimize()) - } -} - impl OptimizationPreset for SimpleOptimization { #[allow(clippy::redundant_closure_for_method_calls)] fn optimize(&self, seq: Vec) -> Vec { @@ -63,6 +42,7 @@ impl OptimizationPreset for SimpleOptimization { .pipe(FoldBinaryOperatorInvocationWithConstant).pipe(|x| x.optimize()) .pipe(FoldIfWithConstantCondition).pipe(|x| x.optimize()) .pipe(InlineSimpleBlock).pipe(|x| x.optimize()) + .pipe(EliminateAfterExit).pipe(|x| x.optimize()) } } diff --git a/package/origlang-ir/src/lib.rs b/package/origlang-ir/src/lib.rs index 71e3fa9b..6169386d 100644 --- a/package/origlang-ir/src/lib.rs +++ b/package/origlang-ir/src/lib.rs @@ -6,38 +6,24 @@ use origlang_ast::after_parse::BinaryOperatorKind; use origlang_ast::Identifier; use origlang_typesystem_model::{Type, TypedExpression, TypedIntLiteral, TypedRootAst, TypedStatement}; -/// The initial form of IR. This IR defines [`Self::Exit`] operation that aborts current execution. -/// However, IR commands after it is cut-down when lowering to [`IR1`]. -#[derive(Eq, PartialEq, Debug)] -pub enum IR0 { - Normal(IR1), - Exit, -} - -impl IR0 { - pub fn create(from: T) -> Vec { - from.into_ir() - } -} - pub trait IntoVerbatimSequencedIR { - fn into_ir(self) -> Vec; + fn into_ir(self) -> Vec; } impl IntoVerbatimSequencedIR for TypedStatement { - fn into_ir(self) -> Vec { + fn into_ir(self) -> Vec { let statement = self; match statement { Self::Print { expression } => { vec![ - IR0::Normal(IR1::Output(expression)) + (IR1::Output(expression)) ] } Self::VariableDeclaration { identifier, expression } | Self::VariableAssignment { identifier, expression } => { vec![ - IR0::Normal(IR1::UpdateVariable { + (IR1::UpdateVariable { ident: identifier, value: expression, }) @@ -47,20 +33,20 @@ impl IntoVerbatimSequencedIR for TypedStatement { let mut vec = inner_statements.into_iter() .flat_map(::into_ir) .collect::>(); - vec.push_front(IR0::Normal(IR1::PushScope)); - vec.push_back(IR0::Normal(IR1::PopScope)); + vec.push_front(IR1::PushScope); + vec.push_back(IR1::PopScope); vec.into() } - Self::Exit => vec![IR0::Exit], + Self::Exit => vec![(IR1::Exit)], Self::EvalAndForget { expression } => { - vec![IR0::Normal(IR1::EvalAndForget { expression })] + vec![(IR1::EvalAndForget { expression })] }, } } } impl IntoVerbatimSequencedIR for TypedRootAst { - fn into_ir(self) -> Vec { + fn into_ir(self) -> Vec { self.statements.into_iter() .flat_map(::into_ir) .collect() @@ -68,7 +54,7 @@ impl IntoVerbatimSequencedIR for TypedRootAst { } impl IntoVerbatimSequencedIR for Vec { - fn into_ir(self) -> Vec { + fn into_ir(self) -> Vec { self.into_iter().flat_map(IntoVerbatimSequencedIR::into_ir).collect() } } diff --git a/package/origlang-runtime/src/lib.rs b/package/origlang-runtime/src/lib.rs index 356fd239..07d319ea 100644 --- a/package/origlang-runtime/src/lib.rs +++ b/package/origlang-runtime/src/lib.rs @@ -193,27 +193,27 @@ impl Runtime { /// Start runtime. Never returns until execution is completed. #[allow(dead_code)] - pub fn start<'s: 'o, 'o>(&'s self, seq: Vec) -> &'o RefCell { + pub fn start<'s: 'o, 'o>(&'s self, seq: &[IR2]) -> &'o RefCell { // info!("{ast:?}", ast = &ast); let x = seq; // info!("{x:?}", x = &x); x - .into_iter().for_each(|x| self.invoke(x)); + .iter().for_each(|x| self.invoke(x)); &self.o } - pub fn execute(&self, ir: Vec) { - ir.into_iter().for_each(|x| self.invoke(x)); + pub fn execute(&self, ir: &[IR2]) { + ir.iter().for_each(|x| self.invoke(x)); } - pub fn invoke(&self, ir: IR2) { + pub fn invoke(&self, ir: &IR2) { match ir { IR2::Output(e) => { self.o.as_ref().borrow_mut().output(e.evaluate(self).expect("runtime exception")); } IR2::UpdateVariable { ident, value } => { self.upsert_member_to_current_scope( - ident, + ident.clone(), value.evaluate(self).expect("self exception") ); } @@ -229,7 +229,7 @@ impl Runtime { } } IR2::EvalAndForget { expression } => { - self.evaluate(&expression).expect("runtime exception"); + self.evaluate(expression).expect("runtime exception"); } } } @@ -421,7 +421,7 @@ impl CanBeEvaluated for CompiledTypedExpression { } Self::Block { inner: intermediate_statements, final_expression, return_type: _ } => { runtime.push_scope(); - runtime.execute(intermediate_statements.clone()); + runtime.execute(intermediate_statements); runtime.pop_scope(); final_expression.as_ref().evaluate(runtime) diff --git a/package/origlang-testsuite/src/main.rs b/package/origlang-testsuite/src/main.rs index 698d26a3..a2d879cb 100644 --- a/package/origlang-testsuite/src/main.rs +++ b/package/origlang-testsuite/src/main.rs @@ -78,9 +78,7 @@ impl Test { let ir = checked.into_ir(); let ir = transpiler.optimizer().optimize(ir); let ir = transpiler.lower(ir); - let ir = transpiler.optimizer().optimize(ir); - let ir = transpiler.lower(ir); - let o = runtime.start(ir); + let o = runtime.start(&ir); println!("{o:?}", o = &o); let x = Ok(o.borrow().acc().expect("???")); x @@ -455,7 +453,6 @@ print 1 fn test_exit() -> Result<(), Err> { assert_eq!(Self::ast("exit\n")?.statement, [ Statement::Exit ]); assert_eq!(Self::evaluated_expressions("exit\n")?, []); - assert_eq!(Self::evaluated_expressions_with_optimization_preset("exit\nprint 1\n", &SimpleOptimization)?, []); Ok(()) }