mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 05:43:53 +01:00
sorted mers_lib/src/program/configs/ and added cargo features
This commit is contained in:
parent
b81dac682e
commit
07745488b3
@ -6,5 +6,5 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
mers_lib = { path = "../mers_lib" }
|
||||
mers_lib = { path = "../mers_lib", features = ["parse"] }
|
||||
clap = { version = "4.3.19", features = ["derive"] }
|
||||
|
8
mers/src/cfg_globals.rs
Normal file
8
mers/src/cfg_globals.rs
Normal 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)))
|
||||
}
|
@ -2,8 +2,11 @@ use clap::{Parser, Subcommand, ValueEnum};
|
||||
use mers_lib::prelude_compile::*;
|
||||
use std::{fmt::Display, fs, path::PathBuf};
|
||||
|
||||
mod cfg_globals;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
/// controls availability of features when compiling/running
|
||||
#[arg(long, value_enum, default_value_t = Configs::Std)]
|
||||
config: Configs,
|
||||
#[command(subcommand)]
|
||||
@ -11,18 +14,22 @@ struct Args {
|
||||
}
|
||||
#[derive(Subcommand)]
|
||||
enum Command {
|
||||
/// runs the file
|
||||
Run { file: PathBuf },
|
||||
/// runs cli argument
|
||||
Exec { source: String },
|
||||
}
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||
enum Configs {
|
||||
None,
|
||||
Base,
|
||||
Std,
|
||||
}
|
||||
impl Display for Configs {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::None => write!(f, "none"),
|
||||
Self::Base => write!(f, "base"),
|
||||
Self::Std => write!(f, "std"),
|
||||
}
|
||||
}
|
||||
@ -30,10 +37,11 @@ impl Display for Configs {
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let config = match args.config {
|
||||
let config = cfg_globals::add_general(match args.config {
|
||||
Configs::None => Config::new(),
|
||||
Configs::Base => Config::new().bundle_base(),
|
||||
Configs::Std => Config::new().bundle_std(),
|
||||
};
|
||||
});
|
||||
let (mut info1, mut info2) = config.infos();
|
||||
match args.command {
|
||||
Command::Run { file } => {
|
||||
|
@ -9,7 +9,19 @@ list := (
|
||||
8,
|
||||
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
|
||||
"---".println
|
||||
list := iter.as_list
|
||||
list.println
|
||||
list.sum.println
|
||||
list.enumerate.as_list.println
|
||||
|
||||
"mers cli: ".print
|
||||
mers_cli.println
|
||||
|
@ -2,3 +2,9 @@
|
||||
name = "mers_lib"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
[features]
|
||||
default = []
|
||||
parse = ["run"]
|
||||
run = []
|
||||
|
@ -1,8 +1,13 @@
|
||||
/// data and types in mers
|
||||
pub mod data;
|
||||
/// shared code handling scopes to guarantee that compiler and runtime scopes match
|
||||
pub mod info;
|
||||
/// parser implementation.
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod parsing;
|
||||
pub mod program;
|
||||
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod prelude_compile {
|
||||
pub use crate::parsing::parse;
|
||||
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::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;
|
||||
}
|
||||
|
@ -7,8 +7,11 @@ use crate::{
|
||||
};
|
||||
|
||||
mod with_command_running;
|
||||
mod with_get;
|
||||
mod with_iters;
|
||||
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()
|
||||
/// bundle_* for bundles (combines multiple groups or even bundles)
|
||||
@ -27,14 +30,6 @@ pub struct Config {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
globals: 0,
|
||||
info_parsed: Default::default(),
|
||||
info_run: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// standard utilitis used in many programs
|
||||
/// `bundle_base()`
|
||||
/// `with_list()`
|
||||
@ -51,134 +46,12 @@ impl Config {
|
||||
self.with_iters().with_get().with_math().with_prints()
|
||||
}
|
||||
|
||||
/// `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()
|
||||
}),
|
||||
}),
|
||||
)
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
globals: 0,
|
||||
info_parsed: Default::default(),
|
||||
info_run: Default::default(),
|
||||
}
|
||||
/// `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 {
|
||||
@ -187,7 +60,7 @@ impl Config {
|
||||
self.globals += 1;
|
||||
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
|
||||
self
|
||||
}
|
||||
|
41
mers_lib/src/program/configs/with_get.rs
Normal file
41
mers_lib/src/program/configs/with_get.rs
Normal 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")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
@ -10,6 +10,10 @@ use super::Config;
|
||||
impl Config {
|
||||
/// Adds functions to deal with iterables
|
||||
/// `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 {
|
||||
self.add_var(
|
||||
"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),
|
||||
Filter(data::function::Function),
|
||||
FilterMap(data::function::Function),
|
||||
Enumerate,
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Iter(Iters, Data);
|
||||
@ -152,6 +165,12 @@ impl MersData for Iter {
|
||||
.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!(),
|
||||
})
|
||||
}
|
||||
|
45
mers_lib/src/program/configs/with_math.rs
Normal file
45
mers_lib/src/program/configs/with_math.rs
Normal 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")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
73
mers_lib/src/program/configs/with_prints.rs
Normal file
73
mers_lib/src/program/configs/with_prints.rs
Normal 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()
|
||||
}),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
/// generates `Info`s required to compile and then run a program
|
||||
pub mod configs;
|
||||
/// used to represent a parsed program
|
||||
pub mod parsed;
|
||||
/// used to represent an executable program
|
||||
pub mod run;
|
||||
|
@ -2,16 +2,27 @@ use std::{collections::HashMap, fmt::Debug};
|
||||
|
||||
use crate::info;
|
||||
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod assign_to;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod block;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod chain;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod function;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod r#if;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod init_to;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod r#loop;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod switch;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod tuple;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod value;
|
||||
#[cfg(feature = "parse")]
|
||||
pub mod variable;
|
||||
|
||||
pub trait MersStatement: Debug {
|
||||
|
@ -5,15 +5,25 @@ use crate::{
|
||||
info,
|
||||
};
|
||||
|
||||
#[cfg(feature = "run")]
|
||||
pub mod assign_to;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod block;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod chain;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod function;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod r#if;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod r#loop;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod switch;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod tuple;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod value;
|
||||
#[cfg(feature = "run")]
|
||||
pub mod variable;
|
||||
|
||||
pub trait MersStatement: std::fmt::Debug {
|
||||
|
Loading…
Reference in New Issue
Block a user