From 690a4716fdbc0cf2246100a2a49791b00e6b6d88 Mon Sep 17 00:00:00 2001 From: Dummi26 Date: Sat, 29 Apr 2023 01:48:06 +0200 Subject: [PATCH] add missing files --- macro.mers | 8 +++ mers/src/script/code_macro.rs | 105 ++++++++++++++++++++++++++++++++++ my_macro.mers | 2 + 3 files changed, 115 insertions(+) create mode 100755 macro.mers create mode 100644 mers/src/script/code_macro.rs create mode 100644 my_macro.mers diff --git a/macro.mers b/macro.mers new file mode 100755 index 0000000..6cec7de --- /dev/null +++ b/macro.mers @@ -0,0 +1,8 @@ +val = "some string" +val = !(mers { + println("macro is running now!") + "macro returned value" +}) +println(val) +val = !(mers "my_macro.mers") +println(val) diff --git a/mers/src/script/code_macro.rs b/mers/src/script/code_macro.rs new file mode 100644 index 0000000..808188c --- /dev/null +++ b/mers/src/script/code_macro.rs @@ -0,0 +1,105 @@ +use std::{fmt::Display, fs}; + +use crate::parse::{ + file::File, + parse::{self, ParseError, ScriptError}, +}; + +use super::{code_runnable::RScript, val_data::VData}; + +pub fn parse_macro(file: &mut File) -> Result { + file.skip_whitespaces(); + let macro_type = file.collect_to_whitespace(); + Ok(match macro_type.as_str() { + "mers" => Macro::StaticMers({ + let code = parse_mers_code(file)?; + let mut args = vec![]; + loop { + file.skip_whitespaces(); + if let Some(')') = file.peek() { + file.next(); + break; + } + args.push(parse_string_val(file)); + } + let val = code.run(args); + if val.safe_to_share() { + val + } else { + return Err(MacroError::StaticValueNotSafeToShare); + } + }), + _ => return Err(MacroError::UnknownMacroType(macro_type)), + }) +} + +fn parse_string_val(file: &mut File) -> String { + parse::implementation::parse_string_val(file, |ch| ch.is_whitespace() || ch == ')') +} + +fn parse_mers_code(file: &mut File) -> Result { + file.skip_whitespaces(); + if let Some('{') = file.peek() { + _ = file.next(); + match parse::parse(file) { + Ok(v) => Ok(v), + Err(e) => Err(e.into()), + } + } else { + let path = parse_string_val(file); + #[cfg(debug_assertions)] + eprintln!("macro: mers: path: {path}"); + let path = crate::libs::path::path_from_string(path.as_str(), file.path()) + .expect("can't include mers code because no file was found at that path"); + let mut file = File::new( + fs::read_to_string(&path) + .expect("can't include mers code because the file could not be read"), + path.into(), + ); + Ok(parse::parse(&mut file)?) + } +} + +pub enum Macro { + /// Compiles and executes the provided mers code at compile-time and inserts the value + StaticMers(VData), +} + +impl Display for Macro { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::StaticMers(v) => write!(f, "mers {v}"), + } + } +} + +pub enum MacroError { + MersStatementArgError(Box), + UnknownMacroType(String), + StaticValueNotSafeToShare, +} + +impl Display for MacroError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::MersStatementArgError(e) => write!(f, "error in mers statement argument: {e}"), + Self::UnknownMacroType(t) => write!( + f, + "unknown macro type '{t}', try mers-include or mers-static." + ), + Self::StaticValueNotSafeToShare => write!(f, "static value cannot safely be shared (cannot use value returned by mers-static in your code - maybe it was a reference, an enum, ...)"), + } + } +} + +impl From for MacroError { + fn from(value: ScriptError) -> Self { + Self::MersStatementArgError(Box::new(value)) + } +} +impl From for MacroError { + fn from(value: ParseError) -> Self { + let value: ScriptError = value.into(); + value.into() + } +} diff --git a/my_macro.mers b/my_macro.mers new file mode 100644 index 0000000..5901214 --- /dev/null +++ b/my_macro.mers @@ -0,0 +1,2 @@ +println("my macro running in ./my_macro.mers") +"value returned from ./my_macro.mers :)"