mirror of
				https://github.com/Dummi26/mers.git
				synced 2025-10-31 11:46:15 +01:00 
			
		
		
		
	add #include
This commit is contained in:
		
							parent
							
								
									e851559016
								
							
						
					
					
						commit
						39951a59e9
					
				| @ -1,6 +1,6 @@ | ||||
| use clap::{Parser, Subcommand, ValueEnum}; | ||||
| use mers_lib::prelude_compile::*; | ||||
| use std::{fmt::Display, fs, path::PathBuf}; | ||||
| use std::{fmt::Display, fs, path::PathBuf, process::exit}; | ||||
| 
 | ||||
| mod cfg_globals; | ||||
| 
 | ||||
| @ -67,17 +67,33 @@ fn main() { | ||||
|     let (mut info_parsed, mut info_run, mut info_check) = config.infos(); | ||||
|     let mut source = match args.command { | ||||
|         Command::Run { file } => { | ||||
|             let str = fs::read_to_string(file).unwrap(); | ||||
|             let str = match fs::read_to_string(&file) { | ||||
|                 Ok(s) => s, | ||||
|                 Err(e) => { | ||||
|                     eprintln!("Can't read file {file:?}: {e}"); | ||||
|                     exit(10); | ||||
|                 } | ||||
|             }; | ||||
|             Source::new(str) | ||||
|         } | ||||
|         Command::Exec { source } => Source::new(source), | ||||
|     }; | ||||
|     let parsed = parse(&mut source).unwrap(); | ||||
|     let parsed = match parse(&mut source) { | ||||
|         Ok(v) => v, | ||||
|         Err(e) => { | ||||
|             eprintln!("{}", e.display(&source)); | ||||
|             exit(20); | ||||
|         } | ||||
|     }; | ||||
|     #[cfg(debug_assertions)] | ||||
|     dbg!(&parsed); | ||||
|     let run = parsed | ||||
|         .compile(&mut info_parsed, Default::default()) | ||||
|         .unwrap(); | ||||
|     let run = match parsed.compile(&mut info_parsed, Default::default()) { | ||||
|         Ok(v) => v, | ||||
|         Err(e) => { | ||||
|             eprintln!("{}", e.display(&source)); | ||||
|             exit(24); | ||||
|         } | ||||
|     }; | ||||
|     #[cfg(debug_assertions)] | ||||
|     dbg!(&run); | ||||
|     match args.check { | ||||
| @ -89,7 +105,7 @@ fn main() { | ||||
|                 Ok(v) => v, | ||||
|                 Err(e) => { | ||||
|                     eprint!("{}", e.display(&source)); | ||||
|                     std::process::exit(36); | ||||
|                     exit(28); | ||||
|                 } | ||||
|             }; | ||||
|             if args.check == Check::Yes { | ||||
|  | ||||
| @ -23,6 +23,7 @@ pub trait Local: Default + Debug { | ||||
|     fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData>; | ||||
|     // fn add_type(&mut self, id: Self::TypesIdentifier, new_type: Self::TypesType);
 | ||||
|     // fn get_type(&self, id: Self::TypesIdentifier) -> Option<&Self::TypesType>;
 | ||||
|     fn duplicate(&self) -> Self; | ||||
| } | ||||
| 
 | ||||
| impl<L: Local> Info<L> { | ||||
| @ -47,6 +48,11 @@ impl<L: Local> Local for Info<L> { | ||||
|     fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> { | ||||
|         self.scopes.iter_mut().find_map(|l| l.get_var_mut(id)) | ||||
|     } | ||||
|     fn duplicate(&self) -> Self { | ||||
|         Self { | ||||
|             scopes: self.scopes.iter().map(|v| v.duplicate()).collect(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<L: Local> Default for Info<L> { | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| use crate::program::{self, parsed::block::Block}; | ||||
| use crate::program::{self, parsed::block::Block, run::CheckError}; | ||||
| 
 | ||||
| pub mod errors; | ||||
| pub mod statements; | ||||
| pub mod types; | ||||
| 
 | ||||
| pub fn parse(src: &mut Source) -> Result<Box<dyn program::parsed::MersStatement>, ()> { | ||||
| pub fn parse(src: &mut Source) -> Result<Box<dyn program::parsed::MersStatement>, CheckError> { | ||||
|     let pos_in_src = src.get_pos(); | ||||
|     let statements = statements::parse_multiple(src, "")?; | ||||
|     let block = Block { | ||||
|  | ||||
| @ -1,10 +1,16 @@ | ||||
| use super::Source; | ||||
| use std::fs; | ||||
| 
 | ||||
| use colored::{Color, Colorize}; | ||||
| 
 | ||||
| use super::{Source, SourcePos}; | ||||
| use crate::{ | ||||
|     data::Data, | ||||
|     program::{self, parsed::MersStatement}, | ||||
|     program::{self, parsed::MersStatement, run::CheckError}, | ||||
| }; | ||||
| 
 | ||||
| pub fn parse(src: &mut Source) -> Result<Option<Box<dyn program::parsed::MersStatement>>, ()> { | ||||
| pub fn parse( | ||||
|     src: &mut Source, | ||||
| ) -> Result<Option<Box<dyn program::parsed::MersStatement>>, CheckError> { | ||||
|     src.section_begin("statement".to_string()); | ||||
|     let mut first = if let Some(s) = parse_no_chain(src)? { | ||||
|         s | ||||
| @ -16,7 +22,14 @@ pub fn parse(src: &mut Source) -> Result<Option<Box<dyn program::parsed::MersSta | ||||
|         ":=" => { | ||||
|             let pos_in_src = src.get_pos(); | ||||
|             src.next_word(); | ||||
|             let source = parse(src)?.expect("todo"); | ||||
|             let source = parse(src)?.ok_or_else(|| { | ||||
|                 CheckError::new() | ||||
|                     .src(vec![( | ||||
|                         (pos_in_src, src.get_pos()).into(), | ||||
|                         Some(Color::BrightBlack), | ||||
|                     )]) | ||||
|                     .msg(format!("EOF after :=")) | ||||
|             })?; | ||||
|             first = Box::new(program::parsed::init_to::InitTo { | ||||
|                 pos_in_src: (pos_in_src, src.get_pos()).into(), | ||||
|                 target: first, | ||||
| @ -26,7 +39,14 @@ pub fn parse(src: &mut Source) -> Result<Option<Box<dyn program::parsed::MersSta | ||||
|         "=" => { | ||||
|             let pos_in_src = src.get_pos(); | ||||
|             src.next_word(); | ||||
|             let source = parse(src)?.expect("todo"); | ||||
|             let source = parse(src)?.ok_or_else(|| { | ||||
|                 CheckError::new() | ||||
|                     .src(vec![( | ||||
|                         (pos_in_src, src.get_pos()).into(), | ||||
|                         Some(Color::BrightBlack), | ||||
|                     )]) | ||||
|                     .msg(format!("EOF after =")) | ||||
|             })?; | ||||
|             first = Box::new(program::parsed::assign_to::AssignTo { | ||||
|                 pos_in_src: (pos_in_src, src.get_pos()).into(), | ||||
|                 target: first, | ||||
| @ -73,7 +93,10 @@ pub fn parse(src: &mut Source) -> Result<Option<Box<dyn program::parsed::MersSta | ||||
|     } | ||||
|     Ok(Some(first)) | ||||
| } | ||||
| pub fn parse_multiple(src: &mut Source, end: &str) -> Result<Vec<Box<dyn MersStatement>>, ()> { | ||||
| pub fn parse_multiple( | ||||
|     src: &mut Source, | ||||
|     end: &str, | ||||
| ) -> Result<Vec<Box<dyn MersStatement>>, CheckError> { | ||||
|     src.section_begin("block".to_string()); | ||||
|     let mut statements = vec![]; | ||||
|     loop { | ||||
| @ -92,10 +115,68 @@ pub fn parse_multiple(src: &mut Source, end: &str) -> Result<Vec<Box<dyn MersSta | ||||
| } | ||||
| pub fn parse_no_chain( | ||||
|     src: &mut Source, | ||||
| ) -> Result<Option<Box<dyn program::parsed::MersStatement>>, ()> { | ||||
| ) -> Result<Option<Box<dyn program::parsed::MersStatement>>, CheckError> { | ||||
|     src.section_begin("statement no chain".to_string()); | ||||
|     src.skip_whitespace(); | ||||
|     match src.peek_char() { | ||||
|         Some('#') => { | ||||
|             let pos_in_src = src.get_pos(); | ||||
|             src.next_char(); | ||||
|             if src.peek_char().is_none() { | ||||
|                 return Err(CheckError::new() | ||||
|                     .src(vec![((pos_in_src, src.get_pos()).into(), Some(Color::Red))]) | ||||
|                     .msg(format!("EOF after #"))); | ||||
|             } | ||||
|             if src.peek_char().is_some_and(|ch| ch.is_whitespace()) { | ||||
|                 src.skip_whitespace(); | ||||
|                 return Err(CheckError::new() | ||||
|                     .src(vec![((pos_in_src, src.get_pos()).into(), Some(Color::Red))]) | ||||
|                     .msg(format!("Whitespace after #"))); | ||||
|             } | ||||
|             match src.next_word() { | ||||
|                 "include" => { | ||||
|                     let end_in_src = src.get_pos(); | ||||
|                     src.skip_whitespace(); | ||||
|                     let string_in_src = src.get_pos(); | ||||
|                     if src.next_char() == Some('"') { | ||||
|                         let s = parse_string(src, string_in_src)?; | ||||
|                         match fs::read_to_string(&s) { | ||||
|                             Ok(s) => { | ||||
|                                 return Ok(Some(Box::new( | ||||
|                                     program::parsed::include_mers::IncludeMers { | ||||
|                                         pos_in_src: (pos_in_src, src.get_pos()).into(), | ||||
|                                         include: super::parse(&mut Source::new(s))?, | ||||
|                                     }, | ||||
|                                 ))); | ||||
|                             } | ||||
|                             Err(e) => { | ||||
|                                 return Err(CheckError::new() | ||||
|                                     .src(vec![ | ||||
|                                         ((pos_in_src, end_in_src).into(), None), | ||||
|                                         ((string_in_src, src.get_pos()).into(), Some(Color::Red)), | ||||
|                                     ]) | ||||
|                                     .msg(format!("Can't load file '{s}': {e}"))); | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                         return Err(CheckError::new() | ||||
|                             .src(vec![ | ||||
|                                 ((pos_in_src, end_in_src).into(), Some(Color::BrightBlack)), | ||||
|                                 ((string_in_src, src.get_pos()).into(), Some(Color::Red)), | ||||
|                             ]) | ||||
|                             .msg(format!( | ||||
|                                 "#include must be followed by a string literal like \"file.mers\" (\" expected)." | ||||
|                             ))); | ||||
|                     } | ||||
|                 } | ||||
|                 other => { | ||||
|                     let msg = format!("Unknown #statement: {other}"); | ||||
|                     return Err(CheckError::new() | ||||
|                         .src(vec![((pos_in_src, src.get_pos()).into(), Some(Color::Red))]) | ||||
|                         .msg(msg)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Some('{') => { | ||||
|             let pos_in_src = src.get_pos(); | ||||
|             src.next_char(); | ||||
| @ -118,28 +199,7 @@ pub fn parse_no_chain( | ||||
|             src.section_begin("string literal".to_string()); | ||||
|             let pos_in_src = src.get_pos(); | ||||
|             src.next_char(); | ||||
|             let mut s = String::new(); | ||||
|             loop { | ||||
|                 if let Some(ch) = src.next_char() { | ||||
|                     if ch == '\\' { | ||||
|                         s.push(match src.next_char() { | ||||
|                             Some('\\') => '\\', | ||||
|                             Some('r') => '\r', | ||||
|                             Some('n') => '\n', | ||||
|                             Some('t') => '\t', | ||||
|                             Some('"') => '"', | ||||
|                             Some(o) => todo!("err: unknown backslash escape '\\{o}'"), | ||||
|                             None => todo!("err: eof in backslash escape"), | ||||
|                         }); | ||||
|                     } else if ch == '"' { | ||||
|                         break; | ||||
|                     } else { | ||||
|                         s.push(ch); | ||||
|                     } | ||||
|                 } else { | ||||
|                     todo!("err: eof in string") | ||||
|                 } | ||||
|             } | ||||
|             let s = parse_string(src, pos_in_src)?; | ||||
|             return Ok(Some(Box::new(program::parsed::value::Value { | ||||
|                 pos_in_src: (pos_in_src, src.get_pos()).into(), | ||||
|                 data: Data::new(crate::data::string::String(s)), | ||||
| @ -222,3 +282,50 @@ pub fn parse_no_chain( | ||||
|         } | ||||
|     })) | ||||
| } | ||||
| 
 | ||||
| /// expects to be called *after* a " character is consumed from src
 | ||||
| pub fn parse_string(src: &mut Source, double_quote: SourcePos) -> Result<String, CheckError> { | ||||
|     let mut s = String::new(); | ||||
|     loop { | ||||
|         if let Some(ch) = src.next_char() { | ||||
|             if ch == '\\' { | ||||
|                 let backslash_in_src = src.get_pos(); | ||||
|                 s.push(match src.next_char() { | ||||
|                     Some('\\') => '\\', | ||||
|                     Some('r') => '\r', | ||||
|                     Some('n') => '\n', | ||||
|                     Some('t') => '\t', | ||||
|                     Some('"') => '"', | ||||
|                     Some(o) => { | ||||
|                         return Err(CheckError::new() | ||||
|                             .src(vec![( | ||||
|                                 (backslash_in_src, src.get_pos()).into(), | ||||
|                                 Some(Color::Red), | ||||
|                             )]) | ||||
|                             .msg(format!("unknown backslash escape '\\{o}'"))); | ||||
|                     } | ||||
|                     None => { | ||||
|                         return Err(CheckError::new() | ||||
|                             .src(vec![( | ||||
|                                 (backslash_in_src, src.get_pos()).into(), | ||||
|                                 Some(Color::Red), | ||||
|                             )]) | ||||
|                             .msg(format!("EOF in backslash escape"))); | ||||
|                     } | ||||
|                 }); | ||||
|             } else if ch == '"' { | ||||
|                 break; | ||||
|             } else { | ||||
|                 s.push(ch); | ||||
|             } | ||||
|         } else { | ||||
|             return Err(CheckError::new() | ||||
|                 .src(vec![( | ||||
|                     (double_quote, src.get_pos()).into(), | ||||
|                     Some(Color::BrightBlack), | ||||
|                 )]) | ||||
|                 .msg(format!("EOF in string literal"))); | ||||
|         } | ||||
|     } | ||||
|     Ok(s) | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,7 @@ | ||||
| use crate::program::{self, run::SourceRange}; | ||||
| use crate::program::{ | ||||
|     self, | ||||
|     run::{CheckError, SourceRange}, | ||||
| }; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| 
 | ||||
| @ -17,7 +20,7 @@ impl MersStatement for AssignTo { | ||||
|         &self, | ||||
|         info: &mut crate::info::Info<super::Local>, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         Ok(Box::new(program::run::assign_to::AssignTo { | ||||
|             pos_in_src: self.pos_in_src, | ||||
|             is_init: false, | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| use crate::{ | ||||
|     info, | ||||
|     program::{self, run::SourceRange}, | ||||
|     program::{ | ||||
|         self, | ||||
|         run::{CheckError, SourceRange}, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| @ -18,7 +21,7 @@ impl MersStatement for Block { | ||||
|         &self, | ||||
|         info: &mut info::Info<super::Local>, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         Ok(Box::new(program::run::block::Block { | ||||
|             pos_in_src: self.pos_in_src, | ||||
|             statements: self | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use crate::program::run::SourceRange; | ||||
| use crate::program::run::{CheckError, SourceRange}; | ||||
| use crate::{info, program}; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| @ -17,7 +17,7 @@ impl MersStatement for Chain { | ||||
|         &self, | ||||
|         info: &mut info::Info<super::Local>, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         Ok(Box::new(program::run::chain::Chain { | ||||
|             pos_in_src: self.pos_in_src, | ||||
|             first: self.first.compile(info, comp)?, | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use crate::program::run::SourceRange; | ||||
| use crate::program::run::{CheckError, SourceRange}; | ||||
| use std::sync::{Arc, Mutex}; | ||||
| 
 | ||||
| use crate::{ | ||||
| @ -24,7 +24,7 @@ impl MersStatement for Function { | ||||
|         &self, | ||||
|         info: &mut crate::info::Info<super::Local>, | ||||
|         mut comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         comp.is_init = true; | ||||
|         let arg_target = Arc::new(self.arg.compile(info, comp)?); | ||||
|         comp.is_init = false; | ||||
|  | ||||
| @ -1,4 +1,7 @@ | ||||
| use crate::program::{self, run::SourceRange}; | ||||
| use crate::program::{ | ||||
|     self, | ||||
|     run::{CheckError, SourceRange}, | ||||
| }; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| 
 | ||||
| @ -18,7 +21,7 @@ impl MersStatement for If { | ||||
|         &self, | ||||
|         info: &mut crate::info::Info<super::Local>, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         Ok(Box::new(program::run::r#if::If { | ||||
|             pos_in_src: self.pos_in_src, | ||||
|             condition: self.condition.compile(info, comp)?, | ||||
|  | ||||
							
								
								
									
										60
									
								
								mers_lib/src/program/parsed/include_mers.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								mers_lib/src/program/parsed/include_mers.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| use std::sync::{Arc, Mutex}; | ||||
| 
 | ||||
| use colored::Colorize; | ||||
| 
 | ||||
| use crate::{ | ||||
|     data::{self, Data}, | ||||
|     info::{self, Local}, | ||||
|     program::{ | ||||
|         self, | ||||
|         run::{CheckError, SourceRange}, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct IncludeMers { | ||||
|     pub pos_in_src: SourceRange, | ||||
|     pub include: Box<dyn MersStatement>, | ||||
| } | ||||
| impl MersStatement for IncludeMers { | ||||
|     fn has_scope(&self) -> bool { | ||||
|         true | ||||
|     } | ||||
|     fn compile_custom( | ||||
|         &self, | ||||
|         info: &mut info::Info<super::Local>, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         let compiled = match self.include.compile(info, comp) { | ||||
|             Ok(v) => Arc::new(v), | ||||
|             Err(e) => { | ||||
|                 return Err(CheckError::new() | ||||
|                     .src(vec![(self.pos_in_src, Some(colored::Color::Red))]) | ||||
|                     .msg("Error in inner mers statement! (note: inner errors may refer to a different file)".red().to_string()) | ||||
|                 .err(e)) | ||||
|             } | ||||
|         }; | ||||
|         let compiled2 = Arc::clone(&compiled); | ||||
|         Ok(Box::new(program::run::chain::Chain { | ||||
|             pos_in_src: self.pos_in_src, | ||||
|             first: Box::new(program::run::value::Value { | ||||
|                 pos_in_src: self.pos_in_src, | ||||
|                 val: Data::empty_tuple(), | ||||
|             }), | ||||
|             chained: Box::new(program::run::function::Function { | ||||
|                 pos_in_src: self.pos_in_src, | ||||
|                 func_no_info: data::function::Function { | ||||
|                     info: Arc::new(info::Info::neverused()), | ||||
|                     info_check: Arc::new(Mutex::new(info::Info::neverused())), | ||||
|                     out: Arc::new(move |_, i| compiled.check(&mut i.duplicate(), None)), | ||||
|                     run: Arc::new(move |_, i| compiled2.run(&mut i.duplicate())), | ||||
|                 }, | ||||
|             }), | ||||
|         })) | ||||
|     } | ||||
|     fn source_range(&self) -> SourceRange { | ||||
|         self.pos_in_src | ||||
|     } | ||||
| } | ||||
| @ -1,5 +1,5 @@ | ||||
| use crate::program; | ||||
| use crate::program::run::SourceRange; | ||||
| use crate::program::{self, run::CheckError}; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| 
 | ||||
| @ -18,7 +18,7 @@ impl MersStatement for InitTo { | ||||
|         &self, | ||||
|         info: &mut crate::info::Info<super::Local>, | ||||
|         mut comp: CompInfo, | ||||
|     ) -> Result<Box<dyn crate::program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn crate::program::run::MersStatement>, CheckError> { | ||||
|         comp.is_init = true; | ||||
|         let target = self.target.compile(info, comp)?; | ||||
|         comp.is_init = false; | ||||
|  | ||||
| @ -2,7 +2,7 @@ use std::{collections::HashMap, fmt::Debug}; | ||||
| 
 | ||||
| use crate::info; | ||||
| 
 | ||||
| use super::run::SourceRange; | ||||
| use super::run::{CheckError, SourceRange}; | ||||
| 
 | ||||
| #[cfg(feature = "parse")] | ||||
| pub mod assign_to; | ||||
| @ -15,6 +15,8 @@ pub mod function; | ||||
| #[cfg(feature = "parse")] | ||||
| pub mod r#if; | ||||
| #[cfg(feature = "parse")] | ||||
| pub mod include_mers; | ||||
| #[cfg(feature = "parse")] | ||||
| pub mod init_to; | ||||
| #[cfg(feature = "parse")] | ||||
| pub mod tuple; | ||||
| @ -29,12 +31,12 @@ pub trait MersStatement: Debug + Send + Sync { | ||||
|         &self, | ||||
|         info: &mut Info, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn super::run::MersStatement>, String>; | ||||
|     ) -> Result<Box<dyn super::run::MersStatement>, CheckError>; | ||||
|     fn compile( | ||||
|         &self, | ||||
|         info: &mut Info, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn super::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn super::run::MersStatement>, CheckError> { | ||||
|         if self.has_scope() { | ||||
|             info.create_scope(); | ||||
|         } | ||||
| @ -77,4 +79,7 @@ impl info::Local for Local { | ||||
|     fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> { | ||||
|         self.vars.get_mut(id) | ||||
|     } | ||||
|     fn duplicate(&self) -> Self { | ||||
|         self.clone() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| use crate::{ | ||||
|     info, | ||||
|     program::{self, run::SourceRange}, | ||||
|     program::{ | ||||
|         self, | ||||
|         run::{CheckError, SourceRange}, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| @ -18,7 +21,7 @@ impl MersStatement for Tuple { | ||||
|         &self, | ||||
|         info: &mut info::Info<super::Local>, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         Ok(Box::new(program::run::tuple::Tuple { | ||||
|             pos_in_src: self.pos_in_src, | ||||
|             elems: self | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use crate::program::run::SourceRange; | ||||
| use crate::program::run::{CheckError, SourceRange}; | ||||
| use crate::{data::Data, program}; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| @ -17,7 +17,7 @@ impl MersStatement for Value { | ||||
|         &self, | ||||
|         _info: &mut crate::info::Info<super::Local>, | ||||
|         _comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         Ok(Box::new(program::run::value::Value { | ||||
|             pos_in_src: self.pos_in_src, | ||||
|             val: self.data.clone(), | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| use crate::{ | ||||
|     info::Local, | ||||
|     program::{self, run::SourceRange}, | ||||
|     program::{ | ||||
|         self, | ||||
|         run::{CheckError, SourceRange}, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| use super::{CompInfo, MersStatement}; | ||||
| @ -20,7 +23,7 @@ impl MersStatement for Variable { | ||||
|         &self, | ||||
|         info: &mut crate::info::Info<super::Local>, | ||||
|         comp: CompInfo, | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, String> { | ||||
|     ) -> Result<Box<dyn program::run::MersStatement>, CheckError> { | ||||
|         if comp.is_init { | ||||
|             info.init_var( | ||||
|                 self.var.clone(), | ||||
| @ -37,7 +40,9 @@ impl MersStatement for Variable { | ||||
|             var: if let Some(v) = info.get_var(&self.var) { | ||||
|                 *v | ||||
|             } else { | ||||
|                 return Err(format!("No variable named '{}' found!", self.var)); | ||||
|                 return Err(CheckError::new() | ||||
|                     .src(vec![(self.pos_in_src, Some(colored::Color::Red))]) | ||||
|                     .msg(format!("No variable named '{}' found!", self.var))); | ||||
|             }, | ||||
|         })) | ||||
|     } | ||||
|  | ||||
| @ -268,6 +268,15 @@ impl info::Local for Local { | ||||
|             None => None, | ||||
|         } | ||||
|     } | ||||
|     fn duplicate(&self) -> Self { | ||||
|         Self { | ||||
|             vars: self | ||||
|                 .vars | ||||
|                 .iter() | ||||
|                 .map(|v| Arc::new(RwLock::new(v.read().unwrap().clone()))) | ||||
|                 .collect(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| impl info::Local for CheckLocal { | ||||
|     type VariableIdentifier = usize; | ||||
| @ -290,4 +299,7 @@ impl info::Local for CheckLocal { | ||||
|             None => None, | ||||
|         } | ||||
|     } | ||||
|     fn duplicate(&self) -> Self { | ||||
|         self.clone() | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Mark
						Mark