add linked list

This commit is contained in:
Daniella / Tove 2024-10-05 15:16:56 +02:00
parent e48f06a8b5
commit 1c1f9a4566
4 changed files with 239 additions and 4 deletions

View file

@ -13,12 +13,12 @@ construct _Iter {
foreach { | with callable this ;
!!-
while { !!- this:next dup null eq not } {
!!- callable call
!!- callable callp
}
pop
}
collect { array | with this ;
[ { any | } this:foreach ]
[ { | } this:foreach ]
}
map { MapIter | with map-function this ;
map-function this MapIter:new

120
spl/linkedlist.spl Normal file
View file

@ -0,0 +1,120 @@
construct LinkedList {
next
value
;
construct { this | }
len { mega | with this ;
def i this:value null eq not =i
while { this:next null eq not } {
this:next =this
i ++ =i
}
i
}
push { this | with item this ;
item:unwrap;
this:value null eq if {
item this:=value;
this 2 stop
}
LinkedList:new
dup :=value;<item>
this:last-entry:=next;
this
}
last-entry { list | with this ;
while { this:next null eq not } {
this:next =this
}
this
}
peek { value | with this ;
this:last-entry:value
}
pop { item | with this ;
def item this =item
null
while { item:next null eq not } {
pop item
item:next =item
}
"if theres no next item in this";
dup null eq if {
pop
this:value (null this:=value;) 2 stop
}
:=next;<null>
item:value
}
push-front { list | with item this ;
item:unwrap;
this:value null eq if {
item this:=value;
this 2 stop
}
LinkedList:new
dup :=next;<this>
dup :=value;<item>
}
insert { list | with item index this ;
item:unwrap;
index 0 eq if {
item this:push-front 2 stop
}
def list this =list
while { index 1 gt } {
list:next =list
index -- =index
}
item list:next:push-front list:=next;
this
}
pop-front { item list | with this ;
this:value this:next
}
remove { item list | with index this ;
index 0 eq if {
this:pop-front 2 stop
}
def list this =list
while { index 1 gt } {
list:next =list
index -- =index
}
list:next:pop-front list:=next
this
}
get { item | with index this ;
while { index 0 gt } {
this:next =this
index -- =index
}
this:value
}
foreach { | with callable this ;
while { this null eq not } {
this:value dup null eq not if { callable:call; }
this:next =this
}
}
iter { LinkedListIter | with this ;
this LinkedListIter:new
}
}
construct LinkedListIter {
cur-list
;
construct { this | with list this ;
list this:=cur-list
this
}
next { item | with this ;
this:cur-list dup null eq if { 2 stop }
:value
this:cur-list:next this:=cur-list;
}
}
include _Iter in LinkedListIter

View file

@ -1,5 +1,5 @@
use std::{
collections::VecDeque,
collections::{HashMap, VecDeque},
env::{args, vars},
fs,
io::{stdin, stdout, Write},
@ -930,9 +930,73 @@ pub fn mega_to_str_radix(stack: &mut Stack) -> OError {
return Ok(());
}
pub fn properties(stack: &mut Stack) -> OError {
let o = stack.pop();
let o = o.lock_ro();
let additional: Vec<AMObject> = vec![
Value::Array(vec![";".to_owned().spl(), o.native.clone().spl()]).spl(),
Value::Array(vec![
":".to_owned().spl(),
o.kind.lock_ro().get_name().spl(),
])
.spl(),
];
stack.push(
Value::Array(
o.property_map
.iter()
.map(|(k, v)| Value::Array(vec![k.clone().spl(), v.clone()]).spl())
.chain(additional.into_iter())
.collect(),
)
.spl(),
);
Ok(())
}
pub fn from_properties(stack: &mut Stack) -> OError {
require_array_on_stack!(props, stack, "from-properties");
let mut map = HashMap::with_capacity(props.len());
for prop in props {
require_array!(prop, prop, stack, "from-properties");
if prop.len() != 2 {
stack.err(ErrorKind::InvalidCall("from-properties".to_string()))?;
}
let Value::Str(ref s) = prop[0].lock_ro().native else {
return Err(stack.error(ErrorKind::InvalidCall("from-properties".to_string())));
};
map.insert(s.to_owned(), prop[1].clone());
}
let Value::Str(kind) = map
.get(":")
.ok_or(stack.error(ErrorKind::InvalidCall("from-properties".to_string())))?
.lock_ro()
.native
.clone()
else {
return Err(stack.error(ErrorKind::InvalidCall("from-properties".to_string())));
};
let kind = runtime(|rt| rt.get_type_by_name(&kind))
.ok_or(stack.error(ErrorKind::TypeNotFound(kind.to_owned())))?;
let native = map
.get(";")
.ok_or(stack.error(ErrorKind::InvalidCall("from-properties".to_owned())))?
.lock_ro()
.native
.clone();
map.remove(";");
map.remove(":");
stack.push(Arc::new(Mut::new(Object {
kind,
native,
property_map: map,
})));
Ok(())
}
pub fn register(r: &mut Stack, o: Arc<Frame>) {
type Fn = fn(&mut Stack) -> OError;
let fns: [(&str, Fn, u32); 59] = [
let fns: [(&str, Fn, u32); 61] = [
("pop", pop, 0),
("dup", dup, 2),
("dup2", dup2, 3),
@ -992,6 +1056,8 @@ pub fn register(r: &mut Stack, o: Arc<Frame>) {
("str-readf", str_readf, 1),
("str-to-mega-radix", str_to_mega_radix, 1),
("mega-to-str-radix", mega_to_str_radix, 1),
("properties", properties, 1),
("from-properties", from_properties, 1),
];
for f in fns {
r.define_func(

View file

@ -5,6 +5,7 @@
"#server.spl" import
"#time.spl" import
"#httpserver/base.spl" import
"#linkedlist.spl" import
"SPL tester" =program-name
@ -236,6 +237,54 @@ func main { int | with args ;
"hello! this is a test of URL encoding!" net:http:urlencode dup println;
net:http:urldecode println;
"" println;
"testing linked lists" println;
def list LinkedList:new =list
"=> len of an empty list: " print;
list:len println;
"=> len of a list with one element: " print;
list:push;<"Hello!">
list:len println;
"=> list should not have a next yet... " print;
list:next null eq dup if { "ok" swap } not if { "BAD" } println
"=> element zero should be 'Hello!': " print list:get<0> println;
"=> iter of list should start with that too: " print list:iter dup:next println;
"=> then should be null: " print :next dup null eq if { pop "ok" } println;
"=> list should contain 'Hello!': " print list:iter:join<", "> println;
"=> with new element after that: " print
list:push;<"One!!">
list:iter:join<", "> println;
"=> pushing numbers 2..10: " print
2 10 Range:new:iter:foreach;<{ | list:push; }>
list:iter:join<", "> println;
"=> popping 9: " print
list:pop;
list:iter:join<", "> println;
"=> removing 5: " print
list:remove<5> =list pop
list:iter:join<", "> println;
"=> popping front: " print
list:pop-front =list pop
list:iter:join<", "> println;
"=> inserting 0 back: " print
0 list:insert<0> =list
list:iter:join<", "> println;
"=> inserting 5 back: " print
5 list:insert<5> =list
list:iter:join<", "> println;
5 :foreach<{ | "" println }>