added slice function
This commit is contained in:
parent
15e294085c
commit
adff10b56a
2 changed files with 107 additions and 0 deletions
101
stdlib/list.go
101
stdlib/list.go
|
|
@ -19,6 +19,7 @@ package stdlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"gitlab.com/whom/shs/ast"
|
"gitlab.com/whom/shs/ast"
|
||||||
"gitlab.com/whom/shs/log"
|
"gitlab.com/whom/shs/log"
|
||||||
)
|
)
|
||||||
|
|
@ -144,3 +145,103 @@ func Tail(input *ast.Token, vars ast.VarTable, funcs ast.FuncTable) *ast.Token {
|
||||||
|
|
||||||
return iter.Copy()
|
return iter.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Slice
|
||||||
|
* Takes 3 args and returns a list
|
||||||
|
* Arg 1: starting index of sublist
|
||||||
|
* Arg 2: end index of sublist
|
||||||
|
* Arg 3: source list
|
||||||
|
* returns sublist, or nil if non list applied, or nil if start or end arent INTEGERS
|
||||||
|
* first index in a list is 0
|
||||||
|
*
|
||||||
|
* Example: (slice 1 2 (1 2 3)) -> (2 3)
|
||||||
|
* Example: (slice 0 0 (1 2 3)) -> (1)
|
||||||
|
*/
|
||||||
|
func Slice(input *ast.Token, vars ast.VarTable, funcs ast.FuncTable) *ast.Token {
|
||||||
|
input = input.Eval(funcs, vars, false)
|
||||||
|
start := input
|
||||||
|
end := input.Next
|
||||||
|
source := end.Next
|
||||||
|
|
||||||
|
if start.Tag != ast.NUMBER || end.Tag != ast.NUMBER {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"start and end must both be integers",
|
||||||
|
"slice")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if source.Tag != ast.LIST {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"non-list as parameter to head",
|
||||||
|
"head")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
st, err := strconv.ParseInt(start.Value(), 10, 64)
|
||||||
|
en, errr := strconv.ParseInt(end.Value(), 10, 64)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"couldnt parse integer from start value: " + err.Error(),
|
||||||
|
"slice")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if errr != nil {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"couldnt parse integer from end value: " + errr.Error(),
|
||||||
|
"slice")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if st < 0 || en < 0 {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"both indices must be positive",
|
||||||
|
"slice")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if st > en {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"end index must be greater than start index",
|
||||||
|
"slice")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
en = en - st
|
||||||
|
var inner *ast.Token
|
||||||
|
buildIter := &inner
|
||||||
|
sourceIter := source.Expand()
|
||||||
|
|
||||||
|
for st > 0 {
|
||||||
|
if sourceIter == nil {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"start index out of bounds",
|
||||||
|
"slice")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceIter = sourceIter.Next
|
||||||
|
st -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for en >= 0 {
|
||||||
|
if sourceIter == nil {
|
||||||
|
log.Log(log.ERR,
|
||||||
|
"end index out of bounds",
|
||||||
|
"slice")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
*buildIter = sourceIter.Copy()
|
||||||
|
(*buildIter).Next = nil
|
||||||
|
|
||||||
|
buildIter = &((*buildIter).Next)
|
||||||
|
sourceIter = sourceIter.Next
|
||||||
|
en -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := &ast.Token{Tag: ast.LIST}
|
||||||
|
ret.Direct(inner)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,12 @@ func GenFuncTable() ast.FuncTable {
|
||||||
Args: 1,
|
Args: 1,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"slice": &ast.Function{
|
||||||
|
Function: Slice,
|
||||||
|
Name: "slice",
|
||||||
|
TimesCalled: 0,
|
||||||
|
Args: 3,
|
||||||
|
},
|
||||||
|
|
||||||
"export": &ast.Function{
|
"export": &ast.Function{
|
||||||
Function: Export,
|
Function: Export,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue