From fd4610e175aace9b01f099727a57db979a02e3a5 Mon Sep 17 00:00:00 2001 From: greg Date: Mon, 23 Jan 2017 19:11:50 -0800 Subject: [PATCH] Make newtype for LLVM code strings --- src/language.rs | 4 ++- src/main.rs | 52 ++++++++++++++++++++++++++++++++-- src/schala_lang/compilation.rs | 50 ++------------------------------ src/schala_lang/mod.rs | 4 +-- 4 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/language.rs b/src/language.rs index a114450..fe562a3 100644 --- a/src/language.rs +++ b/src/language.rs @@ -8,6 +8,8 @@ pub struct ParseError { pub msg: String, } +pub struct LLVMCodeString(pub String); + pub trait ProgrammingLanguage { type Token: Debug; type AST: Debug; @@ -15,5 +17,5 @@ pub trait ProgrammingLanguage { fn tokenize(input: &str) -> Result, TokenError>; fn parse(input: Vec) -> Result; fn evaluate(ast: Self::AST, evaluator: &mut Evaluator) -> Vec; - fn compile(ast: Self::AST) -> String; + fn compile(ast: Self::AST) -> LLVMCodeString; } diff --git a/src/main.rs b/src/main.rs index ee3202b..072d2d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,13 +6,13 @@ use std::path::Path; use std::fs::File; use std::io::Read; use std::process; +use std::io::Write; mod schala_lang; use schala_lang::eval::Evaluator; -use schala_lang::compilation::compilation_sequence; use schala_lang::Schala; -use language::{ProgrammingLanguage, ParseError, TokenError}; +use language::{ProgrammingLanguage, ParseError, TokenError, LLVMCodeString}; mod language; mod llvm_wrap; @@ -168,7 +168,7 @@ impl<'a> Repl<'a> { } if self.show_llvm_ir { - let s = T::compile(ast); + let LLVMCodeString(s) = T::compile(ast); output.push_str(&s); } else { // for now only handle last output @@ -230,3 +230,49 @@ impl<'a> Repl<'a> { } } +pub fn compilation_sequence(llvm_code: LLVMCodeString, sourcefile: &str) { + use std::process::Command; + + let ll_filename = "out.ll"; + let obj_filename = "out.o"; + let q: Vec<&str> = sourcefile.split('.').collect(); + let bin_filename = match &q[..] { + &[name, "schala"] => name, + _ => panic!("Bad filename {}", sourcefile), + }; + + let LLVMCodeString(llvm_str) = llvm_code; + + println!("Compilation process finished for {}", ll_filename); + File::create(ll_filename) + .and_then(|mut f| f.write_all(llvm_str.as_bytes())) + .expect("Error writing file"); + + let llc_output = Command::new("llc") + .args(&["-filetype=obj", ll_filename, "-o", obj_filename]) + .output() + .expect("Failed to run llc"); + + + if !llc_output.status.success() { + println!("{}", String::from_utf8_lossy(&llc_output.stderr)); + } + + let gcc_output = Command::new("gcc") + .args(&["-o", bin_filename, &obj_filename]) + .output() + .expect("failed to run gcc"); + + if !gcc_output.status.success() { + println!("{}", String::from_utf8_lossy(&gcc_output.stdout)); + println!("{}", String::from_utf8_lossy(&gcc_output.stderr)); + } + + for filename in [obj_filename].iter() { + Command::new("rm") + .arg(filename) + .output() + .expect(&format!("failed to run rm {}", filename)); + } +} + diff --git a/src/schala_lang/compilation.rs b/src/schala_lang/compilation.rs index 1ffb6ed..5c36955 100644 --- a/src/schala_lang/compilation.rs +++ b/src/schala_lang/compilation.rs @@ -2,59 +2,15 @@ extern crate llvm_sys; use std::collections::HashMap; use std::fs::File; -use std::io::Write; use self::llvm_sys::prelude::*; use self::llvm_sys::{LLVMIntPredicate, LLVMRealPredicate}; use schala_lang::parser::{AST, Statement, Function, Prototype, Expression, BinOp}; +use language::LLVMCodeString; use llvm_wrap as LLVMWrap; -pub fn compilation_sequence(llvm_code: String, sourcefile: &str) { - use std::process::Command; - - let ll_filename = "out.ll"; - let obj_filename = "out.o"; - let q: Vec<&str> = sourcefile.split('.').collect(); - let bin_filename = match &q[..] { - &[name, "schala"] => name, - _ => panic!("Bad filename {}", sourcefile), - }; - - println!("Compilation process finished for {}", ll_filename); - File::create(ll_filename) - .and_then(|mut f| f.write_all(llvm_code.as_bytes())) - .expect("Error writing file"); - - let llc_output = Command::new("llc") - .args(&["-filetype=obj", ll_filename, "-o", obj_filename]) - .output() - .expect("Failed to run llc"); - - - if !llc_output.status.success() { - println!("{}", String::from_utf8_lossy(&llc_output.stderr)); - } - - let gcc_output = Command::new("gcc") - .args(&["-o", bin_filename, &obj_filename]) - .output() - .expect("failed to run gcc"); - - if !gcc_output.status.success() { - println!("{}", String::from_utf8_lossy(&gcc_output.stdout)); - println!("{}", String::from_utf8_lossy(&gcc_output.stderr)); - } - - for filename in [obj_filename].iter() { - Command::new("rm") - .arg(filename) - .output() - .expect(&format!("failed to run rm {}", filename)); - } -} - type VariableMap = HashMap; struct CompilationData { @@ -66,7 +22,7 @@ struct CompilationData { current_function: Option, } -pub fn compile_ast(ast: AST) -> String { +pub fn compile_ast(ast: AST) -> LLVMCodeString { println!("Compiling!"); let names: VariableMap = HashMap::new(); @@ -100,7 +56,7 @@ pub fn compile_ast(ast: AST) -> String { LLVMWrap::DisposeBuilder(builder); LLVMWrap::DisposeModule(module); LLVMWrap::ContextDispose(context); - ret + LLVMCodeString(ret) } trait CodeGen { diff --git a/src/schala_lang/mod.rs b/src/schala_lang/mod.rs index f225c8c..1e56691 100644 --- a/src/schala_lang/mod.rs +++ b/src/schala_lang/mod.rs @@ -3,7 +3,7 @@ pub mod parser; pub mod eval; pub mod compilation; -use language::{ProgrammingLanguage, ParseError, TokenError}; +use language::{ProgrammingLanguage, ParseError, TokenError, LLVMCodeString}; pub struct Schala { } @@ -21,7 +21,7 @@ impl<'a> ProgrammingLanguage> for Schala { fn evaluate(ast: Self::AST, evaluator: &mut eval::Evaluator) -> Vec { evaluator.run(ast) } - fn compile(ast: Self::AST) -> String { + fn compile(ast: Self::AST) -> LLVMCodeString { compilation::compile_ast(ast) } }