while loop constructs

This commit is contained in:
pca006132 2021-08-09 16:10:17 +08:00
parent d8c713ce3d
commit 7a90ff5791
2 changed files with 49 additions and 1 deletions

View File

@ -82,6 +82,48 @@ impl<'ctx> CodeGenContext<'ctx> {
self.gen_assignment(target, value); self.gen_assignment(target, value);
} }
} }
StmtKind::Continue => {
self.builder.build_unconditional_branch(self.loop_bb.unwrap().0);
}
StmtKind::Break => {
self.builder.build_unconditional_branch(self.loop_bb.unwrap().1);
}
StmtKind::While { test, body, orelse } => {
let current = self.builder.get_insert_block().unwrap().get_parent().unwrap();
let test_bb = self.ctx.append_basic_block(current, "test");
let body_bb = self.ctx.append_basic_block(current, "body");
let cont_bb = self.ctx.append_basic_block(current, "cont");
// if there is no orelse, we just go to cont_bb
let orelse_bb = if orelse.is_empty() {
cont_bb
} else {
self.ctx.append_basic_block(current, "orelse")
};
// store loop bb information and restore it later
let loop_bb = self.loop_bb.replace((test_bb, cont_bb));
self.builder.build_unconditional_branch(test_bb);
self.builder.position_at_end(test_bb);
let test = self.gen_expr(test);
if let BasicValueEnum::IntValue(test) = test {
self.builder.build_conditional_branch(test, body_bb, orelse_bb);
} else {
unreachable!()
};
self.builder.position_at_end(body_bb);
for stmt in body.iter() {
self.gen_stmt(stmt);
}
self.builder.build_unconditional_branch(test_bb);
if !orelse.is_empty() {
self.builder.position_at_end(orelse_bb);
for stmt in orelse.iter() {
self.gen_stmt(stmt);
}
self.builder.build_unconditional_branch(cont_bb);
}
self.builder.position_at_end(cont_bb);
self.loop_bb = loop_bb;
}
_ => unimplemented!(), _ => unimplemented!(),
} }
} }

View File

@ -3,7 +3,10 @@ use std::{collections::HashMap, sync::Arc};
use super::typecheck::type_inferencer::PrimitiveStore; use super::typecheck::type_inferencer::PrimitiveStore;
use super::typecheck::typedef::{SharedUnifier, Type, Unifier}; use super::typecheck::typedef::{SharedUnifier, Type, Unifier};
use crate::symbol_resolver::SymbolResolver; use crate::symbol_resolver::SymbolResolver;
use inkwell::{builder::Builder, context::Context, module::Module, types::BasicTypeEnum, values::PointerValue}; use inkwell::{
basic_block::BasicBlock, builder::Builder, context::Context, module::Module,
types::BasicTypeEnum, values::PointerValue,
};
use parking_lot::RwLock; use parking_lot::RwLock;
use rustpython_parser::ast::Stmt; use rustpython_parser::ast::Stmt;
@ -65,4 +68,7 @@ pub struct CodeGenContext<'ctx> {
pub var_assignment: HashMap<String, PointerValue<'ctx>>, pub var_assignment: HashMap<String, PointerValue<'ctx>>,
pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>, pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>,
pub primitives: PrimitiveStore, pub primitives: PrimitiveStore,
// where continue and break should go to respectively
// the first one is the test_bb, and the second one is bb after the loop
pub loop_bb: Option<(BasicBlock<'ctx>, BasicBlock<'ctx>)>,
} }