matching
This commit is contained in:
parent
3445b27fa9
commit
215b6f2748
4 changed files with 184 additions and 4 deletions
72
spl/std.spl
72
spl/std.spl
|
@ -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 {
|
||||
|
|
42
src/lexer.rs
42
src/lexer.rs
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
44
test.spl
44
test.spl
|
@ -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 }>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue