implement transpile function for multiple script paths
This commit is contained in:
parent
e80809b3f9
commit
de285639a2
130
src/lib.rs
130
src/lib.rs
|
@ -83,48 +83,16 @@ pub fn parse(path: &Path) -> Result<ProgramFile> {
|
||||||
/// - If an error occurs while parsing the source code.
|
/// - If an error occurs while parsing the source code.
|
||||||
/// - If an error occurs while transpiling the source code.
|
/// - If an error occurs while transpiling the source code.
|
||||||
#[cfg(feature = "shulkerbox")]
|
#[cfg(feature = "shulkerbox")]
|
||||||
pub fn transpile(path: &Path) -> Result<Datapack> {
|
pub fn transpile<P>(script_paths: &[(String, P)]) -> Result<Datapack>
|
||||||
let source_file = SourceFile::load(path)?;
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
let printer = Printer::new();
|
let printer = Printer::new();
|
||||||
|
|
||||||
let tokens = TokenStream::tokenize(&source_file, &printer);
|
let programs = script_paths
|
||||||
|
.iter()
|
||||||
if printer.has_printed() {
|
.map(|(program_identifier, path)| {
|
||||||
return Err(Error::Other(
|
let source_file = SourceFile::load(path.as_ref())?;
|
||||||
"An error occurred while tokenizing the source code.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut parser = Parser::new(&tokens);
|
|
||||||
let program = parser.parse_program(&printer).ok_or(Error::Other(
|
|
||||||
"An error occured while parsing the source code.",
|
|
||||||
))?;
|
|
||||||
|
|
||||||
if printer.has_printed() {
|
|
||||||
return Err(Error::Other(
|
|
||||||
"An error occurred while parsing the source code.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut transpiler = Transpiler::new("shulkerscript-pack", 27);
|
|
||||||
transpiler.transpile(&program, &printer)?;
|
|
||||||
let datapack = transpiler.into_datapack();
|
|
||||||
|
|
||||||
Ok(datapack)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compiles the given source code.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// - If an error occurs while reading the file.
|
|
||||||
/// - If an error occurs while parsing the source code.
|
|
||||||
/// - If an error occurs while transpiling the source code.
|
|
||||||
#[cfg(feature = "shulkerbox")]
|
|
||||||
pub fn compile(path: &Path) -> Result<VFolder> {
|
|
||||||
let source_file = SourceFile::load(path)?;
|
|
||||||
|
|
||||||
let printer = Printer::new();
|
|
||||||
|
|
||||||
let tokens = TokenStream::tokenize(&source_file, &printer);
|
let tokens = TokenStream::tokenize(&source_file, &printer);
|
||||||
|
|
||||||
|
@ -147,10 +115,86 @@ pub fn compile(path: &Path) -> Result<VFolder> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// println!("program: {program:#?}");
|
Ok((program_identifier, program))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut transpiler = Transpiler::new("shulkerscript-pack", 27);
|
if programs.iter().any(Result::is_err) {
|
||||||
transpiler.transpile(&program, &printer)?;
|
return Err(programs.into_iter().find_map(Result::err).unwrap());
|
||||||
|
}
|
||||||
|
let programs = programs
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut transpiler = Transpiler::new(27);
|
||||||
|
transpiler.transpile(&programs, &printer)?;
|
||||||
|
let datapack = transpiler.into_datapack();
|
||||||
|
|
||||||
|
// println!("datapack: {datapack:#?}");
|
||||||
|
|
||||||
|
if printer.has_printed() {
|
||||||
|
return Err(Error::Other(
|
||||||
|
"An error occurred while transpiling the source code.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(datapack)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compiles the given source code.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// - If an error occurs while reading the file.
|
||||||
|
/// - If an error occurs while parsing the source code.
|
||||||
|
/// - If an error occurs while transpiling the source code.
|
||||||
|
#[cfg(feature = "shulkerbox")]
|
||||||
|
pub fn compile<P>(script_paths: &[(String, P)]) -> Result<VFolder>
|
||||||
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
|
let printer = Printer::new();
|
||||||
|
|
||||||
|
let programs = script_paths
|
||||||
|
.iter()
|
||||||
|
.map(|(program_identifier, path)| {
|
||||||
|
let source_file = SourceFile::load(path.as_ref())?;
|
||||||
|
|
||||||
|
let tokens = TokenStream::tokenize(&source_file, &printer);
|
||||||
|
|
||||||
|
// println!("tokens: {tokens:#?}");
|
||||||
|
|
||||||
|
if printer.has_printed() {
|
||||||
|
return Err(Error::Other(
|
||||||
|
"An error occurred while tokenizing the source code.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut parser = Parser::new(&tokens);
|
||||||
|
let program = parser.parse_program(&printer).ok_or(Error::Other(
|
||||||
|
"An error occured while parsing the source code.",
|
||||||
|
))?;
|
||||||
|
|
||||||
|
if printer.has_printed() {
|
||||||
|
return Err(Error::Other(
|
||||||
|
"An error occurred while parsing the source code.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((program_identifier, program))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if programs.iter().any(Result::is_err) {
|
||||||
|
return Err(programs.into_iter().find_map(Result::err).unwrap());
|
||||||
|
}
|
||||||
|
let programs = programs
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut transpiler = Transpiler::new(27);
|
||||||
|
transpiler.transpile(&programs, &printer)?;
|
||||||
let datapack = transpiler.into_datapack();
|
let datapack = transpiler.into_datapack();
|
||||||
|
|
||||||
// println!("datapack: {datapack:#?}");
|
// println!("datapack: {datapack:#?}");
|
||||||
|
|
|
@ -24,7 +24,8 @@ use super::error::{TranspileError, TranspileResult};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Transpiler {
|
pub struct Transpiler {
|
||||||
datapack: shulkerbox::datapack::Datapack,
|
datapack: shulkerbox::datapack::Datapack,
|
||||||
functions: RwLock<HashMap<String, FunctionData>>,
|
/// Key: (program identifier, function name)
|
||||||
|
functions: RwLock<HashMap<(String, String), FunctionData>>,
|
||||||
function_locations: RwLock<HashMap<String, String>>,
|
function_locations: RwLock<HashMap<String, String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +39,9 @@ struct FunctionData {
|
||||||
impl Transpiler {
|
impl Transpiler {
|
||||||
/// Creates a new transpiler.
|
/// Creates a new transpiler.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(pack_name: &str, pack_format: u8) -> Self {
|
pub fn new(pack_format: u8) -> Self {
|
||||||
Self {
|
Self {
|
||||||
datapack: shulkerbox::datapack::Datapack::new(pack_name, pack_format),
|
datapack: shulkerbox::datapack::Datapack::new(pack_format),
|
||||||
functions: RwLock::new(HashMap::new()),
|
functions: RwLock::new(HashMap::new()),
|
||||||
function_locations: RwLock::new(HashMap::new()),
|
function_locations: RwLock::new(HashMap::new()),
|
||||||
}
|
}
|
||||||
|
@ -52,19 +53,36 @@ impl Transpiler {
|
||||||
self.datapack
|
self.datapack
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transpiles the given program.
|
/// Transpiles the given programs.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// - [`TranspileError::MissingFunctionDeclaration`] If a called function is missing
|
/// - [`TranspileError::MissingFunctionDeclaration`] If a called function is missing
|
||||||
pub fn transpile(
|
pub fn transpile<Ident>(
|
||||||
|
&mut self,
|
||||||
|
programs: &[(Ident, ProgramFile)],
|
||||||
|
handler: &impl Handler<TranspileError>,
|
||||||
|
) -> Result<(), TranspileError>
|
||||||
|
where
|
||||||
|
Ident: AsRef<str>,
|
||||||
|
{
|
||||||
|
for (identifier, program) in programs {
|
||||||
|
self.transpile_program(program, identifier.as_ref(), handler)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transpiles the given program.
|
||||||
|
fn transpile_program(
|
||||||
&mut self,
|
&mut self,
|
||||||
program: &ProgramFile,
|
program: &ProgramFile,
|
||||||
|
identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> Result<(), TranspileError> {
|
) -> TranspileResult<()> {
|
||||||
let namespace = program.namespace();
|
let namespace = program.namespace();
|
||||||
|
|
||||||
for declaration in program.declarations() {
|
for declaration in program.declarations() {
|
||||||
self.transpile_declaration(declaration, namespace, handler);
|
self.transpile_declaration(declaration, namespace, identifier, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut always_transpile_functions = Vec::new();
|
let mut always_transpile_functions = Vec::new();
|
||||||
|
@ -72,18 +90,18 @@ impl Transpiler {
|
||||||
#[allow(clippy::significant_drop_in_scrutinee)]
|
#[allow(clippy::significant_drop_in_scrutinee)]
|
||||||
{
|
{
|
||||||
let functions = self.functions.read().unwrap();
|
let functions = self.functions.read().unwrap();
|
||||||
for (name, data) in functions.iter() {
|
for (function_identifier, data) in functions.iter() {
|
||||||
let always_transpile_function = data.annotations.contains_key("tick")
|
let always_transpile_function = data.annotations.contains_key("tick")
|
||||||
|| data.annotations.contains_key("load")
|
|| data.annotations.contains_key("load")
|
||||||
|| data.annotations.contains_key("deobfuscate");
|
|| data.annotations.contains_key("deobfuscate");
|
||||||
if always_transpile_function {
|
if always_transpile_function {
|
||||||
always_transpile_functions.push(name.clone());
|
always_transpile_functions.push(function_identifier.to_owned());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for name in always_transpile_functions {
|
for (program_identifier, name) in always_transpile_functions {
|
||||||
self.get_or_transpile_function(&name, handler)?;
|
self.get_or_transpile_function(&name, &program_identifier, handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -94,6 +112,7 @@ impl Transpiler {
|
||||||
&mut self,
|
&mut self,
|
||||||
declaration: &Declaration,
|
declaration: &Declaration,
|
||||||
namespace: &Namespace,
|
namespace: &Namespace,
|
||||||
|
program_identifier: &str,
|
||||||
_handler: &impl Handler<TranspileError>,
|
_handler: &impl Handler<TranspileError>,
|
||||||
) {
|
) {
|
||||||
match declaration {
|
match declaration {
|
||||||
|
@ -113,7 +132,7 @@ impl Transpiler {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.functions.write().unwrap().insert(
|
self.functions.write().unwrap().insert(
|
||||||
name,
|
(program_identifier.to_string(), name),
|
||||||
FunctionData {
|
FunctionData {
|
||||||
namespace: namespace.namespace_name().str_content().to_string(),
|
namespace: namespace.namespace_name().str_content().to_string(),
|
||||||
statements,
|
statements,
|
||||||
|
@ -130,6 +149,7 @@ impl Transpiler {
|
||||||
fn get_or_transpile_function(
|
fn get_or_transpile_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<String> {
|
) -> TranspileResult<String> {
|
||||||
let already_transpiled = {
|
let already_transpiled = {
|
||||||
|
@ -139,17 +159,21 @@ impl Transpiler {
|
||||||
if !already_transpiled {
|
if !already_transpiled {
|
||||||
let statements = {
|
let statements = {
|
||||||
let functions = self.functions.read().unwrap();
|
let functions = self.functions.read().unwrap();
|
||||||
let function_data = functions.get(name).ok_or_else(|| {
|
let function_data = functions
|
||||||
|
.get(&(program_identifier.to_string(), name.to_string()))
|
||||||
|
.ok_or_else(|| {
|
||||||
let error = TranspileError::MissingFunctionDeclaration(name.to_string());
|
let error = TranspileError::MissingFunctionDeclaration(name.to_string());
|
||||||
handler.receive(error.clone());
|
handler.receive(error.clone());
|
||||||
error
|
error
|
||||||
})?;
|
})?;
|
||||||
function_data.statements.clone()
|
function_data.statements.clone()
|
||||||
};
|
};
|
||||||
let commands = self.transpile_function(&statements, handler)?;
|
let commands = self.transpile_function(&statements, program_identifier, handler)?;
|
||||||
|
|
||||||
let functions = self.functions.read().unwrap();
|
let functions = self.functions.read().unwrap();
|
||||||
let function_data = functions.get(name).ok_or_else(|| {
|
let function_data = functions
|
||||||
|
.get(&(program_identifier.to_string(), name.to_string()))
|
||||||
|
.ok_or_else(|| {
|
||||||
let error = TranspileError::MissingFunctionDeclaration(name.to_string());
|
let error = TranspileError::MissingFunctionDeclaration(name.to_string());
|
||||||
handler.receive(error.clone());
|
handler.receive(error.clone());
|
||||||
error
|
error
|
||||||
|
@ -159,7 +183,10 @@ impl Transpiler {
|
||||||
.annotations
|
.annotations
|
||||||
.get("deobfuscate")
|
.get("deobfuscate")
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| Some("shu/".to_string() + &md5::hash(name).to_hex_lowercase()[..16]),
|
|| {
|
||||||
|
let hash_data = program_identifier.to_string() + "\0" + name;
|
||||||
|
Some("shu/".to_string() + &md5::hash(hash_data).to_hex_lowercase()[..16])
|
||||||
|
},
|
||||||
Clone::clone,
|
Clone::clone,
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|| name.to_string());
|
.unwrap_or_else(|| name.to_string());
|
||||||
|
@ -202,13 +229,14 @@ impl Transpiler {
|
||||||
fn transpile_function(
|
fn transpile_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
statements: &[Statement],
|
statements: &[Statement],
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<Vec<Command>> {
|
) -> TranspileResult<Vec<Command>> {
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
let commands = statements
|
let commands = statements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|statement| {
|
.filter_map(|statement| {
|
||||||
self.transpile_statement(statement, handler)
|
self.transpile_statement(statement, program_identifier, handler)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
None
|
None
|
||||||
|
@ -226,6 +254,7 @@ impl Transpiler {
|
||||||
fn transpile_statement(
|
fn transpile_statement(
|
||||||
&mut self,
|
&mut self,
|
||||||
statement: &Statement,
|
statement: &Statement,
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<Option<Command>> {
|
) -> TranspileResult<Option<Command>> {
|
||||||
match statement {
|
match statement {
|
||||||
|
@ -233,9 +262,9 @@ impl Transpiler {
|
||||||
Ok(Some(literal_command.clean_command().into()))
|
Ok(Some(literal_command.clean_command().into()))
|
||||||
}
|
}
|
||||||
Statement::Run(run) => match run.expression() {
|
Statement::Run(run) => match run.expression() {
|
||||||
Expression::Primary(Primary::FunctionCall(func)) => {
|
Expression::Primary(Primary::FunctionCall(func)) => self
|
||||||
self.transpile_function_call(func, handler).map(Some)
|
.transpile_function_call(func, program_identifier, handler)
|
||||||
}
|
.map(Some),
|
||||||
Expression::Primary(Primary::StringLiteral(string)) => {
|
Expression::Primary(Primary::StringLiteral(string)) => {
|
||||||
Ok(Some(Command::Raw(string.str_content().to_string())))
|
Ok(Some(Command::Raw(string.str_content().to_string())))
|
||||||
}
|
}
|
||||||
|
@ -246,7 +275,9 @@ impl Transpiler {
|
||||||
Statement::Block(_) => {
|
Statement::Block(_) => {
|
||||||
unreachable!("Only literal commands are allowed in functions at this time.")
|
unreachable!("Only literal commands are allowed in functions at this time.")
|
||||||
}
|
}
|
||||||
Statement::ExecuteBlock(execute) => self.transpile_execute_block(execute, handler),
|
Statement::ExecuteBlock(execute) => {
|
||||||
|
self.transpile_execute_block(execute, program_identifier, handler)
|
||||||
|
}
|
||||||
Statement::DocComment(doccomment) => {
|
Statement::DocComment(doccomment) => {
|
||||||
let content = doccomment.content();
|
let content = doccomment.content();
|
||||||
Ok(Some(Command::Comment(content.to_string())))
|
Ok(Some(Command::Comment(content.to_string())))
|
||||||
|
@ -257,7 +288,7 @@ impl Transpiler {
|
||||||
let commands = statements
|
let commands = statements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|statement| {
|
.filter_map(|statement| {
|
||||||
self.transpile_statement(statement, handler)
|
self.transpile_statement(statement, program_identifier, handler)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
None
|
None
|
||||||
|
@ -275,9 +306,9 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
#[allow(clippy::match_wildcard_for_single_variants)]
|
#[allow(clippy::match_wildcard_for_single_variants)]
|
||||||
Statement::Semicolon(semi) => match semi.expression() {
|
Statement::Semicolon(semi) => match semi.expression() {
|
||||||
Expression::Primary(Primary::FunctionCall(func)) => {
|
Expression::Primary(Primary::FunctionCall(func)) => self
|
||||||
self.transpile_function_call(func, handler).map(Some)
|
.transpile_function_call(func, program_identifier, handler)
|
||||||
}
|
.map(Some),
|
||||||
unexpected => {
|
unexpected => {
|
||||||
let error = TranspileError::UnexpectedExpression(unexpected.clone());
|
let error = TranspileError::UnexpectedExpression(unexpected.clone());
|
||||||
handler.receive(error.clone());
|
handler.receive(error.clone());
|
||||||
|
@ -290,26 +321,30 @@ impl Transpiler {
|
||||||
fn transpile_function_call(
|
fn transpile_function_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &FunctionCall,
|
func: &FunctionCall,
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<Command> {
|
) -> TranspileResult<Command> {
|
||||||
let identifier = func.identifier().span();
|
let identifier = func.identifier().span();
|
||||||
let identifier_name = identifier.str();
|
let identifier_name = identifier.str();
|
||||||
let location = self.get_or_transpile_function(identifier_name, handler)?;
|
let location =
|
||||||
|
self.get_or_transpile_function(identifier_name, program_identifier, handler)?;
|
||||||
Ok(Command::Raw(format!("function {location}")))
|
Ok(Command::Raw(format!("function {location}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transpile_execute_block(
|
fn transpile_execute_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
execute: &ExecuteBlock,
|
execute: &ExecuteBlock,
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<Option<Command>> {
|
) -> TranspileResult<Option<Command>> {
|
||||||
self.transpile_execute_block_internal(execute, handler)
|
self.transpile_execute_block_internal(execute, program_identifier, handler)
|
||||||
.map(|ex| ex.map(Command::Execute))
|
.map(|ex| ex.map(Command::Execute))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transpile_execute_block_internal(
|
fn transpile_execute_block_internal(
|
||||||
&mut self,
|
&mut self,
|
||||||
execute: &ExecuteBlock,
|
execute: &ExecuteBlock,
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<Option<Execute>> {
|
) -> TranspileResult<Option<Execute>> {
|
||||||
match execute {
|
match execute {
|
||||||
|
@ -321,7 +356,8 @@ impl Transpiler {
|
||||||
.statements()
|
.statements()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|s| {
|
.filter_map(|s| {
|
||||||
self.transpile_statement(s, handler).unwrap_or_else(|err| {
|
self.transpile_statement(s, program_identifier, handler)
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
|
@ -337,12 +373,15 @@ impl Transpiler {
|
||||||
Ok(Some(Execute::Runs(commands)))
|
Ok(Some(Execute::Runs(commands)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExecuteBlockTail::ExecuteBlock(_, execute_block) => {
|
ExecuteBlockTail::ExecuteBlock(_, execute_block) => self
|
||||||
self.transpile_execute_block_internal(execute_block, handler)
|
.transpile_execute_block_internal(
|
||||||
}
|
execute_block,
|
||||||
|
program_identifier,
|
||||||
|
handler,
|
||||||
|
),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
self.combine_execute_head_tail(head, tail, handler)
|
self.combine_execute_head_tail(head, tail, program_identifier, handler)
|
||||||
}
|
}
|
||||||
ExecuteBlock::IfElse(cond, block, el) => {
|
ExecuteBlock::IfElse(cond, block, el) => {
|
||||||
let statements = block.statements();
|
let statements = block.statements();
|
||||||
|
@ -353,7 +392,7 @@ impl Transpiler {
|
||||||
let commands = statements
|
let commands = statements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|statement| {
|
.filter_map(|statement| {
|
||||||
self.transpile_statement(statement, handler)
|
self.transpile_statement(statement, program_identifier, handler)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
None
|
None
|
||||||
|
@ -365,13 +404,21 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
Some(Execute::Runs(commands))
|
Some(Execute::Runs(commands))
|
||||||
} else {
|
} else {
|
||||||
self.transpile_statement(&statements[0], handler)?
|
self.transpile_statement(&statements[0], program_identifier, handler)?
|
||||||
.map(|cmd| Execute::Run(Box::new(cmd)))
|
.map(|cmd| Execute::Run(Box::new(cmd)))
|
||||||
};
|
};
|
||||||
|
|
||||||
then.map_or_else(
|
then.map_or_else(
|
||||||
|| Ok(None),
|
|| Ok(None),
|
||||||
|then| self.transpile_conditional(cond, then, Some(el), handler),
|
|then| {
|
||||||
|
self.transpile_conditional(
|
||||||
|
cond,
|
||||||
|
then,
|
||||||
|
Some(el),
|
||||||
|
program_identifier,
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,6 +429,7 @@ impl Transpiler {
|
||||||
cond: &Conditional,
|
cond: &Conditional,
|
||||||
then: Execute,
|
then: Execute,
|
||||||
el: Option<&Else>,
|
el: Option<&Else>,
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<Option<Execute>> {
|
) -> TranspileResult<Option<Execute>> {
|
||||||
let (_, cond) = cond.clone().dissolve();
|
let (_, cond) = cond.clone().dissolve();
|
||||||
|
@ -395,7 +443,7 @@ impl Transpiler {
|
||||||
if statements.is_empty() {
|
if statements.is_empty() {
|
||||||
None
|
None
|
||||||
} else if statements.len() == 1 {
|
} else if statements.len() == 1 {
|
||||||
self.transpile_statement(&statements[0], handler)
|
self.transpile_statement(&statements[0], program_identifier, handler)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
None
|
None
|
||||||
|
@ -405,7 +453,7 @@ impl Transpiler {
|
||||||
let commands = statements
|
let commands = statements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|statement| {
|
.filter_map(|statement| {
|
||||||
self.transpile_statement(statement, handler)
|
self.transpile_statement(statement, program_identifier, handler)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
None
|
None
|
||||||
|
@ -432,12 +480,13 @@ impl Transpiler {
|
||||||
&mut self,
|
&mut self,
|
||||||
head: &ExecuteBlockHead,
|
head: &ExecuteBlockHead,
|
||||||
tail: Option<Execute>,
|
tail: Option<Execute>,
|
||||||
|
program_identifier: &str,
|
||||||
handler: &impl Handler<TranspileError>,
|
handler: &impl Handler<TranspileError>,
|
||||||
) -> TranspileResult<Option<Execute>> {
|
) -> TranspileResult<Option<Execute>> {
|
||||||
Ok(match head {
|
Ok(match head {
|
||||||
ExecuteBlockHead::Conditional(cond) => {
|
ExecuteBlockHead::Conditional(cond) => {
|
||||||
if let Some(tail) = tail {
|
if let Some(tail) = tail {
|
||||||
self.transpile_conditional(cond, tail, None, handler)?
|
self.transpile_conditional(cond, tail, None, program_identifier, handler)?
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue