Make newtype for LLVM code strings
This commit is contained in:
parent
5103f03fa5
commit
fd4610e175
@ -8,6 +8,8 @@ pub struct ParseError {
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
pub struct LLVMCodeString(pub String);
|
||||
|
||||
pub trait ProgrammingLanguage<Evaluator> {
|
||||
type Token: Debug;
|
||||
type AST: Debug;
|
||||
@ -15,5 +17,5 @@ pub trait ProgrammingLanguage<Evaluator> {
|
||||
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError>;
|
||||
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError>;
|
||||
fn evaluate(ast: Self::AST, evaluator: &mut Evaluator) -> Vec<String>;
|
||||
fn compile(ast: Self::AST) -> String;
|
||||
fn compile(ast: Self::AST) -> LLVMCodeString;
|
||||
}
|
||||
|
52
src/main.rs
52
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<String, LLVMValueRef>;
|
||||
|
||||
struct CompilationData {
|
||||
@ -66,7 +22,7 @@ struct CompilationData {
|
||||
current_function: Option<LLVMValueRef>,
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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<eval::Evaluator<'a>> for Schala {
|
||||
fn evaluate(ast: Self::AST, evaluator: &mut eval::Evaluator) -> Vec<String> {
|
||||
evaluator.run(ast)
|
||||
}
|
||||
fn compile(ast: Self::AST) -> String {
|
||||
fn compile(ast: Self::AST) -> LLVMCodeString {
|
||||
compilation::compile_ast(ast)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user