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 msg: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct LLVMCodeString(pub String);
|
||||||
|
|
||||||
pub trait ProgrammingLanguage<Evaluator> {
|
pub trait ProgrammingLanguage<Evaluator> {
|
||||||
type Token: Debug;
|
type Token: Debug;
|
||||||
type AST: Debug;
|
type AST: Debug;
|
||||||
@ -15,5 +17,5 @@ pub trait ProgrammingLanguage<Evaluator> {
|
|||||||
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError>;
|
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError>;
|
||||||
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError>;
|
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError>;
|
||||||
fn evaluate(ast: Self::AST, evaluator: &mut Evaluator) -> Vec<String>;
|
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::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
mod schala_lang;
|
mod schala_lang;
|
||||||
use schala_lang::eval::Evaluator;
|
use schala_lang::eval::Evaluator;
|
||||||
use schala_lang::compilation::compilation_sequence;
|
|
||||||
use schala_lang::Schala;
|
use schala_lang::Schala;
|
||||||
|
|
||||||
use language::{ProgrammingLanguage, ParseError, TokenError};
|
use language::{ProgrammingLanguage, ParseError, TokenError, LLVMCodeString};
|
||||||
mod language;
|
mod language;
|
||||||
|
|
||||||
mod llvm_wrap;
|
mod llvm_wrap;
|
||||||
@ -168,7 +168,7 @@ impl<'a> Repl<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.show_llvm_ir {
|
if self.show_llvm_ir {
|
||||||
let s = T::compile(ast);
|
let LLVMCodeString(s) = T::compile(ast);
|
||||||
output.push_str(&s);
|
output.push_str(&s);
|
||||||
} else {
|
} else {
|
||||||
// for now only handle last output
|
// 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::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use self::llvm_sys::prelude::*;
|
use self::llvm_sys::prelude::*;
|
||||||
use self::llvm_sys::{LLVMIntPredicate, LLVMRealPredicate};
|
use self::llvm_sys::{LLVMIntPredicate, LLVMRealPredicate};
|
||||||
|
|
||||||
use schala_lang::parser::{AST, Statement, Function, Prototype, Expression, BinOp};
|
use schala_lang::parser::{AST, Statement, Function, Prototype, Expression, BinOp};
|
||||||
|
use language::LLVMCodeString;
|
||||||
|
|
||||||
use llvm_wrap as LLVMWrap;
|
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>;
|
type VariableMap = HashMap<String, LLVMValueRef>;
|
||||||
|
|
||||||
struct CompilationData {
|
struct CompilationData {
|
||||||
@ -66,7 +22,7 @@ struct CompilationData {
|
|||||||
current_function: Option<LLVMValueRef>,
|
current_function: Option<LLVMValueRef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_ast(ast: AST) -> String {
|
pub fn compile_ast(ast: AST) -> LLVMCodeString {
|
||||||
println!("Compiling!");
|
println!("Compiling!");
|
||||||
let names: VariableMap = HashMap::new();
|
let names: VariableMap = HashMap::new();
|
||||||
|
|
||||||
@ -100,7 +56,7 @@ pub fn compile_ast(ast: AST) -> String {
|
|||||||
LLVMWrap::DisposeBuilder(builder);
|
LLVMWrap::DisposeBuilder(builder);
|
||||||
LLVMWrap::DisposeModule(module);
|
LLVMWrap::DisposeModule(module);
|
||||||
LLVMWrap::ContextDispose(context);
|
LLVMWrap::ContextDispose(context);
|
||||||
ret
|
LLVMCodeString(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CodeGen {
|
trait CodeGen {
|
||||||
|
@ -3,7 +3,7 @@ pub mod parser;
|
|||||||
pub mod eval;
|
pub mod eval;
|
||||||
pub mod compilation;
|
pub mod compilation;
|
||||||
|
|
||||||
use language::{ProgrammingLanguage, ParseError, TokenError};
|
use language::{ProgrammingLanguage, ParseError, TokenError, LLVMCodeString};
|
||||||
|
|
||||||
pub struct Schala { }
|
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> {
|
fn evaluate(ast: Self::AST, evaluator: &mut eval::Evaluator) -> Vec<String> {
|
||||||
evaluator.run(ast)
|
evaluator.run(ast)
|
||||||
}
|
}
|
||||||
fn compile(ast: Self::AST) -> String {
|
fn compile(ast: Self::AST) -> LLVMCodeString {
|
||||||
compilation::compile_ast(ast)
|
compilation::compile_ast(ast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user