Skip to content

Commit

Permalink
=Convert list methods to new declaration style
Browse files Browse the repository at this point in the history
  • Loading branch information
Axel Liljencrantz committed Jul 17, 2024
1 parent 5aa0958 commit 66944b4
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 151 deletions.
5 changes: 2 additions & 3 deletions src/lang/data/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,12 @@ impl List {
cells.clear();
}

pub fn remove(&self, idx: usize) -> CrushResult<()> {
pub fn remove(&self, idx: usize) -> CrushResult<Value> {
let mut cells = self.cells.lock().unwrap();
if idx >= cells.len() {
return argument_error_legacy("Index out of bounds");
}
cells.remove(idx);
Ok(())
Ok(cells.remove(idx))
}

pub fn insert(&self, idx: usize, value: Value) -> CrushResult<()> {
Expand Down
1 change: 1 addition & 0 deletions src/lib/control/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ output = Known(ValueType::BinaryInputStream),
can_block = true,
)]
pub struct Cmd {
#[description("The file path to the command to execute")]
command: PathBuf,
#[named()]
#[description("Switches to pass in to the command. The name will be prepended with a double dash '--', unless it is a single character name, in which case a single dash '-' will be prepended")]
Expand Down
286 changes: 138 additions & 148 deletions src/lib/types/list.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::clone::Clone;
use crate::lang::command::OutputType::Known;
use crate::lang::command::OutputType::Unknown;
use crate::lang::command::TypeMap;
Expand All @@ -9,6 +10,7 @@ use lazy_static::lazy_static;
use ordered_map::OrderedMap;
use signature::signature;
use crate::data::table::ColumnVec;
use crate::lang::pipe::{Stream, ValueSender};
use crate::lang::state::argument_vector::ArgumentVector;
use crate::lang::state::this::This;
use crate::util::replace::Replace;
Expand All @@ -24,36 +26,12 @@ lazy_static! {
Len::declare_method(&mut res, &path);
Empty::declare_method(&mut res, &path);
Clear::declare_method(&mut res, &path);
res.declare(
full("push"),
push,
false,
"list:push",
"Push an element to the end of the list",
None,
Unknown,
[],
);
res.declare(
full("pop"),
pop,
false,
"list:pop",
"Remove the last element from the list",
None,
Unknown,
[],
);
res.declare(
full("peek"),
peek,
false,
"list:peek",
"Return the last element from the list",
None,
Unknown,
[],
);
Push::declare_method(&mut res, &path);
Pop::declare_method(&mut res, &path);
Peek::declare_method(&mut res, &path);
Remove::declare_method(&mut res, &path);
Insert::declare_method(&mut res, &path);
Truncate::declare_method(&mut res, &path);
res.declare(
full("__setitem__"),
setitem,
Expand All @@ -64,66 +42,9 @@ lazy_static! {
Known(ValueType::Empty),
[],
);
res.declare(
full("remove"),
remove,
false,
"list:remove idx:integer",
"Remove the element at the specified index",
None,
Unknown,
[],
);
res.declare(
full("insert"),
insert,
false,
"list:insert idx:integer value:any",
"Insert a new element at the specified index",
None,
Unknown,
[],
);
res.declare(
full("truncate"),
truncate,
false,
"list:truncate idx:integer",
"Remove all elements past the specified index",
None,
Unknown,
[],
);
res.declare(
full("clone"),
clone,
false,
"list:clone",
"Create a duplicate of the list",
None,
Unknown,
[],
);
res.declare(
full("of"),
of,
true,
"list:of element:any...",
"Create a new list containing the supplied elements",
None,
Unknown,
[],
);
res.declare(
full("collect"),
collect,
true,
"list:collect [column]",
"Create a new list by reading a column from the input",
Some(" If no elements are supplied as arguments, input must be a stream with\n exactly one column."),
Unknown,
[],
);
CloneCmd::declare_method(&mut res, &path);
Of::declare_method(&mut res, &path);
Collect::declare_method(&mut res, &path);
res.declare(
full("new"),
new,
Expand Down Expand Up @@ -217,57 +138,62 @@ fn __call__(mut context: CommandContext) -> CrushResult<()> {
_ => argument_error_legacy("Invalid this, expected type list"),
}
}
#[signature(
of,
can_block = false,
output = Known(ValueType::List(Box::from(ValueType::Empty))),
short = "Create a new list containing the supplied elements.",
)]
struct Of {
#[description("the elements of the new list.")]
#[unnamed()]
values: Vec<Value>,
}

fn of(mut context: CommandContext) -> CrushResult<()> {
match context.arguments.len() {
let cfg: Of = Of::parse(context.arguments, &context.global_state.printer())?;
match cfg.values.len() {
0 => argument_error_legacy("Expected at least one argument"),
_ => context.output.send(
List::new_without_type(
context.arguments
.drain(..)
.map(|a| a.value)
.collect()
).into()
),
_ => context.output.send(List::new_without_type(cfg.values).into()),
}
}

#[signature(
collect,
can_block = false,
output = Known(ValueType::List(Box::from(ValueType::Empty))),
short = "Create a new list by reading a column from the input.",
long= "If no elements are supplied as arguments, input must be a stream with exactly one column."
)]
struct Collect {
column: Option<String>,
}

fn collect_internal(mut input: Stream, idx: usize, value_type: ValueType, output: ValueSender) -> CrushResult<()> {
let mut lst = Vec::new();
while let Ok(row) = input.read() {
lst.push(Vec::from(row).replace(idx, Value::Empty));
}

output.send(List::new(value_type, lst).into())
}

fn collect(context: CommandContext) -> CrushResult<()> {
let cfg: Collect = Collect::parse(context.arguments, &context.global_state.printer())?;
let mut input = mandate(context.input.recv()?.stream()?, "Expected a stream")?;
let input_type = input.types().to_vec();
let mut lst = Vec::new();
match context.arguments.len() {
0 => {
if input_type.len() != 1 {
return data_error("Expected input with exactly one column");
}
while let Ok(row) = input.read() {
lst.push(Vec::from(row).remove(0));
match (input_type.len(), cfg.column) {
(_, Some(name)) =>
match input_type.as_slice().find(&name) {
Ok(idx) =>
collect_internal(input, idx, input_type[idx].cell_type.clone(), context.output),
_ => data_error(format!("Column {} not found", name))
}
context
.output
.send(List::new(input_type[0].cell_type.clone(), lst).into())
}
1 => {
match &context.arguments[0].value {
Value::String(s) => {
match input_type.as_slice().find(s) {
Ok(idx) => {
while let Ok(row) = input.read() {
lst.push(Vec::from(row).replace(idx, Value::Empty));
}
context
.output
.send(List::new(input_type[idx].cell_type.clone(), lst).into())
}
_ => argument_error("Column not found", context.arguments[0].location)
}
}
_ => argument_error("Expected argument of type string", context.arguments[0].location),
}
}
_ => argument_error("Expected a single argument", context.arguments[0].location),

(1, None) =>
collect_internal(input, 0, input_type[0].cell_type.clone(), context.output),

_ => data_error("Expected either input with exactly one column or an argument specifying which column to pick"),
}
}

Expand Down Expand Up @@ -309,29 +235,58 @@ fn empty(mut context: CommandContext) -> CrushResult<()> {
.send(Value::Bool(context.this.list()?.len() == 0))
}

#[signature(
push,
can_block = false,
output = Known(ValueType::List(Box::from(ValueType::Empty))),
short = "Push elements to the end of the list.",
)]
struct Push {
#[unnamed()]
#[description("the values to push")]
values: Vec<Value>,
}

fn push(mut context: CommandContext) -> CrushResult<()> {
let l = context.this.list()?;
let mut new_elements: Vec<Value> = Vec::new();
for el in context.arguments.drain(..) {
if el.value.value_type() == l.element_type() || l.element_type() == ValueType::Any {
new_elements.push(el.value)
} else {
return argument_error_legacy("Invalid element type");
let mut cfg: Push = Push::parse(context.remove_arguments(), &context.global_state.printer())?;

for el in &cfg.values {
if el.value_type() != l.element_type() && l.element_type() != ValueType::Any {
return argument_error_legacy(format!("Invalid element type, got {} but expected {}", el.value_type().to_string(), l.element_type().to_string()));
}
}
if !new_elements.is_empty() {
l.append(&mut new_elements)?;
if !cfg.values.is_empty() {
l.append(&mut cfg.values)?;
}
context.output.send(l.into())
}

#[signature(
pop,
can_block = false,
output = Known(ValueType::Empty),
short = "Remove the last element from the list.",
)]
struct Pop {
}

fn pop(mut context: CommandContext) -> CrushResult<()> {
context.arguments.check_len(0)?;
let o = context.output;
context.this.list()?.pop().map(|c| o.send(c));
Ok(())
}

#[signature(
peek,
can_block = false,
output = Known(ValueType::Empty),
short = "Return the last element from the list without removing it.",
)]
struct Peek {
}

fn peek(mut context: CommandContext) -> CrushResult<()> {
context.arguments.check_len(0)?;
let o = context.output;
Expand Down Expand Up @@ -364,29 +319,64 @@ fn setitem(mut context: CommandContext) -> CrushResult<()> {
context.output.empty()
}

#[signature(
remove,
can_block = false,
output = Known(ValueType::Empty),
short = "Remove the element at the specified index and return it.",
)]
struct Remove {
idx: usize,
}

fn remove(mut context: CommandContext) -> CrushResult<()> {
context.arguments.check_len(1)?;
let list = context.this.list()?;
let idx = context.arguments.integer(0)?;
list.remove(idx as usize)
let cfg: Remove = Remove::parse(context.remove_arguments(), &context.global_state.printer())?;
context.output.send(list.remove(cfg.idx)?)
}

#[signature(
insert,
can_block = false,
output = Unknown,
short = "Insert a new element at the specified index. Following values will be shifted forward.",
)]
struct Insert {
idx: usize,
value: Value,
}

fn insert(mut context: CommandContext) -> CrushResult<()> {
context.arguments.check_len(2)?;
let list = context.this.list()?;
let idx = context.arguments.integer(0)?;
let value = context.arguments.value(1)?;
list.insert(idx as usize, value)
let cfg: Insert = Insert::parse(context.remove_arguments(), &context.global_state.printer())?;
list.insert(cfg.idx, cfg.value)
}

#[signature(
truncate,
can_block = false,
output = Unknown,
short = "Remove all elements past the specified index.",
)]
struct Truncate {
idx: Option<usize>,
}

fn truncate(mut context: CommandContext) -> CrushResult<()> {
context.arguments.check_len(1)?;
let list = context.this.list()?;
let idx = context.arguments.integer(0)?;
list.truncate(idx as usize);
let cfg: Truncate = Truncate::parse(context.remove_arguments(), &context.global_state.printer())?;
list.truncate(cfg.idx.unwrap_or_default());
Ok(())
}

#[signature(
clone,
can_block = false,
output = Known(ValueType::List(Box::from(ValueType::Empty))),
short = "Create a duplicate of the list.",
)]
struct CloneCmd {}

fn clone(mut context: CommandContext) -> CrushResult<()> {
context.arguments.check_len(0)?;
context
Expand Down

0 comments on commit 66944b4

Please sign in to comment.