mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
changed regex builtin and added binaries to git repo
This commit is contained in:
parent
f0314817a2
commit
b6d01c7c25
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,5 +2,4 @@
|
|||||||
/mers/Cargo.lock
|
/mers/Cargo.lock
|
||||||
/mers_libs/*/target
|
/mers_libs/*/target
|
||||||
/mers_libs/*/Cargo.lock
|
/mers_libs/*/Cargo.lock
|
||||||
/build_scripts/mers
|
|
||||||
/build_scripts/nu_plugin_mers
|
/build_scripts/nu_plugin_mers
|
||||||
|
5
build_scripts/build_cross.sh
Executable file
5
build_scripts/build_cross.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
./build_musl.sh
|
||||||
|
cd ../mers
|
||||||
|
cargo build --release --target x86_64-pc-windows-gnu
|
||||||
|
cp target/x86_64-pc-windows-gnu/release/mers.exe ../build_scripts
|
BIN
build_scripts/mers
Executable file
BIN
build_scripts/mers
Executable file
Binary file not shown.
BIN
build_scripts/mers.exe
Executable file
BIN
build_scripts/mers.exe
Executable file
Binary file not shown.
@ -157,4 +157,19 @@ replaces occurences of arg1 in arg0 with arg2
|
|||||||
|
|
||||||
### regex
|
### regex
|
||||||
|
|
||||||
returns a list of matches of the arg0 regex that were found in the string arg1
|
given a regex (in string form), this function returns either `Err(string)` or a function which, when called with another string, returns a list of matches found in that string:
|
||||||
|
|
||||||
|
lines_regex := regex(".*").assume_no_enum()
|
||||||
|
fn lines(s string) {
|
||||||
|
lines_regex.run(s)
|
||||||
|
}
|
||||||
|
debug("a string\nwith multiple\nlines!".lines())
|
||||||
|
|
||||||
|
This is done because compiling regex is somewhat slow, so if multiple strings have to be searched by the regex,
|
||||||
|
it would be inefficient to recompile the regex every time. (btw: credit goes to the Regex crate, which is used to implement this)
|
||||||
|
|
||||||
|
### split
|
||||||
|
|
||||||
|
given two strings, splits the first one at the pattern specified by the second one:
|
||||||
|
|
||||||
|
word_count := "a string containing five words".split(" ").len()
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
input := fs_read("/tmp/pin.txt").assume_no_enum().bytes_to_string().assume_no_enum()
|
|
||||||
|
|
||||||
fn prio(s string) {
|
|
||||||
switch! "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".index_of(s) {
|
|
||||||
[] [] 0
|
|
||||||
int n n + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sum := 0
|
|
||||||
for line input.regex(".*").assume_no_enum() {
|
|
||||||
left := line.substring(0, line.len() / 2)
|
|
||||||
right := line.substring(line.len() / 2)
|
|
||||||
for ch right.regex(".").assume_no_enum() {
|
|
||||||
if left.contains(ch) {
|
|
||||||
&sum = sum + prio(ch)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[]
|
|
||||||
}
|
|
||||||
|
|
||||||
println("sum: " + sum.to_string())
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
input := fs_read("/tmp/pin.txt").assume_no_enum().bytes_to_string().assume_no_enum()
|
|
||||||
|
|
||||||
fn prio(s string) {
|
|
||||||
switch! "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".index_of(s) {
|
|
||||||
[] [] 0
|
|
||||||
int n n + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sum := 0
|
|
||||||
for group input.regex(".*\\n.*\\n.*\\n?").assume_no_enum() {
|
|
||||||
rucksacks := group.regex(".*").assume_no_enum()
|
|
||||||
a := rucksacks.get(0).assume1()
|
|
||||||
b := rucksacks.get(1).assume1()
|
|
||||||
c := rucksacks.get(2).assume1()
|
|
||||||
println(a)
|
|
||||||
println(b)
|
|
||||||
println(c)
|
|
||||||
println("---")
|
|
||||||
badge_type := for ch "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".regex(".").assume_no_enum() {
|
|
||||||
if a.contains(ch) && b.contains(ch) && c.contains(ch) {
|
|
||||||
ch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch! badge_type {
|
|
||||||
string s &sum = sum + prio(s)
|
|
||||||
[] [] []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println("sum: " + sum.to_string())
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
|||||||
input := fs_read("/tmp/pin.txt").assume_no_enum().bytes_to_string().assume_no_enum()
|
|
||||||
|
|
||||||
fn get_pair(s string) {
|
|
||||||
list := s.regex("[^-]+").assume_no_enum()
|
|
||||||
[
|
|
||||||
list.get(0).assume1("A").parse_int().assume1("a")
|
|
||||||
list.get(1).assume1("B").parse_int().assume1("b")
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
for pair input.regex(".+").assume_no_enum() {
|
|
||||||
s := pair.regex("[^,]*").assume_no_enum()
|
|
||||||
s1 := get_pair(s.get(0).assume1("bb"))
|
|
||||||
s2 := get_pair(s.get(1).assume1("aa"))
|
|
||||||
if { s1.0 <= s2.0 && s1.1 >= s2.1 } || { s1.0 >= s2.0 && s1.1 <= s2.1 } {
|
|
||||||
&count = count + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println("count: " + count.to_string())
|
|
@ -1,29 +0,0 @@
|
|||||||
input := fs_read("/tmp/pin.txt").assume_no_enum().bytes_to_string().assume_no_enum()
|
|
||||||
|
|
||||||
fn get_pair(s string) {
|
|
||||||
list := s.regex("[^-]+").assume_no_enum()
|
|
||||||
[
|
|
||||||
list.get(0).assume1().parse_int().assume1()
|
|
||||||
list.get(1).assume1().parse_int().assume1()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
for pair input.regex(".+").assume_no_enum() {
|
|
||||||
s := pair.regex("[^,]*").assume_no_enum()
|
|
||||||
s1 := get_pair(s.get(0).assume1())
|
|
||||||
s2 := get_pair(s.get(1).assume1())
|
|
||||||
if {
|
|
||||||
s1.0 <= s2.0 && s2.0 <= s1.1
|
|
||||||
} || {
|
|
||||||
s1.0 <= s2.1 && s2.1 <= s1.1
|
|
||||||
} || {
|
|
||||||
s2.0 <= s1.0 && s1.0 <= s2.1
|
|
||||||
} || {
|
|
||||||
s2.0 <= s1.1 && s1.1 <= s2.1
|
|
||||||
} {
|
|
||||||
&count = count + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println("count: " + count.to_string())
|
|
@ -16,7 +16,7 @@ fn rnd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
words := rnd()
|
words := rnd()
|
||||||
for word text.regex("\\S+").assume_no_enum()
|
for word regex("\\S+").assume_no_enum().run(text)
|
||||||
if words > 0 {
|
if words > 0 {
|
||||||
print(word + " ")
|
print(word + " ")
|
||||||
&words = words - 1
|
&words = words - 1
|
||||||
|
2
mers/Cargo.lock
generated
2
mers/Cargo.lock
generated
@ -647,7 +647,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mers"
|
name = "mers"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"colorize",
|
"colorize",
|
||||||
"edit",
|
"edit",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mers"
|
name = "mers"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
edition = "2021"
|
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
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{io::Write, path::PathBuf, sync::Arc, time::Duration};
|
use std::{io::Write, path::PathBuf, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
code_runnable::RStatement,
|
code_runnable::{RFunction, RFunctionType, RStatement},
|
||||||
global_info::{GSInfo, GlobalScriptInfo},
|
global_info::{GSInfo, GlobalScriptInfo},
|
||||||
val_data::{thread::VDataThreadEnum, VData, VDataEnum},
|
val_data::{thread::VDataThreadEnum, VData, VDataEnum},
|
||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
@ -82,6 +82,7 @@ pub enum BuiltinFunction {
|
|||||||
Substring,
|
Substring,
|
||||||
Replace,
|
Replace,
|
||||||
Regex,
|
Regex,
|
||||||
|
Split,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltinFunction {
|
impl BuiltinFunction {
|
||||||
@ -145,6 +146,7 @@ impl BuiltinFunction {
|
|||||||
"substring" => Self::Substring,
|
"substring" => Self::Substring,
|
||||||
"replace" => Self::Replace,
|
"replace" => Self::Replace,
|
||||||
"regex" => Self::Regex,
|
"regex" => Self::Regex,
|
||||||
|
"split" => Self::Split,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -472,7 +474,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// two strings
|
// two strings
|
||||||
Self::Contains | Self::StartsWith | Self::EndsWith | Self::Regex => {
|
Self::Contains | Self::StartsWith | Self::EndsWith => {
|
||||||
input.len() == 2
|
input.len() == 2
|
||||||
&& input
|
&& input
|
||||||
.iter()
|
.iter()
|
||||||
@ -503,6 +505,15 @@ impl BuiltinFunction {
|
|||||||
Self::Trim => {
|
Self::Trim => {
|
||||||
input.len() == 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty()
|
input.len() == 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty()
|
||||||
}
|
}
|
||||||
|
Self::Regex => {
|
||||||
|
input.len() == 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty()
|
||||||
|
}
|
||||||
|
Self::Split => {
|
||||||
|
input.len() == 2
|
||||||
|
&& input
|
||||||
|
.iter()
|
||||||
|
.all(|v| v.fits_in(&VSingleType::String.to(), info).is_empty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// for invalid inputs, may panic
|
/// for invalid inputs, may panic
|
||||||
@ -781,12 +792,20 @@ impl BuiltinFunction {
|
|||||||
Self::Replace => VSingleType::String.to(),
|
Self::Replace => VSingleType::String.to(),
|
||||||
Self::Regex => VType {
|
Self::Regex => VType {
|
||||||
types: vec![
|
types: vec![
|
||||||
// [string ...]
|
// fn((string [string ...]))
|
||||||
VSingleType::List(VSingleType::String.to()),
|
VSingleType::Function(vec![(
|
||||||
|
vec![VSingleType::String.to()],
|
||||||
|
VSingleType::List(VSingleType::String.to()).to(),
|
||||||
|
)]),
|
||||||
// Err(string)
|
// Err(string)
|
||||||
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
|
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
Self::Split => VSingleType::List(
|
||||||
|
// [string ...]
|
||||||
|
VSingleType::String.to(),
|
||||||
|
)
|
||||||
|
.to(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn run(&self, args: &Vec<RStatement>, info: &GSInfo) -> VData {
|
pub fn run(&self, args: &Vec<RStatement>, info: &GSInfo) -> VData {
|
||||||
@ -964,39 +983,22 @@ impl BuiltinFunction {
|
|||||||
}),
|
}),
|
||||||
BuiltinFunction::Run => args[0].run(info).operate_on_data_immut(|v| {
|
BuiltinFunction::Run => args[0].run(info).operate_on_data_immut(|v| {
|
||||||
if let VDataEnum::Function(f) = v {
|
if let VDataEnum::Function(f) = v {
|
||||||
if f.inputs.len() != args.len() - 1 {
|
f.run(info, args.iter().skip(1).map(|v| v.run(info)).collect())
|
||||||
unreachable!("wrong input count")
|
|
||||||
}
|
|
||||||
for (i, var) in f.inputs.iter().enumerate() {
|
|
||||||
let val = args[i + 1].run(info).clone_data();
|
|
||||||
var.lock().unwrap().0 = val;
|
|
||||||
}
|
|
||||||
f.run(info)
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
BuiltinFunction::Thread => args[0].run(info).operate_on_data_immut(|v| {
|
BuiltinFunction::Thread => args[0].run(info).operate_on_data_immut(|v| {
|
||||||
if let VDataEnum::Function(f) = v {
|
if let VDataEnum::Function(f) = v {
|
||||||
if f.inputs.len() != args.len() - 1 {
|
let args: Vec<_> = args.into_iter().skip(1).map(|v| v.run(info)).collect();
|
||||||
unreachable!("wrong input count")
|
|
||||||
}
|
|
||||||
let mut run_input_types = vec![];
|
|
||||||
for (i, var) in f.inputs.iter().enumerate() {
|
|
||||||
let val = args[i + 1].run(info).clone_data();
|
|
||||||
run_input_types.push(val.out_single());
|
|
||||||
var.lock().unwrap().0 = val;
|
|
||||||
}
|
|
||||||
let out_type = f
|
let out_type = f
|
||||||
.out_by_map(
|
.out_by_map(&args.iter().map(|v| v.out()).collect(), &info)
|
||||||
&run_input_types.iter().map(|v| v.clone().into()).collect(),
|
|
||||||
&info,
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let info = Arc::clone(info);
|
let info = Arc::clone(info);
|
||||||
let f = Arc::clone(f);
|
let f = Arc::clone(f);
|
||||||
VDataEnum::Thread(
|
VDataEnum::Thread(
|
||||||
VDataThreadEnum::Running(std::thread::spawn(move || f.run(&info))).to(),
|
VDataThreadEnum::Running(std::thread::spawn(move || f.run(&info, args)))
|
||||||
|
.to(),
|
||||||
out_type,
|
out_type,
|
||||||
)
|
)
|
||||||
.to()
|
.to()
|
||||||
@ -1680,28 +1682,67 @@ impl BuiltinFunction {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
Self::Regex => args[0].run(info).operate_on_data_immut(|a| {
|
Self::Regex => args[0].run(info).operate_on_data_immut(|regex_string| {
|
||||||
args[1].run(info).operate_on_data_immut(|regex| {
|
if let VDataEnum::String(regex_string) = regex_string {
|
||||||
if let (VDataEnum::String(a), VDataEnum::String(regex)) = (a, regex) {
|
match regex::RegexBuilder::new(®ex_string).build() {
|
||||||
match regex::Regex::new(regex.as_str()) {
|
Ok(regex) => VDataEnum::Function(Arc::new(RFunction {
|
||||||
Ok(regex) => VDataEnum::List(
|
statement: RFunctionType::Func(Box::new(move |_info, args| {
|
||||||
|
// this is the function returned by regex().
|
||||||
|
// it takes one string as its argument
|
||||||
|
// and returns another function
|
||||||
|
args[0].operate_on_data_immut(|s| {
|
||||||
|
if let VDataEnum::String(s) = s {
|
||||||
|
// when the regex function is given a string to operate on,
|
||||||
|
// it returns all the matches.
|
||||||
|
VDataEnum::List(
|
||||||
VSingleType::String.to(),
|
VSingleType::String.to(),
|
||||||
regex
|
regex
|
||||||
.find_iter(a.as_str())
|
.find_iter(s)
|
||||||
.map(|v| VDataEnum::String(v.as_str().to_string()).to())
|
.map(|m| {
|
||||||
|
VDataEnum::String(
|
||||||
|
s[m.start()..m.end()].to_owned(),
|
||||||
|
)
|
||||||
|
.to()
|
||||||
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
|
.to()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})),
|
||||||
|
out_map: vec![],
|
||||||
|
}))
|
||||||
.to(),
|
.to(),
|
||||||
Err(e) => VDataEnum::EnumVariant(
|
Err(err) => VDataEnum::EnumVariant(
|
||||||
EV_ERR,
|
EV_ERR,
|
||||||
Box::new(VDataEnum::String(e.to_string()).to()),
|
Box::new(VDataEnum::String(err.to_string()).to()),
|
||||||
)
|
)
|
||||||
.to(),
|
.to(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
Self::Split => args[0].run(info).operate_on_data_immut(|a| {
|
||||||
|
if let VDataEnum::String(a) = a {
|
||||||
|
args[1].run(info).operate_on_data_immut(|b| {
|
||||||
|
if let VDataEnum::String(b) = b {
|
||||||
|
VDataEnum::List(
|
||||||
|
VSingleType::String.to(),
|
||||||
|
a.split(b)
|
||||||
|
.map(|v| VDataEnum::String(v.to_owned()).to())
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.to()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::{
|
||||||
|
fmt::Debug,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
builtins::BuiltinFunction,
|
builtins::BuiltinFunction,
|
||||||
@ -54,13 +57,21 @@ impl RBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct RFunction {
|
pub struct RFunction {
|
||||||
pub inputs: Vec<Arc<Mutex<(VData, VType)>>>,
|
pub statement: RFunctionType,
|
||||||
pub input_types: Vec<VType>,
|
|
||||||
pub statement: RStatement,
|
|
||||||
pub out_map: Vec<(Vec<VType>, VType)>,
|
pub out_map: Vec<(Vec<VType>, VType)>,
|
||||||
}
|
}
|
||||||
|
impl Debug for RFunction {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?}", self.out_map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub enum RFunctionType {
|
||||||
|
/// ignores all args and returns some default value
|
||||||
|
Dummy,
|
||||||
|
Statement(Vec<Arc<Mutex<(VData, VType)>>>, RStatement, Vec<VType>),
|
||||||
|
Func(Box<dyn Fn(&GSInfo, Vec<VData>) -> VData + Send + Sync>),
|
||||||
|
}
|
||||||
impl PartialEq for RFunction {
|
impl PartialEq for RFunction {
|
||||||
fn eq(&self, _other: &Self) -> bool {
|
fn eq(&self, _other: &Self) -> bool {
|
||||||
false
|
false
|
||||||
@ -70,8 +81,17 @@ impl Eq for RFunction {
|
|||||||
fn assert_receiver_is_total_eq(&self) {}
|
fn assert_receiver_is_total_eq(&self) {}
|
||||||
}
|
}
|
||||||
impl RFunction {
|
impl RFunction {
|
||||||
pub fn run(&self, info: &GSInfo) -> VData {
|
pub fn run(&self, info: &GSInfo, args: Vec<VData>) -> VData {
|
||||||
self.statement.run(info)
|
match &self.statement {
|
||||||
|
RFunctionType::Dummy => VDataEnum::Bool(false).to(),
|
||||||
|
RFunctionType::Statement(inputs, s, _) => {
|
||||||
|
for (i, input) in inputs.iter().enumerate() {
|
||||||
|
input.lock().unwrap().0.assign(args[i].clone_mut());
|
||||||
|
}
|
||||||
|
s.run(info)
|
||||||
|
}
|
||||||
|
RFunctionType::Func(f) => f(info, args),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn out_by_map(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> Option<VType> {
|
pub fn out_by_map(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> Option<VType> {
|
||||||
// NOTE: This can ONLY use self.out_map, because it's used by the VSingleType.fits_in method.
|
// NOTE: This can ONLY use self.out_map, because it's used by the VSingleType.fits_in method.
|
||||||
@ -104,23 +124,31 @@ impl RFunction {
|
|||||||
t
|
t
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn out_by_statement(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> VType {
|
pub fn out_by_statement(
|
||||||
let mut actual = Vec::with_capacity(self.inputs.len());
|
&self,
|
||||||
|
input_types: &Vec<VType>,
|
||||||
|
info: &GlobalScriptInfo,
|
||||||
|
) -> Option<VType> {
|
||||||
|
if let RFunctionType::Statement(inputs, statement, _) = &self.statement {
|
||||||
|
let mut actual = Vec::with_capacity(inputs.len());
|
||||||
// simulate these variable types
|
// simulate these variable types
|
||||||
for (fn_input, c_type) in self.inputs.iter().zip(input_types.iter()) {
|
for (fn_input, c_type) in inputs.iter().zip(input_types.iter()) {
|
||||||
actual.push(std::mem::replace(
|
actual.push(std::mem::replace(
|
||||||
&mut fn_input.lock().unwrap().1,
|
&mut fn_input.lock().unwrap().1,
|
||||||
c_type.clone(),
|
c_type.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// not get the return type if these were the actual types
|
// not get the return type if these were the actual types
|
||||||
let out = self.statement.out(info);
|
let out = statement.out(info);
|
||||||
// reset
|
// reset
|
||||||
for (fn_input, actual) in self.inputs.iter().zip(actual) {
|
for (fn_input, actual) in inputs.iter().zip(actual) {
|
||||||
fn_input.lock().unwrap().1 = actual;
|
fn_input.lock().unwrap().1 = actual;
|
||||||
}
|
}
|
||||||
// return
|
// return
|
||||||
out
|
Some(out)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,10 +229,7 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::FunctionCall(func, args) => {
|
Self::FunctionCall(func, args) => {
|
||||||
for (i, input) in func.inputs.iter().enumerate() {
|
func.run(info, args.iter().map(|s| s.run(info)).collect())
|
||||||
input.lock().unwrap().0.assign(args[i].run(info));
|
|
||||||
}
|
|
||||||
func.run(info)
|
|
||||||
}
|
}
|
||||||
Self::BuiltinFunctionCall(v, args) => v.run(args, info),
|
Self::BuiltinFunctionCall(v, args) => v.run(args, info),
|
||||||
Self::LibFunctionCall(libid, fnid, args, _) => {
|
Self::LibFunctionCall(libid, fnid, args, _) => {
|
||||||
@ -270,7 +295,7 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDataEnum::Function(f) => loop {
|
VDataEnum::Function(f) => loop {
|
||||||
if let Some(v) = f.run(info).matches() {
|
if let Some(v) = f.run(info, vec![]).matches() {
|
||||||
if let Some(v) = in_loop(v).matches() {
|
if let Some(v) = in_loop(v).matches() {
|
||||||
oval = v;
|
oval = v;
|
||||||
break;
|
break;
|
||||||
@ -430,9 +455,6 @@ impl RScript {
|
|||||||
Ok(Self { main, info })
|
Ok(Self { main, info })
|
||||||
}
|
}
|
||||||
pub fn run(&self, args: Vec<VData>) -> VData {
|
pub fn run(&self, args: Vec<VData>) -> VData {
|
||||||
for (input, arg) in self.main.inputs.iter().zip(args.into_iter()) {
|
self.main.run(&self.info, args)
|
||||||
input.lock().unwrap().0 = arg;
|
|
||||||
}
|
|
||||||
self.main.run(&self.info)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ use super::{
|
|||||||
builtins::BuiltinFunction,
|
builtins::BuiltinFunction,
|
||||||
code_macro::Macro,
|
code_macro::Macro,
|
||||||
code_parsed::{SBlock, SFunction, SStatement, SStatementEnum},
|
code_parsed::{SBlock, SFunction, SStatement, SStatementEnum},
|
||||||
code_runnable::{RBlock, RFunction, RScript, RStatement, RStatementEnum},
|
code_runnable::{RBlock, RFunction, RFunctionType, RScript, RStatement, RStatementEnum},
|
||||||
fmtgs::FormatGs,
|
fmtgs::FormatGs,
|
||||||
global_info::GSInfo,
|
global_info::GSInfo,
|
||||||
};
|
};
|
||||||
@ -235,42 +235,55 @@ fn function(
|
|||||||
}
|
}
|
||||||
let mut o = RFunction {
|
let mut o = RFunction {
|
||||||
out_map: vec![],
|
out_map: vec![],
|
||||||
inputs: input_vars,
|
statement: RFunctionType::Statement(
|
||||||
|
input_vars,
|
||||||
|
statement(&s.statement, ginfo, &mut linfo.clone())?,
|
||||||
input_types,
|
input_types,
|
||||||
statement: statement(&s.statement, ginfo, &mut linfo.clone())?,
|
),
|
||||||
};
|
};
|
||||||
o.out_map = {
|
o.out_map = {
|
||||||
let mut map = vec![];
|
let mut map = vec![];
|
||||||
let mut indices: Vec<_> = o.input_types.iter().map(|_| 0).collect();
|
let mut indices: Vec<_> = if let RFunctionType::Statement(_, _, input_types) = &o.statement
|
||||||
|
{
|
||||||
|
input_types.iter().map(|_| 0).collect()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
// like counting: advance first index, when we reach the end, reset to zero and advance the next index, ...
|
// like counting: advance first index, when we reach the end, reset to zero and advance the next index, ...
|
||||||
loop {
|
loop {
|
||||||
let mut current_types = Vec::with_capacity(o.input_types.len());
|
if let RFunctionType::Statement(_, _, input_types) = &o.statement {
|
||||||
|
let mut current_types = Vec::with_capacity(input_types.len());
|
||||||
let mut adv = true;
|
let mut adv = true;
|
||||||
let mut was_last = o.input_types.is_empty();
|
let mut was_last = input_types.is_empty();
|
||||||
for i in 0..o.input_types.len() {
|
for i in 0..input_types.len() {
|
||||||
current_types.push(match o.input_types[i].types.get(indices[i]) {
|
current_types.push(match input_types[i].types.get(indices[i]) {
|
||||||
Some(v) => v.clone().to(),
|
Some(v) => v.clone().to(),
|
||||||
None => VType::empty(),
|
None => VType::empty(),
|
||||||
});
|
});
|
||||||
if adv {
|
if adv {
|
||||||
if indices[i] + 1 < o.input_types[i].types.len() {
|
if indices[i] + 1 < input_types[i].types.len() {
|
||||||
indices[i] += 1;
|
indices[i] += 1;
|
||||||
adv = false;
|
adv = false;
|
||||||
} else {
|
} else {
|
||||||
indices[i] = 0;
|
indices[i] = 0;
|
||||||
// we just reset the last index back to 0 - if we don't break
|
// we just reset the last index back to 0 - if we don't break
|
||||||
// from the loop, we will just start all over again.
|
// from the loop, we will just start all over again.
|
||||||
if i + 1 == o.input_types.len() {
|
if i + 1 == input_types.len() {
|
||||||
was_last = true;
|
was_last = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let out = o.out_by_statement(¤t_types, &ginfo);
|
let out = o
|
||||||
|
.out_by_statement(¤t_types, &ginfo)
|
||||||
|
.expect("this should always be a Statement function type");
|
||||||
map.push((current_types, out));
|
map.push((current_types, out));
|
||||||
if was_last {
|
if was_last {
|
||||||
break map;
|
break map;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(o)
|
Ok(o)
|
||||||
@ -438,12 +451,13 @@ fn statement_adv(
|
|||||||
func: &RFunction,
|
func: &RFunction,
|
||||||
ginfo: &GlobalScriptInfo,
|
ginfo: &GlobalScriptInfo,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
func.inputs.len() == arg_types.len()
|
func.out_by_map(arg_types, ginfo).is_some()
|
||||||
&& func
|
// func.inputs.len() == arg_types.len()
|
||||||
.inputs
|
// && func
|
||||||
.iter()
|
// .inputs
|
||||||
.zip(arg_types.iter())
|
// .iter()
|
||||||
.all(|(fn_in, arg)| arg.fits_in(&fn_in.lock().unwrap().1, ginfo).is_empty())
|
// .zip(arg_types.iter())
|
||||||
|
// .all(|(fn_in, arg)| arg.fits_in(&fn_in.lock().unwrap().1, ginfo).is_empty())
|
||||||
}
|
}
|
||||||
if let Some(funcs) = linfo.fns.get(v) {
|
if let Some(funcs) = linfo.fns.get(v) {
|
||||||
'find_func: {
|
'find_func: {
|
||||||
|
@ -4,10 +4,9 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
code_runnable::{RFunction, RStatementEnum},
|
code_runnable::{RFunction, RFunctionType},
|
||||||
fmtgs::FormatGs,
|
fmtgs::FormatGs,
|
||||||
global_info::{GSInfo, GlobalScriptInfo},
|
global_info::{GSInfo, GlobalScriptInfo},
|
||||||
val_data::VDataEnum,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::global_info::LogMsg;
|
use super::global_info::LogMsg;
|
||||||
@ -375,9 +374,7 @@ impl VSingleType {
|
|||||||
(Self::Function(a), Self::Function(b)) => 'fnt: {
|
(Self::Function(a), Self::Function(b)) => 'fnt: {
|
||||||
// since RFunction.out only uses out_map, we can create a dummy RFunction here.
|
// since RFunction.out only uses out_map, we can create a dummy RFunction here.
|
||||||
let af = RFunction {
|
let af = RFunction {
|
||||||
inputs: vec![],
|
statement: RFunctionType::Dummy,
|
||||||
input_types: vec![],
|
|
||||||
statement: RStatementEnum::Value(VDataEnum::Bool(false).to()).to(),
|
|
||||||
out_map: a.clone(),
|
out_map: a.clone(),
|
||||||
};
|
};
|
||||||
for (ins, out) in b {
|
for (ins, out) in b {
|
||||||
|
@ -29,7 +29,7 @@ fn normal_main() {
|
|||||||
let mut args_to_skip = 2;
|
let mut args_to_skip = 2;
|
||||||
let mut file = match args.len() {
|
let mut file = match args.len() {
|
||||||
0 => {
|
0 => {
|
||||||
println!("Please provide some arguments, such as the path to a file or \"-e <code>\".");
|
println!("no arguments, use -h for help");
|
||||||
std::process::exit(100);
|
std::process::exit(100);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -50,8 +50,38 @@ fn normal_main() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match ch {
|
match ch {
|
||||||
|
'h' => {
|
||||||
|
eprintln!("~~~~ mers help ~~~~");
|
||||||
|
eprintln!();
|
||||||
|
eprintln!(" ~~ cli ~~");
|
||||||
|
eprintln!("Mers has the following cli options:");
|
||||||
|
eprintln!("-h shows this Help message");
|
||||||
|
eprintln!("-e - mers will treat the run argument as code to be Executed rather than a file path");
|
||||||
|
eprintln!(" mers -e 'println(\"Hello, World!\")'");
|
||||||
|
eprintln!(
|
||||||
|
"-c - mers will Check the code for errors, but won't run it"
|
||||||
|
);
|
||||||
|
eprintln!("-f - mers will Format the code and print it. useful if you suspect the parser might be misinterpreting your code");
|
||||||
|
eprintln!(
|
||||||
|
"+c - use Colors in the output to better visualize things"
|
||||||
|
);
|
||||||
|
eprintln!("+C - don't use colors (opposite of +c, redundant since this is the default)");
|
||||||
|
eprintln!("-v - mers will be more Verbose");
|
||||||
|
eprintln!("+???+ - customize what mers is verbose about and how - bad syntax, barely useful, don't use it until it gets improved (TODO!)");
|
||||||
|
eprintln!("-i - launches an Interactive session to play around with (opens your editor and runs code on each file save)");
|
||||||
|
eprintln!("+t - spawns a new terminal for the editor (if you use a terminal editors, add +t)");
|
||||||
|
eprintln!(" mers -i+t");
|
||||||
|
eprintln!("-t - launches the Tutor, which will attempt to Teach you the basics of the language");
|
||||||
|
eprintln!();
|
||||||
|
eprintln!(" ~~ getting started ~~");
|
||||||
|
eprintln!("mers doesn't need a specific structure for directories, just create a UTF-8 text file, write code, and run it:");
|
||||||
|
eprintln!(" echo 'println(\"Hello, World!\")' > hello.mers");
|
||||||
|
eprintln!(" mers hello.mers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
'e' => execute = true,
|
'e' => execute = true,
|
||||||
'v' => verbose = true,
|
'v' => verbose = true,
|
||||||
|
'c' => run = false,
|
||||||
'f' => {
|
'f' => {
|
||||||
run = false;
|
run = false;
|
||||||
info.log.after_parse.stderr = true;
|
info.log.after_parse.stderr = true;
|
||||||
@ -178,7 +208,7 @@ fn normal_main() {
|
|||||||
file.into(),
|
file.into(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
println!("please provide either a file or -e and a script to run!");
|
println!("nothing to do - missing arguments?");
|
||||||
std::process::exit(101);
|
std::process::exit(101);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user