Unified the C# mod and the Rust compiler into a monorepo
This commit is contained in:
58
rust_compiler/src/lib.rs
Normal file
58
rust_compiler/src/lib.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use compiler::Compiler;
|
||||
use parser::Parser;
|
||||
use std::{
|
||||
ffi::{CStr, CString},
|
||||
io::BufWriter,
|
||||
};
|
||||
use tokenizer::Tokenizer;
|
||||
|
||||
/// Takes a raw pointer to a string and compiles the `slang` code into valid IC10
|
||||
/// # Safety
|
||||
/// This must be called with a valid string pointer from C# (or wherever is calling this function)
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn compile_from_string(
|
||||
input_ptr: *const std::os::raw::c_char,
|
||||
) -> *mut std::os::raw::c_char {
|
||||
if input_ptr.is_null() {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(input_ptr) };
|
||||
|
||||
let Ok(input_str) = c_str.to_str() else {
|
||||
return std::ptr::null_mut();
|
||||
};
|
||||
|
||||
let mut writer = BufWriter::new(Vec::new());
|
||||
let tokenizer = Tokenizer::from(input_str);
|
||||
let parser = Parser::new(tokenizer);
|
||||
|
||||
let compiler = Compiler::new(parser, &mut writer, None);
|
||||
|
||||
let Ok(()) = compiler.compile() else {
|
||||
return std::ptr::null_mut();
|
||||
};
|
||||
|
||||
let Ok(buffer) = writer.into_inner() else {
|
||||
return std::ptr::null_mut();
|
||||
};
|
||||
|
||||
let c_string = CString::from_vec_unchecked(buffer);
|
||||
|
||||
c_string.into_raw()
|
||||
}
|
||||
|
||||
/// Takes ownership of the string pointer and drops it, freeing the memory
|
||||
/// # Safety
|
||||
/// Must be called with a valid string pointer
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn free_slang_string(input_ptr: *mut std::os::raw::c_char) {
|
||||
if input_ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// Takes ownership of the input string, and then drops it immediately
|
||||
let _ = CString::from_raw(input_ptr);
|
||||
}
|
||||
}
|
||||
86
rust_compiler/src/main.rs
Normal file
86
rust_compiler/src/main.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
#[macro_use]
|
||||
extern crate quick_error;
|
||||
|
||||
use clap::Parser;
|
||||
use compiler::Compiler;
|
||||
use parser::Parser as ASTParser;
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufWriter, Read, Write},
|
||||
path::PathBuf,
|
||||
};
|
||||
use tokenizer::{self, Tokenizer};
|
||||
|
||||
quick_error! {
|
||||
#[derive(Debug)]
|
||||
enum StationlangError {
|
||||
TokenizerError(err: tokenizer::Error) {
|
||||
from()
|
||||
display("Tokenizer error: {}", err)
|
||||
}
|
||||
ParserError(err: parser::Error) {
|
||||
from()
|
||||
display("Parser error: {}", err)
|
||||
}
|
||||
CompileError(err: compiler::Error) {
|
||||
from()
|
||||
display("Compile error: {}", err)
|
||||
}
|
||||
IoError(err: std::io::Error) {
|
||||
from()
|
||||
display("IO error: {}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Args {
|
||||
/// What file should be compiled. If not set, input will be read from stdin.
|
||||
#[arg(short, long)]
|
||||
input_file: Option<PathBuf>,
|
||||
/// The output file for the compiled program. If not set, output will go to stdout.
|
||||
#[arg(short, long)]
|
||||
output_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn run_logic() -> Result<(), StationlangError> {
|
||||
let args = Args::parse();
|
||||
let input_file = args.input_file;
|
||||
|
||||
let tokenizer: Tokenizer = match input_file {
|
||||
Some(input_file) => Tokenizer::from_path(&input_file)?,
|
||||
None => {
|
||||
let mut buf = String::new();
|
||||
let stdin = std::io::stdin();
|
||||
|
||||
let read_result = stdin.lock().read_to_string(&mut buf)?;
|
||||
|
||||
if read_result == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Tokenizer::from(buf)
|
||||
}
|
||||
};
|
||||
|
||||
let parser = ASTParser::new(tokenizer);
|
||||
|
||||
let mut writer: BufWriter<Box<dyn Write>> = match args.output_file {
|
||||
Some(output_file) => BufWriter::new(Box::new(File::create(output_file)?)),
|
||||
None => BufWriter::new(Box::new(std::io::stdout())),
|
||||
};
|
||||
|
||||
let compiler = Compiler::new(parser, &mut writer, None);
|
||||
|
||||
compiler.compile()?;
|
||||
writer.flush()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), StationlangError> {
|
||||
run_logic()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user