implement error on conflicting function names and deterministic function generation order
This commit is contained in:
parent
61b8f1ffb9
commit
0133661ad4
|
@ -1,6 +1,6 @@
|
||||||
//! Errors that can occur during transpilation.
|
//! Errors that can occur during transpilation.
|
||||||
|
|
||||||
use std::{collections::HashMap, fmt::Display};
|
use std::{collections::BTreeMap, fmt::Display};
|
||||||
|
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -27,6 +27,8 @@ pub enum TranspileError {
|
||||||
LuaDisabled,
|
LuaDisabled,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
LuaRuntimeError(#[from] LuaRuntimeError),
|
LuaRuntimeError(#[from] LuaRuntimeError),
|
||||||
|
#[error(transparent)]
|
||||||
|
ConflictingFunctionNames(#[from] ConflictingFunctionNames),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of a transpilation operation.
|
/// The result of a transpilation operation.
|
||||||
|
@ -44,7 +46,7 @@ pub struct MissingFunctionDeclaration {
|
||||||
impl MissingFunctionDeclaration {
|
impl MissingFunctionDeclaration {
|
||||||
pub(super) fn from_context(
|
pub(super) fn from_context(
|
||||||
identifier_span: Span,
|
identifier_span: Span,
|
||||||
functions: &HashMap<(String, String), FunctionData>,
|
functions: &BTreeMap<(String, String), FunctionData>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let own_name = identifier_span.str();
|
let own_name = identifier_span.str();
|
||||||
let own_program_identifier = identifier_span.source_file().identifier();
|
let own_program_identifier = identifier_span.source_file().identifier();
|
||||||
|
@ -163,3 +165,30 @@ impl Display for UnexpectedExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for UnexpectedExpression {}
|
impl std::error::Error for UnexpectedExpression {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct ConflictingFunctionNames {
|
||||||
|
pub definition: Span,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ConflictingFunctionNames {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
Message::new(
|
||||||
|
Severity::Error,
|
||||||
|
format!("the following function declaration conflicts with an existing function with name `{}`", self.name)
|
||||||
|
)
|
||||||
|
)?;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"\n{}",
|
||||||
|
SourceCodeDisplay::new(&self.definition, Option::<u8>::None)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for ConflictingFunctionNames {}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
//! Transpiler for `ShulkerScript`
|
//! Transpiler for `ShulkerScript`
|
||||||
|
|
||||||
use chksum_md5 as md5;
|
use chksum_md5 as md5;
|
||||||
use std::{collections::HashMap, iter, sync::RwLock};
|
use std::{
|
||||||
|
collections::{BTreeMap, HashMap},
|
||||||
|
iter,
|
||||||
|
sync::RwLock,
|
||||||
|
};
|
||||||
|
|
||||||
use shulkerbox::datapack::{self, Command, Datapack, Execute};
|
use shulkerbox::datapack::{self, Command, Datapack, Execute};
|
||||||
|
|
||||||
|
@ -20,7 +24,7 @@ use crate::{
|
||||||
Statement,
|
Statement,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
transpile::error::MissingFunctionDeclaration,
|
transpile::error::{ConflictingFunctionNames, MissingFunctionDeclaration},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::error::{TranspileError, TranspileResult, UnexpectedExpression};
|
use super::error::{TranspileError, TranspileResult, UnexpectedExpression};
|
||||||
|
@ -30,7 +34,7 @@ use super::error::{TranspileError, TranspileResult, UnexpectedExpression};
|
||||||
pub struct Transpiler {
|
pub struct Transpiler {
|
||||||
datapack: shulkerbox::datapack::Datapack,
|
datapack: shulkerbox::datapack::Datapack,
|
||||||
/// Key: (program identifier, function name)
|
/// Key: (program identifier, function name)
|
||||||
functions: RwLock<HashMap<(String, String), FunctionData>>,
|
functions: RwLock<BTreeMap<(String, String), FunctionData>>,
|
||||||
function_locations: RwLock<HashMap<(String, String), (String, bool)>>,
|
function_locations: RwLock<HashMap<(String, String), (String, bool)>>,
|
||||||
aliases: RwLock<HashMap<(String, String), (String, String)>>,
|
aliases: RwLock<HashMap<(String, String), (String, String)>>,
|
||||||
}
|
}
|
||||||
|
@ -50,7 +54,7 @@ impl Transpiler {
|
||||||
pub fn new(pack_format: u8) -> Self {
|
pub fn new(pack_format: u8) -> Self {
|
||||||
Self {
|
Self {
|
||||||
datapack: shulkerbox::datapack::Datapack::new(pack_format),
|
datapack: shulkerbox::datapack::Datapack::new(pack_format),
|
||||||
functions: RwLock::new(HashMap::new()),
|
functions: RwLock::new(BTreeMap::new()),
|
||||||
function_locations: RwLock::new(HashMap::new()),
|
function_locations: RwLock::new(HashMap::new()),
|
||||||
aliases: RwLock::new(HashMap::new()),
|
aliases: RwLock::new(HashMap::new()),
|
||||||
}
|
}
|
||||||
|
@ -80,7 +84,7 @@ impl Transpiler {
|
||||||
|
|
||||||
let mut always_transpile_functions = Vec::new();
|
let mut always_transpile_functions = Vec::new();
|
||||||
|
|
||||||
#[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 (_, data) in functions.iter() {
|
for (_, data) in functions.iter() {
|
||||||
|
@ -144,6 +148,7 @@ impl Transpiler {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
#[allow(clippy::significant_drop_tightening)]
|
||||||
self.functions.write().unwrap().insert(
|
self.functions.write().unwrap().insert(
|
||||||
(program_identifier, name),
|
(program_identifier, name),
|
||||||
FunctionData {
|
FunctionData {
|
||||||
|
@ -268,10 +273,18 @@ impl Transpiler {
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|| identifier_span.str().to_string());
|
.unwrap_or_else(|| identifier_span.str().to_string());
|
||||||
|
|
||||||
let function = self
|
let namespace = self.datapack.namespace_mut(&function_data.namespace);
|
||||||
.datapack
|
|
||||||
.namespace_mut(&function_data.namespace)
|
if namespace.function(&modified_name).is_some() {
|
||||||
.function_mut(&modified_name);
|
let err = TranspileError::ConflictingFunctionNames(ConflictingFunctionNames {
|
||||||
|
name: modified_name,
|
||||||
|
definition: identifier_span.clone(),
|
||||||
|
});
|
||||||
|
handler.receive(err.clone());
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
let function = namespace.function_mut(&modified_name);
|
||||||
function.get_commands_mut().extend(commands);
|
function.get_commands_mut().extend(commands);
|
||||||
|
|
||||||
let function_location = format!(
|
let function_location = format!(
|
||||||
|
|
Loading…
Reference in New Issue