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: Support Int#<, etc. #554

Merged
merged 9 commits into from
Oct 25, 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
3 changes: 3 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion lib/shiika_ffi/src/core_class.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod bool;
mod int;

pub use bool::SkBool;
pub use int::SkInt;
29 changes: 29 additions & 0 deletions lib/shiika_ffi/src/core_class/bool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
extern "C" {
fn shiika_intrinsic_box_bool(b: bool) -> SkBool;
}

#[repr(C)]
#[derive(Debug)]
pub struct SkBool(*const ShiikaBool);

unsafe impl Send for SkBool {}

#[repr(C)]
#[derive(Debug)]
struct ShiikaBool {
vtable: *const u8,
class_obj: *const u8,
value: bool,
}

impl From<SkBool> for bool {
fn from(sk_bool: SkBool) -> Self {
unsafe { (*sk_bool.0).value }
}
}

impl From<bool> for SkBool {
fn from(b: bool) -> Self {
unsafe { shiika_intrinsic_box_bool(b) }
}
}
20 changes: 16 additions & 4 deletions lib/shiika_ffi/src/core_class/int.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//extern "C" {
// fn shiika_intrinsic_box_int(i: i64) -> SkInt;
//}
extern "C" {
fn shiika_intrinsic_box_int(i: i64) -> SkInt;
}

#[repr(C)]
#[derive(Debug)]
Expand All @@ -16,8 +16,20 @@ struct ShiikaInt {
value: i64,
}

impl From<SkInt> for i64 {
fn from(sk_int: SkInt) -> Self {
unsafe { (*sk_int.0).value }
}
}

impl From<i64> for SkInt {
fn from(i: i64) -> Self {
unsafe { shiika_intrinsic_box_int(i) }
}
}

impl SkInt {
pub fn value(&self) -> i64 {
pub fn val(&self) -> i64 {
unsafe { (*self.0).value }
}
}
3 changes: 3 additions & 0 deletions lib/shiika_ffi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod core_class;

/// Returns the C-level name of a Shiika method
/// (eg: `Int#+`, `Meta:Class#new`)
pub fn mangle_method(method_name: &str) -> String {
let s = method_name
// Replace '_' to use '_' as delimiter
Expand Down Expand Up @@ -29,6 +31,7 @@ pub fn mangle_method(method_name: &str) -> String {
}
}

/// Returns the C-level name of a Shiika constant.
pub fn mangle_const(const_name: &str) -> String {
let s = const_name
// Replace '_' to use '_' as delimiter
Expand Down
7 changes: 6 additions & 1 deletion lib/shiika_parser/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,12 @@ impl<'a> Parser<'a> {
let (begin, end) = self.lexer.location_span();
let path = format!("{}", self.ast.filepath.display()); // ariadne 0.1.5 needs Id: Display (zesterer/ariadne#12)
let span = (&path, begin.pos..end.pos);
let src = Source::from(fs::read_to_string(&*self.ast.filepath).unwrap_or_default());
let src = if path.is_empty() {
// TODO: Use Option
Source::from(self.lexer.src)
} else {
Source::from(fs::read_to_string(&*self.ast.filepath).unwrap())
};
let mut report = vec![];
Report::build(ReportKind::Error, &path, begin.pos)
.with_message(msg)
Expand Down
3 changes: 3 additions & 0 deletions lib/skc_async_experiment/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
shiika_ast = { path = "../shiika_ast" }
shiika_parser = { path = "../shiika_parser" }
shiika_ffi = { path = "../shiika_ffi" }
inkwell = { git = "https://github.com/TheDan64/inkwell", features = ["llvm16-0"], rev = "4030f76" }
nom = "7.1.3"
peg = "0.8.2"
Expand All @@ -14,3 +15,5 @@ anyhow = "1.0"
either = "1.9.0"
nom_locate = "4.2.0"
os_info = "3.7.0"
# To read exports.json5
json5 = "0.2.8"
20 changes: 11 additions & 9 deletions lib/skc_async_experiment/src/codegen.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::names::FunctionName;
mod codegen_context;
mod instance;
mod intrinsics;
Expand Down Expand Up @@ -58,12 +59,13 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {

fn compile_extern(&self, ext: hir::Extern) {
let func_type = self.llvm_function_type(&ext.fun_ty);
self.module.add_function(&ext.name, func_type, None);
self.module
.add_function(&ext.name.mangle(), func_type, None);
}

fn declare_func(&self, f: &hir::Function) {
let func_type = self.llvm_function_type(&f.fun_ty());
self.module.add_function(&f.name, func_type, None);
self.module.add_function(&f.name.mangle(), func_type, None);
}

fn compile_func(&mut self, f: hir::Function) {
Expand Down Expand Up @@ -103,9 +105,6 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {
hir::Expr::LVarRef(name) => self.compile_lvarref(ctx, name),
hir::Expr::ArgRef(idx) => self.compile_argref(ctx, idx),
hir::Expr::FuncRef(name) => self.compile_funcref(name),
// hir::Expr::OpCall(op, lhs, rhs) => {
// self.compile_op_call(blocks, block, lvars, op, lhs, rhs)
// }
hir::Expr::FunCall(fexpr, arg_exprs) => self.compile_funcall(ctx, fexpr, arg_exprs),
hir::Expr::If(cond, then, els) => self.compile_if(ctx, cond, then, els),
// hir::Expr::While(cond, exprs) => self.compile_while(blocks, block, lvars, cond, exprs),
Expand Down Expand Up @@ -139,9 +138,12 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {
Some(v)
}

fn compile_funcref(&self, name: &str) -> Option<inkwell::values::BasicValueEnum<'run>> {
fn compile_funcref(
&self,
name: &FunctionName,
) -> Option<inkwell::values::BasicValueEnum<'run>> {
let f = self
.get_llvm_func(name)
.get_llvm_func(&name)
.as_global_value()
.as_pointer_value();
Some(f.into())
Expand Down Expand Up @@ -373,9 +375,9 @@ impl<'run, 'ictx: 'run> CodeGen<'run, 'ictx> {
.unwrap()
}

fn get_llvm_func(&self, name: &str) -> inkwell::values::FunctionValue<'run> {
fn get_llvm_func(&self, name: &FunctionName) -> inkwell::values::FunctionValue<'run> {
self.module
.get_function(name)
.get_function(&name.mangle())
.unwrap_or_else(|| panic!("function `{:?}' not found", name))
}
}
3 changes: 2 additions & 1 deletion lib/skc_async_experiment/src/codegen/instance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::codegen::{llvm_struct, value::SkObj, CodeGen};
use crate::names::FunctionName;
use inkwell::values::BasicValue;

pub fn build_ivar_load_raw<'run>(
Expand Down Expand Up @@ -61,7 +62,7 @@ fn shiika_malloc<'run>(
gen: &mut CodeGen<'run, '_>,
size: inkwell::values::IntValue<'run>,
) -> inkwell::values::PointerValue<'run> {
let func = gen.get_llvm_func("shiika_malloc");
let func = gen.get_llvm_func(&FunctionName::mangled("shiika_malloc"));
gen.builder
.build_direct_call(func, &[size.as_basic_value_enum().into()], "mem")
.try_as_basic_value()
Expand Down
5 changes: 3 additions & 2 deletions lib/skc_async_experiment/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod ty;
pub mod typing;
pub mod untyped;
pub mod visitor;
use crate::names::FunctionName;
pub use expr::{CastType, Expr, PseudoVar, Typed, TypedExpr};
use std::fmt;
pub use ty::{FunTy, Ty};
Expand Down Expand Up @@ -35,7 +36,7 @@ impl Program {

#[derive(Debug, Clone)]
pub struct Extern {
pub name: String,
pub name: FunctionName,
pub fun_ty: FunTy,
}

Expand All @@ -59,7 +60,7 @@ impl Extern {
pub struct Function {
pub generated: bool,
pub asyncness: Asyncness,
pub name: String,
pub name: FunctionName,
pub params: Vec<Param>,
pub ret_ty: Ty,
pub body_stmts: Vec<Typed<Expr>>,
Expand Down
36 changes: 16 additions & 20 deletions lib/skc_async_experiment/src/hir/asyncness_check.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::hir;
use crate::hir::rewriter::HirRewriter;
use crate::hir::visitor::HirVisitor;
use crate::names::FunctionName;
use anyhow::Result;
use std::collections::{HashMap, HashSet, VecDeque};

Expand Down Expand Up @@ -63,20 +64,20 @@ pub fn run(mut hir: hir::Program) -> hir::Program {
/// Check if a function is async or not.
struct Check<'a> {
is_async: bool,
funcs: &'a HashMap<String, &'a hir::Function>,
current_func: &'a str,
known: &'a mut HashMap<String, bool>,
checking: &'a mut HashSet<String>,
depends: HashSet<String>,
unresolved_deps: &'a mut HashMap<String, HashSet<String>>,
funcs: &'a HashMap<FunctionName, &'a hir::Function>,
current_func: &'a FunctionName,
known: &'a mut HashMap<FunctionName, bool>,
checking: &'a mut HashSet<FunctionName>,
depends: HashSet<FunctionName>,
unresolved_deps: &'a mut HashMap<FunctionName, HashSet<FunctionName>>,
}
impl<'a> Check<'a> {
fn run(
funcs: &HashMap<String, &hir::Function>,
fname: &str,
known: &mut HashMap<String, bool>,
checking: &mut HashSet<String>,
unresolved_deps: &mut HashMap<String, HashSet<String>>,
funcs: &HashMap<FunctionName, &hir::Function>,
fname: &FunctionName,
known: &mut HashMap<FunctionName, bool>,
checking: &mut HashSet<FunctionName>,
unresolved_deps: &mut HashMap<FunctionName, HashSet<FunctionName>>,
) {
let mut c = Check {
is_async: false,
Expand All @@ -87,18 +88,13 @@ impl<'a> Check<'a> {
depends: HashSet::new(),
unresolved_deps,
};
c.checking.insert(fname.to_string());
c.checking.insert(fname.clone());
let func = funcs.get(fname).unwrap();
c.walk_exprs(&func.body_stmts).unwrap();
if c.depends.is_empty() {
let mut is_async = c.is_async;
// HACK: force endif-functions to be marked as async
if fname.ends_with("'e") {
is_async = true;
}
c.known.insert(fname.to_string(), is_async);
c.known.insert(fname.clone(), c.is_async);
} else {
c.unresolved_deps.insert(fname.to_string(), c.depends);
c.unresolved_deps.insert(fname.clone(), c.depends);
}
}

Expand Down Expand Up @@ -171,7 +167,7 @@ impl<'a> HirVisitor for Check<'a> {

/// Update function references to reflect the asyncness check result.
struct Update<'a> {
known: &'a HashMap<String, bool>,
known: &'a HashMap<FunctionName, bool>,
}
impl<'a> Update<'a> {
fn set_func_asyncness(&self, hir: &mut hir::Program) {
Expand Down
21 changes: 5 additions & 16 deletions lib/skc_async_experiment/src/hir/expr.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::hir::FunctionName;
use crate::hir::{FunTy, Ty};

pub type Typed<T> = (T, Ty);
Expand All @@ -9,8 +10,7 @@ pub enum Expr {
PseudoVar(PseudoVar),
LVarRef(String),
ArgRef(usize),
FuncRef(String),
OpCall(String, Box<Typed<Expr>>, Box<Typed<Expr>>),
FuncRef(FunctionName),
FunCall(Box<Typed<Expr>>, Vec<Typed<Expr>>),
If(Box<Typed<Expr>>, Box<Typed<Expr>>, Option<Box<Typed<Expr>>>),
While(Box<Typed<Expr>>, Vec<Typed<Expr>>),
Expand Down Expand Up @@ -61,7 +61,6 @@ impl std::fmt::Display for Expr {
Expr::LVarRef(name) => write!(f, "{}", name),
Expr::ArgRef(idx) => write!(f, "%arg_{}", idx),
Expr::FuncRef(name) => write!(f, "{}", name),
Expr::OpCall(op, lhs, rhs) => write!(f, "({} {} {})", lhs.0, op, rhs.0),
Expr::FunCall(func, args) => {
let Ty::Fun(fun_ty) = &func.1 else {
panic!("[BUG] not a function: {:?}", func);
Expand Down Expand Up @@ -133,18 +132,8 @@ impl Expr {
(Expr::ArgRef(idx), ty)
}

pub fn func_ref(name: impl Into<String>, fun_ty: FunTy) -> TypedExpr {
(Expr::FuncRef(name.into()), fun_ty.into())
}

pub fn op_call(op_: impl Into<String>, lhs: TypedExpr, rhs: TypedExpr) -> TypedExpr {
let op = op_.into();
let ty = match &op[..] {
"+" | "-" | "*" | "/" => Ty::Int,
"<" | "<=" | ">" | ">=" | "==" | "!=" => Ty::Bool,
_ => panic!("[BUG] unknown operator: {op}"),
};
(Expr::OpCall(op, Box::new(lhs), Box::new(rhs)), ty)
pub fn func_ref(name: FunctionName, fun_ty: FunTy) -> TypedExpr {
(Expr::FuncRef(name), fun_ty.into())
}

pub fn fun_call(func: TypedExpr, args: Vec<TypedExpr>) -> TypedExpr {
Expand Down Expand Up @@ -200,7 +189,7 @@ impl Expr {
}

pub fn return_(e: TypedExpr) -> TypedExpr {
(Expr::Return(Box::new(e)), Ty::Void)
(Expr::Return(Box::new(e)), Ty::Never)
}

pub fn exprs(exprs: Vec<TypedExpr>) -> TypedExpr {
Expand Down
3 changes: 0 additions & 3 deletions lib/skc_async_experiment/src/hir/rewriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ pub trait HirRewriter {
hir::Expr::LVarRef(_) => expr,
hir::Expr::ArgRef(_) => expr,
hir::Expr::FuncRef(_) => expr,
hir::Expr::OpCall(op, lhs, rhs) => {
hir::Expr::op_call(op, self.walk_expr(*lhs)?, self.walk_expr(*rhs)?)
}
hir::Expr::FunCall(fexpr, arg_exprs) => {
hir::Expr::fun_call(self.walk_expr(*fexpr)?, self.walk_exprs(arg_exprs)?)
}
Expand Down
14 changes: 3 additions & 11 deletions lib/skc_async_experiment/src/hir/typing.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::hir;
use crate::names::FunctionName;
use anyhow::{anyhow, Result};
use std::collections::HashMap;

struct Typing<'f> {
sigs: HashMap<String, hir::FunTy>,
current_func_name: Option<&'f String>,
sigs: HashMap<FunctionName, hir::FunTy>,
current_func_name: Option<&'f FunctionName>,
current_func_params: Option<&'f [hir::Param]>,
current_func_ret_ty: Option<&'f hir::Ty>,
}
Expand Down Expand Up @@ -68,15 +69,6 @@ impl<'f> Typing<'f> {
return Err(anyhow!("[BUG] unknown function `{name}'"));
}
}
hir::Expr::OpCall(op, l, r) => {
self.compile_expr(lvars, &mut *l)?;
self.compile_expr(lvars, &mut *r)?;
e.1 = match &op[..] {
"+" | "-" | "*" | "/" => hir::Ty::Int,
"<" | "<=" | ">" | ">=" | "==" | "!=" => hir::Ty::Bool,
_ => return Err(anyhow!("[BUG] unknown operator: {op}")),
};
}
hir::Expr::FunCall(fexpr, arg_exprs) => {
self.compile_expr(lvars, &mut *fexpr)?;
let hir::Ty::Fun(fun_ty) = &fexpr.1 else {
Expand Down
Loading
Loading