mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
add #include
This commit is contained in:
parent
e851559016
commit
39951a59e9
@ -1,6 +1,6 @@
|
|||||||
use clap::{Parser, Subcommand, ValueEnum};
|
use clap::{Parser, Subcommand, ValueEnum};
|
||||||
use mers_lib::prelude_compile::*;
|
use mers_lib::prelude_compile::*;
|
||||||
use std::{fmt::Display, fs, path::PathBuf};
|
use std::{fmt::Display, fs, path::PathBuf, process::exit};
|
||||||
|
|
||||||
mod cfg_globals;
|
mod cfg_globals;
|
||||||
|
|
||||||
@ -67,17 +67,33 @@ fn main() {
|
|||||||
let (mut info_parsed, mut info_run, mut info_check) = config.infos();
|
let (mut info_parsed, mut info_run, mut info_check) = config.infos();
|
||||||
let mut source = match args.command {
|
let mut source = match args.command {
|
||||||
Command::Run { file } => {
|
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)
|
Source::new(str)
|
||||||
}
|
}
|
||||||
Command::Exec { source } => Source::new(source),
|
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)]
|
#[cfg(debug_assertions)]
|
||||||
dbg!(&parsed);
|
dbg!(&parsed);
|
||||||
let run = parsed
|
let run = match parsed.compile(&mut info_parsed, Default::default()) {
|
||||||
.compile(&mut info_parsed, Default::default())
|
Ok(v) => v,
|
||||||
.unwrap();
|
Err(e) => {
|
||||||
|
eprintln!("{}", e.display(&source));
|
||||||
|
exit(24);
|
||||||
|
}
|
||||||
|
};
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dbg!(&run);
|
dbg!(&run);
|
||||||
match args.check {
|
match args.check {
|
||||||
@ -89,7 +105,7 @@ fn main() {
|
|||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprint!("{}", e.display(&source));
|
eprint!("{}", e.display(&source));
|
||||||
std::process::exit(36);
|
exit(28);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if args.check == Check::Yes {
|
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 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 add_type(&mut self, id: Self::TypesIdentifier, new_type: Self::TypesType);
|
||||||
// fn get_type(&self, id: Self::TypesIdentifier) -> Option<&Self::TypesType>;
|
// fn get_type(&self, id: Self::TypesIdentifier) -> Option<&Self::TypesType>;
|
||||||
|
fn duplicate(&self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L: Local> Info<L> {
|
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> {
|
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))
|
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> {
|
impl<L: Local> Default for Info<L> {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::sync::Arc;
|
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 errors;
|
||||||
pub mod statements;
|
pub mod statements;
|
||||||
pub mod types;
|
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 pos_in_src = src.get_pos();
|
||||||
let statements = statements::parse_multiple(src, "")?;
|
let statements = statements::parse_multiple(src, "")?;
|
||||||
let block = Block {
|
let block = Block {
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
use super::Source;
|
use std::fs;
|
||||||
|
|
||||||
|
use colored::{Color, Colorize};
|
||||||
|
|
||||||
|
use super::{Source, SourcePos};
|
||||||
use crate::{
|
use crate::{
|
||||||
data::Data,
|
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());
|
src.section_begin("statement".to_string());
|
||||||
let mut first = if let Some(s) = parse_no_chain(src)? {
|
let mut first = if let Some(s) = parse_no_chain(src)? {
|
||||||
s
|
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();
|
let pos_in_src = src.get_pos();
|
||||||
src.next_word();
|
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 {
|
first = Box::new(program::parsed::init_to::InitTo {
|
||||||
pos_in_src: (pos_in_src, src.get_pos()).into(),
|
pos_in_src: (pos_in_src, src.get_pos()).into(),
|
||||||
target: first,
|
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();
|
let pos_in_src = src.get_pos();
|
||||||
src.next_word();
|
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 {
|
first = Box::new(program::parsed::assign_to::AssignTo {
|
||||||
pos_in_src: (pos_in_src, src.get_pos()).into(),
|
pos_in_src: (pos_in_src, src.get_pos()).into(),
|
||||||
target: first,
|
target: first,
|
||||||
@ -73,7 +93,10 @@ pub fn parse(src: &mut Source) -> Result<Option<Box<dyn program::parsed::MersSta
|
|||||||
}
|
}
|
||||||
Ok(Some(first))
|
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());
|
src.section_begin("block".to_string());
|
||||||
let mut statements = vec![];
|
let mut statements = vec![];
|
||||||
loop {
|
loop {
|
||||||
@ -92,10 +115,68 @@ pub fn parse_multiple(src: &mut Source, end: &str) -> Result<Vec<Box<dyn MersSta
|
|||||||
}
|
}
|
||||||
pub fn parse_no_chain(
|
pub fn parse_no_chain(
|
||||||
src: &mut Source,
|
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.section_begin("statement no chain".to_string());
|
||||||
src.skip_whitespace();
|
src.skip_whitespace();
|
||||||
match src.peek_char() {
|
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('{') => {
|
Some('{') => {
|
||||||
let pos_in_src = src.get_pos();
|
let pos_in_src = src.get_pos();
|
||||||
src.next_char();
|
src.next_char();
|
||||||
@ -118,28 +199,7 @@ pub fn parse_no_chain(
|
|||||||
src.section_begin("string literal".to_string());
|
src.section_begin("string literal".to_string());
|
||||||
let pos_in_src = src.get_pos();
|
let pos_in_src = src.get_pos();
|
||||||
src.next_char();
|
src.next_char();
|
||||||
let mut s = String::new();
|
let s = parse_string(src, pos_in_src)?;
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(Some(Box::new(program::parsed::value::Value {
|
return Ok(Some(Box::new(program::parsed::value::Value {
|
||||||
pos_in_src: (pos_in_src, src.get_pos()).into(),
|
pos_in_src: (pos_in_src, src.get_pos()).into(),
|
||||||
data: Data::new(crate::data::string::String(s)),
|
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};
|
use super::{CompInfo, MersStatement};
|
||||||
|
|
||||||
@ -17,7 +20,7 @@ impl MersStatement for AssignTo {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut crate::info::Info<super::Local>,
|
info: &mut crate::info::Info<super::Local>,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
Ok(Box::new(program::run::assign_to::AssignTo {
|
Ok(Box::new(program::run::assign_to::AssignTo {
|
||||||
pos_in_src: self.pos_in_src,
|
pos_in_src: self.pos_in_src,
|
||||||
is_init: false,
|
is_init: false,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
info,
|
info,
|
||||||
program::{self, run::SourceRange},
|
program::{
|
||||||
|
self,
|
||||||
|
run::{CheckError, SourceRange},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CompInfo, MersStatement};
|
use super::{CompInfo, MersStatement};
|
||||||
@ -18,7 +21,7 @@ impl MersStatement for Block {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut info::Info<super::Local>,
|
info: &mut info::Info<super::Local>,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
Ok(Box::new(program::run::block::Block {
|
Ok(Box::new(program::run::block::Block {
|
||||||
pos_in_src: self.pos_in_src,
|
pos_in_src: self.pos_in_src,
|
||||||
statements: self
|
statements: self
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::program::run::SourceRange;
|
use crate::program::run::{CheckError, SourceRange};
|
||||||
use crate::{info, program};
|
use crate::{info, program};
|
||||||
|
|
||||||
use super::{CompInfo, MersStatement};
|
use super::{CompInfo, MersStatement};
|
||||||
@ -17,7 +17,7 @@ impl MersStatement for Chain {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut info::Info<super::Local>,
|
info: &mut info::Info<super::Local>,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
Ok(Box::new(program::run::chain::Chain {
|
Ok(Box::new(program::run::chain::Chain {
|
||||||
pos_in_src: self.pos_in_src,
|
pos_in_src: self.pos_in_src,
|
||||||
first: self.first.compile(info, comp)?,
|
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 std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -24,7 +24,7 @@ impl MersStatement for Function {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut crate::info::Info<super::Local>,
|
info: &mut crate::info::Info<super::Local>,
|
||||||
mut comp: CompInfo,
|
mut comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
comp.is_init = true;
|
comp.is_init = true;
|
||||||
let arg_target = Arc::new(self.arg.compile(info, comp)?);
|
let arg_target = Arc::new(self.arg.compile(info, comp)?);
|
||||||
comp.is_init = false;
|
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};
|
use super::{CompInfo, MersStatement};
|
||||||
|
|
||||||
@ -18,7 +21,7 @@ impl MersStatement for If {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut crate::info::Info<super::Local>,
|
info: &mut crate::info::Info<super::Local>,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
Ok(Box::new(program::run::r#if::If {
|
Ok(Box::new(program::run::r#if::If {
|
||||||
pos_in_src: self.pos_in_src,
|
pos_in_src: self.pos_in_src,
|
||||||
condition: self.condition.compile(info, comp)?,
|
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::run::SourceRange;
|
||||||
|
use crate::program::{self, run::CheckError};
|
||||||
|
|
||||||
use super::{CompInfo, MersStatement};
|
use super::{CompInfo, MersStatement};
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ impl MersStatement for InitTo {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut crate::info::Info<super::Local>,
|
info: &mut crate::info::Info<super::Local>,
|
||||||
mut comp: CompInfo,
|
mut comp: CompInfo,
|
||||||
) -> Result<Box<dyn crate::program::run::MersStatement>, String> {
|
) -> Result<Box<dyn crate::program::run::MersStatement>, CheckError> {
|
||||||
comp.is_init = true;
|
comp.is_init = true;
|
||||||
let target = self.target.compile(info, comp)?;
|
let target = self.target.compile(info, comp)?;
|
||||||
comp.is_init = false;
|
comp.is_init = false;
|
||||||
|
@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt::Debug};
|
|||||||
|
|
||||||
use crate::info;
|
use crate::info;
|
||||||
|
|
||||||
use super::run::SourceRange;
|
use super::run::{CheckError, SourceRange};
|
||||||
|
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
pub mod assign_to;
|
pub mod assign_to;
|
||||||
@ -15,6 +15,8 @@ pub mod function;
|
|||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
pub mod r#if;
|
pub mod r#if;
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
|
pub mod include_mers;
|
||||||
|
#[cfg(feature = "parse")]
|
||||||
pub mod init_to;
|
pub mod init_to;
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
pub mod tuple;
|
pub mod tuple;
|
||||||
@ -29,12 +31,12 @@ pub trait MersStatement: Debug + Send + Sync {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut Info,
|
info: &mut Info,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn super::run::MersStatement>, String>;
|
) -> Result<Box<dyn super::run::MersStatement>, CheckError>;
|
||||||
fn compile(
|
fn compile(
|
||||||
&self,
|
&self,
|
||||||
info: &mut Info,
|
info: &mut Info,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn super::run::MersStatement>, String> {
|
) -> Result<Box<dyn super::run::MersStatement>, CheckError> {
|
||||||
if self.has_scope() {
|
if self.has_scope() {
|
||||||
info.create_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> {
|
fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> {
|
||||||
self.vars.get_mut(id)
|
self.vars.get_mut(id)
|
||||||
}
|
}
|
||||||
|
fn duplicate(&self) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
info,
|
info,
|
||||||
program::{self, run::SourceRange},
|
program::{
|
||||||
|
self,
|
||||||
|
run::{CheckError, SourceRange},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CompInfo, MersStatement};
|
use super::{CompInfo, MersStatement};
|
||||||
@ -18,7 +21,7 @@ impl MersStatement for Tuple {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut info::Info<super::Local>,
|
info: &mut info::Info<super::Local>,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
Ok(Box::new(program::run::tuple::Tuple {
|
Ok(Box::new(program::run::tuple::Tuple {
|
||||||
pos_in_src: self.pos_in_src,
|
pos_in_src: self.pos_in_src,
|
||||||
elems: self
|
elems: self
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::program::run::SourceRange;
|
use crate::program::run::{CheckError, SourceRange};
|
||||||
use crate::{data::Data, program};
|
use crate::{data::Data, program};
|
||||||
|
|
||||||
use super::{CompInfo, MersStatement};
|
use super::{CompInfo, MersStatement};
|
||||||
@ -17,7 +17,7 @@ impl MersStatement for Value {
|
|||||||
&self,
|
&self,
|
||||||
_info: &mut crate::info::Info<super::Local>,
|
_info: &mut crate::info::Info<super::Local>,
|
||||||
_comp: CompInfo,
|
_comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
Ok(Box::new(program::run::value::Value {
|
Ok(Box::new(program::run::value::Value {
|
||||||
pos_in_src: self.pos_in_src,
|
pos_in_src: self.pos_in_src,
|
||||||
val: self.data.clone(),
|
val: self.data.clone(),
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
info::Local,
|
info::Local,
|
||||||
program::{self, run::SourceRange},
|
program::{
|
||||||
|
self,
|
||||||
|
run::{CheckError, SourceRange},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CompInfo, MersStatement};
|
use super::{CompInfo, MersStatement};
|
||||||
@ -20,7 +23,7 @@ impl MersStatement for Variable {
|
|||||||
&self,
|
&self,
|
||||||
info: &mut crate::info::Info<super::Local>,
|
info: &mut crate::info::Info<super::Local>,
|
||||||
comp: CompInfo,
|
comp: CompInfo,
|
||||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||||
if comp.is_init {
|
if comp.is_init {
|
||||||
info.init_var(
|
info.init_var(
|
||||||
self.var.clone(),
|
self.var.clone(),
|
||||||
@ -37,7 +40,9 @@ impl MersStatement for Variable {
|
|||||||
var: if let Some(v) = info.get_var(&self.var) {
|
var: if let Some(v) = info.get_var(&self.var) {
|
||||||
*v
|
*v
|
||||||
} else {
|
} 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,
|
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 {
|
impl info::Local for CheckLocal {
|
||||||
type VariableIdentifier = usize;
|
type VariableIdentifier = usize;
|
||||||
@ -290,4 +299,7 @@ impl info::Local for CheckLocal {
|
|||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn duplicate(&self) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user