use std::ffi::CString;
use luaur_compiler::records::compile_options::CompileOptions;
#[derive(Debug, Clone)]
pub struct Compiler {
optimization_level: u8,
debug_level: u8,
type_info_level: u8,
coverage_level: u8,
vector_lib: Option<CString>,
vector_ctor: Option<CString>,
vector_type: Option<CString>,
mutable_globals: Vec<CString>,
}
impl Default for Compiler {
fn default() -> Self {
Self::new()
}
}
impl Compiler {
pub fn new() -> Self {
let defaults = CompileOptions::default();
Compiler {
optimization_level: defaults.optimization_level as u8,
debug_level: defaults.debug_level as u8,
type_info_level: defaults.type_info_level as u8,
coverage_level: defaults.coverage_level as u8,
vector_lib: None,
vector_ctor: None,
vector_type: None,
mutable_globals: Vec::new(),
}
}
pub fn set_optimization_level(mut self, level: u8) -> Self {
self.optimization_level = level;
self
}
pub fn set_debug_level(mut self, level: u8) -> Self {
self.debug_level = level;
self
}
pub fn set_type_info_level(mut self, level: u8) -> Self {
self.type_info_level = level;
self
}
pub fn set_coverage_level(mut self, level: u8) -> Self {
self.coverage_level = level;
self
}
pub fn set_vector_lib(mut self, lib: impl Into<Vec<u8>>) -> Self {
self.vector_lib = CString::new(lib).ok();
self
}
pub fn set_vector_ctor(mut self, ctor: impl Into<Vec<u8>>) -> Self {
self.vector_ctor = CString::new(ctor).ok();
self
}
pub fn set_vector_type(mut self, ty: impl Into<Vec<u8>>) -> Self {
self.vector_type = CString::new(ty).ok();
self
}
pub fn set_mutable_globals(mut self, globals: Vec<String>) -> Self {
self.mutable_globals = globals
.into_iter()
.filter_map(|g| CString::new(g).ok())
.collect();
self
}
pub(crate) fn to_options<'a>(
&'a self,
scratch: &'a mut Vec<*const core::ffi::c_char>,
) -> CompileOptions {
let mut options = CompileOptions::default();
options.optimization_level = self.optimization_level as core::ffi::c_int;
options.debug_level = self.debug_level as core::ffi::c_int;
options.type_info_level = self.type_info_level as core::ffi::c_int;
options.coverage_level = self.coverage_level as core::ffi::c_int;
if let Some(s) = &self.vector_lib {
options.vector_lib = s.as_ptr();
}
if let Some(s) = &self.vector_ctor {
options.vector_ctor = s.as_ptr();
}
if let Some(s) = &self.vector_type {
options.vector_type = s.as_ptr();
}
if !self.mutable_globals.is_empty() {
scratch.clear();
for g in &self.mutable_globals {
scratch.push(g.as_ptr());
}
scratch.push(core::ptr::null());
options.mutable_globals = scratch.as_ptr();
}
options
}
}