Skip to content

Commit

Permalink
Merge pull request #300 from KisaragiEffective/refactor/remove-ir0
Browse files Browse the repository at this point in the history
  • Loading branch information
KisaragiEffective authored Oct 22, 2023
2 parents 349da34 + 0b67e28 commit 68b588e
Show file tree
Hide file tree
Showing 15 changed files with 53 additions and 112 deletions.
1 change: 0 additions & 1 deletion package/origlang-cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ pub enum EmitPhase {
LexerToken,
Ast,
TypedAst,
Ir0,
Ir1,
Ir2,
}
Expand Down
9 changes: 0 additions & 9 deletions package/origlang-cli/src/task/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<IR1> = the_lower.optimizer().optimize(ir_sequence);

Expand Down
3 changes: 1 addition & 2 deletions package/origlang-cli/src/task/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
4 changes: 1 addition & 3 deletions package/origlang-cli/src/task/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ impl Repl {
fn naive_lower(tra: TypedRootAst) -> Vec<IR2> {
let ir = tra.into_ir();
let trans = TheTranspiler::new(&NoOptimization);
let ir = trans.lower(ir);


trans.lower(ir)
}
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 2 additions & 5 deletions package/origlang-compiler-entrypoint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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(..)));

Expand Down Expand Up @@ -146,15 +146,13 @@ pub trait Scanner<T> {
}

pub struct OptimizationPresetCollection {
pub ir0: Box<dyn OptimizationPreset<IR0>>,
pub ir1: Box<dyn OptimizationPreset<IR1>>,
pub ir2: Box<dyn OptimizationPreset<IR2>>,
}

impl OptimizationPresetCollection {
fn none() -> Self {
Self {
ir0: Box::new(NoOptimization) as Box<_>,
ir1: Box::new(NoOptimization) as Box<_>,
ir2: Box::new(NoOptimization) as Box<_>,
}
Expand All @@ -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);
3 changes: 1 addition & 2 deletions package/origlang-interop/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down
12 changes: 0 additions & 12 deletions package/origlang-ir-optimizer/src/ir0.rs

This file was deleted.

13 changes: 12 additions & 1 deletion package/origlang-ir-optimizer/src/ir1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,15 @@ impl InlineSimpleBlock {
other => other,
}
}
}
}

pub struct EliminateAfterExit(pub Vec<IR1>);

impl EliminateAfterExit {
#[must_use = "return value is optimized IR, dropping it will waste it"]
pub fn optimize(self) -> Vec<IR1> {
let mut x = self.0.into_iter().take_while(|x| *x != IR1::Exit).collect::<Vec<_>>();
x.push(IR1::Exit);
x
}
}
11 changes: 10 additions & 1 deletion package/origlang-ir-optimizer/src/ir1/tests.rs
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down Expand Up @@ -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 ]);
}
1 change: 0 additions & 1 deletion package/origlang-ir-optimizer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
20 changes: 4 additions & 16 deletions package/origlang-ir-optimizer/src/lower.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -19,9 +19,9 @@ impl<'t> TheTranspiler<'t> {
}
}

pub trait EachStep: OptimizationPreset<IR0> + OptimizationPreset<IR1> + OptimizationPreset<IR2> {}
pub trait EachStep: OptimizationPreset<IR1> + OptimizationPreset<IR2> {}

impl<T: OptimizationPreset<IR0> + OptimizationPreset<IR1> + OptimizationPreset<IR2> + ?Sized> EachStep for T {}
impl<T: OptimizationPreset<IR1> + OptimizationPreset<IR2> + ?Sized> EachStep for T {}

impl TheTranspiler<'_> {
fn compile_typed_expression(&self, te: TypedExpression) -> CompiledTypedExpression {
Expand Down Expand Up @@ -62,9 +62,7 @@ impl TheTranspiler<'_> {
}

fn compile_typed_statement(&self, ts: TypedStatement) -> Vec<IR2> {
let opt_ir0 = self.optimization_preset.optimize(ts.into_ir());
let ir1 = self.lower(opt_ir0);
let opt_ir1 = OptimizationPreset::<IR1>::optimize(self.optimization_preset, ir1);
let opt_ir1 = OptimizationPreset::<IR1>::optimize(self.optimization_preset, ts.into_ir());
let ir2 = self.lower(opt_ir1);

OptimizationPreset::<IR2>::optimize(self.optimization_preset, ir2)
Expand All @@ -75,16 +73,6 @@ pub trait LowerStep<From, To> {
fn lower(&self, ir: Vec<From>) -> Vec<To>;
}

impl LowerStep<IR0, IR1> for TheTranspiler<'_> {
fn lower(&self, ir: Vec<IR0>) -> Vec<IR1> {
// 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<IR1, IR2> for TheTranspiler<'_> {
fn lower(&self, ir: Vec<IR1>) -> Vec<IR2> {
ir.into_iter().map(|x| match x {
Expand Down
26 changes: 3 additions & 23 deletions package/origlang-ir-optimizer/src/preset.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use tap::Pipe;
use origlang_ir::{IR0, IR1, IR2};
use origlang_ir::{IR1, IR2};

pub trait OptimizationPreset<IR> {
/// 最適化をする。
Expand All @@ -13,23 +13,13 @@ pub trait OptimizationPreset<IR> {
/// Do not perform optimization at all.
pub struct NoOptimization;

impl OptimizationPreset<IR0> for NoOptimization {
#[allow(clippy::redundant_closure_for_method_calls)]
fn optimize(&self, seq: Vec<IR0>) -> Vec<IR0> {
#[allow(clippy::wildcard_imports)]
use crate::ir0::*;

seq
.pipe(EliminateAfterExit).pipe(|x| x.optimize())
}
}

impl OptimizationPreset<IR1> for NoOptimization {
fn optimize(&self, seq: Vec<IR1>) -> Vec<IR1> {
#[allow(unused_imports)]
use crate::ir1::*;

seq
.pipe(EliminateAfterExit).pipe(|x| x.optimize())
}
}

Expand All @@ -42,17 +32,6 @@ impl OptimizationPreset<IR2> for NoOptimization {
/// Enables some basic optimization.
pub struct SimpleOptimization;

impl OptimizationPreset<IR0> for SimpleOptimization {
#[allow(clippy::redundant_closure_for_method_calls)]
fn optimize(&self, seq: Vec<IR0>) -> Vec<IR0> {
#[allow(clippy::wildcard_imports)]
use crate::ir0::*;

seq
.pipe(EliminateAfterExit).pipe(|x| x.optimize())
}
}

impl OptimizationPreset<IR1> for SimpleOptimization {
#[allow(clippy::redundant_closure_for_method_calls)]
fn optimize(&self, seq: Vec<IR1>) -> Vec<IR1> {
Expand All @@ -63,6 +42,7 @@ impl OptimizationPreset<IR1> 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())
}
}

Expand Down
34 changes: 10 additions & 24 deletions package/origlang-ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: IntoVerbatimSequencedIR>(from: T) -> Vec<Self> {
from.into_ir()
}
}

pub trait IntoVerbatimSequencedIR {
fn into_ir(self) -> Vec<IR0>;
fn into_ir(self) -> Vec<IR1>;
}

impl IntoVerbatimSequencedIR for TypedStatement {
fn into_ir(self) -> Vec<IR0> {
fn into_ir(self) -> Vec<IR1> {
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,
})
Expand All @@ -47,28 +33,28 @@ impl IntoVerbatimSequencedIR for TypedStatement {
let mut vec = inner_statements.into_iter()
.flat_map(<Self as IntoVerbatimSequencedIR>::into_ir)
.collect::<VecDeque<_>>();
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<IR0> {
fn into_ir(self) -> Vec<IR1> {
self.statements.into_iter()
.flat_map(<TypedStatement as IntoVerbatimSequencedIR>::into_ir)
.collect()
}
}

impl<T: IntoVerbatimSequencedIR> IntoVerbatimSequencedIR for Vec<T> {
fn into_ir(self) -> Vec<IR0> {
fn into_ir(self) -> Vec<IR1> {
self.into_iter().flat_map(IntoVerbatimSequencedIR::into_ir).collect()
}
}
Expand Down
16 changes: 8 additions & 8 deletions package/origlang-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<IR2>) -> &'o RefCell<dyn OutputAccumulator> {
pub fn start<'s: 'o, 'o>(&'s self, seq: &[IR2]) -> &'o RefCell<dyn OutputAccumulator> {
// 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<IR2>) {
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")
);
}
Expand All @@ -229,7 +229,7 @@ impl Runtime {
}
}
IR2::EvalAndForget { expression } => {
self.evaluate(&expression).expect("runtime exception");
self.evaluate(expression).expect("runtime exception");
}
}
}
Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 68b588e

Please sign in to comment.