Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new_runtime: Fix failing tests #555

Merged
merged 24 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ jobs:
set -eux
cd lib/skc_rustlib; cargo build; cd ../../
env -- cargo run -- build-corelib
env -- rake async_integration_test
env -- cargo test
env -- bash release_test.sh

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
/target
/tests/tmp.*
/tests/tmp/hello.txt
/tests/new_runtime/*.out
/tests/new_runtime/*.actual_out
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,16 @@ task :async do
sh "cargo run --bin exp_shiika -- a.milika"
end
task async_test: :async do
sh "./a"
sh "./a.out"
end
task :async_integration_test do
cd "lib/skc_runtime/" do
sh "cargo build"
end
Dir["tests/new_runtime/*.sk"].each do |path|
name = path.sub(".sk", "")
sh "cargo run --bin exp_shiika -- #{name}.sk > #{name}.actual_out"
sh "cargo run --bin exp_shiika -- #{name}.sk"
sh "#{name}.out > #{name}.actual_out"
sh "diff #{name}.actual_out #{name}.expected_out"
end
end
3 changes: 3 additions & 0 deletions lib/skc_async_experiment/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ nom_locate = "4.2.0"
os_info = "3.7.0"
# To read exports.json5
json5 = "0.2.8"

[dev-dependencies]
insta = { version = "1.32.0", features = ["glob"] }
14 changes: 4 additions & 10 deletions lib/skc_async_experiment/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {
lvars: Default::default(),
};

for stmt in &f.body_stmts {
self.compile_expr(&mut ctx, stmt);
}
self.compile_expr(&mut ctx, &f.body_stmts);
}

fn compile_value_expr(
Expand Down Expand Up @@ -120,7 +118,7 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {
// self.compile_cond_br(blocks, block, lvars, cond, true_block_id, false_block_id)
// }
// hir::Expr::BlockArgRef => self.compile_block_arg_ref(block),
// hir::Expr::Nop => Ok(None),
hir::Expr::Nop => None,
_ => panic!("should be lowered before codegen.rs: {:?}", texpr.0),
}
}
Expand Down Expand Up @@ -199,7 +197,7 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {
ctx: &mut CodeGenContext<'run>,
cond_expr: &hir::TypedExpr,
then_exprs: &hir::TypedExpr,
else_exprs: &Option<Box<hir::TypedExpr>>,
else_exprs: &hir::TypedExpr,
) -> Option<inkwell::values::BasicValueEnum<'run>> {
let begin_block = self.context.append_basic_block(ctx.function, "IfBegin");
let then_block = self.context.append_basic_block(ctx.function, "IfThen");
Expand All @@ -220,11 +218,7 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {
let then_block_end = self.builder.get_insert_block().unwrap();
// IfElse:
self.builder.position_at_end(else_block);
let else_value = if let Some(else_exprs) = else_exprs {
self.compile_expr(ctx, else_exprs)
} else {
None
};
let else_value = self.compile_expr(ctx, else_exprs);
if else_value.is_some() {
self.builder.build_unconditional_branch(merge_block);
}
Expand Down
6 changes: 2 additions & 4 deletions lib/skc_async_experiment/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub struct Function {
pub name: FunctionName,
pub params: Vec<Param>,
pub ret_ty: Ty,
pub body_stmts: Vec<Typed<Expr>>,
pub body_stmts: Typed<Expr>,
}

impl fmt::Display for Function {
Expand All @@ -80,9 +80,7 @@ impl fmt::Display for Function {
"fun{} {}{}({}) -> {} {{\n",
gen, self.name, self.asyncness, para, self.ret_ty
)?;
for expr in &self.body_stmts {
write!(f, " {} #-> {}\n", &expr.0, &expr.1)?;
}
write!(f, "{}\n", &self.body_stmts.0.pretty_print(1, true),)?;
write!(f, "}}\n")
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/skc_async_experiment/src/hir/asyncness_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ impl<'a> Check<'a> {
};
c.checking.insert(fname.clone());
let func = funcs.get(fname).unwrap();
c.walk_exprs(&func.body_stmts).unwrap();
c.walk_expr(&func.body_stmts).unwrap();
if c.depends.is_empty() {
c.known.insert(fname.clone(), c.is_async);
} else {
Expand Down Expand Up @@ -216,7 +216,7 @@ impl Assert {
}

fn check_func(&mut self, f: &hir::Function) -> bool {
self.walk_exprs(&f.body_stmts).unwrap();
self.walk_expr(&f.body_stmts).unwrap();
if self.found_async_call && !f.asyncness.is_async() {
panic!(
"Function {} is marked as sync, but found async call",
Expand Down
192 changes: 109 additions & 83 deletions lib/skc_async_experiment/src/hir/expr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::hir::FunctionName;
use crate::hir::{FunTy, Ty};
use anyhow::{anyhow, Result};

pub type Typed<T> = (T, Ty);
pub type TypedExpr = Typed<Expr>;
Expand All @@ -12,7 +13,7 @@ pub enum Expr {
ArgRef(usize),
FuncRef(FunctionName),
FunCall(Box<Typed<Expr>>, Vec<Typed<Expr>>),
If(Box<Typed<Expr>>, Box<Typed<Expr>>, Option<Box<Typed<Expr>>>),
If(Box<Typed<Expr>>, Box<Typed<Expr>>, Box<Typed<Expr>>),
While(Box<Typed<Expr>>, Vec<Typed<Expr>>),
Spawn(Box<Typed<Expr>>),
Alloc(String),
Expand Down Expand Up @@ -51,66 +52,6 @@ impl CastType {
}
}

impl std::fmt::Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expr::Number(n) => write!(f, "{}", n),
Expr::PseudoVar(PseudoVar::True) => write!(f, "true"),
Expr::PseudoVar(PseudoVar::False) => write!(f, "false"),
Expr::PseudoVar(PseudoVar::Void) => write!(f, "null"),
Expr::LVarRef(name) => write!(f, "{}", name),
Expr::ArgRef(idx) => write!(f, "%arg_{}", idx),
Expr::FuncRef(name) => write!(f, "{}", name),
Expr::FunCall(func, args) => {
let Ty::Fun(fun_ty) = &func.1 else {
panic!("[BUG] not a function: {:?}", func);
};
write!(f, "{}{}(", func.0, fun_ty.asyncness)?;
for (i, arg) in args.iter().enumerate() {
if i != 0 {
write!(f, ", ")?;
}
write!(f, "{}", arg.0)?;
}
write!(f, ")")
}
Expr::If(cond, then, else_) => {
write!(f, "if ({}) {{\n", cond.0)?;
write!(f, "{}\n", then.0)?;
write!(f, " }}")?;
if let Some(else_) = else_ {
write!(f, " else {{\n")?;
write!(f, " {}\n", else_.0)?;
write!(f, " }}")?;
}
Ok(())
}
Expr::While(cond, body) => {
write!(f, "while {} {{\n", cond.0)?;
for stmt in body {
write!(f, " {}\n", stmt.0)?;
}
write!(f, "}}")
}
Expr::Spawn(e) => write!(f, "spawn {}", e.0),
Expr::Alloc(name) => write!(f, "alloc {}", name),
Expr::Assign(name, e) => write!(f, "{} = {}", name, e.0),
Expr::Return(e) => write!(f, "return {} # {}", e.0, e.1),
Expr::Exprs(exprs) => {
for expr in exprs {
write!(f, " {}\n", expr.0)?;
}
Ok(())
}
Expr::Cast(cast_type, e) => write!(f, "({} as {})", e.0, cast_type.result_ty()),
Expr::Unbox(e) => write!(f, "unbox {}", e.0),
Expr::RawI64(n) => write!(f, "{}.raw", n),
Expr::Nop => write!(f, "%nop"),
//_ => todo!("{:?}", self),
}
}
}

impl Expr {
pub fn number(n: i64) -> TypedExpr {
(Expr::Number(n), Ty::Int)
Expand Down Expand Up @@ -144,31 +85,37 @@ impl Expr {
(Expr::FunCall(Box::new(func), args), result_ty)
}

pub fn if_(cond: TypedExpr, then: TypedExpr, else_: Option<TypedExpr>) -> TypedExpr {
if cond.1 != Ty::Bool {
panic!("[BUG] if cond not bool: {:?}", cond);
}
let t1 = &then.1;
let t2 = match &else_ {
Some(e) => e.1.clone(),
None => Ty::Void,
};
let if_ty = if *t1 == Ty::Void {
t2.clone()
} else if t2 == Ty::Void {
t1.clone()
} else if *t1 == t2 {
t1.clone()
} else {
panic!("[BUG] if types mismatch (t1: {:?}, t2: {:?})", t1, t2);
};

pub fn if_(cond: TypedExpr, then: TypedExpr, else_: TypedExpr) -> TypedExpr {
let if_ty = Expr::if_ty(&then.1, &else_.1).unwrap();
(
Expr::If(Box::new(cond), Box::new(then), else_.map(Box::new)),
Expr::If(Box::new(cond), Box::new(then), Box::new(else_)),
if_ty,
)
}

pub fn if_ty(then_ty: &Ty, else_ty: &Ty) -> Result<Ty> {
let t1 = then_ty;
let t2 = else_ty;
let if_ty = if *t1 == Ty::Never {
t2
} else if *t2 == Ty::Never {
t1
} else if *t1 == Ty::Void {
t2
} else if *t2 == Ty::Void {
t1
} else if t1 != t2 {
return Err(anyhow!(
"then and else should have the same type but got {:?} and {:?}",
t1,
t2
));
} else {
t1
};
Ok(if_ty.clone())
}

pub fn while_(cond: TypedExpr, body: Vec<TypedExpr>) -> TypedExpr {
if cond.1 != Ty::Bool {
panic!("[BUG] while cond not bool: {:?}", cond);
Expand All @@ -192,8 +139,10 @@ impl Expr {
(Expr::Return(Box::new(e)), Ty::Never)
}

pub fn exprs(exprs: Vec<TypedExpr>) -> TypedExpr {
debug_assert!(!exprs.is_empty());
pub fn exprs(mut exprs: Vec<TypedExpr>) -> TypedExpr {
if exprs.is_empty() {
exprs.push(Expr::pseudo_var(PseudoVar::Void));
}
let t = exprs.last().unwrap().1.clone();
(Expr::Exprs(exprs), t)
}
Expand Down Expand Up @@ -230,6 +179,10 @@ impl Expr {
_ => false,
}
}

pub fn pretty_print(&self, lv: usize, as_stmt: bool) -> String {
pretty_print(self, lv, as_stmt)
}
}

pub fn into_exprs(expr: TypedExpr) -> Vec<TypedExpr> {
Expand All @@ -238,3 +191,76 @@ pub fn into_exprs(expr: TypedExpr) -> Vec<TypedExpr> {
_ => vec![expr],
}
}

fn pretty_print(node: &Expr, lv: usize, as_stmt: bool) -> String {
let sp = " ".repeat(lv);
let mut indent = as_stmt;
let s = match node {
Expr::Number(n) => format!("{}", n),
Expr::PseudoVar(PseudoVar::True) => "true".to_string(),
Expr::PseudoVar(PseudoVar::False) => "false".to_string(),
Expr::PseudoVar(PseudoVar::Void) => "Void".to_string(),
Expr::LVarRef(name) => format!("{}", name),
Expr::ArgRef(idx) => format!("%arg{}", idx),
Expr::FuncRef(name) => format!("{}", name),
Expr::FunCall(func, args) => {
let Ty::Fun(fun_ty) = &func.1 else {
panic!("[BUG] not a function: {:?}", func);
};
format!("{}{}(", func.0.pretty_print(0, false), fun_ty.asyncness)
+ args
.iter()
.map(|arg| arg.0.pretty_print(0, false))
.collect::<Vec<String>>()
.join(", ")
.as_str()
+ ")"
}
Expr::If(cond, then, else_) => {
"if ".to_string()
+ cond.0.pretty_print(lv + 1, false).as_str()
+ "\n"
+ then.0.pretty_print(lv + 1, true).as_str()
+ &format!("\n{}else\n", sp)
+ else_.0.pretty_print(lv + 1, true).as_str()
+ &format!("\n{}end", sp)
}
Expr::While(cond, body) => {
"while ".to_string()
+ cond.0.pretty_print(lv + 1, false).as_str()
+ "\n"
+ body
.iter()
.map(|stmt| stmt.0.pretty_print(lv + 1, true))
.collect::<Vec<String>>()
.join("\n")
.as_str()
}
Expr::Spawn(e) => format!("spawn {}", pretty_print(&e.0, lv, false)),
Expr::Alloc(name) => format!("alloc {}", name),
Expr::Assign(name, e) => format!("{} = {}", name, pretty_print(&e.0, lv, false)),
Expr::Return(e) => format!("return {} # {}", pretty_print(&e.0, lv, false), e.1),
Expr::Exprs(exprs) => {
indent = false;
exprs
.iter()
.map(|expr| format!("{} #-> {}", pretty_print(&expr.0, lv, true), &expr.1))
.collect::<Vec<String>>()
.join("\n")
}
Expr::Cast(cast_type, e) => format!(
"({} as {})",
pretty_print(&e.0, lv, false),
cast_type.result_ty()
),
Expr::Unbox(e) => format!("unbox {}", pretty_print(&e.0, lv, false)),
Expr::RawI64(n) => format!("{}", n),
Expr::Nop => "%nop".to_string(),
//_ => todo!("{:?}", self),
};
if indent {
format!("{}{}", sp, s)
} else {
s
}
}
8 changes: 3 additions & 5 deletions lib/skc_async_experiment/src/hir/rewriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub trait HirRewriter {
.funcs
.into_iter()
.map(|f| {
let body_stmts = self.walk_exprs(f.body_stmts)?;
let body_stmts = self.walk_expr(f.body_stmts)?;
Ok(hir::Function { body_stmts, ..f })
})
.collect::<Result<_>>()?;
Expand All @@ -31,12 +31,10 @@ pub trait HirRewriter {
hir::Expr::FunCall(fexpr, arg_exprs) => {
hir::Expr::fun_call(self.walk_expr(*fexpr)?, self.walk_exprs(arg_exprs)?)
}
hir::Expr::If(cond_expr, then_exprs, opt_else_exprs) => hir::Expr::if_(
hir::Expr::If(cond_expr, then_exprs, else_exprs) => hir::Expr::if_(
self.walk_expr(*cond_expr)?,
self.walk_expr(*then_exprs)?,
opt_else_exprs
.map(|else_exprs| self.walk_expr(*else_exprs))
.transpose()?,
self.walk_expr(*else_exprs)?,
),
hir::Expr::While(cond_expr, body_exprs) => {
hir::Expr::while_(self.walk_expr(*cond_expr)?, self.walk_exprs(body_exprs)?)
Expand Down
Loading
Loading