sorted mers_lib/src/program/configs/ and added cargo features

This commit is contained in:
Mark 2023-07-28 15:20:02 +02:00
parent b81dac682e
commit 07745488b3
14 changed files with 267 additions and 140 deletions

View File

@ -6,5 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
mers_lib = { path = "../mers_lib" } mers_lib = { path = "../mers_lib", features = ["parse"] }
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }

8
mers/src/cfg_globals.rs Normal file
View File

@ -0,0 +1,8 @@
use mers_lib::{
data::{self, Data},
prelude_extend_config::*,
};
pub fn add_general(cfg: Config) -> Config {
cfg.add_var("mers_cli".to_string(), Data::new(data::bool::Bool(true)))
}

View File

@ -2,8 +2,11 @@ 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};
mod cfg_globals;
#[derive(Parser)] #[derive(Parser)]
struct Args { struct Args {
/// controls availability of features when compiling/running
#[arg(long, value_enum, default_value_t = Configs::Std)] #[arg(long, value_enum, default_value_t = Configs::Std)]
config: Configs, config: Configs,
#[command(subcommand)] #[command(subcommand)]
@ -11,18 +14,22 @@ struct Args {
} }
#[derive(Subcommand)] #[derive(Subcommand)]
enum Command { enum Command {
/// runs the file
Run { file: PathBuf }, Run { file: PathBuf },
/// runs cli argument
Exec { source: String }, Exec { source: String },
} }
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum Configs { enum Configs {
None, None,
Base,
Std, Std,
} }
impl Display for Configs { impl Display for Configs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::None => write!(f, "none"), Self::None => write!(f, "none"),
Self::Base => write!(f, "base"),
Self::Std => write!(f, "std"), Self::Std => write!(f, "std"),
} }
} }
@ -30,10 +37,11 @@ impl Display for Configs {
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
let config = match args.config { let config = cfg_globals::add_general(match args.config {
Configs::None => Config::new(), Configs::None => Config::new(),
Configs::Base => Config::new().bundle_base(),
Configs::Std => Config::new().bundle_std(), Configs::Std => Config::new().bundle_std(),
}; });
let (mut info1, mut info2) = config.infos(); let (mut info1, mut info2) = config.infos();
match args.command { match args.command {
Command::Run { file } => { Command::Run { file } => {

View File

@ -9,7 +9,19 @@ list := (
8, 8,
9, 9,
); );
total := 0
(list item -> &total = (total, item).sum).iter
"total: ".print
total.println
"sum: ".print
list.sum.println
iter := (list item -> { item.println 12 }).map iter := (list item -> { item.println 12 }).map
"---".println "---".println
list := iter.as_list list := iter.as_list
list.println list.println
list.sum.println
list.enumerate.as_list.println
"mers cli: ".print
mers_cli.println

View File

@ -2,3 +2,9 @@
name = "mers_lib" name = "mers_lib"
version = "0.3.0" version = "0.3.0"
edition = "2021" edition = "2021"
[features]
default = []
parse = ["run"]
run = []

View File

@ -1,8 +1,13 @@
/// data and types in mers
pub mod data; pub mod data;
/// shared code handling scopes to guarantee that compiler and runtime scopes match
pub mod info; pub mod info;
/// parser implementation.
#[cfg(feature = "parse")]
pub mod parsing; pub mod parsing;
pub mod program; pub mod program;
#[cfg(feature = "parse")]
pub mod prelude_compile { pub mod prelude_compile {
pub use crate::parsing::parse; pub use crate::parsing::parse;
pub use crate::parsing::Source; pub use crate::parsing::Source;
@ -10,3 +15,16 @@ pub mod prelude_compile {
pub use crate::program::parsed::MersStatement as ParsedMersStatement; pub use crate::program::parsed::MersStatement as ParsedMersStatement;
pub use crate::program::run::MersStatement as RunMersStatement; pub use crate::program::run::MersStatement as RunMersStatement;
} }
/// can be used to extend the mers config.
/// with this, you can add values (usually functions),
/// or add your own types to the language:
///
/// fn add_thing(cfg: Config) -> Config {
/// /// use the methods on Config to add things (see the Config source code for examples)
/// }
///
/// then use the Config when compiling and running your code, and your customizations will be available.
pub mod prelude_extend_config {
pub use crate::program::configs::Config;
}

View File

@ -7,8 +7,11 @@ use crate::{
}; };
mod with_command_running; mod with_command_running;
mod with_get;
mod with_iters; mod with_iters;
mod with_list; mod with_list;
mod with_math;
mod with_prints;
/// Usage: create an empty Config using Config::new(), use the methods to customize it, then get the Infos using Config::infos() /// Usage: create an empty Config using Config::new(), use the methods to customize it, then get the Infos using Config::infos()
/// bundle_* for bundles (combines multiple groups or even bundles) /// bundle_* for bundles (combines multiple groups or even bundles)
@ -27,14 +30,6 @@ pub struct Config {
} }
impl Config { impl Config {
pub fn new() -> Self {
Self {
globals: 0,
info_parsed: Default::default(),
info_run: Default::default(),
}
}
/// standard utilitis used in many programs /// standard utilitis used in many programs
/// `bundle_base()` /// `bundle_base()`
/// `with_list()` /// `with_list()`
@ -51,134 +46,12 @@ impl Config {
self.with_iters().with_get().with_math().with_prints() self.with_iters().with_get().with_math().with_prints()
} }
/// `println: fn` prints to stdout and adds a newline to the end pub fn new() -> Self {
/// `print: fn` prints to stdout Self {
/// `eprintln: fn` prints to stderr and adds a newline to the end globals: 0,
/// `eprint: fn` prints to stderr info_parsed: Default::default(),
/// `debug: fn` debug-prints any value info_run: Default::default(),
pub fn with_prints(self) -> Self { }
self.add_var(
"debug".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
eprintln!("{:#?}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"eprint".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
eprint!("{}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"eprintln".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
eprintln!("{}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"print".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
print!("{}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"println".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
println!("{}", a.get());
Data::empty_tuple()
}),
}),
)
}
/// `sum: fn` returns the sum of all the numbers in the tuple
pub fn with_math(self) -> Self {
self.add_var(
"sum".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
let mut sumi = 0;
let mut sumf = 0.0;
let mut usef = false;
for val in &tuple.0 {
if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
sumi += i.0;
} else if let Some(i) =
val.get().as_any().downcast_ref::<data::float::Float>()
{
sumf += i.0;
usef = true;
}
}
if usef {
Data::new(data::float::Float(sumi as f64 + sumf))
} else {
Data::new(data::int::Int(sumi))
}
} else {
unreachable!("sum called on non-tuple")
}
}),
}),
)
}
/// `get: fn` is used to retrieve elements from collections
pub fn with_get(self) -> Self {
self.add_var(
"get".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
if let (Some(v), Some(i)) = (tuple.get(0), tuple.get(1)) {
if let Some(i) = i.get().as_any().downcast_ref::<data::int::Int>() {
if let Ok(i) = i.0.try_into() {
if let Some(v) = v.get().get(i) {
Data::one_tuple(v)
} else {
Data::empty_tuple()
}
} else {
Data::empty_tuple()
}
} else {
unreachable!("get called with non-int index")
}
} else {
unreachable!("get called on tuple with len < 2")
}
} else {
unreachable!("get called on non-tuple, arg must be (_, index)")
}
}),
}),
)
} }
pub fn add_var(mut self, name: String, val: Data) -> Self { pub fn add_var(mut self, name: String, val: Data) -> Self {
@ -187,7 +60,7 @@ impl Config {
self.globals += 1; self.globals += 1;
self self
} }
pub fn add_type(mut self, name: String, t: Type) -> Self { pub fn add_type(self, _name: String, _t: Type) -> Self {
// TODO! needed for type syntax in the parser, everything else probably(?) works already // TODO! needed for type syntax in the parser, everything else probably(?) works already
self self
} }

View File

@ -0,0 +1,41 @@
use std::sync::Arc;
use crate::{
data::{self, Data},
program,
};
use super::Config;
impl Config {
/// `get: fn` is used to retrieve elements from collections
pub fn with_get(self) -> Self {
self.add_var(
"get".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
let a = a.get();
if let (Some(v), Some(i)) = (a.get(0), a.get(1)) {
if let Some(i) = i.get().as_any().downcast_ref::<data::int::Int>() {
if let Ok(i) = i.0.try_into() {
if let Some(v) = v.get().get(i) {
Data::one_tuple(v)
} else {
Data::empty_tuple()
}
} else {
Data::empty_tuple()
}
} else {
unreachable!("get called with non-int index")
}
} else {
unreachable!("get called with less than 2 args")
}
}),
}),
)
}
}

View File

@ -10,6 +10,10 @@ use super::Config;
impl Config { impl Config {
/// Adds functions to deal with iterables /// Adds functions to deal with iterables
/// `iter: fn` executes a function once for each element of the iterable /// `iter: fn` executes a function once for each element of the iterable
/// `map: fn` maps each value in the iterable to a new one by applying a transformation function
/// `filter: fn` filters the iterable by removing all elements where the filter function doesn't return true
/// `filter_map: fn` combines filter and map via matching
/// `enumerate: fn` transforms an iterator over T into one over (Int, T), where Int is the index of the element
pub fn with_iters(self) -> Self { pub fn with_iters(self) -> Self {
self.add_var( self.add_var(
"iter".to_string(), "iter".to_string(),
@ -113,6 +117,14 @@ impl Config {
}), }),
}), }),
) )
.add_var(
"enumerate".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| Data::new(Iter(Iters::Enumerate, a.clone()))),
}),
)
} }
} }
@ -121,6 +133,7 @@ pub enum Iters {
Map(data::function::Function), Map(data::function::Function),
Filter(data::function::Function), Filter(data::function::Function),
FilterMap(data::function::Function), FilterMap(data::function::Function),
Enumerate,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Iter(Iters, Data); pub struct Iter(Iters, Data);
@ -152,6 +165,12 @@ impl MersData for Iter {
.filter_map(move |v| f.run(v).get().matches()), .filter_map(move |v| f.run(v).get().matches()),
) )
} }
Iters::Enumerate => Box::new(self.1.get().iterable()?.enumerate().map(|(i, v)| {
Data::new(data::tuple::Tuple(vec![
Data::new(data::int::Int(i as _)),
v,
]))
})),
_ => todo!(), _ => todo!(),
}) })
} }

View File

@ -0,0 +1,45 @@
use std::sync::Arc;
use crate::{
data::{self, Data},
program,
};
use super::Config;
impl Config {
/// `sum: fn` returns the sum of all the numbers in the tuple
pub fn with_math(self) -> Self {
self.add_var(
"sum".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
if let Some(i) = a.get().iterable() {
let mut sumi = 0;
let mut sumf = 0.0;
let mut usef = false;
for val in i {
if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
sumi += i.0;
} else if let Some(i) =
val.get().as_any().downcast_ref::<data::float::Float>()
{
sumf += i.0;
usef = true;
}
}
if usef {
Data::new(data::float::Float(sumi as f64 + sumf))
} else {
Data::new(data::int::Int(sumi))
}
} else {
unreachable!("sum called on non-tuple")
}
}),
}),
)
}
}

View File

@ -0,0 +1,73 @@
use std::sync::Arc;
use crate::{
data::{self, Data},
program,
};
use super::Config;
impl Config {
/// `println: fn` prints to stdout and adds a newline to the end
/// `print: fn` prints to stdout
/// `eprintln: fn` prints to stderr and adds a newline to the end
/// `eprint: fn` prints to stderr
/// `debug: fn` debug-prints any value
pub fn with_prints(self) -> Self {
self.add_var(
"debug".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
eprintln!("{:#?}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"eprint".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
eprint!("{}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"eprintln".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
eprintln!("{}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"print".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
print!("{}", a.get());
Data::empty_tuple()
}),
}),
)
.add_var(
"println".to_string(),
Data::new(data::function::Function {
info: program::run::Info::neverused(),
out: Arc::new(|_a| todo!()),
run: Arc::new(|a, _i| {
println!("{}", a.get());
Data::empty_tuple()
}),
}),
)
}
}

View File

@ -1,3 +1,6 @@
/// generates `Info`s required to compile and then run a program
pub mod configs; pub mod configs;
/// used to represent a parsed program
pub mod parsed; pub mod parsed;
/// used to represent an executable program
pub mod run; pub mod run;

View File

@ -2,16 +2,27 @@ use std::{collections::HashMap, fmt::Debug};
use crate::info; use crate::info;
#[cfg(feature = "parse")]
pub mod assign_to; pub mod assign_to;
#[cfg(feature = "parse")]
pub mod block; pub mod block;
#[cfg(feature = "parse")]
pub mod chain; pub mod chain;
#[cfg(feature = "parse")]
pub mod function; pub mod function;
#[cfg(feature = "parse")]
pub mod r#if; pub mod r#if;
#[cfg(feature = "parse")]
pub mod init_to; pub mod init_to;
#[cfg(feature = "parse")]
pub mod r#loop; pub mod r#loop;
#[cfg(feature = "parse")]
pub mod switch; pub mod switch;
#[cfg(feature = "parse")]
pub mod tuple; pub mod tuple;
#[cfg(feature = "parse")]
pub mod value; pub mod value;
#[cfg(feature = "parse")]
pub mod variable; pub mod variable;
pub trait MersStatement: Debug { pub trait MersStatement: Debug {

View File

@ -5,15 +5,25 @@ use crate::{
info, info,
}; };
#[cfg(feature = "run")]
pub mod assign_to; pub mod assign_to;
#[cfg(feature = "run")]
pub mod block; pub mod block;
#[cfg(feature = "run")]
pub mod chain; pub mod chain;
#[cfg(feature = "run")]
pub mod function; pub mod function;
#[cfg(feature = "run")]
pub mod r#if; pub mod r#if;
#[cfg(feature = "run")]
pub mod r#loop; pub mod r#loop;
#[cfg(feature = "run")]
pub mod switch; pub mod switch;
#[cfg(feature = "run")]
pub mod tuple; pub mod tuple;
#[cfg(feature = "run")]
pub mod value; pub mod value;
#[cfg(feature = "run")]
pub mod variable; pub mod variable;
pub trait MersStatement: std::fmt::Debug { pub trait MersStatement: std::fmt::Debug {