diff --git a/src/base/error.rs b/src/base/error.rs index de12dbf..2eefe7d 100644 --- a/src/base/error.rs +++ b/src/base/error.rs @@ -11,7 +11,7 @@ pub enum Error { #[error("An error occurred while parsing the source code.")] ParseError(#[from] crate::syntax::error::Error), #[error("An error occurred while compiling the source code.")] - CompileError(#[from] crate::compile::error::CompileError), + CompileError(#[from] crate::transpile::error::TranspileError), #[error("An error occurred")] Other(&'static str), } diff --git a/src/compile/mod.rs b/src/compile/mod.rs deleted file mode 100644 index a234824..0000000 --- a/src/compile/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! The compile module is responsible for compiling the abstract syntax tree into a data pack. - -pub mod compiler; -pub mod error; diff --git a/src/lib.rs b/src/lib.rs index 1b9cd6d..7e7aabc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,15 +13,15 @@ #![allow(clippy::missing_panics_doc, clippy::missing_const_for_fn)] pub mod base; -pub mod compile; pub mod lexical; pub mod syntax; +pub mod transpile; use std::{cell::Cell, fmt::Display, path::Path}; use base::{source_file::SourceFile, Handler, Result}; -use compile::compiler::Compiler; use syntax::syntax_tree::program::Program; +use transpile::transpiler::Transpiler; #[cfg(feature = "shulkerbox")] use shulkerbox::{datapack::Datapack, util::compile::CompileOptions, virtual_fs::VFolder}; @@ -103,8 +103,8 @@ pub fn transpile(path: &Path) -> Result { )); } - let mut compiler = Compiler::new(); - let datapack = compiler.compile(&program, &printer)?; + let mut transpiler = Transpiler::new(); + let datapack = transpiler.transpile(&program, &printer)?; Ok(datapack) } @@ -144,8 +144,8 @@ pub fn compile(path: &Path) -> Result { // println!("program: {program:#?}"); - let mut compiler = Compiler::new(); - let datapack = compiler.compile(&program, &printer)?; + let mut transpiler = Transpiler::new(); + let datapack = transpiler.transpile(&program, &printer)?; // println!("datapack: {datapack:#?}"); diff --git a/src/compile/error.rs b/src/transpile/error.rs similarity index 91% rename from src/compile/error.rs rename to src/transpile/error.rs index be1eeab..5bc69d0 100644 --- a/src/compile/error.rs +++ b/src/transpile/error.rs @@ -3,7 +3,7 @@ /// Errors that can occur during compilation. #[allow(clippy::module_name_repetitions, missing_docs)] #[derive(Debug, thiserror::Error, Clone, Copy)] -pub enum CompileError { +pub enum TranspileError { #[error("No main function was found in the source code.")] MissingMainFunction, } diff --git a/src/transpile/mod.rs b/src/transpile/mod.rs new file mode 100644 index 0000000..129a19b --- /dev/null +++ b/src/transpile/mod.rs @@ -0,0 +1,4 @@ +//! The transpile module is responsible for transpiling the abstract syntax tree into a data pack. + +pub mod error; +pub mod transpiler; diff --git a/src/compile/compiler.rs b/src/transpile/transpiler.rs similarity index 68% rename from src/compile/compiler.rs rename to src/transpile/transpiler.rs index a3b9812..65f8506 100644 --- a/src/compile/compiler.rs +++ b/src/transpile/transpiler.rs @@ -9,15 +9,16 @@ use crate::{ syntax::syntax_tree::{declaration::Declaration, program::Program, statement::Statement}, }; -use super::error::{self, CompileError}; +use super::error::{self, TranspileError}; -/// A compiler for `ShulkerScript`. +/// A transpiler for `ShulkerScript`. #[derive(Debug, Clone, Default)] -pub struct Compiler { - functions: HashMap>, +pub struct Transpiler { + functions: HashMap, AnnotationMap)>, } +type AnnotationMap = HashMap>; -impl Compiler { +impl Transpiler { /// Creates a new compiler. #[must_use] pub fn new() -> Self { @@ -29,24 +30,39 @@ impl Compiler { /// Compiles the given program. /// /// # Errors - /// - [`CompileError::MissingMainFunction`] If the main function is missing. - pub fn compile( + /// - [`TranspileError::MissingMainFunction`] If the main function is missing. + pub fn transpile( &mut self, program: &Program, - handler: &impl Handler, - ) -> Result { + handler: &impl Handler, + ) -> Result { for declaration in program.declarations() { match declaration { - Declaration::Function(function) => self.functions.insert( - function.identifier().span().str().to_string(), - function.block().statements().clone(), - ), + Declaration::Function(function) => { + let name = function.identifier().span().str().to_string(); + let statements = function.block().statements().clone(); + let annotations = function + .annotations() + .iter() + .map(|annotation| { + let key = annotation.identifier(); + let value = annotation.value(); + ( + key.span().str().to_string(), + value + .as_ref() + .map(|(_, ref v)| v.string_content().to_string()), + ) + }) + .collect(); + self.functions.insert(name, (statements, annotations)) + } }; } - let Some(main_function) = self.functions.get("main") else { - handler.receive(CompileError::MissingMainFunction); - return Err(CompileError::MissingMainFunction); + let Some((main_function, main_annotations)) = self.functions.get("main") else { + handler.receive(TranspileError::MissingMainFunction); + return Err(TranspileError::MissingMainFunction); }; let main_commands = compile_function(main_function); @@ -56,6 +72,13 @@ impl Compiler { let main_function = namespace.function_mut("main"); main_function.get_commands_mut().extend(main_commands); + if main_annotations.contains_key("tick") { + datapack.add_tick("shulkerscript:main"); + } + if main_annotations.contains_key("load") { + datapack.add_load("shulkerscript:main"); + } + Ok(datapack) } }