added basic tests

This commit is contained in:
mark 2023-04-30 22:21:27 +02:00
parent 657f282006
commit b83f54cb2d
12 changed files with 103 additions and 36 deletions

View File

@ -25,15 +25,15 @@ println(greeting)
println!();
if let Ok(file_contents) = fs::read_to_string(&temp_file) {
let mut file =
crate::parse::file::File::new(file_contents, temp_file.to_path_buf());
match crate::parse::parse::parse(&mut file) {
crate::parsing::file::File::new(file_contents, temp_file.to_path_buf());
match crate::parsing::parse::parse(&mut file) {
Ok(func) => {
println!(" - - - - -");
let output = func.run(vec![]);
println!(" - - - - -");
println!("{}", output);
}
Err(e) => println!("{}", e.0.with_file_and_gsinfo(&file, e.1.as_ref())),
Err(e) => println!("{}", e.with_file(&file)),
}
} else {
println!("can't read file at {:?}!", temp_file);

View File

@ -2,9 +2,9 @@
#![allow(dead_code)]
mod libs;
mod parse;
mod parsing;
mod script;
pub use libs::inlib::*;
pub use parse::*;
pub use parsing::*;
pub use script::{val_data::*, val_type::*};

View File

@ -10,7 +10,7 @@ use std::{
};
use crate::{
parse::{file::File, parse},
parsing::{file::File, parse},
script::{
val_data::{VData, VDataEnum},
val_type::VType,

View File

@ -9,7 +9,7 @@ mod interactive_mode;
mod libs;
#[cfg(feature = "nushell_plugin")]
mod nushell_plugin;
mod parse;
mod parsing;
mod script;
mod tutor;
@ -105,7 +105,7 @@ fn normal_main() {
};
return;
} else if execute {
parse::file::File::new(
parsing::file::File::new(
args.iter().skip(1).fold(String::new(), |mut s, v| {
if !s.is_empty() {
s.push(' ');
@ -120,11 +120,11 @@ fn normal_main() {
std::process::exit(101);
}
} else {
parse::file::File::new(std::fs::read_to_string(&args[0]).unwrap(), path.into())
parsing::file::File::new(std::fs::read_to_string(&args[0]).unwrap(), path.into())
}
}
};
match parse::parse::parse(&mut file) {
match parsing::parse::parse(&mut file) {
Ok(script) => {
println!(" - - - - -");
let start = Instant::now();
@ -134,10 +134,7 @@ fn normal_main() {
println!("Output ({}s)\n{out}", elapsed.as_secs_f64());
}
Err(e) => {
println!(
"Couldn't compile:\n{}",
e.0.with_file_and_gsinfo(&file, e.1.as_ref())
);
println!("Couldn't compile:\n{}", e.with_file(&file));
std::process::exit(99);
}
}

View File

@ -1,4 +1,4 @@
use std::{process::Command, sync::Arc};
use std::{fmt::Debug, process::Command, sync::Arc};
use crate::{
libs,
@ -6,7 +6,7 @@ use crate::{
code_macro::MacroError,
code_parsed::*,
code_runnable::RScript,
global_info::{GlobalScriptInfo, GSInfo},
global_info::{GSInfo, GlobalScriptInfo},
to_runnable::{self, ToRunnableError},
val_data::VDataEnum,
val_type::{VSingleType, VType},
@ -61,7 +61,11 @@ impl<'a> ScriptError {
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 {
pub fn with_file_and_gsinfo(
&'a self,
file: &'a File,
info: &'a GlobalScriptInfo,
) -> ScriptErrorWithFileAndInfo {
ScriptErrorWithFileAndInfo(self, file, info)
}
}
@ -82,7 +86,12 @@ impl<'a> std::fmt::Display for ScriptErrorWithFileAndInfo<'a> {
}
impl ScriptError {
fn fmt_custom(&self, f: &mut std::fmt::Formatter<'_>, file: Option<&File>, info: Option<&GlobalScriptInfo>) -> std::fmt::Result {
fn fmt_custom(
&self,
f: &mut std::fmt::Formatter<'_>,
file: Option<&File>,
info: Option<&GlobalScriptInfo>,
) -> std::fmt::Result {
match &self {
ScriptError::CannotFindPathForLibrary(e) => write!(f, "{e}"),
ScriptError::ParseError(e) => {
@ -102,28 +111,51 @@ impl ScriptError {
pub const PARSE_VERSION: u64 = 0;
pub struct Error {
pub err: ScriptError,
pub ginfo: GSInfo,
}
impl From<(ScriptError, GSInfo)> for Error {
fn from(value: (ScriptError, GSInfo)) -> Self {
Self {
err: value.0,
ginfo: value.1,
}
}
}
impl Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.err.with_gsinfo(&self.ginfo))
}
}
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())
}
}
/// executes the 4 parse_steps in order: lib_paths => interpret => libs_load => compile
pub fn parse(file: &mut File) -> Result<RScript, (ScriptError, GSInfo)> {
pub fn parse(file: &mut File) -> Result<RScript, Error> {
let mut ginfo = GlobalScriptInfo::default();
let libs = match parse_step_lib_paths(file) {
Ok(v) => v,
Err(e) => return Err((e.into(), ginfo.to_arc())),
Err(e) => return Err((e.into(), ginfo.to_arc()).into()),
};
let func = match parse_step_interpret(file) {
Ok(v) => v,
Err(e) => return Err((e.into(), ginfo.to_arc())),
Err(e) => return Err((e.into(), ginfo.to_arc()).into()),
};
ginfo.libs = match parse_step_libs_load(libs, &mut ginfo) {
Ok(v) => v,
Err(e) => return Err((e.into(), ginfo.to_arc())),
Err(e) => return Err((e.into(), ginfo.to_arc()).into()),
};
let run = match parse_step_compile(func, ginfo) {
Ok(v) => v,
Err(e) => return Err((e.0.into(), e.1)),
Err(e) => return Err((e.0.into(), e.1).into()),
};
Ok(run)
@ -198,7 +230,10 @@ pub fn parse_step_libs_load(
Ok(libs)
}
pub fn parse_step_compile(main_func: SFunction, ginfo: GlobalScriptInfo) -> Result<RScript, (ToRunnableError, GSInfo)> {
pub fn parse_step_compile(
main_func: SFunction,
ginfo: GlobalScriptInfo,
) -> Result<RScript, (ToRunnableError, GSInfo)> {
to_runnable::to_runnable(main_func, ginfo)
}
@ -341,6 +376,8 @@ use implementation::*;
pub mod implementation {
use crate::parsing::file::FilePosition;
use super::*;
fn parse_block(file: &mut File) -> Result<SBlock, ParseError> {
@ -733,7 +770,11 @@ pub mod implementation {
}
"type" => {
file.skip_whitespaces();
break SStatementEnum::TypeDefinition(file.collect_to_whitespace(), parse_type(file)?).to();
break SStatementEnum::TypeDefinition(
file.collect_to_whitespace(),
parse_type(file)?,
)
.to();
}
"true" => break SStatementEnum::Value(VDataEnum::Bool(true).to()).to(),
"false" => {
@ -940,7 +981,7 @@ pub mod implementation {
/// Assumes the function name and opening bracket have already been parsed. File should continue like "name type name type ...) <statement>"
fn parse_function(
file: &mut File,
err_fn_start: Option<crate::parse::file::FilePosition>,
err_fn_start: Option<FilePosition>,
) -> Result<SFunction, ParseError> {
file.skip_whitespaces();
// find the arguments to the function

View File

@ -1,6 +1,6 @@
use std::{fmt::Display, fs};
use crate::parse::{
use crate::parsing::{
file::File,
parse::{self, ParseError, ScriptError},
};
@ -43,7 +43,7 @@ fn parse_mers_code(file: &mut File) -> Result<RScript, MacroError> {
_ = file.next();
match parse::parse(file) {
Ok(v) => Ok(v),
Err(e) => Err(e.0.into()),
Err(e) => Err(e.err.into()),
}
} else {
let path = parse_string_val(file);
@ -58,7 +58,7 @@ fn parse_mers_code(file: &mut File) -> Result<RScript, MacroError> {
);
Ok(match parse::parse(&mut file) {
Ok(v) => v,
Err(e) => return Err(e.0.into()),
Err(e) => return Err(e.err.into()),
})
}
}

View File

@ -1,8 +1,8 @@
use std::{path::PathBuf, thread::JoinHandle, time::Instant};
use crate::{
parse::{self, parse::ScriptError, file::File},
script::{code_runnable::RScript, val_data::VDataEnum, global_info::GSInfo},
parsing::{self, file::File, parse::ScriptError},
script::{code_runnable::RScript, global_info::GSInfo, val_data::VDataEnum},
};
mod base_comments;
@ -30,8 +30,8 @@ false
",
Box::new(move |file| {
let mut file =
parse::file::File::new(std::fs::read_to_string(file).unwrap(), PathBuf::new());
sender.send((parse::parse::parse(&mut file), file)).unwrap();
parsing::file::File::new(std::fs::read_to_string(file).unwrap(), PathBuf::new());
sender.send((parsing::parse::parse(&mut file), file)).unwrap();
}),
)
.unwrap();
@ -60,7 +60,7 @@ pub struct Tutor {
written_status_byte_len: usize,
editor_join_handle: JoinHandle<()>,
file_path: PathBuf,
receiver: std::sync::mpsc::Receiver<(Result<RScript, (ScriptError, GSInfo)>, File)>,
receiver: std::sync::mpsc::Receiver<(Result<RScript, parsing::parse::Error>, File)>,
// i_ are inputs from the user
pub i_name: Option<String>,
}
@ -70,10 +70,11 @@ impl Tutor {
// eprintln!(" - - - - - - - - - - - - - - - - - - - - - - - - -");
let script = loop {
match self.receiver.recv().unwrap() {
(Err((e, info)), file) => {
(Err(e), file) => {
self.current_status = format!(
" - Error during build{}",
e.with_file_and_gsinfo(&file, info.as_ref()).to_string()
e.with_file(&file)
.to_string()
.lines()
.map(|v| format!("\n// {v}"))
.collect::<String>()

View File

@ -0,0 +1 @@
true

View File

@ -0,0 +1,24 @@
use std::{fs, path::Path};
use mers_libs::file::File;
use mers_libs::{parse, VDataEnum};
#[test]
fn run_all() {
for file in fs::read_dir(Path::new(file!()).parent().unwrap())
.unwrap()
.filter_map(|v| v.ok())
{
if let Some(file_name) = file.file_name().to_str() {
if file_name.ends_with(".mers") {
eprintln!("Checking {}", file_name);
let mut file = File::new(fs::read_to_string(file.path()).unwrap(), file.path());
// has to return true, otherwise the test will fail
assert!(matches!(
parse::parse(&mut file).unwrap().run(vec![]).data,
VDataEnum::Bool(true)
));
}
}
}
}

View File

@ -0,0 +1,3 @@
var: [string ...] = [...]
&var.push("a string")
var.len().eq(1)