This commit is contained in:
Daniella / Tove 2024-11-15 11:54:54 +01:00
parent 3445b27fa9
commit 215b6f2748
Signed by: TudbuT
GPG key ID: B3CF345217F202D3
4 changed files with 184 additions and 4 deletions

View file

@ -644,6 +644,78 @@ func times { | with amount callable ;
}
}
func check-match { bool | with input output ;
output gettype "func" eq if {
1 2 stop
}
input output eq if {
1 2 stop
}
output gettype "array" eq if {
def i, n
0 =i
output:len =n
input:len n eq not if { 0 2 stop }
1 while { i n lt } {
input:get<i> output:get<i> check-match and
i ++ =i
}
2 stop
}
0
}
func match-unchecked { | with input output ;
output gettype "func" eq if {
input output call
2 stop
}
output gettype "array" eq if {
def i, n
0 =i
output:len =n
input:len n eq not if { 2 stop }
while { i n lt } {
input:get<i> output:get<i> match-unchecked
i ++ =i
}
}
}
func match { bool | with input output ;
output gettype "func" eq if {
input output call
1 2 stop
}
input output eq if {
1 2 stop
}
output gettype "array" eq if {
def i, n
0 =i
output:len =n
input:len n eq not if { 0 2 stop }
1 while { i n lt } {
input:get<i> output:get<i> check-match and
i ++ =i
} dup if {
0 =i
while { i n lt } {
input:get<i> output:get<i> match-unchecked
i ++ =i
}
}
2 stop
}
0
}
func _'match-else-error { |
not if {
"match unsuccessful" throw
}
}
def _'has-been-called 0 =_'has-been-called
func _ { |
_'has-been-called not if {

View file

@ -78,6 +78,10 @@ fn read_block_dyn(
);
}
"def" => {
while let Some(w) = str_words[i + 1].strip_suffix(',') {
words.push(Word::Key(Keyword::Def(w.to_owned())));
i += 1;
}
words.push(Word::Key(Keyword::Def(str_words[i + 1].to_owned())));
i += 1;
}
@ -253,6 +257,44 @@ fn read_block_dyn(
}
words.push(Word::Key(Keyword::With(vars)));
}
"=" => {
if str_words[i + 1] == ">" {
i += 1;
let throwing = if str_words[i + 1] == "?" {
i += 1;
false
} else {
true
};
if str_words[i + 1] == "[" {
i += 1;
let mut block =
read_block_dyn(&str_words[i + 1..], false, "]".to_owned(), compat)?;
i += block.2 + 1;
words.push(Word::Call("[".to_owned(), false, 0));
words.append(&mut block.1.words);
words.push(Word::Call("]".to_owned(), false, 0));
} else {
words.append(
&mut read_block_dyn(
&[str_words[i + 1].clone()],
false,
"".to_owned(),
false,
)?
.1
.words,
);
i += 1;
}
words.push(Word::Call("match".to_owned(), false, 0));
if throwing {
words.push(Word::Call("_'match-else-error".to_owned(), false, 0));
}
} else {
words.push(Word::Call("=".to_owned(), false, 0));
}
}
"inline-callable" => {
words.push(Word::Key(Keyword::InlineCallable));
}

View file

@ -525,7 +525,7 @@ impl Stack {
ret_count: 1,
origin: Arc::new(Frame::dummy()),
to_call: FuncImpl::NativeDyn(Arc::new(Box::new(move |stack| {
stack.push(stack.get_frame().get_var(tmpname.clone(), stack)?);
stack.push(stack.get_var(tmpname.clone())?);
Ok(())
}))),
run_as_base: false,
@ -541,7 +541,7 @@ impl Stack {
origin: Arc::new(Frame::dummy()),
to_call: FuncImpl::NativeDyn(Arc::new(Box::new(move |stack| {
let v = stack.pop();
stack.get_frame().set_var(tmpname.clone(), v, stack)
stack.set_var(tmpname.clone(), v)
}))),
run_as_base: false,
fname: Some("RUNTIME".to_owned()),
@ -570,11 +570,33 @@ impl Stack {
}
pub fn set_var(&self, name: String, obj: AMObject) -> OError {
self.get_frame().set_var(name, obj, self)
if let Err(x) = self.get_frame().set_var(name.clone(), obj.clone(), self) {
for i in 1..self.frames.len() {
if self
.peek_frame(i)
.set_var(name.clone(), obj.clone(), self)
.is_ok()
{
return Ok(());
}
}
return Err(x);
}
Ok(())
}
pub fn get_var(&self, name: String) -> Result<AMObject, Error> {
self.get_frame().get_var(name, self)
match self.get_frame().get_var(name.clone(), self) {
Err(x) => {
for i in 1..self.frames.len() {
if let Ok(x) = self.peek_frame(i).get_var(name.clone(), self) {
return Ok(x);
}
}
Err(x)
}
Ok(x) => Ok(x),
}
}
pub fn push(&mut self, obj: AMObject) {

View file

@ -285,6 +285,50 @@ func main { int | with args ;
5 list:insert;<5>
list:iter:join<", "> println;
^ println
"testing match" println
"a -> b (0): " print "a" "b" match _str println
"a -> a (1): " print "a" "a" match _str println
"[a b] -> [a a] (0): " print [ "a" "b" ] [ "a" "a" ] match _str println
"[a b] -> [a b] (1): " print [ "a" "b" ] [ "a" "b" ] match _str println
def mtesta, mtestb
"a => =mtesta (1): " print "a" &=mtesta match _str println
"[a b] => [a =mtesta] (1): " print [ "a" "b" ] [ "a" &=mtesta ] match _str println
"[b a] => [a =mtesta] (0): " print [ "b" "a" ] [ "a" &=mtesta ] match _str println
"[a b] => [=mtesta a] (0): " print [ "b" "a" ] [ "a" &=mtesta ] match _str println
"-> mtesta = (b) " mtesta _str concat println
"^ok => ^ok (1): " print ^ok =>? ^ok _str println
"^bad => ^ok (0): " print ^bad =>? ^ok _str println
"[^bad a] => [^ok =mtestb] (0): " print [ ^bad "a" ] =>? [ ^ok &=mtestb ] _str println
"[^ok b] => [^ok =mtestb] (1): " print [ ^ok "b" ] =>? [ ^ok &=mtestb ] _str println
"-> mtestb = (b) " mtestb _str concat println
def result, val
[ ^ok "hello, world" ] =result
result => [ ^ok &=val ]
val println
[ ^error "bad" ] =result
catch Custom {
result => [ ^ok &println ]
} { with e ;
e:message "match unsuccessful" eq if {
"err value: " print
result => [ ^error &println ]
}
}
5 :foreach<{ | pop "" println }>