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
|
def _'has-been-called 0 =_'has-been-called
|
||||||
func _ { |
|
func _ { |
|
||||||
_'has-been-called not if {
|
_'has-been-called not if {
|
||||||
|
|
42
src/lexer.rs
42
src/lexer.rs
|
@ -78,6 +78,10 @@ fn read_block_dyn(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
"def" => {
|
"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())));
|
words.push(Word::Key(Keyword::Def(str_words[i + 1].to_owned())));
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -253,6 +257,44 @@ fn read_block_dyn(
|
||||||
}
|
}
|
||||||
words.push(Word::Key(Keyword::With(vars)));
|
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" => {
|
"inline-callable" => {
|
||||||
words.push(Word::Key(Keyword::InlineCallable));
|
words.push(Word::Key(Keyword::InlineCallable));
|
||||||
}
|
}
|
||||||
|
|
|
@ -525,7 +525,7 @@ impl Stack {
|
||||||
ret_count: 1,
|
ret_count: 1,
|
||||||
origin: Arc::new(Frame::dummy()),
|
origin: Arc::new(Frame::dummy()),
|
||||||
to_call: FuncImpl::NativeDyn(Arc::new(Box::new(move |stack| {
|
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(())
|
Ok(())
|
||||||
}))),
|
}))),
|
||||||
run_as_base: false,
|
run_as_base: false,
|
||||||
|
@ -541,7 +541,7 @@ impl Stack {
|
||||||
origin: Arc::new(Frame::dummy()),
|
origin: Arc::new(Frame::dummy()),
|
||||||
to_call: FuncImpl::NativeDyn(Arc::new(Box::new(move |stack| {
|
to_call: FuncImpl::NativeDyn(Arc::new(Box::new(move |stack| {
|
||||||
let v = stack.pop();
|
let v = stack.pop();
|
||||||
stack.get_frame().set_var(tmpname.clone(), v, stack)
|
stack.set_var(tmpname.clone(), v)
|
||||||
}))),
|
}))),
|
||||||
run_as_base: false,
|
run_as_base: false,
|
||||||
fname: Some("RUNTIME".to_owned()),
|
fname: Some("RUNTIME".to_owned()),
|
||||||
|
@ -570,11 +570,33 @@ impl Stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_var(&self, name: String, obj: AMObject) -> OError {
|
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> {
|
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) {
|
pub fn push(&mut self, obj: AMObject) {
|
||||||
|
|
44
test.spl
44
test.spl
|
@ -286,6 +286,50 @@ func main { int | with args ;
|
||||||
list:iter:join<", "> println;
|
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 }>
|
5 :foreach<{ | pop "" println }>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue