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 (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"gitlab.com/whom/shs/ast"
|
||||
"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()
|
||||
}
|
||||
|
||||
/* 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,
|
||||
},
|
||||
|
||||
"slice": &ast.Function{
|
||||
Function: Slice,
|
||||
Name: "slice",
|
||||
TimesCalled: 0,
|
||||
Args: 3,
|
||||
},
|
||||
|
||||
"export": &ast.Function{
|
||||
Function: Export,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue