Last active
August 29, 2015 14:00
-
-
Save mcilloni/11386147 to your computer and use it in GitHub Desktop.
Helm linked list sample (see http://github.com/mcilloni/first-step )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file is part of First Step. | |
# | |
# First Step is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software | |
# Foundation, either version 3 of the License, or (at your option) any later version. | |
# | |
# First Step is distributed in the hope that it will be useful, but | |
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU Lesser General Public License for more details. | |
# | |
# You should have received a copy of the GNU Lesser General Public License | |
# along with First Step. If not, see <http://www.gnu.org/licenses/> | |
# | |
# Copyright (C) Marco Cilloni <marco.cilloni@yahoo.com> 2014 | |
import libc | |
alias Lnode struct( | |
prec, succ ptr Lnode, | |
value uint64 | |
) | |
alias List struct( | |
start, end ptr Lnode, | |
len uint64, | |
current ptr Lnode, | |
pos uint64 | |
) | |
func list_seekAhead(list ptr List, pos uint64) | |
if (list'current == null) or (pos == 0) | |
list'current = list'start | |
list'pos = 0 | |
/if | |
while list'pos < pos | |
list'current = list'current'succ | |
list'pos++ | |
/while | |
/func | |
func list_seekBehind(list ptr List, pos uint64) | |
if (list'current == null) or ((list'len - 1) == pos) | |
list'current = list'end | |
list'pos = list'len - 1 | |
/if | |
while list'pos > pos | |
list'current = list'current'prec | |
list'pos-- | |
/while | |
/func | |
func list_seek(list ptr List, pos uint64) | |
if (list'current == null) and (pos == 0) | |
list'current = list'start | |
list'pos = 0 | |
/if | |
if pos > list'pos | |
list_seekAhead(list, pos) | |
else | |
if pos < list'pos | |
list_seekBehind(list, pos) | |
/if | |
/if | |
/func | |
func list_pushint(list ptr List, value uintptr) | |
var new = cast<ptr Lnode> libc:calloc(1, size(Lnode)) | |
new'succ = list'start | |
if list'start != null | |
list'start'prec = new | |
/if | |
if list'end == null | |
list'end = new | |
list'current = new | |
else | |
list'pos++ | |
/if | |
new'value = value | |
list'start = new | |
list'len++ | |
/func | |
var list_push = cast<ptr func(ptr List, data)> ptr list_pushint | |
func list_appendint(list ptr List, value uintptr) int64 | |
if list'start == null | |
list_pushint(list, value) | |
return 1 | |
/if | |
var new = cast<ptr Lnode> libc:calloc(1, size(Lnode)) | |
new'value = value | |
new'prec = list'end | |
list'end'succ = new | |
list'end = new | |
return cast<int64> list'len++ | |
/func | |
var list_append = cast<ptr func(ptr List, data) int64> ptr list_appendint | |
func list_addint(list ptr List, pos uint64, value uintptr) int64 | |
if pos > list'len | |
return -1 | |
/if | |
if pos == list'len | |
return list_appendint(list, value) | |
/if | |
list_seek(list, pos) | |
var new = cast<ptr Lnode> libc:calloc(1, size(Lnode)) | |
var prec = list'current'prec | |
if prec != null | |
prec'succ = new | |
/if | |
new'prec = prec | |
new'value = value | |
new'succ = list'current | |
list'current'prec = new | |
list'current = cast<ptr Lnode>(list'pos = 0) | |
list'len++ | |
return cast<int64> pos | |
/func | |
var list_add = cast<ptr func(ptr List, uint64, data) int64> ptr list_addint | |
func list_new() ptr List | |
return cast<ptr List> libc:calloc(1, size(List)) | |
/func | |
func list_extract(list ptr List, start uint64, len int64) ptr List | |
var extract = list_new() | |
if start < list'len | |
if len > list'len | |
len = cast<int64> (list'len - start) | |
/if | |
if len < 0 | |
len = cast<int64> (list'len - start) | |
/if | |
list_seek(list, start) | |
var prec = list'current'prec | |
var link1 ptr ptr Lnode | |
if prec != null | |
link1 = ptr prec'succ | |
else | |
link1 = ptr list'start | |
/if | |
extract'current = extract'start = extract'end = list'current | |
list_seek(list, start + len - 1) | |
var succ = list'current'succ | |
var link2 ptr ptr Lnode | |
if succ != null | |
link2 = ptr succ'prec | |
else | |
link2 = ptr list'end | |
/if | |
extract'end = list'current | |
extract'len = len | |
val link1 = succ | |
val link2 = prec | |
extract'start'prec = extract'end'succ = null | |
list'len = list'len - len | |
list'current = list'start | |
list'pos = 0 | |
/if | |
return extract | |
/func | |
decl free func(data) | |
func lnode_free(lnode ptr Lnode) | |
if lnode != null | |
lnode_free(lnode'succ) | |
free(lnode) | |
/if | |
/func | |
func list_free(list ptr List) | |
lnode_free(list'start) | |
free(list) | |
/func | |
func lnode_freeAll(lnode ptr Lnode, freefunc ptr func(data)) | |
if lnode != null | |
lnode_freeAll(lnode'succ, freefunc) | |
freefunc(cast<data> lnode'value) | |
free(lnode) | |
/if | |
/func | |
func list_freeAll(list ptr List, freefunc ptr func(data)) | |
lnode_freeAll(list'start, freefunc) | |
free(list) | |
/func | |
func lnode_freeContents(lnode ptr Lnode, freefunc ptr func(data)) | |
if lnode != null | |
lnode_freeContents(lnode'succ, freefunc) | |
freefunc(cast<data> lnode'value) | |
/if | |
/func | |
func list_freeContents(list ptr List, freefunc ptr func(data)) | |
lnode_freeContents(list'start, freefunc) | |
/func | |
func list_getint(list ptr List, pos uint64) ptr uintptr | |
if pos >= list'len | |
return null | |
/if | |
list_seek(list, pos) | |
if list'current != null | |
return ptr list'current'value | |
/if | |
return null | |
/func | |
var list_get = cast<ptr func(ptr List, uint64) ptr data> list_getint | |
func list_insertint(list ptr List, pos uint64, value uintptr) int64 | |
if pos > list'len | |
return -1 | |
/if | |
if pos == list'len | |
return list_appendint(list, value) | |
/if | |
list_seek(list, pos) | |
list'current'value = value | |
return cast<int64> list'pos | |
/func | |
var list_insert = cast<ptr func(ptr List, uint64, data) int64> list_insertint | |
func list_len(list ptr List) uint64 | |
return list'len | |
/func | |
decl memset func(data, uint64, uint64) | |
func list_popint(list ptr List) uintptr | |
if list'start == null | |
return 0 | |
/if | |
var next = list'start'succ | |
var ret = list'start'value | |
free(list'start) | |
next'prec = null | |
if list'start == list'end | |
memset(list, 0, size(List)) | |
else | |
list'start = next | |
/if | |
return ret | |
/func | |
var list_pop = cast<ptr func(data) data> list_popint | |
func list_prune(list ptr List) | |
lnode_free(list'start) | |
memset(list, 0, size(List)) | |
/func | |
func list_shallowCopy(list ptr List) ptr List | |
var new = list_new() | |
var len = list_len(list) | |
var i uint64 = 0 | |
while i < len | |
list_appendint(new, val list_getint(list, i)) | |
i++ | |
/while | |
return new | |
/func | |
func printlist(list ptr List) | |
var stdout libc:FILE = libc:stdout_file() | |
var inside = false | |
libc:fputs("[ ", stdout) | |
var len = list_len(list) | |
var i uint8 = 0 | |
while i < len | |
if inside | |
libc:fputs(", ",stdout) | |
else | |
inside = true | |
/if | |
libc:printint(val list_getint(list, i)) | |
i++ | |
/while | |
libc:puts(" ]") | |
/func | |
entry | |
var stdout libc:FILE = libc:stdout_file() | |
var list = list_new() | |
var i uint8 = 0 | |
while i < 31 | |
list_appendint(list, i) | |
i++ | |
/while | |
libc:fputs("list[] == ", stdout) | |
printlist(list) | |
var extract = list_extract(list, 3, 11) | |
libc:fputs("list[3:14] == ", stdout) | |
printlist(extract) | |
libc:fputs("list[] == ", stdout) | |
printlist(list) | |
list_free(extract) | |
extract = list_extract(list, 12, -1) | |
libc:fputs("list[12:] == ", stdout) | |
printlist(extract) | |
list_free(extract) | |
libc:fputs("list[] == ", stdout) | |
printlist(list) | |
libc:puts("list[3] <- 23") | |
list_addint(list, 3, 23) | |
libc:fputs("list[] == ", stdout) | |
printlist(list) | |
list_free(list) | |
/entry |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment