add SourceCodeDisplay to MissingFunctionDeclaration error
This commit is contained in:
parent
4505def6c0
commit
659683bd39
|
@ -10,7 +10,7 @@ pub enum Error {
|
||||||
TokenizeError(#[from] crate::lexical::token::TokenizeError),
|
TokenizeError(#[from] crate::lexical::token::TokenizeError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ParseError(#[from] crate::syntax::error::Error),
|
ParseError(#[from] crate::syntax::error::Error),
|
||||||
#[error("An error occurred while transpiling the source code.")]
|
#[error(transparent)]
|
||||||
TranspileError(#[from] crate::transpile::TranspileError),
|
TranspileError(#[from] crate::transpile::TranspileError),
|
||||||
#[error("An error occurred")]
|
#[error("An error occurred")]
|
||||||
Other(&'static str),
|
Other(&'static str),
|
||||||
|
|
|
@ -21,6 +21,9 @@ pub struct SourceFile {
|
||||||
/// Get the path of the source file.
|
/// Get the path of the source file.
|
||||||
#[get = "pub"]
|
#[get = "pub"]
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
/// Get the identifier of the source file.
|
||||||
|
#[get = "pub"]
|
||||||
|
identifier: String,
|
||||||
/// Get the content of the source file
|
/// Get the content of the source file
|
||||||
#[get = "pub"]
|
#[get = "pub"]
|
||||||
content: String,
|
content: String,
|
||||||
|
@ -38,11 +41,12 @@ impl Debug for SourceFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceFile {
|
impl SourceFile {
|
||||||
fn new(path: PathBuf, content: String) -> Arc<Self> {
|
fn new(path: PathBuf, identifier: String, content: String) -> Arc<Self> {
|
||||||
let lines = get_line_byte_positions(&content);
|
let lines = get_line_byte_positions(&content);
|
||||||
|
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
path,
|
path,
|
||||||
|
identifier,
|
||||||
content,
|
content,
|
||||||
lines,
|
lines,
|
||||||
})
|
})
|
||||||
|
@ -83,9 +87,13 @@ impl SourceFile {
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// - [`Error::IoError`]: Error occurred when reading the file contents.
|
/// - [`Error::IoError`]: Error occurred when reading the file contents.
|
||||||
pub fn load(path: &Path, provider: &impl FileProvider) -> Result<Arc<Self>, Error> {
|
pub fn load(
|
||||||
|
path: &Path,
|
||||||
|
identifier: String,
|
||||||
|
provider: &impl FileProvider,
|
||||||
|
) -> Result<Arc<Self>, Error> {
|
||||||
let source = provider.read_to_string(path)?;
|
let source = provider.read_to_string(path)?;
|
||||||
Ok(Self::new(path.to_path_buf(), source))
|
Ok(Self::new(path.to_path_buf(), identifier, source))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the [`Location`] of a given byte index
|
/// Get the [`Location`] of a given byte index
|
||||||
|
|
|
@ -628,7 +628,8 @@ mod tests {
|
||||||
let source_file = VFile::Text(String::from(content));
|
let source_file = VFile::Text(String::from(content));
|
||||||
let mut vfolder = VFolder::new();
|
let mut vfolder = VFolder::new();
|
||||||
vfolder.add_file("test.shu", source_file);
|
vfolder.add_file("test.shu", source_file);
|
||||||
let source_file = SourceFile::load(Path::new("test.shu"), &vfolder).unwrap();
|
let source_file =
|
||||||
|
SourceFile::load(Path::new("test.shu"), "test".to_string(), &vfolder).unwrap();
|
||||||
|
|
||||||
Span::new(source_file, 0, content.len()).unwrap()
|
Span::new(source_file, 0, content.len()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
19
src/lib.rs
19
src/lib.rs
|
@ -39,17 +39,18 @@ use crate::lexical::token_stream::TokenStream;
|
||||||
/// use std::path::Path;
|
/// use std::path::Path;
|
||||||
/// use shulkerscript::{tokenize, base::{FsProvider, PrintHandler}};
|
/// use shulkerscript::{tokenize, base::{FsProvider, PrintHandler}};
|
||||||
///
|
///
|
||||||
/// let token_stream = tokenize(&PrintHandler::new(), &FsProvider::default(), Path::new("path/to/file.shu"))?;
|
/// let token_stream = tokenize(&PrintHandler::new(), &FsProvider::default(), Path::new("path/to/file.shu"), "file".to_string())?;
|
||||||
/// # Ok::<(), shulkerscript::base::Error>(())
|
/// # Ok::<(), shulkerscript::base::Error>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub fn tokenize(
|
pub fn tokenize(
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
file_provider: &impl FileProvider,
|
file_provider: &impl FileProvider,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
identifier: String,
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
tracing::info!("Tokenizing the source code at path: {}", path.display());
|
tracing::info!("Tokenizing the source code at path: {}", path.display());
|
||||||
|
|
||||||
let source_file = SourceFile::load(path, file_provider)?;
|
let source_file = SourceFile::load(path, identifier, file_provider)?;
|
||||||
|
|
||||||
Ok(TokenStream::tokenize(&source_file, handler))
|
Ok(TokenStream::tokenize(&source_file, handler))
|
||||||
}
|
}
|
||||||
|
@ -65,15 +66,16 @@ pub fn tokenize(
|
||||||
/// use std::path::Path;
|
/// use std::path::Path;
|
||||||
/// use shulkerscript::{parse, base::{FsProvider, PrintHandler}};
|
/// use shulkerscript::{parse, base::{FsProvider, PrintHandler}};
|
||||||
///
|
///
|
||||||
/// let program_file = parse(&PrintHandler::new(), &FsProvider::default(), Path::new("path/to/file.shu"))?;
|
/// let program_file = parse(&PrintHandler::new(), &FsProvider::default(), Path::new("path/to/file.shu"), "file".to_string())?;
|
||||||
/// # Ok::<(), shulkerscript::base::Error>(())
|
/// # Ok::<(), shulkerscript::base::Error>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
file_provider: &impl FileProvider,
|
file_provider: &impl FileProvider,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
identifier: String,
|
||||||
) -> Result<ProgramFile> {
|
) -> Result<ProgramFile> {
|
||||||
let tokens = tokenize(handler, file_provider, path)?;
|
let tokens = tokenize(handler, file_provider, path, identifier)?;
|
||||||
|
|
||||||
if handler.has_received() {
|
if handler.has_received() {
|
||||||
return Err(Error::Other(
|
return Err(Error::Other(
|
||||||
|
@ -137,9 +139,14 @@ where
|
||||||
let programs = script_paths
|
let programs = script_paths
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(program_identifier, path)| {
|
.map(|(program_identifier, path)| {
|
||||||
let program = parse(handler, file_provider, path.as_ref())?;
|
let program = parse(
|
||||||
|
handler,
|
||||||
|
file_provider,
|
||||||
|
path.as_ref(),
|
||||||
|
program_identifier.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok((program_identifier, program))
|
Ok(program)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ impl Display for UnexpectedSyntax {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"\n{}",
|
"\n{}",
|
||||||
SourceCodeDisplay::new(span.span(), Option::<i32>::None)
|
SourceCodeDisplay::new(span.span(), Option::<u8>::None)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
//! Errors that can occur during transpilation.
|
//! Errors that can occur during transpilation.
|
||||||
|
|
||||||
use crate::{base::source_file::SourceElement, syntax::syntax_tree::expression::Expression};
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
base::{
|
||||||
|
log::{Message, Severity, SourceCodeDisplay},
|
||||||
|
source_file::{SourceElement, Span},
|
||||||
|
},
|
||||||
|
syntax::syntax_tree::expression::Expression,
|
||||||
|
};
|
||||||
|
|
||||||
/// Errors that can occur during transpilation.
|
/// Errors that can occur during transpilation.
|
||||||
#[allow(clippy::module_name_repetitions, missing_docs)]
|
#[allow(clippy::module_name_repetitions, missing_docs)]
|
||||||
#[derive(Debug, thiserror::Error, Clone)]
|
#[derive(Debug, thiserror::Error, Clone)]
|
||||||
pub enum TranspileError {
|
pub enum TranspileError {
|
||||||
#[error("Function {} was called but never declared.", .0)]
|
#[error(transparent)]
|
||||||
MissingFunctionDeclaration(String),
|
MissingFunctionDeclaration(#[from] MissingFunctionDeclaration),
|
||||||
#[error("Unexpected expression: {}", .0.span().str())]
|
#[error("Unexpected expression: {}", .0.span().str())]
|
||||||
UnexpectedExpression(Expression),
|
UnexpectedExpression(Expression),
|
||||||
#[error("Lua code evaluation is disabled.")]
|
#[error("Lua code evaluation is disabled.")]
|
||||||
|
@ -18,3 +26,27 @@ pub enum TranspileError {
|
||||||
|
|
||||||
/// The result of a transpilation operation.
|
/// The result of a transpilation operation.
|
||||||
pub type TranspileResult<T> = Result<T, TranspileError>;
|
pub type TranspileResult<T> = Result<T, TranspileError>;
|
||||||
|
|
||||||
|
/// An error that occurs when a function declaration is missing.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct MissingFunctionDeclaration {
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MissingFunctionDeclaration {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let message = format!(
|
||||||
|
"no matching function declaration found for invocation of function `{}`",
|
||||||
|
self.span.str()
|
||||||
|
);
|
||||||
|
write!(f, "{}", Message::new(Severity::Error, message))?;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"\n{}",
|
||||||
|
SourceCodeDisplay::new(&self.span, Option::<u8>::None)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for MissingFunctionDeclaration {}
|
||||||
|
|
|
@ -6,7 +6,11 @@ use std::{collections::HashMap, iter, sync::RwLock};
|
||||||
use shulkerbox::datapack::{self, Command, Datapack, Execute};
|
use shulkerbox::datapack::{self, Command, Datapack, Execute};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
base::{self, source_file::SourceElement, Handler},
|
base::{
|
||||||
|
self,
|
||||||
|
source_file::{SourceElement, Span},
|
||||||
|
Handler,
|
||||||
|
},
|
||||||
syntax::syntax_tree::{
|
syntax::syntax_tree::{
|
||||||
declaration::{Declaration, ImportItems},
|
declaration::{Declaration, ImportItems},
|
||||||
expression::{Expression, FunctionCall, Primary},
|
expression::{Expression, FunctionCall, Primary},
|
||||||
|
@ -16,6 +20,7 @@ use crate::{
|
||||||
Statement,
|
Statement,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
transpile::error::MissingFunctionDeclaration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::error::{TranspileError, TranspileResult};
|
use super::error::{TranspileError, TranspileResult};
|
||||||
|
@ -33,6 +38,7 @@ pub struct Transpiler {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct FunctionData {
|
struct FunctionData {
|
||||||
namespace: String,
|
namespace: String,
|
||||||
|
identifier_span: Span,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
public: bool,
|
public: bool,
|
||||||
annotations: HashMap<String, Option<String>>,
|
annotations: HashMap<String, Option<String>>,
|
||||||
|
@ -61,18 +67,15 @@ impl Transpiler {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// - [`TranspileError::MissingFunctionDeclaration`] If a called function is missing
|
/// - [`TranspileError::MissingFunctionDeclaration`] If a called function is missing
|
||||||
#[tracing::instrument(level = "trace", skip_all)]
|
#[tracing::instrument(level = "trace", skip_all)]
|
||||||
pub fn transpile<Ident>(
|
pub fn transpile(
|
||||||
&mut self,
|
&mut self,
|
||||||
programs: &[(Ident, ProgramFile)],
|
programs: &[ProgramFile],
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
) -> Result<(), TranspileError>
|
) -> Result<(), TranspileError> {
|
||||||
where
|
|
||||||
Ident: AsRef<str>,
|
|
||||||
{
|
|
||||||
tracing::trace!("Transpiling program declarations");
|
tracing::trace!("Transpiling program declarations");
|
||||||
|
|
||||||
for (identifier, program) in programs {
|
for program in programs {
|
||||||
self.transpile_program_declarations(program, identifier.as_ref(), handler);
|
self.transpile_program_declarations(program, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut always_transpile_functions = Vec::new();
|
let mut always_transpile_functions = Vec::new();
|
||||||
|
@ -80,12 +83,12 @@ 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 (function_identifier, data) in functions.iter() {
|
for (_, 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(function_identifier.to_owned());
|
always_transpile_functions.push(data.identifier_span.clone());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,8 +98,8 @@ impl Transpiler {
|
||||||
always_transpile_functions
|
always_transpile_functions
|
||||||
);
|
);
|
||||||
|
|
||||||
for (program_identifier, name) in always_transpile_functions {
|
for identifier_span in always_transpile_functions {
|
||||||
self.get_or_transpile_function(&name, &program_identifier, handler)?;
|
self.get_or_transpile_function(&identifier_span, handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -106,13 +109,12 @@ impl Transpiler {
|
||||||
fn transpile_program_declarations(
|
fn transpile_program_declarations(
|
||||||
&mut self,
|
&mut self,
|
||||||
program: &ProgramFile,
|
program: &ProgramFile,
|
||||||
identifier: &str,
|
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
) {
|
) {
|
||||||
let namespace = program.namespace();
|
let namespace = program.namespace();
|
||||||
|
|
||||||
for declaration in program.declarations() {
|
for declaration in program.declarations() {
|
||||||
self.transpile_declaration(declaration, namespace, identifier, handler);
|
self.transpile_declaration(declaration, namespace, handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,12 +124,13 @@ impl Transpiler {
|
||||||
&mut self,
|
&mut self,
|
||||||
declaration: &Declaration,
|
declaration: &Declaration,
|
||||||
namespace: &Namespace,
|
namespace: &Namespace,
|
||||||
program_identifier: &str,
|
|
||||||
_handler: &impl Handler<base::Error>,
|
_handler: &impl Handler<base::Error>,
|
||||||
) {
|
) {
|
||||||
|
let program_identifier = declaration.span().source_file().identifier().clone();
|
||||||
match declaration {
|
match declaration {
|
||||||
Declaration::Function(function) => {
|
Declaration::Function(function) => {
|
||||||
let name = function.identifier().span().str().to_string();
|
let identifier_span = &function.identifier().span;
|
||||||
|
let name = identifier_span.str().to_string();
|
||||||
let statements = function.block().statements().clone();
|
let statements = function.block().statements().clone();
|
||||||
let annotations = function
|
let annotations = function
|
||||||
.annotations()
|
.annotations()
|
||||||
|
@ -142,9 +145,10 @@ impl Transpiler {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.functions.write().unwrap().insert(
|
self.functions.write().unwrap().insert(
|
||||||
(program_identifier.to_string(), name),
|
(program_identifier, name),
|
||||||
FunctionData {
|
FunctionData {
|
||||||
namespace: namespace.namespace_name().str_content().to_string(),
|
namespace: namespace.namespace_name().str_content().to_string(),
|
||||||
|
identifier_span: identifier_span.clone(),
|
||||||
statements,
|
statements,
|
||||||
public: function.is_public(),
|
public: function.is_public(),
|
||||||
annotations,
|
annotations,
|
||||||
|
@ -154,7 +158,7 @@ impl Transpiler {
|
||||||
Declaration::Import(import) => {
|
Declaration::Import(import) => {
|
||||||
let path = import.module().str_content();
|
let path = import.module().str_content();
|
||||||
let import_identifier =
|
let import_identifier =
|
||||||
super::util::calculate_import_identifier(program_identifier, path);
|
super::util::calculate_import_identifier(&program_identifier, path);
|
||||||
|
|
||||||
let mut aliases = self.aliases.write().unwrap();
|
let mut aliases = self.aliases.write().unwrap();
|
||||||
|
|
||||||
|
@ -167,7 +171,7 @@ impl Transpiler {
|
||||||
for item in items {
|
for item in items {
|
||||||
let name = item.span.str();
|
let name = item.span.str();
|
||||||
aliases.insert(
|
aliases.insert(
|
||||||
(program_identifier.to_string(), name.to_string()),
|
(program_identifier.clone(), name.to_string()),
|
||||||
(import_identifier.clone(), name.to_string()),
|
(import_identifier.clone(), name.to_string()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -183,11 +187,14 @@ impl Transpiler {
|
||||||
#[tracing::instrument(level = "trace", skip(self, handler))]
|
#[tracing::instrument(level = "trace", skip(self, handler))]
|
||||||
fn get_or_transpile_function(
|
fn get_or_transpile_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
identifier_span: &Span,
|
||||||
program_identifier: &str,
|
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
) -> TranspileResult<String> {
|
) -> TranspileResult<String> {
|
||||||
let program_query = (program_identifier.to_string(), name.to_string());
|
let program_identifier = identifier_span.source_file().identifier();
|
||||||
|
let program_query = (
|
||||||
|
program_identifier.to_string(),
|
||||||
|
identifier_span.str().to_string(),
|
||||||
|
);
|
||||||
let alias_query = {
|
let alias_query = {
|
||||||
let aliases = self.aliases.read().unwrap();
|
let aliases = self.aliases.read().unwrap();
|
||||||
aliases.get(&program_query).cloned()
|
aliases.get(&program_query).cloned()
|
||||||
|
@ -216,7 +223,11 @@ impl Transpiler {
|
||||||
.and_then(|q| functions.get(&q).filter(|f| f.public))
|
.and_then(|q| functions.get(&q).filter(|f| f.public))
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let error = TranspileError::MissingFunctionDeclaration(name.to_string());
|
let error = TranspileError::MissingFunctionDeclaration(
|
||||||
|
MissingFunctionDeclaration {
|
||||||
|
span: identifier_span.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
handler.receive(error.clone());
|
handler.receive(error.clone());
|
||||||
error
|
error
|
||||||
})?;
|
})?;
|
||||||
|
@ -233,7 +244,10 @@ impl Transpiler {
|
||||||
.and_then(|q| functions.get(&q).filter(|f| f.public))
|
.and_then(|q| functions.get(&q).filter(|f| f.public))
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let error = TranspileError::MissingFunctionDeclaration(name.to_string());
|
let error =
|
||||||
|
TranspileError::MissingFunctionDeclaration(MissingFunctionDeclaration {
|
||||||
|
span: identifier_span.clone(),
|
||||||
|
});
|
||||||
handler.receive(error.clone());
|
handler.receive(error.clone());
|
||||||
error
|
error
|
||||||
})?;
|
})?;
|
||||||
|
@ -243,12 +257,13 @@ impl Transpiler {
|
||||||
.get("deobfuscate")
|
.get("deobfuscate")
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let hash_data = program_identifier.to_string() + "\0" + name;
|
let hash_data =
|
||||||
|
program_identifier.to_string() + "\0" + identifier_span.str();
|
||||||
Some("shu/".to_string() + &md5::hash(hash_data).to_hex_lowercase()[..16])
|
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(|| identifier_span.str().to_string());
|
||||||
|
|
||||||
let function = self
|
let function = self
|
||||||
.datapack
|
.datapack
|
||||||
|
@ -269,7 +284,10 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.function_locations.write().unwrap().insert(
|
self.function_locations.write().unwrap().insert(
|
||||||
(program_identifier.to_string(), name.to_string()),
|
(
|
||||||
|
program_identifier.to_string(),
|
||||||
|
identifier_span.str().to_string(),
|
||||||
|
),
|
||||||
(function_location, function_data.public),
|
(function_location, function_data.public),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -279,7 +297,10 @@ impl Transpiler {
|
||||||
.get(&program_query)
|
.get(&program_query)
|
||||||
.or_else(|| alias_query.and_then(|q| locations.get(&q).filter(|(_, p)| *p)))
|
.or_else(|| alias_query.and_then(|q| locations.get(&q).filter(|(_, p)| *p)))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let error = TranspileError::MissingFunctionDeclaration(name.to_string());
|
let error =
|
||||||
|
TranspileError::MissingFunctionDeclaration(MissingFunctionDeclaration {
|
||||||
|
span: identifier_span.clone(),
|
||||||
|
});
|
||||||
handler.receive(error.clone());
|
handler.receive(error.clone());
|
||||||
error
|
error
|
||||||
})
|
})
|
||||||
|
@ -322,9 +343,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)) => self
|
Expression::Primary(Primary::FunctionCall(func)) => {
|
||||||
.transpile_function_call(func, program_identifier, handler)
|
self.transpile_function_call(func, handler).map(Some)
|
||||||
.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())))
|
||||||
}
|
}
|
||||||
|
@ -366,9 +387,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)) => self
|
Expression::Primary(Primary::FunctionCall(func)) => {
|
||||||
.transpile_function_call(func, program_identifier, handler)
|
self.transpile_function_call(func, handler).map(Some)
|
||||||
.map(Some),
|
}
|
||||||
unexpected => {
|
unexpected => {
|
||||||
let error = TranspileError::UnexpectedExpression(unexpected.clone());
|
let error = TranspileError::UnexpectedExpression(unexpected.clone());
|
||||||
handler.receive(error.clone());
|
handler.receive(error.clone());
|
||||||
|
@ -381,13 +402,9 @@ impl Transpiler {
|
||||||
fn transpile_function_call(
|
fn transpile_function_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &FunctionCall,
|
func: &FunctionCall,
|
||||||
program_identifier: &str,
|
|
||||||
handler: &impl Handler<base::Error>,
|
handler: &impl Handler<base::Error>,
|
||||||
) -> TranspileResult<Command> {
|
) -> TranspileResult<Command> {
|
||||||
let identifier = func.identifier().span();
|
let location = self.get_or_transpile_function(&func.identifier().span, handler)?;
|
||||||
let identifier_name = identifier.str();
|
|
||||||
let location =
|
|
||||||
self.get_or_transpile_function(identifier_name, program_identifier, handler)?;
|
|
||||||
Ok(Command::Raw(format!("function {location}")))
|
Ok(Command::Raw(format!("function {location}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,13 @@ fn parsing_test1() {
|
||||||
let mut dir = VFolder::new();
|
let mut dir = VFolder::new();
|
||||||
dir.add_file("test1.shu", VFile::Text(source.to_string()));
|
dir.add_file("test1.shu", VFile::Text(source.to_string()));
|
||||||
|
|
||||||
let parsed = shulkerscript::parse(&PrintHandler::default(), &dir, Path::new("test1.shu"))
|
let parsed = shulkerscript::parse(
|
||||||
.expect("Failed to parse");
|
&PrintHandler::default(),
|
||||||
|
&dir,
|
||||||
|
Path::new("test1.shu"),
|
||||||
|
"test1".to_string(),
|
||||||
|
)
|
||||||
|
.expect("Failed to parse");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parsed.namespace().namespace_name().str_content(),
|
parsed.namespace().namespace_name().str_content(),
|
||||||
|
@ -49,6 +54,11 @@ fn parsing_invalid() {
|
||||||
let mut dir = VFolder::new();
|
let mut dir = VFolder::new();
|
||||||
dir.add_file("invalid.shu", VFile::Text(source.to_string()));
|
dir.add_file("invalid.shu", VFile::Text(source.to_string()));
|
||||||
|
|
||||||
shulkerscript::parse(&PrintHandler::default(), &dir, Path::new("invalid.shu"))
|
shulkerscript::parse(
|
||||||
.expect_err("Expecting parsing failure");
|
&PrintHandler::default(),
|
||||||
|
&dir,
|
||||||
|
Path::new("invalid.shu"),
|
||||||
|
"invalid".to_string(),
|
||||||
|
)
|
||||||
|
.expect_err("Expecting parsing failure");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue