mirror of
https://github.com/Dummi26/mers.git
synced 2025-04-28 18:16:05 +02:00
-f+c will print the parsed script with colored highlighting
This commit is contained in:
parent
79797e6718
commit
b5924b5da1
@ -20,8 +20,9 @@ for word text.regex("\\S+").assume_no_enum()
|
||||
if words > 0 {
|
||||
print(word + " ")
|
||||
words = words - 1
|
||||
sleep(0.1)
|
||||
} else if words == 0 {
|
||||
println(word)
|
||||
words = rnd()
|
||||
sleep(0.75)
|
||||
sleep(0.5)
|
||||
}
|
||||
|
7
mers/Cargo.lock
generated
7
mers/Cargo.lock
generated
@ -159,6 +159,12 @@ dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorize"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc17e449bc7854c50b943d113a98bc0e01dc6585d2c66eaa09ca645ebd8a7e62"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.4"
|
||||
@ -643,6 +649,7 @@ dependencies = [
|
||||
name = "mers"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"colorize",
|
||||
"edit",
|
||||
"notify",
|
||||
"nu-plugin",
|
||||
|
@ -16,6 +16,7 @@ regex = "1.7.2"
|
||||
static_assertions = "1.1.0"
|
||||
nu-plugin = { version = "0.79.0", optional = true }
|
||||
nu-protocol = { version = "0.79.0", features = ["plugin"], optional = true }
|
||||
colorize = "0.1.0"
|
||||
|
||||
[features]
|
||||
# default = ["nushell_plugin"]
|
||||
|
@ -7,6 +7,8 @@ pub mod fs_watcher {
|
||||
thread::{self, JoinHandle},
|
||||
};
|
||||
|
||||
use crate::lang::fmtgs::FormatGs;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Error(String);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::{
|
||||
io::Write,
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
@ -835,9 +836,15 @@ impl BuiltinFunction {
|
||||
BuiltinFunction::Print => args[0].run(info).operate_on_data_immut(|v| {
|
||||
if let VDataEnum::String(arg) = v {
|
||||
#[cfg(not(feature = "nushell_plugin"))]
|
||||
print!("{}", arg);
|
||||
{
|
||||
print!("{}", arg);
|
||||
std::io::stdout().flush();
|
||||
}
|
||||
#[cfg(feature = "nushell_plugin")]
|
||||
eprint!("{}", arg);
|
||||
{
|
||||
eprint!("{}", arg);
|
||||
std::io::stderr().flush();
|
||||
}
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
} else {
|
||||
unreachable!("print function called with non-string arg")
|
||||
|
@ -1,6 +1,11 @@
|
||||
use std::fmt::{self, Display, Formatter, Pointer};
|
||||
|
||||
use super::{code_macro::Macro, global_info::GlobalScriptInfo, val_data::VData, val_type::VType};
|
||||
use crate::lang::global_info::ColorFormatMode;
|
||||
|
||||
use super::{
|
||||
code_macro::Macro, fmtgs::FormatGs, global_info::GlobalScriptInfo, val_data::VData,
|
||||
val_type::VType,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SStatementEnum {
|
||||
@ -82,101 +87,142 @@ impl SFunction {
|
||||
|
||||
//
|
||||
|
||||
impl SStatementEnum {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
impl FormatGs for SStatementEnum {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Value(v) => v.fmtgs(f, info),
|
||||
Self::Value(v) => v.fmtgs(f, info, form, file),
|
||||
Self::Tuple(v) => {
|
||||
write!(f, "[")?;
|
||||
write!(f, "{}", form.open_bracket(info, "[".to_owned()))?;
|
||||
for (i, v) in v.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
write!(f, "]")
|
||||
write!(f, "{}", form.close_bracket(info, "]".to_owned()))
|
||||
}
|
||||
Self::List(v) => {
|
||||
write!(f, "[")?;
|
||||
write!(f, "{}", form.open_bracket(info, "[".to_owned()))?;
|
||||
for (i, v) in v.iter().enumerate() {
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "...]")
|
||||
write!(f, "{}", form.close_bracket(info, "...]".to_owned()))
|
||||
}
|
||||
Self::Variable(var, reference) => {
|
||||
if *reference {
|
||||
write!(f, "&{var}")
|
||||
} else {
|
||||
write!(f, "{var}")
|
||||
write!(f, "{}", form.variable_ref_symbol(info, "&".to_owned()))?;
|
||||
}
|
||||
write!(f, "{}", form.variable(info, var.to_owned()))
|
||||
}
|
||||
Self::FunctionCall(func, args) => {
|
||||
write!(f, "{func}(")?;
|
||||
for arg in args {
|
||||
arg.fmtgs(f, info)?;
|
||||
write!(
|
||||
f,
|
||||
"{}{}",
|
||||
form.fncall(info, func.to_owned()),
|
||||
form.open_bracket(info, "(".to_owned())
|
||||
)?;
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(f, " ");
|
||||
}
|
||||
arg.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
write!(f, ")")
|
||||
write!(f, "{}", form.close_bracket(info, ")".to_owned()))
|
||||
}
|
||||
Self::FunctionDefinition(name, func) => {
|
||||
if let Some(name) = name {
|
||||
write!(f, "{name}")?;
|
||||
write!(
|
||||
f,
|
||||
"{} {}",
|
||||
form.fndef_fn(info, "fn".to_owned()),
|
||||
form.fndef_name(info, name.to_owned())
|
||||
)?;
|
||||
}
|
||||
func.fmtgs(f, info)
|
||||
func.fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::Block(b) => b.fmtgs(f, info),
|
||||
Self::Block(b) => b.fmtgs(f, info, form, file),
|
||||
Self::If(condition, yes, no) => {
|
||||
write!(f, "if ")?;
|
||||
condition.fmtgs(f, info)?;
|
||||
write!(f, "{} ", form.if_if(info, "if".to_owned()))?;
|
||||
condition.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ")?;
|
||||
yes.fmtgs(f, info)?;
|
||||
yes.fmtgs(f, info, form, file)?;
|
||||
if let Some(no) = no {
|
||||
write!(f, " else ")?;
|
||||
no.fmtgs(f, info)?;
|
||||
write!(f, " {} ", form.if_else(info, "else".to_owned()))?;
|
||||
no.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Self::Loop(b) => {
|
||||
write!(f, "loop ")?;
|
||||
b.fmtgs(f, info)
|
||||
write!(f, "{} ", form.loop_loop(info, "loop".to_owned()))?;
|
||||
b.fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::For(var, i, b) => {
|
||||
write!(f, "for {} ", var)?;
|
||||
i.fmtgs(f, info)?;
|
||||
write!(f, "{} {} ", form.loop_for(info, "for".to_owned()), var)?;
|
||||
i.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ")?;
|
||||
b.fmtgs(f, info)
|
||||
b.fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::Switch(var, arms, force) => {
|
||||
if *force {
|
||||
writeln!(f, "switch! {var} {{")?;
|
||||
writeln!(
|
||||
f,
|
||||
"{} {var} {}",
|
||||
form.kw_switch(info, "switch!".to_owned()),
|
||||
form.open_bracket(info, "{".to_owned())
|
||||
)?;
|
||||
} else {
|
||||
writeln!(f, "switch {var} {{")?;
|
||||
writeln!(
|
||||
f,
|
||||
"{} {var} {}",
|
||||
form.kw_switch(info, "switch".to_owned()),
|
||||
form.open_bracket(info, "{".to_owned())
|
||||
)?;
|
||||
}
|
||||
form.go_deeper();
|
||||
for (t, action) in arms {
|
||||
t.fmtgs(f, info)?;
|
||||
write!(f, "{}", form.line_prefix())?;
|
||||
t.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ")?;
|
||||
action.fmtgs(f, info)?;
|
||||
action.fmtgs(f, info, form, file)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
form.go_shallower();
|
||||
write!(f, "{}", form.line_prefix())?;
|
||||
write!(f, "{}", form.close_bracket(info, "}".to_owned()))
|
||||
}
|
||||
Self::Match(var, arms) => {
|
||||
write!(f, "match {var} {{")?;
|
||||
write!(
|
||||
f,
|
||||
"{} {var} {}",
|
||||
form.kw_match(info, "match".to_owned()),
|
||||
form.open_bracket(info, "{".to_owned())
|
||||
)?;
|
||||
form.go_deeper();
|
||||
for (condition, action) in arms {
|
||||
condition.fmtgs(f, info)?;
|
||||
write!(f, "{}", form.line_prefix())?;
|
||||
condition.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ")?;
|
||||
action.fmtgs(f, info)?;
|
||||
action.fmtgs(f, info, form, file)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
form.go_shallower();
|
||||
write!(f, "{}", form.line_prefix())?;
|
||||
write!(f, "{}", form.close_bracket(info, "}".to_owned()))
|
||||
}
|
||||
Self::IndexFixed(statement, index) => {
|
||||
statement.fmtgs(f, info)?;
|
||||
statement.fmtgs(f, info, form, file)?;
|
||||
write!(f, ".{index}")
|
||||
}
|
||||
Self::EnumVariant(variant, inner) => {
|
||||
write!(f, "{variant}: ")?;
|
||||
inner.fmtgs(f, info)
|
||||
inner.fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::TypeDefinition(name, t) => write!(f, "type {name} {t}"),
|
||||
Self::Macro(m) => {
|
||||
@ -187,32 +233,58 @@ impl SStatementEnum {
|
||||
}
|
||||
impl Display for SStatementEnum {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.fmtgs(f, None)
|
||||
self.fmtgs(f, None, &mut super::fmtgs::FormatInfo::default(), None)
|
||||
}
|
||||
}
|
||||
|
||||
impl SStatement {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
impl FormatGs for SStatement {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
if let Some((opt, derefs)) = &self.output_to {
|
||||
if let Some(forced_type) = &self.force_output_type {
|
||||
write!(f, "{}{}::", "*".repeat(*derefs), opt)?;
|
||||
forced_type.fmtgs(f, info)?;
|
||||
write!(f, " = ")?;
|
||||
} else {
|
||||
write!(f, "{}{} = ", "*".repeat(*derefs), opt)?;
|
||||
// TODO!
|
||||
match opt.statement.as_ref() {
|
||||
SStatementEnum::Variable(name, is_ref) => {
|
||||
let derefs = if !is_ref { *derefs + 1 } else { *derefs };
|
||||
write!(
|
||||
f,
|
||||
"{}{} = ",
|
||||
"*".repeat(derefs),
|
||||
SStatementEnum::Variable(name.to_owned(), false).with(info, file)
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
if let Some(forced_type) = &self.force_output_type {
|
||||
write!(f, "{}{}::", "*".repeat(*derefs), opt.with(info, file))?;
|
||||
forced_type.fmtgs(f, info, form, file)?;
|
||||
write!(f, " = ")?;
|
||||
} else {
|
||||
write!(f, "{}{} = ", "*".repeat(*derefs), opt.with(info, file))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.statement.fmtgs(f, info)
|
||||
self.statement.fmtgs(f, info, form, file)
|
||||
}
|
||||
}
|
||||
impl Display for SStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.fmtgs(f, None)
|
||||
self.fmtgs(f, None, &mut super::fmtgs::FormatInfo::default(), None)
|
||||
}
|
||||
}
|
||||
|
||||
impl SFunction {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
impl FormatGs for SFunction {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
write!(f, "(")?;
|
||||
for (i, (name, t)) in self.inputs.iter().enumerate() {
|
||||
if i > 0 {
|
||||
@ -220,25 +292,35 @@ impl SFunction {
|
||||
} else {
|
||||
write!(f, "{name} ")?;
|
||||
}
|
||||
t.fmtgs(f, info)?;
|
||||
t.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
write!(f, ") ")?;
|
||||
self.block.fmtgs(f, info)
|
||||
self.block.fmtgs(f, info, form, file)
|
||||
}
|
||||
}
|
||||
|
||||
impl SBlock {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
impl FormatGs for SBlock {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
match self.statements.len() {
|
||||
0 => write!(f, "{{}}"),
|
||||
1 => self.statements[0].fmtgs(f, info),
|
||||
// 1 => self.statements[0].fmtgs(f, info, form, file),
|
||||
_ => {
|
||||
writeln!(f, "{{")?;
|
||||
writeln!(f, "{}", form.open_bracket(info, "{".to_owned()))?;
|
||||
form.go_deeper();
|
||||
for statement in self.statements.iter() {
|
||||
statement.fmtgs(f, info)?;
|
||||
write!(f, "{}", form.line_prefix())?;
|
||||
statement.fmtgs(f, info, form, file)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
form.go_shallower();
|
||||
write!(f, "{}", form.line_prefix())?;
|
||||
write!(f, "{}", form.close_bracket(info, "}".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -373,7 +373,6 @@ impl RStatementEnum {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RScript {
|
||||
main: RFunction,
|
||||
info: GSInfo,
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
default,
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
@ -8,13 +9,13 @@ use crate::libs;
|
||||
|
||||
use super::{
|
||||
builtins,
|
||||
fmtgs::Color,
|
||||
val_data::VDataEnum,
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
pub type GSInfo = Arc<GlobalScriptInfo>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalScriptInfo {
|
||||
pub libs: Vec<libs::Lib>,
|
||||
pub lib_fns: HashMap<String, (usize, usize)>,
|
||||
@ -24,10 +25,61 @@ pub struct GlobalScriptInfo {
|
||||
pub custom_type_names: HashMap<String, usize>,
|
||||
pub custom_types: Vec<VType>,
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub formatter: ColorFormatter,
|
||||
|
||||
pub log: Logger,
|
||||
}
|
||||
|
||||
pub struct ColorFormatter {
|
||||
pub mode: ColorFormatMode,
|
||||
pub bracket_colors: Vec<Color>,
|
||||
pub value_string_quotes_color: Color,
|
||||
pub value_string_content_color: Color,
|
||||
pub keyword_if_color: Color,
|
||||
pub keyword_else_color: Color,
|
||||
pub keyword_loop_color: Color,
|
||||
pub keyword_for_color: Color,
|
||||
pub keyword_switch_color: Color,
|
||||
pub keyword_match_color: Color,
|
||||
pub function_call_color: Color,
|
||||
pub function_def_fn_color: Color,
|
||||
pub function_def_name_color: Color,
|
||||
pub variable_color: Color,
|
||||
}
|
||||
impl Default for ColorFormatter {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mode: ColorFormatMode::Plain,
|
||||
bracket_colors: vec![
|
||||
Color::Red,
|
||||
Color::Yellow,
|
||||
Color::Cyan,
|
||||
Color::Blue,
|
||||
Color::Magenta,
|
||||
],
|
||||
value_string_quotes_color: Color::Grey,
|
||||
value_string_content_color: Color::Cyan,
|
||||
keyword_if_color: Color::Yellow,
|
||||
keyword_else_color: Color::Yellow,
|
||||
keyword_loop_color: Color::Yellow,
|
||||
keyword_for_color: Color::Yellow,
|
||||
keyword_switch_color: Color::Yellow,
|
||||
keyword_match_color: Color::Yellow,
|
||||
function_call_color: Color::Magenta,
|
||||
function_def_fn_color: Color::Blue,
|
||||
function_def_name_color: Color::Magenta,
|
||||
variable_color: Color::Green,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub enum ColorFormatMode {
|
||||
/// No color.
|
||||
Plain,
|
||||
/// For terminal output
|
||||
Colorize,
|
||||
}
|
||||
|
||||
impl GlobalScriptInfo {
|
||||
pub fn to_arc(self) -> GSInfo {
|
||||
Arc::new(self)
|
||||
@ -42,7 +94,7 @@ impl Default for GlobalScriptInfo {
|
||||
enum_variants: Self::default_enum_variants(),
|
||||
custom_type_names: HashMap::new(),
|
||||
custom_types: vec![],
|
||||
#[cfg(debug_assertions)]
|
||||
formatter: Default::default(),
|
||||
log: Logger::new(),
|
||||
}
|
||||
}
|
||||
@ -57,20 +109,21 @@ impl GlobalScriptInfo {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[derive(Debug)]
|
||||
pub struct Logger {
|
||||
logs: Arc<Mutex<Vec<LogMsg>>>,
|
||||
|
||||
pub after_parse: LogKind,
|
||||
|
||||
pub vdata_clone: LogKind,
|
||||
pub vtype_fits_in: LogKind,
|
||||
pub vsingletype_fits_in: LogKind,
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
impl Logger {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
logs: Arc::new(Mutex::new(vec![])),
|
||||
after_parse: Default::default(),
|
||||
vdata_clone: Default::default(),
|
||||
vtype_fits_in: Default::default(),
|
||||
vsingletype_fits_in: Default::default(),
|
||||
@ -78,17 +131,17 @@ impl Logger {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[derive(Debug)]
|
||||
pub enum LogMsg {
|
||||
AfterParse(String),
|
||||
VDataClone(Option<String>, VDataEnum, usize, usize),
|
||||
VTypeFitsIn(VType, VType, Vec<VSingleType>),
|
||||
VSingleTypeFitsIn(VSingleType, VSingleType, bool),
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
impl Logger {
|
||||
pub fn log(&self, msg: LogMsg) {
|
||||
let kind = match msg {
|
||||
LogMsg::AfterParse(..) => &self.after_parse,
|
||||
LogMsg::VDataClone(..) => &self.vdata_clone,
|
||||
LogMsg::VTypeFitsIn(..) => &self.vtype_fits_in,
|
||||
LogMsg::VSingleTypeFitsIn(..) => &self.vsingletype_fits_in,
|
||||
@ -103,14 +156,16 @@ impl Logger {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
impl Display for LogMsg {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::AfterParse(code) => {
|
||||
write!(f, "AfterParse :: {code}")
|
||||
}
|
||||
Self::VDataClone(varname, data, src_addr, new_addr) => {
|
||||
write!(
|
||||
f,
|
||||
"VDataClone :: {data} ({}{src_addr} -> {new_addr})",
|
||||
"VDataClone ::::\n{data} ({}{src_addr} -> {new_addr})",
|
||||
if let Some(v) = varname {
|
||||
format!("{v} | ")
|
||||
} else {
|
||||
@ -126,13 +181,11 @@ impl Display for LogMsg {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct LogKind {
|
||||
pub stderr: bool,
|
||||
pub log: bool,
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
impl LogKind {
|
||||
pub fn log(&self) -> bool {
|
||||
self.stderr || self.log
|
||||
|
@ -2,6 +2,7 @@ pub mod builtins;
|
||||
pub mod code_macro;
|
||||
pub mod code_parsed;
|
||||
pub mod code_runnable;
|
||||
pub mod fmtgs;
|
||||
pub mod global_info;
|
||||
pub mod to_runnable;
|
||||
pub mod val_data;
|
||||
|
@ -19,6 +19,7 @@ use super::{
|
||||
code_macro::Macro,
|
||||
code_parsed::{SBlock, SFunction, SStatement, SStatementEnum},
|
||||
code_runnable::{RBlock, RFunction, RScript, RStatement, RStatementEnum},
|
||||
fmtgs::FormatGs,
|
||||
global_info::GSInfo,
|
||||
};
|
||||
|
||||
@ -51,18 +52,20 @@ impl Debug for ToRunnableError {
|
||||
}
|
||||
}
|
||||
// TODO:
|
||||
// - Don't use {} to format, use .fmtgs(f, info) instead!
|
||||
// - Don't use {} to format, use .fmtgs(f, info, form, file) instead!
|
||||
// - Show location in code where the error was found
|
||||
impl Display for ToRunnableError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmtgs(f, None)
|
||||
self.fmtgs(f, None, &mut super::fmtgs::FormatInfo::default(), None)
|
||||
}
|
||||
}
|
||||
impl ToRunnableError {
|
||||
pub fn fmtgs(
|
||||
impl FormatGs for ToRunnableError {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::MainWrongInput => write!(
|
||||
@ -75,9 +78,9 @@ impl ToRunnableError {
|
||||
Self::CannotDeclareVariableWithDereference(v) => write!(f, "Cannot declare a variable and dereference it (variable '{v}')."),
|
||||
Self::CannotDereferenceTypeNTimes(og_type, derefs_wanted, last_valid_type) => {
|
||||
write!(f, "Cannot dereference type ")?;
|
||||
og_type.fmtgs(f, info)?;
|
||||
og_type.fmtgs(f, info, form, file)?;
|
||||
write!(f, " {derefs_wanted} times (stopped at ")?;
|
||||
last_valid_type.fmtgs(f, info);
|
||||
last_valid_type.fmtgs(f, info, form, file);
|
||||
write!(f, ")")?;
|
||||
Ok(())
|
||||
},
|
||||
@ -89,28 +92,28 @@ impl ToRunnableError {
|
||||
problematic,
|
||||
} => {
|
||||
write!(f, "Invalid type: Expected ")?;
|
||||
expected.fmtgs(f, info)?;
|
||||
expected.fmtgs(f, info, form, file)?;
|
||||
write!(f, " but found ")?;
|
||||
found.fmtgs(f, info)?;
|
||||
found.fmtgs(f, info, form, file)?;
|
||||
write!(f, ", which includes ")?;
|
||||
problematic.fmtgs(f, info)?;
|
||||
problematic.fmtgs(f, info, form, file)?;
|
||||
write!(f, " which is not covered.")?;
|
||||
Ok(())
|
||||
}
|
||||
Self::CaseForceButTypeNotCovered(v) => {
|
||||
write!(f, "Switch! statement, but not all types covered. Types to cover: ")?;
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
Ok(())
|
||||
}
|
||||
Self::MatchConditionInvalidReturn(v) => {
|
||||
write!(f, "match statement condition returned ")?;
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
write!(f, ", which is not necessarily a tuple of size 0 to 1.")?;
|
||||
Ok(())
|
||||
}
|
||||
Self::NotIndexableFixed(t, i) => {
|
||||
write!(f, "Cannot use fixed-index {i} on type ")?;
|
||||
t.fmtgs(f, info)?;
|
||||
t.fmtgs(f, info, form, file)?;
|
||||
write!(f, ".")?;
|
||||
Ok(())
|
||||
}
|
||||
@ -118,7 +121,7 @@ impl ToRunnableError {
|
||||
write!(f, "Wrong arguments for builtin function \"{}\":", builtin_name)?;
|
||||
for arg in args {
|
||||
write!(f, " ")?;
|
||||
arg.fmtgs(f, info)?;
|
||||
arg.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
write!(f, ".")
|
||||
}
|
||||
@ -126,15 +129,15 @@ impl ToRunnableError {
|
||||
write!(f, "Wrong arguments for library function {}:", name)?;
|
||||
for arg in args {
|
||||
write!(f, " ")?;
|
||||
arg.fmtgs(f, info)?;
|
||||
arg.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
write!(f, ".")
|
||||
}
|
||||
Self::CannotAssignTo(val, target) => {
|
||||
write!(f, "Cannot assign type ")?;
|
||||
val.fmtgs(f, info)?;
|
||||
val.fmtgs(f, info, form, file)?;
|
||||
write!(f, " to ")?;
|
||||
target.fmtgs(f, info)?;
|
||||
target.fmtgs(f, info, form, file)?;
|
||||
write!(f, ".")?;
|
||||
Ok(())
|
||||
},
|
||||
@ -143,11 +146,11 @@ impl ToRunnableError {
|
||||
}
|
||||
Self::StatementRequiresOutputTypeToBeAButItActuallyOutputsBWhichDoesNotFitInA(required, real, problematic) => {
|
||||
write!(f, "the statement requires its output type to be ")?;
|
||||
required.fmtgs(f, info)?;
|
||||
required.fmtgs(f, info, form, file)?;
|
||||
write!(f, ", but its real output type is ")?;
|
||||
real.fmtgs(f, info)?;
|
||||
real.fmtgs(f, info, form, file)?;
|
||||
write!(f, ", which doesn't fit in the required type because of the problematic types ")?;
|
||||
problematic.fmtgs(f, info)?;
|
||||
problematic.fmtgs(f, info, form, file)?;
|
||||
write!(f, ".")?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -4,15 +4,14 @@ use std::{
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
};
|
||||
|
||||
use super::global_info::LogMsg;
|
||||
use super::{
|
||||
code_runnable::RFunction,
|
||||
fmtgs::FormatGs,
|
||||
global_info::{GSInfo, GlobalScriptInfo},
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
use super::global_info::LogMsg;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VDataEnum {
|
||||
Bool(bool),
|
||||
@ -117,11 +116,13 @@ impl VData {
|
||||
// *self doesn't modify the ::Data, it instead points the value that wraps it to a new ::Data, leaving the old one as it was.
|
||||
// for proof: data is untouched, only the new_data is ever modified.
|
||||
let new_vdata = VDataInner::Data(0, new_data).to();
|
||||
#[cfg(debug_assertions)]
|
||||
if info.log.vdata_clone.log() {
|
||||
drop(lock);
|
||||
info.log.log(LogMsg::VDataClone(
|
||||
#[cfg(debug_assertions)]
|
||||
self.1.clone(),
|
||||
#[cfg(not(debug_assertions))]
|
||||
None,
|
||||
self.inner_cloned(),
|
||||
Arc::as_ptr(&self.0) as usize,
|
||||
Arc::as_ptr(&new_vdata.0) as usize,
|
||||
@ -187,9 +188,15 @@ impl Clone for VData {
|
||||
self.clone_data()
|
||||
}
|
||||
}
|
||||
impl VData {
|
||||
pub fn fmtgs(&self, f: &mut Formatter<'_>, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
self.operate_on_data_immut(|v| v.fmtgs(f, info))
|
||||
impl FormatGs for VData {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
self.operate_on_data_immut(|v| v.fmtgs(f, info, form, file))
|
||||
}
|
||||
}
|
||||
impl Debug for VData {
|
||||
@ -476,7 +483,12 @@ pub mod thread {
|
||||
pub struct VDataWInfo(VData, GSInfo);
|
||||
impl Display for VDataWInfo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmtgs(f, Some(&self.1))
|
||||
self.0.fmtgs(
|
||||
f,
|
||||
Some(&self.1),
|
||||
&mut super::fmtgs::FormatInfo::default(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
impl VData {
|
||||
@ -485,39 +497,51 @@ impl VData {
|
||||
}
|
||||
}
|
||||
|
||||
impl VDataEnum {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
impl FormatGs for VDataEnum {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Bool(true) => write!(f, "true"),
|
||||
Self::Bool(false) => write!(f, "false"),
|
||||
Self::Int(v) => write!(f, "{v}"),
|
||||
Self::Float(v) => write!(f, "{v}"),
|
||||
Self::String(v) => write!(f, "\"{v}\""),
|
||||
Self::String(v) => write!(
|
||||
f,
|
||||
"{}{}{}",
|
||||
form.value_string_quotes(info, "\"".to_owned()),
|
||||
form.value_string_content(info, v.to_owned()),
|
||||
form.value_string_quotes(info, "\"".to_owned())
|
||||
),
|
||||
Self::Tuple(v) => {
|
||||
write!(f, "[")?;
|
||||
for (i, v) in v.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
Self::List(_t, v) => {
|
||||
write!(f, "[")?;
|
||||
for (i, v) in v.iter().enumerate() {
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "...]")
|
||||
}
|
||||
Self::Function(func) => {
|
||||
VSingleType::Function(func.input_output_map.clone()).fmtgs(f, info)
|
||||
VSingleType::Function(func.input_output_map.clone()).fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::Thread(..) => write!(f, "[TODO] THREAD"),
|
||||
Self::Reference(inner) => {
|
||||
write!(f, "&")?;
|
||||
inner.fmtgs(f, info)
|
||||
inner.fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::EnumVariant(variant, inner) => {
|
||||
if let Some(name) = if let Some(info) = info {
|
||||
@ -535,13 +559,13 @@ impl VDataEnum {
|
||||
} else {
|
||||
write!(f, "{variant}: ")?;
|
||||
}
|
||||
inner.fmtgs(f, info)
|
||||
inner.fmtgs(f, info, form, file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Display for VDataEnum {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.fmtgs(f, None)
|
||||
self.fmtgs(f, None, &mut super::fmtgs::FormatInfo::default(), None)
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,11 @@ use std::{
|
||||
ops::BitOr,
|
||||
};
|
||||
|
||||
use super::global_info::{self, GSInfo, GlobalScriptInfo};
|
||||
use super::{
|
||||
fmtgs::FormatGs,
|
||||
global_info::{self, GSInfo, GlobalScriptInfo},
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
use super::global_info::LogMsg;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -161,7 +163,6 @@ impl VType {
|
||||
no.push(t.clone())
|
||||
}
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
if info.log.vtype_fits_in.log() {
|
||||
info.log
|
||||
.log(LogMsg::VTypeFitsIn(self.clone(), rhs.clone(), no.clone()))
|
||||
@ -359,7 +360,6 @@ impl VSingleType {
|
||||
(Self::Thread(a), Self::Thread(b)) => a.fits_in(b, info).is_empty(),
|
||||
(Self::Thread(..), _) => false,
|
||||
};
|
||||
#[cfg(debug_assertions)]
|
||||
if info.log.vsingletype_fits_in.log() {
|
||||
info.log
|
||||
.log(LogMsg::VSingleTypeFitsIn(self.clone(), rhs.clone(), o));
|
||||
@ -393,7 +393,12 @@ impl Into<VType> for VSingleType {
|
||||
pub struct VTypeWInfo(VType, GSInfo);
|
||||
impl Display for VTypeWInfo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmtgs(f, Some(&self.1))
|
||||
self.0.fmtgs(
|
||||
f,
|
||||
Some(&self.1),
|
||||
&mut super::fmtgs::FormatInfo::default(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
impl VType {
|
||||
@ -402,8 +407,14 @@ impl VType {
|
||||
}
|
||||
}
|
||||
|
||||
impl VSingleType {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
impl FormatGs for VSingleType {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Bool => write!(f, "bool"),
|
||||
Self::Int => write!(f, "int"),
|
||||
@ -415,13 +426,13 @@ impl VSingleType {
|
||||
if i > 0 {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
Self::List(v) => {
|
||||
write!(f, "[")?;
|
||||
v.fmtgs(f, info)?;
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ...]")
|
||||
}
|
||||
Self::Function(func) => {
|
||||
@ -429,22 +440,22 @@ impl VSingleType {
|
||||
for (inputs, output) in func {
|
||||
write!(f, "(")?;
|
||||
for i in inputs {
|
||||
i.fmtgs(f, info)?;
|
||||
i.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ");
|
||||
}
|
||||
output.fmtgs(f, info)?;
|
||||
output.fmtgs(f, info, form, file)?;
|
||||
write!(f, ")")?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Self::Thread(out) => {
|
||||
write!(f, "thread(")?;
|
||||
out.fmtgs(f, info)?;
|
||||
out.fmtgs(f, info, form, file)?;
|
||||
write!(f, ")")
|
||||
}
|
||||
Self::Reference(inner) => {
|
||||
write!(f, "&")?;
|
||||
inner.fmtgs(f, info)
|
||||
inner.fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::EnumVariant(variant, inner) => {
|
||||
if let Some(name) = if let Some(info) = info {
|
||||
@ -462,12 +473,12 @@ impl VSingleType {
|
||||
} else {
|
||||
write!(f, "{variant}(")?;
|
||||
}
|
||||
inner.fmtgs(f, info)?;
|
||||
inner.fmtgs(f, info, form, file)?;
|
||||
write!(f, ")")
|
||||
}
|
||||
Self::EnumVariantS(name, inner) => {
|
||||
write!(f, "{name}(")?;
|
||||
inner.fmtgs(f, info)?;
|
||||
inner.fmtgs(f, info, form, file)?;
|
||||
write!(f, ")")
|
||||
}
|
||||
Self::CustomType(t) => {
|
||||
@ -510,23 +521,29 @@ impl VSingleType {
|
||||
}
|
||||
impl Display for VSingleType {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.fmtgs(f, None)
|
||||
self.fmtgs(f, None, &mut super::fmtgs::FormatInfo::default(), None)
|
||||
}
|
||||
}
|
||||
|
||||
impl VType {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
impl FormatGs for VType {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut super::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
for (i, t) in self.types.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, "/")?;
|
||||
}
|
||||
t.fmtgs(f, info)?;
|
||||
t.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl Display for VType {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.fmtgs(f, None)
|
||||
self.fmtgs(f, None, &mut super::fmtgs::FormatInfo::default(), None)
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,13 @@
|
||||
|
||||
use std::{fs, time::Instant};
|
||||
|
||||
use lang::global_info::ColorFormatMode;
|
||||
use lang::global_info::GlobalScriptInfo;
|
||||
#[cfg(debug_assertions)]
|
||||
use lang::global_info::LogKind;
|
||||
use notify::Watcher as FsWatcher;
|
||||
|
||||
use crate::lang::fmtgs::FormatGs;
|
||||
|
||||
mod interactive_mode;
|
||||
mod lang;
|
||||
mod libs;
|
||||
@ -26,6 +28,7 @@ fn main() {
|
||||
fn normal_main() {
|
||||
let args: Vec<_> = std::env::args().skip(1).collect();
|
||||
let mut info = GlobalScriptInfo::default();
|
||||
let mut run = true;
|
||||
let mut args_to_skip = 2;
|
||||
let mut file = match args.len() {
|
||||
0 => {
|
||||
@ -52,6 +55,10 @@ fn normal_main() {
|
||||
match ch {
|
||||
'e' => execute = true,
|
||||
'v' => verbose = true,
|
||||
'f' => {
|
||||
run = false;
|
||||
info.log.after_parse.stderr = true;
|
||||
}
|
||||
'V' => print_version = true,
|
||||
'i' => interactive += 1,
|
||||
't' => teachme = true,
|
||||
@ -75,6 +82,11 @@ fn normal_main() {
|
||||
verbose_args.push(ch);
|
||||
}
|
||||
}
|
||||
'f' => match ch {
|
||||
'c' => info.formatter.mode = ColorFormatMode::Colorize,
|
||||
'C' => info.formatter.mode = ColorFormatMode::Plain,
|
||||
_ => eprintln!("Ignoring f+{ch}. (unknown adv char)"),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
@ -97,9 +109,6 @@ fn normal_main() {
|
||||
return;
|
||||
}
|
||||
if verbose {
|
||||
#[cfg(not(debug_assertions))]
|
||||
eprintln!("WARN: Verbose (-v) only works in debug builds!");
|
||||
#[cfg(debug_assertions)]
|
||||
if verbose_args.is_empty() {
|
||||
fn f() -> LogKind {
|
||||
LogKind {
|
||||
@ -187,12 +196,9 @@ fn normal_main() {
|
||||
};
|
||||
match parsing::parse::parse_custom_info(&mut file, info) {
|
||||
Ok(script) => {
|
||||
println!(" - - - - -");
|
||||
let start = Instant::now();
|
||||
let out = script.run(std::env::args().skip(args_to_skip).collect());
|
||||
let elapsed = start.elapsed();
|
||||
println!(" - - - - -");
|
||||
println!("Output ({}s)\n{out}", elapsed.as_secs_f64());
|
||||
if run {
|
||||
script.run(std::env::args().skip(args_to_skip).collect());
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Couldn't compile:\n{}", e.with_file(&file));
|
||||
|
@ -5,6 +5,7 @@ use crate::{
|
||||
code_macro::MacroError,
|
||||
code_parsed::*,
|
||||
code_runnable::RScript,
|
||||
fmtgs::{FormatGs, FormatWithGs},
|
||||
global_info::{GSInfo, GlobalScriptInfo},
|
||||
to_runnable::{self, ToRunnableError},
|
||||
val_data::VDataEnum,
|
||||
@ -13,6 +14,8 @@ use crate::{
|
||||
libs,
|
||||
};
|
||||
|
||||
use crate::lang::global_info::LogMsg;
|
||||
|
||||
use super::file::File;
|
||||
|
||||
pub enum ScriptError {
|
||||
@ -51,59 +54,30 @@ impl std::fmt::Display for ScriptError {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ScriptErrorWithFile<'a>(&'a ScriptError, &'a File);
|
||||
pub struct ScriptErrorWithInfo<'a>(&'a ScriptError, &'a GlobalScriptInfo);
|
||||
pub struct ScriptErrorWithFileAndInfo<'a>(&'a ScriptError, &'a File, &'a GlobalScriptInfo);
|
||||
impl<'a> ScriptError {
|
||||
pub fn with_file(&'a self, file: &'a File) -> ScriptErrorWithFile {
|
||||
ScriptErrorWithFile(self, file)
|
||||
}
|
||||
pub fn with_gsinfo(&'a self, info: &'a GlobalScriptInfo) -> ScriptErrorWithInfo {
|
||||
ScriptErrorWithInfo(self, info)
|
||||
}
|
||||
pub fn with_file_and_gsinfo(
|
||||
&'a self,
|
||||
file: &'a File,
|
||||
info: &'a GlobalScriptInfo,
|
||||
) -> ScriptErrorWithFileAndInfo {
|
||||
ScriptErrorWithFileAndInfo(self, file, info)
|
||||
}
|
||||
}
|
||||
impl<'a> std::fmt::Display for ScriptErrorWithFile<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt_custom(f, Some(self.1), None)
|
||||
}
|
||||
}
|
||||
impl<'a> std::fmt::Display for ScriptErrorWithInfo<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt_custom(f, None, Some(self.1))
|
||||
}
|
||||
}
|
||||
impl<'a> std::fmt::Display for ScriptErrorWithFileAndInfo<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt_custom(f, Some(self.1), Some(self.2))
|
||||
}
|
||||
}
|
||||
|
||||
impl ScriptError {
|
||||
fn fmt_custom(
|
||||
impl FormatGs for ScriptError {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
file: Option<&File>,
|
||||
f: &mut std::fmt::Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut crate::lang::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
match &self {
|
||||
ScriptError::CannotFindPathForLibrary(e) => write!(f, "{e}"),
|
||||
ScriptError::ParseError(e) => {
|
||||
write!(f, "failed while parsing: ")?;
|
||||
e.fmt_custom(f, file)?;
|
||||
e.fmtgs(f, info, form, file)?;
|
||||
Ok(())
|
||||
}
|
||||
ScriptError::UnableToLoadLibrary(e) => write!(f, "{e}"),
|
||||
ScriptError::ToRunnableError(e) => {
|
||||
write!(f, "failed to compile: ")?;
|
||||
e.fmtgs(f, info);
|
||||
Ok(())
|
||||
e.fmtgs(
|
||||
f,
|
||||
info,
|
||||
&mut crate::lang::fmtgs::FormatInfo::default(),
|
||||
file,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,14 +97,25 @@ impl From<(ScriptError, GSInfo)> for Error {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Debug for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.err.with_gsinfo(&self.ginfo))
|
||||
impl FormatGs for Error {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut crate::lang::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
self.err.fmtgs(f, Some(&self.ginfo), form, file)
|
||||
}
|
||||
}
|
||||
impl Error {
|
||||
pub fn with_file<'a>(&'a self, file: &'a File) -> ScriptErrorWithFileAndInfo<'a> {
|
||||
self.err.with_file_and_gsinfo(file, self.ginfo.as_ref())
|
||||
impl Debug for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.err.fmtgs(
|
||||
f,
|
||||
Some(self.ginfo.as_ref()),
|
||||
&mut crate::lang::fmtgs::FormatInfo::default(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,19 +125,16 @@ pub fn parse(file: &mut File) -> Result<RScript, Error> {
|
||||
}
|
||||
/// like parse, but GlobalInfo can be something other than Default::default().
|
||||
pub fn parse_custom_info(file: &mut File, mut ginfo: GlobalScriptInfo) -> Result<RScript, Error> {
|
||||
let libs = match parse_step_lib_paths(file) {
|
||||
let libs = match parse_step_lib_paths(file, &ginfo) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Err((e.into(), ginfo.to_arc()).into()),
|
||||
};
|
||||
|
||||
let func = match parse_step_interpret(file) {
|
||||
let func = match parse_step_interpret(file, &ginfo) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Err((e.into(), ginfo.to_arc()).into()),
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("{func:#?}");
|
||||
|
||||
ginfo.libs = match parse_step_libs_load(libs, &mut ginfo) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Err((e.into(), ginfo.to_arc()).into()),
|
||||
@ -174,7 +156,10 @@ impl std::fmt::Display for CannotFindPathForLibrary {
|
||||
write!(f, "Couldn't find a path for the library with the path '{}'. Maybe set the MERS_LIB_DIR env variable?", self.0)
|
||||
}
|
||||
}
|
||||
pub fn parse_step_lib_paths(file: &mut File) -> Result<Vec<Command>, CannotFindPathForLibrary> {
|
||||
pub fn parse_step_lib_paths(
|
||||
file: &mut File,
|
||||
ginfo: &GlobalScriptInfo,
|
||||
) -> Result<Vec<Command>, CannotFindPathForLibrary> {
|
||||
let mut libs = vec![];
|
||||
loop {
|
||||
file.skip_whitespaces();
|
||||
@ -198,14 +183,23 @@ pub fn parse_step_lib_paths(file: &mut File) -> Result<Vec<Command>, CannotFindP
|
||||
Ok(libs)
|
||||
}
|
||||
|
||||
pub fn parse_step_interpret(file: &mut File) -> Result<SFunction, ParseError> {
|
||||
Ok(SFunction::new(
|
||||
pub fn parse_step_interpret(
|
||||
file: &mut File,
|
||||
ginfo: &GlobalScriptInfo,
|
||||
) -> Result<SFunction, ParseError> {
|
||||
let o = SFunction::new(
|
||||
vec![(
|
||||
"args".to_string(),
|
||||
VSingleType::List(VSingleType::String.into()).to(),
|
||||
)],
|
||||
parse_block_advanced(file, Some(false), true, true, false)?,
|
||||
))
|
||||
);
|
||||
if ginfo.log.after_parse.log() {
|
||||
ginfo.log.log(LogMsg::AfterParse(
|
||||
o.with_info_and_file(ginfo, &file).to_string(),
|
||||
));
|
||||
}
|
||||
Ok(o)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -242,17 +236,6 @@ pub fn parse_step_compile(
|
||||
to_runnable::to_runnable(main_func, ginfo)
|
||||
}
|
||||
|
||||
pub struct ParseErrorWithFile<'a>(&'a ParseError, &'a File);
|
||||
impl<'a> ParseError {
|
||||
pub fn with_file(&'a self, file: &'a File) -> ParseErrorWithFile {
|
||||
ParseErrorWithFile(self, file)
|
||||
}
|
||||
}
|
||||
impl<'a> std::fmt::Display for ParseErrorWithFile<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt_custom(f, Some(self.1))
|
||||
}
|
||||
}
|
||||
pub struct ParseError {
|
||||
err: ParseErrors,
|
||||
// the location of the error
|
||||
@ -264,13 +247,15 @@ pub struct ParseError {
|
||||
)>,
|
||||
info: Option<GlobalScriptInfo>,
|
||||
}
|
||||
impl ParseError {
|
||||
pub fn fmt_custom(
|
||||
impl FormatGs for ParseError {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
file: Option<&super::file::File>,
|
||||
f: &mut std::fmt::Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
form: &mut crate::lang::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
self.err.fmtgs(f, self.info.as_ref(), file)?;
|
||||
self.err.fmtgs(f, self.info.as_ref(), form, file)?;
|
||||
writeln!(f);
|
||||
if let Some(location_end) = self.location_end {
|
||||
writeln!(f, " from {} to {}", self.location, location_end)?;
|
||||
@ -308,7 +293,12 @@ impl ParseError {
|
||||
}
|
||||
impl std::fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_custom(f, None)
|
||||
self.fmtgs(
|
||||
f,
|
||||
None,
|
||||
&mut crate::lang::fmtgs::FormatInfo::default(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
pub enum ParseErrors {
|
||||
@ -327,12 +317,14 @@ pub enum ParseErrors {
|
||||
ErrorParsingFunctionArgs(Box<ParseError>),
|
||||
MacroError(MacroError),
|
||||
}
|
||||
impl ParseErrors {
|
||||
|
||||
impl FormatGs for ParseErrors {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
file: Option<&super::file::File>,
|
||||
form: &mut crate::lang::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::StatementCannotStartWith(ch) => {
|
||||
@ -360,17 +352,17 @@ impl ParseErrors {
|
||||
Self::InvalidType(name) => write!(f, "\"{name}\" is not a type."),
|
||||
Self::CannotUseFixedIndexingWithThisType(t) => {
|
||||
write!(f, "cannot use fixed-indexing with type ")?;
|
||||
t.fmtgs(f, info)?;
|
||||
t.fmtgs(f, info, form, file)?;
|
||||
write!(f, ".")
|
||||
}
|
||||
Self::CannotWrapWithThisStatement(s) => {
|
||||
write!(f, "cannot wrap with this kind of statement: ")?;
|
||||
s.fmtgs(f, info)?;
|
||||
s.fmtgs(f, info, form, file)?;
|
||||
write!(f, ".")
|
||||
}
|
||||
Self::ErrorParsingFunctionArgs(parse_error) => {
|
||||
write!(f, "error parsing function args: ")?;
|
||||
parse_error.fmt_custom(f, file)
|
||||
parse_error.fmtgs(f, info, form, file)
|
||||
}
|
||||
Self::MacroError(e) => write!(f, "error in macro: {e}"),
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{path::PathBuf, thread::JoinHandle, time::Instant};
|
||||
|
||||
use crate::{
|
||||
lang::{code_runnable::RScript, global_info::GSInfo, val_data::VDataEnum},
|
||||
lang::{code_runnable::RScript, fmtgs::FormatGs, global_info::GSInfo, val_data::VDataEnum},
|
||||
parsing::{self, file::File, parse::ScriptError},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user