mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-14 11:16:17 +01:00
full rewrite, kinda works
This commit is contained in:
198
mers_lib/src/program/configs/mod.rs
Executable file
198
mers_lib/src/program/configs/mod.rs
Executable file
@@ -0,0 +1,198 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, Type},
|
||||
info::Local,
|
||||
program,
|
||||
};
|
||||
|
||||
mod with_command_running;
|
||||
mod with_iters;
|
||||
mod with_list;
|
||||
|
||||
/// 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)
|
||||
/// with_* for usage-oriented groups
|
||||
/// add_* to add custom things
|
||||
///
|
||||
/// For doc-comments:
|
||||
/// Description
|
||||
/// `bundle_std()`
|
||||
/// `type` - description
|
||||
/// `var: type` - description
|
||||
pub struct Config {
|
||||
globals: usize,
|
||||
info_parsed: super::parsed::Info,
|
||||
info_run: super::run::Info,
|
||||
}
|
||||
|
||||
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()`
|
||||
/// `with_command_running()`
|
||||
pub fn bundle_std(self) -> Self {
|
||||
self.with_command_running().with_list().bundle_base()
|
||||
}
|
||||
/// base utilities used in most programs
|
||||
/// `with_prints()`
|
||||
/// `with_math()`
|
||||
/// `with_get()`
|
||||
/// `with_iters()`
|
||||
pub fn bundle_base(self) -> Self {
|
||||
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()
|
||||
}),
|
||||
}),
|
||||
)
|
||||
}
|
||||
/// `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 {
|
||||
self.info_parsed.scopes[0].init_var(name, (0, self.globals));
|
||||
self.info_run.scopes[0].init_var(self.globals, val);
|
||||
self.globals += 1;
|
||||
self
|
||||
}
|
||||
pub fn add_type(mut self, name: String, t: Type) -> Self {
|
||||
// TODO! needed for type syntax in the parser, everything else probably(?) works already
|
||||
self
|
||||
}
|
||||
|
||||
pub fn infos(self) -> (super::parsed::Info, super::run::Info) {
|
||||
(self.info_parsed, self.info_run)
|
||||
}
|
||||
}
|
||||
104
mers_lib/src/program/configs/with_command_running.rs
Executable file
104
mers_lib/src/program/configs/with_command_running.rs
Executable file
@@ -0,0 +1,104 @@
|
||||
use std::{fmt::Display, process::Command, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, MersData, MersType},
|
||||
program,
|
||||
};
|
||||
|
||||
use super::Config;
|
||||
|
||||
impl Config {
|
||||
/// adds utilities to run commands installed on the system and get their output.
|
||||
/// `run_command: fn` runs a command with arguments.
|
||||
/// Args: (cmd, args) where cmd is a string and args is an Iterable over strings
|
||||
/// `RunCommandError` holds the error if the command can't be executed
|
||||
pub fn with_command_running(self) -> Self {
|
||||
self.add_var(
|
||||
"run_command".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(cmd) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
|
||||
if let (Some(cmd), Some(args)) = (cmd.get(0), cmd.get(1)) {
|
||||
if let (Some(cmd), Some(args)) = (
|
||||
cmd.get().as_any().downcast_ref::<data::string::String>(),
|
||||
args.get().iterable(),
|
||||
) {
|
||||
match Command::new(&cmd.0)
|
||||
.args(args.map(|v| v.get().to_string()))
|
||||
.output()
|
||||
{
|
||||
Ok(output) => {
|
||||
let status = if let Some(code) = output.status.code() {
|
||||
Data::new(data::int::Int(code as _))
|
||||
} else {
|
||||
Data::empty_tuple()
|
||||
};
|
||||
let stdout =
|
||||
String::from_utf8_lossy(&output.stdout).into_owned();
|
||||
let stderr =
|
||||
String::from_utf8_lossy(&output.stderr).into_owned();
|
||||
Data::new(data::tuple::Tuple(vec![
|
||||
status,
|
||||
Data::new(data::string::String(stdout)),
|
||||
Data::new(data::string::String(stderr)),
|
||||
]))
|
||||
}
|
||||
Err(e) => Data::new(RunCommandError(e.to_string())),
|
||||
}
|
||||
} else {
|
||||
unreachable!("run_command called with arguments other than (String, <Iterable>).")
|
||||
}
|
||||
} else {
|
||||
unreachable!("run_command called with too few arguments")
|
||||
}
|
||||
} else {
|
||||
unreachable!("run_command called with non-tuple argument")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RunCommandError(String);
|
||||
#[derive(Debug)]
|
||||
pub struct RunCommandErrorT;
|
||||
impl MersData for RunCommandError {
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
impl MersType for RunCommandErrorT {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other.as_any().downcast_ref::<Self>().is_some()
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
impl Display for RunCommandError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "RunCommandError: {}", self.0)
|
||||
}
|
||||
}
|
||||
175
mers_lib/src/program/configs/with_iters.rs
Executable file
175
mers_lib/src/program/configs/with_iters.rs
Executable file
@@ -0,0 +1,175 @@
|
||||
use std::{fmt::Display, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, MersData},
|
||||
program,
|
||||
};
|
||||
|
||||
use super::Config;
|
||||
|
||||
impl Config {
|
||||
/// Adds functions to deal with iterables
|
||||
/// `iter: fn` executes a function once for each element of the iterable
|
||||
pub fn with_iters(self) -> Self {
|
||||
self.add_var(
|
||||
"iter".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(f)) = (tuple.get(0), tuple.get(1)) {
|
||||
if let (Some(iter), Some(f)) = (
|
||||
v.get().iterable(),
|
||||
f.get().as_any().downcast_ref::<data::function::Function>(),
|
||||
) {
|
||||
for v in iter {
|
||||
f.run(v);
|
||||
}
|
||||
Data::empty_tuple()
|
||||
} else {
|
||||
unreachable!(
|
||||
"iter called on tuple not containing iterable and function"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on tuple with len < 2")
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on non-tuple")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
"map".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(f)) = (tuple.get(0), tuple.get(1)) {
|
||||
if let Some(f) =
|
||||
f.get().as_any().downcast_ref::<data::function::Function>()
|
||||
{
|
||||
Data::new(Iter(Iters::Map(Clone::clone(f)), v.clone()))
|
||||
} else {
|
||||
unreachable!("iter called on tuple not containing function")
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on tuple with len < 2")
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on non-tuple")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
"filter".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(f)) = (tuple.get(0), tuple.get(1)) {
|
||||
if let Some(f) =
|
||||
f.get().as_any().downcast_ref::<data::function::Function>()
|
||||
{
|
||||
Data::new(Iter(Iters::Filter(Clone::clone(f)), v.clone()))
|
||||
} else {
|
||||
unreachable!("iter called on tuple not containing function")
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on tuple with len < 2")
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on non-tuple")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
"filter_map".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(f)) = (tuple.get(0), tuple.get(1)) {
|
||||
if let Some(f) =
|
||||
f.get().as_any().downcast_ref::<data::function::Function>()
|
||||
{
|
||||
Data::new(Iter(Iters::FilterMap(Clone::clone(f)), v.clone()))
|
||||
} else {
|
||||
unreachable!("iter called on tuple not containing function")
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on tuple with len < 2")
|
||||
}
|
||||
} else {
|
||||
unreachable!("iter called on non-tuple")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Iters {
|
||||
Map(data::function::Function),
|
||||
Filter(data::function::Function),
|
||||
FilterMap(data::function::Function),
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Iter(Iters, Data);
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IterT(Iters);
|
||||
impl MersData for Iter {
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> {
|
||||
Some(match &self.0 {
|
||||
Iters::Map(f) => {
|
||||
let f = Clone::clone(f);
|
||||
Box::new(self.1.get().iterable()?.map(move |v| f.run(v)))
|
||||
}
|
||||
Iters::Filter(f) => {
|
||||
let f = Clone::clone(f);
|
||||
Box::new(self.1.get().iterable()?.filter(move |v| {
|
||||
f.run(v.clone())
|
||||
.get()
|
||||
.as_any()
|
||||
.downcast_ref::<data::bool::Bool>()
|
||||
.is_some_and(|b| b.0)
|
||||
}))
|
||||
}
|
||||
Iters::FilterMap(f) => {
|
||||
let f = Clone::clone(f);
|
||||
Box::new(
|
||||
self.1
|
||||
.get()
|
||||
.iterable()?
|
||||
.filter_map(move |v| f.run(v).get().matches()),
|
||||
)
|
||||
}
|
||||
_ => todo!(),
|
||||
})
|
||||
}
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
impl Display for Iter {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "<Iter>")
|
||||
}
|
||||
}
|
||||
90
mers_lib/src/program/configs/with_list.rs
Executable file
90
mers_lib/src/program/configs/with_list.rs
Executable file
@@ -0,0 +1,90 @@
|
||||
use std::{fmt::Display, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, MersData, MersType, Type},
|
||||
program,
|
||||
};
|
||||
|
||||
use super::Config;
|
||||
|
||||
impl Config {
|
||||
/// Adds a simple list type
|
||||
/// `List` can store a variable number of items
|
||||
/// `as_list: fn` turns a tuple into a list
|
||||
pub fn with_list(self) -> Self {
|
||||
// TODO: Type with generics
|
||||
self.add_type("List".to_string(), Type::new(ListT(Type::empty_tuple())))
|
||||
.add_var(
|
||||
"as_list".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() {
|
||||
Data::new(List(i.collect()))
|
||||
} else {
|
||||
unreachable!("as_list called on non-iterable")
|
||||
}
|
||||
}),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct List(Vec<Data>);
|
||||
#[derive(Debug)]
|
||||
pub struct ListT(Type);
|
||||
impl MersData for List {
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> {
|
||||
Some(Box::new(self.0.clone().into_iter()))
|
||||
}
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
impl MersType for ListT {
|
||||
fn iterable(&self) -> Option<Type> {
|
||||
Some(self.0.clone())
|
||||
}
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other
|
||||
.as_any()
|
||||
.downcast_ref::<Self>()
|
||||
.is_some_and(|v| self.0.is_same_type_as(&v.0))
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
impl Display for List {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "[")?;
|
||||
for (i, c) in self.0.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", c.get())?;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
3
mers_lib/src/program/mod.rs
Executable file
3
mers_lib/src/program/mod.rs
Executable file
@@ -0,0 +1,3 @@
|
||||
pub mod configs;
|
||||
pub mod parsed;
|
||||
pub mod run;
|
||||
25
mers_lib/src/program/parsed/assign_to.rs
Executable file
25
mers_lib/src/program/parsed/assign_to.rs
Executable file
@@ -0,0 +1,25 @@
|
||||
use crate::{info::Local, program};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AssignTo {
|
||||
pub target: Box<dyn MersStatement>,
|
||||
pub source: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for AssignTo {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
mut comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
Ok(Box::new(program::run::assign_to::AssignTo {
|
||||
target: self.target.compile(info, comp)?,
|
||||
source: self.source.compile(info, comp)?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
26
mers_lib/src/program/parsed/block.rs
Executable file
26
mers_lib/src/program/parsed/block.rs
Executable file
@@ -0,0 +1,26 @@
|
||||
use crate::{info, program};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Block {
|
||||
pub statements: Vec<Box<dyn MersStatement>>,
|
||||
}
|
||||
impl MersStatement for Block {
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
Ok(Box::new(program::run::block::Block {
|
||||
statements: self
|
||||
.statements
|
||||
.iter()
|
||||
.map(|v| v.compile(info, comp))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
24
mers_lib/src/program/parsed/chain.rs
Executable file
24
mers_lib/src/program/parsed/chain.rs
Executable file
@@ -0,0 +1,24 @@
|
||||
use crate::{info, program};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Chain {
|
||||
pub first: Box<dyn MersStatement>,
|
||||
pub chained: Box<dyn MersStatement>,
|
||||
}
|
||||
impl MersStatement for Chain {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
Ok(Box::new(program::run::chain::Chain {
|
||||
first: self.first.compile(info, comp)?,
|
||||
chained: self.chained.compile(info, comp)?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
42
mers_lib/src/program/parsed/function.rs
Executable file
42
mers_lib/src/program/parsed/function.rs
Executable file
@@ -0,0 +1,42 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
data::{self, Data},
|
||||
info::Local,
|
||||
program,
|
||||
};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Function {
|
||||
pub arg: Box<dyn MersStatement>,
|
||||
pub run: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for Function {
|
||||
fn has_scope(&self) -> bool {
|
||||
// TODO: what???
|
||||
false
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
mut comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
comp.is_init = true;
|
||||
let arg = self.arg.compile(info, comp)?;
|
||||
comp.is_init = false;
|
||||
let run = self.run.compile(info, comp)?;
|
||||
Ok(Box::new(program::run::function::Function {
|
||||
func_no_info: data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
out: Arc::new(|_i| todo!()),
|
||||
run: Arc::new(move |i, info| {
|
||||
data::defs::assign(i, &arg.run(info));
|
||||
run.run(info)
|
||||
}),
|
||||
},
|
||||
}))
|
||||
}
|
||||
}
|
||||
31
mers_lib/src/program/parsed/if.rs
Executable file
31
mers_lib/src/program/parsed/if.rs
Executable file
@@ -0,0 +1,31 @@
|
||||
use crate::program;
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct If {
|
||||
pub condition: Box<dyn MersStatement>,
|
||||
pub on_true: Box<dyn MersStatement>,
|
||||
pub on_false: Option<Box<dyn MersStatement>>,
|
||||
}
|
||||
|
||||
impl MersStatement for If {
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
Ok(Box::new(program::run::r#if::If {
|
||||
condition: self.condition.compile(info, comp)?,
|
||||
on_true: self.condition.compile(info, comp)?,
|
||||
on_false: if let Some(v) = &self.on_false {
|
||||
Some(v.compile(info, comp)?)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}))
|
||||
}
|
||||
}
|
||||
29
mers_lib/src/program/parsed/init_to.rs
Executable file
29
mers_lib/src/program/parsed/init_to.rs
Executable file
@@ -0,0 +1,29 @@
|
||||
use crate::{info::Local, program};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InitTo {
|
||||
pub target: Box<dyn MersStatement>,
|
||||
pub source: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for InitTo {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
mut comp: CompInfo,
|
||||
) -> Result<Box<dyn crate::program::run::MersStatement>, String> {
|
||||
comp.is_init = true;
|
||||
let target = self.target.compile(info, comp)?;
|
||||
comp.is_init = false;
|
||||
let source = self.source.compile(info, comp)?;
|
||||
Ok(Box::new(program::run::assign_to::AssignTo {
|
||||
target,
|
||||
source,
|
||||
}))
|
||||
}
|
||||
}
|
||||
23
mers_lib/src/program/parsed/loop.rs
Executable file
23
mers_lib/src/program/parsed/loop.rs
Executable file
@@ -0,0 +1,23 @@
|
||||
use crate::program;
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Loop {
|
||||
pub inner: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for Loop {
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
Ok(Box::new(program::run::r#loop::Loop {
|
||||
inner: self.inner.compile(info, comp)?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
68
mers_lib/src/program/parsed/mod.rs
Executable file
68
mers_lib/src/program/parsed/mod.rs
Executable file
@@ -0,0 +1,68 @@
|
||||
use std::{collections::HashMap, fmt::Debug};
|
||||
|
||||
use crate::info;
|
||||
|
||||
pub mod assign_to;
|
||||
pub mod block;
|
||||
pub mod chain;
|
||||
pub mod function;
|
||||
pub mod r#if;
|
||||
pub mod init_to;
|
||||
pub mod r#loop;
|
||||
pub mod switch;
|
||||
pub mod tuple;
|
||||
pub mod value;
|
||||
pub mod variable;
|
||||
|
||||
pub trait MersStatement: Debug {
|
||||
fn has_scope(&self) -> bool;
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut Info,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn super::run::MersStatement>, String>;
|
||||
fn compile(
|
||||
&self,
|
||||
info: &mut Info,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn super::run::MersStatement>, String> {
|
||||
if self.has_scope() {
|
||||
info.create_scope();
|
||||
}
|
||||
let o = self.compile_custom(info, comp);
|
||||
if self.has_scope() {
|
||||
info.end_scope();
|
||||
}
|
||||
o
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CompInfo {
|
||||
is_init: bool,
|
||||
}
|
||||
impl Default for CompInfo {
|
||||
fn default() -> Self {
|
||||
Self { is_init: false }
|
||||
}
|
||||
}
|
||||
|
||||
pub type Info = info::Info<Local>;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Local {
|
||||
vars: HashMap<String, (usize, usize)>,
|
||||
}
|
||||
impl info::Local for Local {
|
||||
type VariableIdentifier = String;
|
||||
type VariableData = (usize, usize);
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
self.vars.insert(id, value);
|
||||
}
|
||||
fn get_var(&self, id: &Self::VariableIdentifier) -> Option<&Self::VariableData> {
|
||||
self.vars.get(id)
|
||||
}
|
||||
fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> {
|
||||
self.vars.get_mut(id)
|
||||
}
|
||||
}
|
||||
27
mers_lib/src/program/parsed/switch.rs
Executable file
27
mers_lib/src/program/parsed/switch.rs
Executable file
@@ -0,0 +1,27 @@
|
||||
use crate::data::Type;
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Switch {
|
||||
source: Box<dyn MersStatement>,
|
||||
arms: Vec<SwitchArm>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SwitchArm {
|
||||
requires_type: Type,
|
||||
}
|
||||
|
||||
impl MersStatement for Switch {
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn crate::program::run::MersStatement>, String> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
26
mers_lib/src/program/parsed/tuple.rs
Executable file
26
mers_lib/src/program/parsed/tuple.rs
Executable file
@@ -0,0 +1,26 @@
|
||||
use crate::{info, program};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tuple {
|
||||
pub elems: Vec<Box<dyn MersStatement>>,
|
||||
}
|
||||
impl MersStatement for Tuple {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
Ok(Box::new(program::run::tuple::Tuple {
|
||||
elems: self
|
||||
.elems
|
||||
.iter()
|
||||
.map(|v| v.compile(info, comp))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
21
mers_lib/src/program/parsed/value.rs
Executable file
21
mers_lib/src/program/parsed/value.rs
Executable file
@@ -0,0 +1,21 @@
|
||||
use crate::{data::Data, program};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Value(pub Data);
|
||||
|
||||
impl MersStatement for Value {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
Ok(Box::new(program::run::value::Value {
|
||||
val: self.0.clone(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
38
mers_lib/src/program/parsed/variable.rs
Executable file
38
mers_lib/src/program/parsed/variable.rs
Executable file
@@ -0,0 +1,38 @@
|
||||
use crate::{info::Local, program};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Variable {
|
||||
pub is_ref: bool,
|
||||
pub var: String,
|
||||
}
|
||||
|
||||
impl MersStatement for Variable {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn compile_custom(
|
||||
&self,
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn program::run::MersStatement>, String> {
|
||||
if comp.is_init {
|
||||
info.init_var(
|
||||
self.var.clone(),
|
||||
(
|
||||
info.scopes.len() - 1,
|
||||
info.scopes.last().unwrap().vars.len(),
|
||||
),
|
||||
)
|
||||
}
|
||||
Ok(Box::new(program::run::variable::Variable {
|
||||
is_ref: comp.is_init || self.is_ref,
|
||||
var: if let Some(v) = info.get_var(&self.var) {
|
||||
*v
|
||||
} else {
|
||||
return Err(format!("No variable named '{}' found!", self.var));
|
||||
},
|
||||
}))
|
||||
}
|
||||
}
|
||||
21
mers_lib/src/program/run/assign_to.rs
Executable file
21
mers_lib/src/program/run/assign_to.rs
Executable file
@@ -0,0 +1,21 @@
|
||||
use crate::data;
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AssignTo {
|
||||
pub target: Box<dyn MersStatement>,
|
||||
pub source: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for AssignTo {
|
||||
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data {
|
||||
let source = self.source.run(info);
|
||||
let target = self.target.run(info);
|
||||
data::defs::assign(source, &target);
|
||||
target
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
20
mers_lib/src/program/run/block.rs
Executable file
20
mers_lib/src/program/run/block.rs
Executable file
@@ -0,0 +1,20 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Block {
|
||||
pub statements: Vec<Box<dyn MersStatement>>,
|
||||
}
|
||||
impl MersStatement for Block {
|
||||
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data {
|
||||
self.statements
|
||||
.iter()
|
||||
.map(|s| s.run(info))
|
||||
.last()
|
||||
.unwrap_or_else(|| crate::data::Data::new(crate::data::tuple::Tuple(vec![])))
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
26
mers_lib/src/program/run/chain.rs
Executable file
26
mers_lib/src/program/run/chain.rs
Executable file
@@ -0,0 +1,26 @@
|
||||
use std::{any::Any, sync::Arc};
|
||||
|
||||
use crate::data::{function::Function, Data};
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Chain {
|
||||
pub first: Box<dyn MersStatement>,
|
||||
pub chained: Box<dyn MersStatement>,
|
||||
}
|
||||
impl MersStatement for Chain {
|
||||
fn run_custom(&self, info: &mut super::Info) -> Data {
|
||||
let f = self.first.run(info);
|
||||
let c = self.chained.run(info);
|
||||
let c = c.get();
|
||||
if let Some(func) = c.as_any().downcast_ref::<crate::data::function::Function>() {
|
||||
func.run(f)
|
||||
} else {
|
||||
todo!("err: not a function");
|
||||
}
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
17
mers_lib/src/program/run/function.rs
Executable file
17
mers_lib/src/program/run/function.rs
Executable file
@@ -0,0 +1,17 @@
|
||||
use crate::data::{self, Data, MersData};
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Function {
|
||||
pub func_no_info: data::function::Function,
|
||||
}
|
||||
|
||||
impl MersStatement for Function {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn run_custom(&self, info: &mut super::Info) -> Data {
|
||||
Data::new(self.func_no_info.with_info(info.clone()))
|
||||
}
|
||||
}
|
||||
18
mers_lib/src/program/run/if.rs
Executable file
18
mers_lib/src/program/run/if.rs
Executable file
@@ -0,0 +1,18 @@
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct If {
|
||||
pub condition: Box<dyn MersStatement>,
|
||||
pub on_true: Box<dyn MersStatement>,
|
||||
pub on_false: Option<Box<dyn MersStatement>>,
|
||||
}
|
||||
|
||||
impl MersStatement for If {
|
||||
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data {
|
||||
self.condition.run(info);
|
||||
todo!("what now?")
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
21
mers_lib/src/program/run/loop.rs
Executable file
21
mers_lib/src/program/run/loop.rs
Executable file
@@ -0,0 +1,21 @@
|
||||
use crate::data::MersData;
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Loop {
|
||||
pub inner: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for Loop {
|
||||
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data {
|
||||
loop {
|
||||
if let Some(break_val) = self.inner.run(info).get().matches() {
|
||||
break break_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
63
mers_lib/src/program/run/mod.rs
Executable file
63
mers_lib/src/program/run/mod.rs
Executable file
@@ -0,0 +1,63 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, Type},
|
||||
info,
|
||||
};
|
||||
|
||||
pub mod assign_to;
|
||||
pub mod block;
|
||||
pub mod chain;
|
||||
pub mod function;
|
||||
pub mod r#if;
|
||||
pub mod r#loop;
|
||||
pub mod switch;
|
||||
pub mod tuple;
|
||||
pub mod value;
|
||||
pub mod variable;
|
||||
|
||||
pub trait MersStatement: std::fmt::Debug {
|
||||
fn run_custom(&self, info: &mut Info) -> Data;
|
||||
/// if true, local variables etc. will be contained inside their own scope.
|
||||
fn has_scope(&self) -> bool;
|
||||
// fn outputs(&self) -> Type;
|
||||
fn run(&self, info: &mut Info) -> Data {
|
||||
if self.has_scope() {
|
||||
info.create_scope();
|
||||
}
|
||||
let o = self.run_custom(info);
|
||||
if self.has_scope() {
|
||||
info.end_scope();
|
||||
}
|
||||
o
|
||||
}
|
||||
}
|
||||
|
||||
pub type Info = info::Info<Local>;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Local {
|
||||
vars: Vec<Data>,
|
||||
}
|
||||
impl info::Local for Local {
|
||||
type VariableIdentifier = usize;
|
||||
type VariableData = Data;
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
while self.vars.len() <= id {
|
||||
self.vars.push(Data::new(data::bool::Bool(false)));
|
||||
}
|
||||
self.vars[id] = value;
|
||||
}
|
||||
fn get_var(&self, id: &Self::VariableIdentifier) -> Option<&Self::VariableData> {
|
||||
match self.vars.get(*id) {
|
||||
Some(v) => Some(v),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> {
|
||||
match self.vars.get_mut(*id) {
|
||||
Some(v) => Some(v),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
23
mers_lib/src/program/run/switch.rs
Executable file
23
mers_lib/src/program/run/switch.rs
Executable file
@@ -0,0 +1,23 @@
|
||||
use crate::data::Type;
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Switch {
|
||||
source: Box<dyn MersStatement>,
|
||||
arms: Vec<SwitchArm>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SwitchArm {
|
||||
requires_type: Type,
|
||||
}
|
||||
|
||||
impl MersStatement for Switch {
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data {
|
||||
todo!("switch")
|
||||
}
|
||||
}
|
||||
18
mers_lib/src/program/run/tuple.rs
Executable file
18
mers_lib/src/program/run/tuple.rs
Executable file
@@ -0,0 +1,18 @@
|
||||
use crate::data::{self, Data};
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tuple {
|
||||
pub elems: Vec<Box<dyn MersStatement>>,
|
||||
}
|
||||
impl MersStatement for Tuple {
|
||||
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data {
|
||||
Data::new(data::tuple::Tuple(
|
||||
self.elems.iter().map(|s| s.run(info)).collect(),
|
||||
))
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
17
mers_lib/src/program/run/value.rs
Executable file
17
mers_lib/src/program/run/value.rs
Executable file
@@ -0,0 +1,17 @@
|
||||
use crate::data::{Data, MersData};
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Value {
|
||||
pub val: Data,
|
||||
}
|
||||
|
||||
impl MersStatement for Value {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn run_custom(&self, info: &mut super::Info) -> Data {
|
||||
self.val.clone()
|
||||
}
|
||||
}
|
||||
30
mers_lib/src/program/run/variable.rs
Executable file
30
mers_lib/src/program/run/variable.rs
Executable file
@@ -0,0 +1,30 @@
|
||||
use crate::data::{self, Data};
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Variable {
|
||||
pub is_ref: bool,
|
||||
pub var: (usize, usize),
|
||||
}
|
||||
|
||||
impl MersStatement for Variable {
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn run_custom(&self, info: &mut super::Info) -> Data {
|
||||
while info.scopes[self.var.0].vars.len() <= self.var.1 {
|
||||
info.scopes[self.var.0]
|
||||
.vars
|
||||
.push(Data::new(data::bool::Bool(false)));
|
||||
}
|
||||
if self.is_ref {
|
||||
Data::new(data::reference::Reference(
|
||||
info.scopes[self.var.0].vars[self.var.1].clone(),
|
||||
))
|
||||
} else {
|
||||
// Full-Clones!
|
||||
Data::new_boxed(info.scopes[self.var.0].vars[self.var.1].get().clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user