Skip to content

Commit

Permalink
Add print function
Browse files Browse the repository at this point in the history
  • Loading branch information
0xekez committed May 30, 2021
1 parent 61da439 commit a6c139b
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 5 deletions.
8 changes: 7 additions & 1 deletion lustc/src/compiler.rs
Expand Up @@ -12,6 +12,7 @@
use std::collections::HashMap;

use crate::conditional;
use crate::conversions::print_lustc_word;
use crate::data;
use crate::escape;
use crate::fatal;
Expand Down Expand Up @@ -65,7 +66,12 @@ pub(crate) struct Context<'a> {

impl Default for JIT {
fn default() -> Self {
let builder = JITBuilder::new(cranelift_module::default_libcall_names());
let mut builder = JITBuilder::new(cranelift_module::default_libcall_names());

// Register the print function.
let print_addr = print_lustc_word as *const u8;
builder.symbol("print_lustc_word", print_addr);

let module = JITModule::new(builder);
let mut jit = Self {
builder_context: FunctionBuilderContext::new(),
Expand Down
29 changes: 29 additions & 0 deletions lustc/src/conversions.rs
@@ -1,3 +1,4 @@
use std::fmt;
use std::os::raw::c_char;

use crate::{Expr, UWord, Word};
Expand Down Expand Up @@ -144,6 +145,34 @@ impl Expr {
}
}

pub fn print_lustc_word(word: Word) -> Word {
let expr = Expr::from_immediate(word);
println!("{}", expr);
Expr::Nil.immediate_rep()
}

impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Expr::Integer(i) => write!(f, "{}", i),
Expr::Char(c) => write!(f, "{}", c),
Expr::Bool(b) => write!(f, "{}", b),
Expr::Nil => write!(f, "nil"),
Expr::List(l) => write!(f, "({}, {})", l[0], l[1]),
// sbcl capitalizes symbols when writing them out to stdout.
Expr::Symbol(s) => write!(f, "{}", s.to_uppercase()),
Expr::String(s) => write!(
f,
"{}",
match s.to_str() {
Ok(s) => s,
Err(_) => return Err(fmt::Error),
}
),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
5 changes: 2 additions & 3 deletions lustc/src/main.rs
Expand Up @@ -30,8 +30,7 @@ fn main() {

timer::init(cli_opts.is_present("timeit"));

match lustc::roundtrip_file(file) {
Ok(e) => println!("=> {:?}", e),
Err(s) => eprintln!("error: {}", s),
if let Err(s) = lustc::roundtrip_file(file) {
eprintln!("error: {}", s)
}
}
60 changes: 59 additions & 1 deletion lustc/src/primitives.rs
@@ -1,4 +1,9 @@
//! Handles primitive functions in Lust.
//! Handles primitive functions in Lust. For primitives that are only
//! used in the head position of a list we don't need to create a
//! higher order version of them and can just emit them inline. For
//! that we use the emit_primcall function. For primitives that are
//! used in a higher order context we don't have such a luxury and
//! need to actually make a function.

use std::collections::HashMap;
use std::collections::HashSet;
Expand Down Expand Up @@ -176,6 +181,36 @@ pub(crate) fn emit_primitives(
})?);
}

if higher_order_primitives.contains("print") {
res.push(emit_primitive("print", 1, jit, |ctx| {
let block = ctx.builder.current_block().unwrap();
let args = ctx.builder.block_params(block);
emit_check_arg_count(1, args[1], ctx, false)?;
let args = get_primitive_args(ctx, block, 1);
let accum = args[0];

let mut sig = ctx.module.make_signature();
sig.params.push(AbiParam::new(ctx.word));
sig.returns.push(AbiParam::new(ctx.word));

let callee = ctx
.module
.declare_function("print_lustc_word", cranelift_module::Linkage::Import, &sig)
.map_err(|e| e.to_string())?;

let local_callee = ctx
.module
.declare_func_in_func(callee, &mut ctx.builder.func);

let args = vec![accum];

let call = ctx.builder.ins().call(local_callee, &args);
let res = ctx.builder.inst_results(call)[0];

Ok(res)
})?);
}

if higher_order_primitives.contains("integer->char") {
res.push(emit_primitive("integer->char", 1, jit, |ctx| {
let block = ctx.builder.current_block().unwrap();
Expand Down Expand Up @@ -789,6 +824,28 @@ pub(crate) fn emit_primcall(name: &str, args: &[Expr], ctx: &mut Context) -> Res
.ins()
.load(ctx.word, MemFlags::new(), address, ctx.word.bytes() as i32)
}

"print" => {
check_arg_len("print", args, 1)?;
let arg = emit_expr(&args[0], ctx)?;
let args = vec![arg];

let mut sig = ctx.module.make_signature();
sig.params.push(AbiParam::new(ctx.word));
sig.returns.push(AbiParam::new(ctx.word));

let callee = ctx
.module
.declare_function("print_lustc_word", cranelift_module::Linkage::Import, &sig)
.map_err(|e| e.to_string())?;

let local_callee = ctx
.module
.declare_func_in_func(callee, &mut ctx.builder.func);

let call = ctx.builder.ins().call(local_callee, &args);
ctx.builder.inst_results(call)[0]
}
_ => panic!("non primitive in emit_primcall: {}", name),
})
}
Expand All @@ -812,6 +869,7 @@ pub(crate) fn string_is_builtin(s: &str) -> bool {

pub(crate) fn string_is_primitive(s: &str) -> bool {
s == "add1"
|| s == "print"
|| s == "integer->char"
|| s == "char->integer"
|| s == "null?"
Expand Down

0 comments on commit a6c139b

Please sign in to comment.