From 574094cc8a7d4d963708954e4a4bbad965b314c3 Mon Sep 17 00:00:00 2001 From: Milos Gligoric Date: Wed, 10 Jan 2024 11:34:19 -0600 Subject: [PATCH 1/3] Add cpu functions --- src/container/list.sh | 522 ------------------------------------- src/container/list_test.sh | 375 -------------------------- src/container/p.sh | 1 - src/lang/p.sh | 1 + src/lang/runtime.sh | 38 +++ src/lang/runtime_test.sh | 35 +++ 6 files changed, 74 insertions(+), 898 deletions(-) delete mode 100644 src/container/list.sh delete mode 100644 src/container/list_test.sh create mode 100644 src/lang/runtime.sh create mode 100644 src/lang/runtime_test.sh diff --git a/src/container/list.sh b/src/container/list.sh deleted file mode 100644 index 9e18e2a..0000000 --- a/src/container/list.sh +++ /dev/null @@ -1,522 +0,0 @@ -#!/bin/bash -# -# https://github.com/EngineeringSoftware/gobash/blob/main/LICENSE -# -# Doubly linked list. -# -# This directly corresponds to https://pkg.go.dev/container/list -# (src/container/list/list.go). Therefore, please check documentation -# for list.go for any method of interest. - -if [ -n "${CONTAINER_LIST_MOD:-}" ]; then return 0; fi -readonly CONTAINER_LIST_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) - -. ${CONTAINER_LIST_MOD}/../lang/p.sh -. ${CONTAINER_LIST_MOD}/../util/p.sh - - -# ---------- -# Functions. - -function container_Element() { - # Construct an element of a list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } - shift 0 || { ctx_wn $ctx; return $EC; } - - make_ $ctx \ - "$FUNCNAME" \ - "value" "$NULL" \ - "_next" "$NULL" \ - "_prev" "$NULL" \ - "_list" "$NULL" -} - -function container_Element_next() { - # Get the next element. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } - local -r e="${1}" - shift 1 || { ctx_wn $ctx; return $EC; } - - [ -z "$e" ] && { ctx_w $ctx "e cannot be empty"; return $EC; } - is_null $ctx "$e" && { ctx_w $ctx "e cannot be null"; return $EC; } - - local l - l=$($e $ctx _list) || { ctx_w $ctx "cannot get list"; return $EC; } - is_null $ctx "$l" && echo "$NULL" && return 0 - - local p - p=$($e $ctx _next) || { ctx_w $ctx "cannot get next"; return $EC; } - - local r - r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } - - [ "$p" = "$r" ] && echo "$NULL" && return 0 - echo "$p" -} - -function container_Element_prev() { - # Get the previous element. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } - local -r e="${1}" - shift 1 || { ctx_wn $ctx; return $EC; } - - [ -z "$e" ] && { ctx_w $ctx "e cannot be empty"; return $EC; } - is_null $ctx "$e" && { ctx_w $ctx "e cannot be null"; return $EC; } - - local l - l=$($e $ctx _list) || { ctx_w $ctx "cannot get list"; return $EC; } - is_null $ctx "$l" && return "$NULL" - - local p - p=$($e $ctx _prev) || { ctx_w $ctx "cannot get prev"; return $EC; } - - local r - r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } - - [ "$p" = "$r" ] && echo "$NULL" && return 0 - echo "$p" -} - -function container_List() { - # Construct a doubly linked list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } - shift 0 || { ctx_wn $ctx; return $EC; } - - local e - e=$(container_Element $ctx) || return $EC - - local l - l=$(make_ $ctx "$FUNCNAME" \ - "_root" "$e" \ - "_len" 0) || return $EC - - $l $ctx init -} - -function container_List_init() { - # Init a list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - shift 1 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - local r - r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } - - $r $ctx _next "$r" || { ctx_w $ctx "cannot set next"; return $EC; } - $r $ctx _prev "$r" || { ctx_w $ctx "cannot set prev"; return $EC; } - $l $ctx _len 0 || { ctx_w $ctx "cannot set len"; return $EC; } - - echo "$l" -} - -function container_List_len() { - # Return length of a list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - shift 1 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - $l $ctx _len -} - -function container_List_front() { - # Return element at the front. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - shift 1 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - local len - len=$($l $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } - [ "${len}" -eq 0 ] && echo "$NULL" && return 0 - - local r - r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } - - local n - n=$($r $ctx _next) || { ctx_w $ctx "cannot get next"; return $EC; } - echo "$n" -} - -function container_List_back() { - # Return element at the back. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - shift 1 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - local len - len=$($l $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } - [ "${len}" -eq 0 ] && echo "$NULL" && return 0 - - local r - r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } - - local p - p=$($r $ctx _prev) || { ctx_w $ctx "cannot get prev"; return $EC; } - echo "$p" -} - -function _container_List_lazy_init() { - # Lazy init the given list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - shift 1 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - local r - r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } - - if [ "$($r $ctx _next)" = "$NULL" ]; then - $l $ctx init || { ctx_w $ctx "cannot init"; return $EC; } - fi -} - -function _container_List_insert() { - # Insert an element at the given element. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - local -r at="${3}" - shift 3 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$e" && return $EC - is_null $ctx "$at" && return $EC - - $e $ctx _prev "$at" || { ctx_w $ctx "cannot set prev"; return $EC; } - - $e $ctx _next "$($at $ctx _next)" || \ - { ctx_w $ctx "cannot set next"; return $EC; } - - $($e $ctx _prev) $ctx _next "$e" || \ - { ctx_w $ctx "cannot set next"; return $EC; } - - $($e $ctx _next) $ctx _prev "$e" || \ - { ctx_w $ctx "cannot set prev"; return $EC; } - - $e $ctx _list "$l" || { ctx_w $ctx "cannot set list"; return $EC; } - - $l $ctx _len "$(( $($l $ctx _len) + 1 ))" || \ - { ctx_w $ctx "cannot set len"; return $EC; } - - echo "$e" -} - -function _container_List_insert_value() { - # Insert a value at the given element. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r v="${2}" - local -r at="${3}" - shift 3 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$at" && return $EC - - local e - e=$(container_Element $ctx) || \ - { ctx_w $ctx "cannot make an element"; return $EC; } - - $e $ctx value "$v" || { ctx_w $ctx "cannot set value"; return $EC; } - - _container_List_insert $ctx "$l" "$e" "$at" || \ - { ctx_w $ctx "cannot insert element"; return $EC; } -} - -function _container_List_remove() { - # Remove the given element from the list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - $($e $ctx _prev) $ctx _next "$($e $ctx _next)" - $($e $ctx _next) $ctx _prev "$($e $ctx _prev)" - $e $ctx _next "$NULL" - $e $ctx _prev "$NULL" - $e $ctx _list "$NULL" - $l $ctx _len "$(( $($l $ctx _len) - 1 ))" -} - -function _container_List_move() { - # Move the given element to the given element. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - local -r at="${3}" - shift 3 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - [ "$e" = "$at" ] && return 0 - - $($e $ctx _prev) $ctx _next "$($e $ctx _next)" - $($e $ctx _next) $ctx _prev "$($e $ctx _prev)" - - $e $ctx _prev "$at" - $e $ctx _next "$($at _next)" - $($e $ctx _prev) $ctx _next "$e" - $($e $ctx _next) $ctx _prev "$e" -} - -function container_List_remove() { - # Remove the given element from this list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$e" && return $EC - - if [ "$($e $ctx _list)" = "$l" ]; then - _container_List_remove $ctx "$l" "$e" || \ - { ctx_w $ctx "cannot remove"; return $EC; } - fi - echo "$($e $ctx value)" -} - -function container_List_push_front() { - # Push a value to the front of this list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r v="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - _container_List_lazy_init $ctx "$l" || \ - { ctx_w $ctx "cannot lazy init"; return $EC; } - - local -r r=$($l $ctx _root) - _container_List_insert_value $ctx "$l" "$v" "$r" || \ - { ctx_w $ctx "cannot insert value"; return $EC; } -} - -function container_List_push_back() { - # Push a value to the back of this list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r v="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - - _container_List_lazy_init $ctx "$l" || \ - { ctx_w $ctx "cannot lazy init"; return $EC; } - - local -r r=$($l $ctx _root) - _container_List_insert_value $ctx "$l" "$v" "$($r $ctx _prev)" || \ - { ctx_w $ctx "cannot insert value"; return $EC; } -} - -function container_List_insert_before() { - # Insert a value before the marker element. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r v="${2}" - local -r mark="${3}" - shift 3 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$mark" && return $EC - - [ "$($mark $ctx _list)" != "$l" ] && echo "$NULL" && return 0 - - _container_List_insert_value $ctx "$l" "$v" "$($mark $ctx _prev)" || \ - { ctx_w $ctx "cannot insert value"; return $EC; } -} - -function container_List_insert_after() { - # Insert a value after the marker element. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r v="${2}" - local -r mark="${3}" - shift 3 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$mark" && return $EC - - [ "$($mark $ctx _list)" != "$l" ] && echo "$NULL" && return 0 - - _container_List_insert_value $ctx "$l" "$v" "$mark" || \ - { ctx_w $ctx "cannot insert value"; return $EC; } -} - -function container_List_move_to_front() { - # Move element to the front of the list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && { ctx_w $ctx "list cannot be null"; return $EC; } - is_null $ctx "$e" && { ctx_w $ctx "element cannot be null"; return $EC; } - - [ "$($e $ctx _list)" != "$l" ] && return 0 - - _container_List_move $ctx "$l" "$e" "$($l $ctx _root)" || \ - { ctx_w $ctx "cannot move"; return $EC; } -} - -function container_List_move_to_back() { - # Move element to the back of the list. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$e" && return $EC - - [ "$($e $ctx _list)" != "$l" ] && return 0 - - _container_List_move $ctx "$l" "$e" "$($($l $ctx _root) $ctx _prev)" || \ - { ctx_w $ctx "cannot move"; return $EC; } -} - -function container_List_move_before() { - # Move element before the given marker. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - local -r mark="${3}" - shift 3 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$e" && return $EC - is_null $ctx "$mark" && return $EC - - [ "$e" = "$mark" ] && return 0 - [ "$($e $ctx _list)" != "$l" ] && return 0 - [ "$($mark $ctx _list)" != "$l" ] && return 0 - - _container_List_move $ctx "$l" "$e" "$($mark $ctx _prev)" || \ - { ctx_w $ctx "cannot move"; return $EC; } -} - -function container_List_move_after() { - # Move element after the given marker. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r e="${2}" - local -r mark="${3}" - shift 3 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$e" && return $EC - is_null $ctx "$mark" && return $EC - - [ "$e" = "$mark" ] && return 0 - [ "$($e $ctx _list)" != "$l" ] && return 0 - [ "$($mark $ctx _list)" != "$l" ] && return 0 - - _container_List_move $ctx "$l" "$e" "$mark" || \ - { ctx_w $ctx "cannot move"; return $EC; } -} - -function container_List_push_back_list() { - # Push one list at the end of another. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r other="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$other" && return $EC - - _container_List_lazy_init $ctx "$l" || \ - { ctx_w $ctx "cannot lazy init"; return $EC; } - - local i - i=$($other $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } - - local e - e=$($other $ctx front) || { ctx_w $ctx "cannot get front"; return $EC; } - - for (( ; i>0; i-- )); do - _container_List_insert_value $ctx "$l" "$($e value)" "$($($l _root) _prev)" || \ - { ctx_w $ctx "cannot insert value"; return $EC; } - e=$($e $ctx next) || { ctx_w $ctx "cannot get next"; return $EC; } - done -} - -function container_List_push_front_list() { - # Push one list to the front of another. - local ctx; is_ctx "${1}" && ctx="${1}" && shift - [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } - local -r l="${1}" - local -r other="${2}" - shift 2 || { ctx_wn $ctx; return $EC; } - - [ -z "$l" ] && return $EC - is_null $ctx "$l" && return $EC - is_null $ctx "$other" && return $EC - - _container_List_lazy_init $ctx "$l" || \ - { ctx_w $ctx "cannot lazy init"; return $EC; } - - local i - i=$($other $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } - - local e - e=$($other $ctx back) || { ctx_w $ctx "cannot get back"; return $EC; } - - for (( ; i>0; i-- )); do - _container_List_insert_value $ctx "$l" "$($e value)" "$($l _root)" || \ - { ctx_w $ctx "cannot insert value"; return $EC; } - e=$($e $ctx prev) || { ctx_w $ctx "cannot get prev"; return $EC; } - done -} diff --git a/src/container/list_test.sh b/src/container/list_test.sh deleted file mode 100644 index 9720ea6..0000000 --- a/src/container/list_test.sh +++ /dev/null @@ -1,375 +0,0 @@ -#!/bin/bash -# -# https://github.com/EngineeringSoftware/gobash/blob/main/LICENSE -# -# Unit tests for the list module. - -if [ -n "${CONTAINER_LIST_TEST_MOD:-}" ]; then return 0; fi -readonly CONTAINER_LIST_TEST_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) - -. ${CONTAINER_LIST_TEST_MOD}/list.sh -. ${CONTAINER_LIST_TEST_MOD}/../testing/bunit.sh - - -# ---------- -# Functions. - -function test_container_list_new() { - local -r l=$(container_List) - - [ "$($l len)" -eq 0 ] || assert_fail -} -readonly -f test_container_list_new - -function test_container_list_push_back() { - local -r l=$(container_List) - - $l push_back 3 - $l push_back 4 - $l push_back 10 - - [ "$($l len)" -eq 3 ] || assert_fail - - local e - local v - - e=$($l front) || assert_fail - v=$($e value) || assert_fail - [ "${v}" = "3" ] || assert_fail - - e=$($l back) || assert_fail - v=$($e value) || assert_fail - [ "${v}" = 10 ] || assert_fail -} -readonly -f test_container_list_push_back - -function test_container_list_push_front() { - local l - l=$(container_List) || assert_fail - - $l push_front 3 - $l push_front 4 - $l push_front 10 - - [ "$($l len)" -eq 3 ] || assert_fail - - local e - local v - - e=$($l front) || assert_fail - v=$($e value) || assert_fail - [ "${v}" = 10 ] || assert_fail - - e=$($l back) || assert_fail - v=$($e value) || assert_fail - [ "${v}" = 3 ] || assert_fail -} -readonly -f test_container_list_push_front - -function test_container_list_remove() { - local l - l=$(container_List) - - $l push_back 3 - $l push_back 10 - $l push_back 55 - - [ "$($l len)" -eq 3 ] || assert_fail - - local e - local v - - e=$($l front) - $l remove "$e" || assert_fail - [ "$($l len)" -eq 2 ] || assert_fail - - e=$($l front) - v=$($e value) - [ "${v}" -eq 10 ] || assert_fail - - e=$($l back) - $l remove "$e" || assert_fail - [ "$($l len)" -eq 1 ] || assert_fail - - e=$($l front) - v=$($e value) - [ "${v}" -eq 10 ] || assert_fail - - e=$($l front) - $l remove "$e" || assert_fail - [ "$($l len)" -eq 0 ] || assert_fail -} -readonly -f test_container_list_remove - -function test_container_list_remove_error() { - local l - l=$(container_List) - $l remove "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_remove_error - -function test_container_list_insert_before() { - local l - l=$(container_List) || assert_fail - - $l push_back 3 || assert_fail - - local e - local v - - e=$($l front) || assert_fail - $l insert_before 10 "$e" || assert_fail - - [ "$($l len)" -eq 2 ] || assert_fail - - e=$($l front) || assert_fail - v=$($e value) || assert_fail - [ "${v}" = 10 ] || assert_fail -} -readonly -f test_container_list_insert_before - -function test_container_list_insert_before_error() { - local l - l=$(container_List) - - $l insert_before 10 "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_insert_before_error - -function test_container_list_insert_after() { - local l - l=$(container_List) || assert_fail - - $l push_back 3 || assert_fail - - local e - local v - - e=$($l front) || assert_fail - $l insert_after 10 "$e" || assert_fail - - [ "$($l len)" -eq 2 ] || assert_fail - - e=$($l front) - v=$($e value) - [ "${v}" = 3 ] || assert_fail -} -readonly -f test_container_list_insert_after - -function test_container_list_insert_after_error() { - local l - l=$(container_List) - - $l insert_after 10 "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_insert_after_error - -function test_container_list_move_to_front() { - local l - l=$(container_List) - - $l push_back 3 - $l push_back 10 - - local e - local v - - e=$($l back) - $l move_to_front "$e" || assert_fail - - e=$($l front) - v=$($e value) - [ "${v}" = 10 ] || assert_fail "was ${v}" -} -readonly -f test_container_list_move_to_front - -function test_container_list_move_to_front_error() { - local l - l=$(container_List) - - $l move_to_front "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_move_to_front_error - -function test_container_list_move_to_back() { - local l - l=$(container_List) - - $l push_back 3 - $l push_back 10 - - local e - local v - - e=$($l front) - $l move_to_back "$e" || assert_fail - - e=$($l front) - v=$($e value) - [ "${v}" = 10 ] || assert_fail "was ${v}" -} -readonly -f test_container_list_move_to_back - -function test_container_list_move_to_back_error() { - local l - l=$(container_List) - - $l move_to_back "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_move_to_back_error - -function test_container_list_move_before() { - local l - l=$(container_List) - - $l push_back 3 - $l push_back 5 - $l push_back 10 - - local e1 - local e2 - local e3 - local v - - e1=$($l front) - e2=$($e1 next) - e3=$($e2 next) - - $l move_before "$e3" "$e2" || assert_fail - [ "$($l len)" = 3 ] || assert_fail - - e2=$($e1 next) - v=$($e2 value) - [ "${v}" = 10 ] || assert_fail -} -readonly -f test_container_list_move_before - -function test_container_list_move_before_error() { - local l - l=$(container_List) - - $l move_before "$NULL" "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_move_before_error - -function test_container_list_move_after() { - local l - l=$(container_List) - - $l push_back 3 - $l push_back 5 - $l push_back 10 - - local e1 - local e2 - local e3 - local v - - e1=$($l front) - e2=$($e1 next) - e3=$($e2 next) - - $l move_after "$e3" "$e1" || assert_fail - [ "$($l len)" = 3 ] || assert_fail - - e2=$($e1 next) - v=$($e2 value) - [ "${v}" = 10 ] || assert_fail -} -readonly -f test_container_list_move_after - -function test_container_list_move_after_error() { - local l - l=$(container_List) - - $l move_after "$NULL" "$NULL" - - return 0 -} -readonly -f test_container_list_move_after_error - -function test_container_list_push_back_list() { - local l1 - l1=$(container_List) - $l1 push_back 2 - $l1 push_back 3 - - local l2 - l2=$(container_List) - $l2 push_back 10 - $l2 push_back 20 - - $l1 push_back_list "$l2" || assert_fail - [ "$($l1 len)" -eq 4 ] || assert_fail - - local e - local v - - e=$($l1 front) - v=$($e value) - [ "${v}" -eq 2 ] || assert_fail - - e=$($l1 back) - v=$($e value) - [ "${v}" -eq 20 ] || assert_fail -} -readonly -f test_container_list_push_back_list - -function test_container_list_push_back_list_error() { - local l1 - l1=$(container_List) - - $l1 push_back_list "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_push_back_list_error - -function test_container_list_push_front_list() { - local l1 - l1=$(container_List) - $l1 push_back 2 - $l1 push_back 3 - - local l2 - l2=$(container_List) - $l2 push_back 10 - $l2 push_back 20 - - $l1 push_front_list "$l2" || assert_fail - [ "$($l1 len)" -eq 4 ] || assert_fail - - local e - local v - - e=$($l1 front) - v=$($e value) - [ "${v}" -eq 10 ] || assert_fail - - e=$($l1 back) - v=$($e value) - [ "${v}" -eq 3 ] || assert_fail -} -readonly -f test_container_list_push_front_list - -function test_container_list_push_front_list_error() { - local l1 - l1=$(container_List) - - $l1 push_front_list "$NULL" && assert_fail - - return 0 -} -readonly -f test_container_list_push_front_list_error diff --git a/src/container/p.sh b/src/container/p.sh index 97294b8..20663ca 100644 --- a/src/container/p.sh +++ b/src/container/p.sh @@ -8,4 +8,3 @@ if [ -n "${CONTAINER_PACKAGE:-}" ]; then return 0; fi readonly CONTAINER_PACKAGE=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) . ${CONTAINER_PACKAGE}/ring.sh -. ${CONTAINER_PACKAGE}/list.sh diff --git a/src/lang/p.sh b/src/lang/p.sh index fed7c13..7c2b782 100644 --- a/src/lang/p.sh +++ b/src/lang/p.sh @@ -10,6 +10,7 @@ readonly LANG_PACKAGE=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) . ${LANG_PACKAGE}/core.sh . ${LANG_PACKAGE}/unsafe.sh . ${LANG_PACKAGE}/os.sh +. ${LANG_PACKAGE}/runtime.sh . ${LANG_PACKAGE}/sys.sh . ${LANG_PACKAGE}/make.sh . ${LANG_PACKAGE}/log.sh diff --git a/src/lang/runtime.sh b/src/lang/runtime.sh new file mode 100644 index 0000000..a2e32f6 --- /dev/null +++ b/src/lang/runtime.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# https://github.com/EngineeringSoftware/gobash/blob/main/LICENSE +# +# Runtime functions. + +if [ -n "${LANG_RUNTIME_MOD:-}" ]; then return 0; fi +readonly LANG_RUNTIME_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +. ${LANG_RUNTIME_MOD}/core.sh + + +# ---------- +# Functions. + +function runtime_num_cpu() { + # Return the number of logical CPUs. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } + shift 0 || { ctx_wn $ctx; return $EC; } + + [ ! -f "/proc/cpuinfo" ] && \ + { ctx_w $ctx "no cpuinfo"; return $EC; } + + cat /proc/cpuinfo | grep 'processor' | wc -l +} + +function runtime_num_physical_cpu() { + # Return the number of physical CPUs. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } + shift 0 || { ctx_wn $ctx; return $EC; } + + [ ! -f "/proc/cpuinfo" ] && \ + { ctx_w $ctx "no cpuinfo"; return $EC; } + + cat /proc/cpuinfo | grep 'core id' | sort -u | wc -l +} diff --git a/src/lang/runtime_test.sh b/src/lang/runtime_test.sh new file mode 100644 index 0000000..32e1cc6 --- /dev/null +++ b/src/lang/runtime_test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# +# https://github.com/EngineeringSoftware/gobash/blob/main/LICENSE +# +# Unit tests for the runtime module. + +if [ -n "${LANG_RUNTIME_TEST_MOD:-}" ]; then return 0; fi +readonly LANG_RUNTIME_TEST_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +. ${LANG_RUNTIME_TEST_MOD}/assert.sh +. ${LANG_RUNTIME_TEST_MOD}/os.sh + + +# ---------- +# Functions. + +function test_runtime_num_cpu() { + local n + n=$(runtime_num_cpu) || assert_fail + + ! is_int "${n}" && assert_fail + [ "${n}" -lt 1 ] && assert_fail + return 0 +} +readonly -f test_runtime_num_cpu + +function test_runtime_num_physical_cpu() { + local n + n=$(runtime_num_physical_cpu) || assert_fail + + ! is_int "${n}" && assert_fail + [ "${n}" -lt 1 ] && assert_fail + return 0 +} +readonly -f test_runtime_num_physical_cpu From 0f0cc187b3a511604f29ad48b4287733f604e92f Mon Sep 17 00:00:00 2001 From: Milos Gligoric Date: Wed, 10 Jan 2024 11:35:17 -0600 Subject: [PATCH 2/3] Revert --- src/container/list.sh | 522 +++++++++++++++++++++++++++++++++++++ src/container/list_test.sh | 375 ++++++++++++++++++++++++++ src/container/p.sh | 1 + 3 files changed, 898 insertions(+) create mode 100644 src/container/list.sh create mode 100644 src/container/list_test.sh diff --git a/src/container/list.sh b/src/container/list.sh new file mode 100644 index 0000000..9e18e2a --- /dev/null +++ b/src/container/list.sh @@ -0,0 +1,522 @@ +#!/bin/bash +# +# https://github.com/EngineeringSoftware/gobash/blob/main/LICENSE +# +# Doubly linked list. +# +# This directly corresponds to https://pkg.go.dev/container/list +# (src/container/list/list.go). Therefore, please check documentation +# for list.go for any method of interest. + +if [ -n "${CONTAINER_LIST_MOD:-}" ]; then return 0; fi +readonly CONTAINER_LIST_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +. ${CONTAINER_LIST_MOD}/../lang/p.sh +. ${CONTAINER_LIST_MOD}/../util/p.sh + + +# ---------- +# Functions. + +function container_Element() { + # Construct an element of a list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } + shift 0 || { ctx_wn $ctx; return $EC; } + + make_ $ctx \ + "$FUNCNAME" \ + "value" "$NULL" \ + "_next" "$NULL" \ + "_prev" "$NULL" \ + "_list" "$NULL" +} + +function container_Element_next() { + # Get the next element. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } + local -r e="${1}" + shift 1 || { ctx_wn $ctx; return $EC; } + + [ -z "$e" ] && { ctx_w $ctx "e cannot be empty"; return $EC; } + is_null $ctx "$e" && { ctx_w $ctx "e cannot be null"; return $EC; } + + local l + l=$($e $ctx _list) || { ctx_w $ctx "cannot get list"; return $EC; } + is_null $ctx "$l" && echo "$NULL" && return 0 + + local p + p=$($e $ctx _next) || { ctx_w $ctx "cannot get next"; return $EC; } + + local r + r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } + + [ "$p" = "$r" ] && echo "$NULL" && return 0 + echo "$p" +} + +function container_Element_prev() { + # Get the previous element. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } + local -r e="${1}" + shift 1 || { ctx_wn $ctx; return $EC; } + + [ -z "$e" ] && { ctx_w $ctx "e cannot be empty"; return $EC; } + is_null $ctx "$e" && { ctx_w $ctx "e cannot be null"; return $EC; } + + local l + l=$($e $ctx _list) || { ctx_w $ctx "cannot get list"; return $EC; } + is_null $ctx "$l" && return "$NULL" + + local p + p=$($e $ctx _prev) || { ctx_w $ctx "cannot get prev"; return $EC; } + + local r + r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } + + [ "$p" = "$r" ] && echo "$NULL" && return 0 + echo "$p" +} + +function container_List() { + # Construct a doubly linked list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } + shift 0 || { ctx_wn $ctx; return $EC; } + + local e + e=$(container_Element $ctx) || return $EC + + local l + l=$(make_ $ctx "$FUNCNAME" \ + "_root" "$e" \ + "_len" 0) || return $EC + + $l $ctx init +} + +function container_List_init() { + # Init a list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + shift 1 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + local r + r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } + + $r $ctx _next "$r" || { ctx_w $ctx "cannot set next"; return $EC; } + $r $ctx _prev "$r" || { ctx_w $ctx "cannot set prev"; return $EC; } + $l $ctx _len 0 || { ctx_w $ctx "cannot set len"; return $EC; } + + echo "$l" +} + +function container_List_len() { + # Return length of a list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + shift 1 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + $l $ctx _len +} + +function container_List_front() { + # Return element at the front. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + shift 1 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + local len + len=$($l $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } + [ "${len}" -eq 0 ] && echo "$NULL" && return 0 + + local r + r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } + + local n + n=$($r $ctx _next) || { ctx_w $ctx "cannot get next"; return $EC; } + echo "$n" +} + +function container_List_back() { + # Return element at the back. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + shift 1 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + local len + len=$($l $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } + [ "${len}" -eq 0 ] && echo "$NULL" && return 0 + + local r + r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } + + local p + p=$($r $ctx _prev) || { ctx_w $ctx "cannot get prev"; return $EC; } + echo "$p" +} + +function _container_List_lazy_init() { + # Lazy init the given list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 1 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + shift 1 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + local r + r=$($l $ctx _root) || { ctx_w $ctx "cannot get root"; return $EC; } + + if [ "$($r $ctx _next)" = "$NULL" ]; then + $l $ctx init || { ctx_w $ctx "cannot init"; return $EC; } + fi +} + +function _container_List_insert() { + # Insert an element at the given element. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + local -r at="${3}" + shift 3 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$e" && return $EC + is_null $ctx "$at" && return $EC + + $e $ctx _prev "$at" || { ctx_w $ctx "cannot set prev"; return $EC; } + + $e $ctx _next "$($at $ctx _next)" || \ + { ctx_w $ctx "cannot set next"; return $EC; } + + $($e $ctx _prev) $ctx _next "$e" || \ + { ctx_w $ctx "cannot set next"; return $EC; } + + $($e $ctx _next) $ctx _prev "$e" || \ + { ctx_w $ctx "cannot set prev"; return $EC; } + + $e $ctx _list "$l" || { ctx_w $ctx "cannot set list"; return $EC; } + + $l $ctx _len "$(( $($l $ctx _len) + 1 ))" || \ + { ctx_w $ctx "cannot set len"; return $EC; } + + echo "$e" +} + +function _container_List_insert_value() { + # Insert a value at the given element. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r v="${2}" + local -r at="${3}" + shift 3 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$at" && return $EC + + local e + e=$(container_Element $ctx) || \ + { ctx_w $ctx "cannot make an element"; return $EC; } + + $e $ctx value "$v" || { ctx_w $ctx "cannot set value"; return $EC; } + + _container_List_insert $ctx "$l" "$e" "$at" || \ + { ctx_w $ctx "cannot insert element"; return $EC; } +} + +function _container_List_remove() { + # Remove the given element from the list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + $($e $ctx _prev) $ctx _next "$($e $ctx _next)" + $($e $ctx _next) $ctx _prev "$($e $ctx _prev)" + $e $ctx _next "$NULL" + $e $ctx _prev "$NULL" + $e $ctx _list "$NULL" + $l $ctx _len "$(( $($l $ctx _len) - 1 ))" +} + +function _container_List_move() { + # Move the given element to the given element. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + local -r at="${3}" + shift 3 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + [ "$e" = "$at" ] && return 0 + + $($e $ctx _prev) $ctx _next "$($e $ctx _next)" + $($e $ctx _next) $ctx _prev "$($e $ctx _prev)" + + $e $ctx _prev "$at" + $e $ctx _next "$($at _next)" + $($e $ctx _prev) $ctx _next "$e" + $($e $ctx _next) $ctx _prev "$e" +} + +function container_List_remove() { + # Remove the given element from this list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$e" && return $EC + + if [ "$($e $ctx _list)" = "$l" ]; then + _container_List_remove $ctx "$l" "$e" || \ + { ctx_w $ctx "cannot remove"; return $EC; } + fi + echo "$($e $ctx value)" +} + +function container_List_push_front() { + # Push a value to the front of this list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r v="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + _container_List_lazy_init $ctx "$l" || \ + { ctx_w $ctx "cannot lazy init"; return $EC; } + + local -r r=$($l $ctx _root) + _container_List_insert_value $ctx "$l" "$v" "$r" || \ + { ctx_w $ctx "cannot insert value"; return $EC; } +} + +function container_List_push_back() { + # Push a value to the back of this list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r v="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + + _container_List_lazy_init $ctx "$l" || \ + { ctx_w $ctx "cannot lazy init"; return $EC; } + + local -r r=$($l $ctx _root) + _container_List_insert_value $ctx "$l" "$v" "$($r $ctx _prev)" || \ + { ctx_w $ctx "cannot insert value"; return $EC; } +} + +function container_List_insert_before() { + # Insert a value before the marker element. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r v="${2}" + local -r mark="${3}" + shift 3 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$mark" && return $EC + + [ "$($mark $ctx _list)" != "$l" ] && echo "$NULL" && return 0 + + _container_List_insert_value $ctx "$l" "$v" "$($mark $ctx _prev)" || \ + { ctx_w $ctx "cannot insert value"; return $EC; } +} + +function container_List_insert_after() { + # Insert a value after the marker element. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r v="${2}" + local -r mark="${3}" + shift 3 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$mark" && return $EC + + [ "$($mark $ctx _list)" != "$l" ] && echo "$NULL" && return 0 + + _container_List_insert_value $ctx "$l" "$v" "$mark" || \ + { ctx_w $ctx "cannot insert value"; return $EC; } +} + +function container_List_move_to_front() { + # Move element to the front of the list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && { ctx_w $ctx "list cannot be null"; return $EC; } + is_null $ctx "$e" && { ctx_w $ctx "element cannot be null"; return $EC; } + + [ "$($e $ctx _list)" != "$l" ] && return 0 + + _container_List_move $ctx "$l" "$e" "$($l $ctx _root)" || \ + { ctx_w $ctx "cannot move"; return $EC; } +} + +function container_List_move_to_back() { + # Move element to the back of the list. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$e" && return $EC + + [ "$($e $ctx _list)" != "$l" ] && return 0 + + _container_List_move $ctx "$l" "$e" "$($($l $ctx _root) $ctx _prev)" || \ + { ctx_w $ctx "cannot move"; return $EC; } +} + +function container_List_move_before() { + # Move element before the given marker. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + local -r mark="${3}" + shift 3 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$e" && return $EC + is_null $ctx "$mark" && return $EC + + [ "$e" = "$mark" ] && return 0 + [ "$($e $ctx _list)" != "$l" ] && return 0 + [ "$($mark $ctx _list)" != "$l" ] && return 0 + + _container_List_move $ctx "$l" "$e" "$($mark $ctx _prev)" || \ + { ctx_w $ctx "cannot move"; return $EC; } +} + +function container_List_move_after() { + # Move element after the given marker. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 3 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r e="${2}" + local -r mark="${3}" + shift 3 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$e" && return $EC + is_null $ctx "$mark" && return $EC + + [ "$e" = "$mark" ] && return 0 + [ "$($e $ctx _list)" != "$l" ] && return 0 + [ "$($mark $ctx _list)" != "$l" ] && return 0 + + _container_List_move $ctx "$l" "$e" "$mark" || \ + { ctx_w $ctx "cannot move"; return $EC; } +} + +function container_List_push_back_list() { + # Push one list at the end of another. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r other="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$other" && return $EC + + _container_List_lazy_init $ctx "$l" || \ + { ctx_w $ctx "cannot lazy init"; return $EC; } + + local i + i=$($other $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } + + local e + e=$($other $ctx front) || { ctx_w $ctx "cannot get front"; return $EC; } + + for (( ; i>0; i-- )); do + _container_List_insert_value $ctx "$l" "$($e value)" "$($($l _root) _prev)" || \ + { ctx_w $ctx "cannot insert value"; return $EC; } + e=$($e $ctx next) || { ctx_w $ctx "cannot get next"; return $EC; } + done +} + +function container_List_push_front_list() { + # Push one list to the front of another. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 2 ] && { ctx_wn $ctx; return $EC; } + local -r l="${1}" + local -r other="${2}" + shift 2 || { ctx_wn $ctx; return $EC; } + + [ -z "$l" ] && return $EC + is_null $ctx "$l" && return $EC + is_null $ctx "$other" && return $EC + + _container_List_lazy_init $ctx "$l" || \ + { ctx_w $ctx "cannot lazy init"; return $EC; } + + local i + i=$($other $ctx _len) || { ctx_w $ctx "cannot get len"; return $EC; } + + local e + e=$($other $ctx back) || { ctx_w $ctx "cannot get back"; return $EC; } + + for (( ; i>0; i-- )); do + _container_List_insert_value $ctx "$l" "$($e value)" "$($l _root)" || \ + { ctx_w $ctx "cannot insert value"; return $EC; } + e=$($e $ctx prev) || { ctx_w $ctx "cannot get prev"; return $EC; } + done +} diff --git a/src/container/list_test.sh b/src/container/list_test.sh new file mode 100644 index 0000000..9720ea6 --- /dev/null +++ b/src/container/list_test.sh @@ -0,0 +1,375 @@ +#!/bin/bash +# +# https://github.com/EngineeringSoftware/gobash/blob/main/LICENSE +# +# Unit tests for the list module. + +if [ -n "${CONTAINER_LIST_TEST_MOD:-}" ]; then return 0; fi +readonly CONTAINER_LIST_TEST_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +. ${CONTAINER_LIST_TEST_MOD}/list.sh +. ${CONTAINER_LIST_TEST_MOD}/../testing/bunit.sh + + +# ---------- +# Functions. + +function test_container_list_new() { + local -r l=$(container_List) + + [ "$($l len)" -eq 0 ] || assert_fail +} +readonly -f test_container_list_new + +function test_container_list_push_back() { + local -r l=$(container_List) + + $l push_back 3 + $l push_back 4 + $l push_back 10 + + [ "$($l len)" -eq 3 ] || assert_fail + + local e + local v + + e=$($l front) || assert_fail + v=$($e value) || assert_fail + [ "${v}" = "3" ] || assert_fail + + e=$($l back) || assert_fail + v=$($e value) || assert_fail + [ "${v}" = 10 ] || assert_fail +} +readonly -f test_container_list_push_back + +function test_container_list_push_front() { + local l + l=$(container_List) || assert_fail + + $l push_front 3 + $l push_front 4 + $l push_front 10 + + [ "$($l len)" -eq 3 ] || assert_fail + + local e + local v + + e=$($l front) || assert_fail + v=$($e value) || assert_fail + [ "${v}" = 10 ] || assert_fail + + e=$($l back) || assert_fail + v=$($e value) || assert_fail + [ "${v}" = 3 ] || assert_fail +} +readonly -f test_container_list_push_front + +function test_container_list_remove() { + local l + l=$(container_List) + + $l push_back 3 + $l push_back 10 + $l push_back 55 + + [ "$($l len)" -eq 3 ] || assert_fail + + local e + local v + + e=$($l front) + $l remove "$e" || assert_fail + [ "$($l len)" -eq 2 ] || assert_fail + + e=$($l front) + v=$($e value) + [ "${v}" -eq 10 ] || assert_fail + + e=$($l back) + $l remove "$e" || assert_fail + [ "$($l len)" -eq 1 ] || assert_fail + + e=$($l front) + v=$($e value) + [ "${v}" -eq 10 ] || assert_fail + + e=$($l front) + $l remove "$e" || assert_fail + [ "$($l len)" -eq 0 ] || assert_fail +} +readonly -f test_container_list_remove + +function test_container_list_remove_error() { + local l + l=$(container_List) + $l remove "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_remove_error + +function test_container_list_insert_before() { + local l + l=$(container_List) || assert_fail + + $l push_back 3 || assert_fail + + local e + local v + + e=$($l front) || assert_fail + $l insert_before 10 "$e" || assert_fail + + [ "$($l len)" -eq 2 ] || assert_fail + + e=$($l front) || assert_fail + v=$($e value) || assert_fail + [ "${v}" = 10 ] || assert_fail +} +readonly -f test_container_list_insert_before + +function test_container_list_insert_before_error() { + local l + l=$(container_List) + + $l insert_before 10 "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_insert_before_error + +function test_container_list_insert_after() { + local l + l=$(container_List) || assert_fail + + $l push_back 3 || assert_fail + + local e + local v + + e=$($l front) || assert_fail + $l insert_after 10 "$e" || assert_fail + + [ "$($l len)" -eq 2 ] || assert_fail + + e=$($l front) + v=$($e value) + [ "${v}" = 3 ] || assert_fail +} +readonly -f test_container_list_insert_after + +function test_container_list_insert_after_error() { + local l + l=$(container_List) + + $l insert_after 10 "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_insert_after_error + +function test_container_list_move_to_front() { + local l + l=$(container_List) + + $l push_back 3 + $l push_back 10 + + local e + local v + + e=$($l back) + $l move_to_front "$e" || assert_fail + + e=$($l front) + v=$($e value) + [ "${v}" = 10 ] || assert_fail "was ${v}" +} +readonly -f test_container_list_move_to_front + +function test_container_list_move_to_front_error() { + local l + l=$(container_List) + + $l move_to_front "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_move_to_front_error + +function test_container_list_move_to_back() { + local l + l=$(container_List) + + $l push_back 3 + $l push_back 10 + + local e + local v + + e=$($l front) + $l move_to_back "$e" || assert_fail + + e=$($l front) + v=$($e value) + [ "${v}" = 10 ] || assert_fail "was ${v}" +} +readonly -f test_container_list_move_to_back + +function test_container_list_move_to_back_error() { + local l + l=$(container_List) + + $l move_to_back "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_move_to_back_error + +function test_container_list_move_before() { + local l + l=$(container_List) + + $l push_back 3 + $l push_back 5 + $l push_back 10 + + local e1 + local e2 + local e3 + local v + + e1=$($l front) + e2=$($e1 next) + e3=$($e2 next) + + $l move_before "$e3" "$e2" || assert_fail + [ "$($l len)" = 3 ] || assert_fail + + e2=$($e1 next) + v=$($e2 value) + [ "${v}" = 10 ] || assert_fail +} +readonly -f test_container_list_move_before + +function test_container_list_move_before_error() { + local l + l=$(container_List) + + $l move_before "$NULL" "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_move_before_error + +function test_container_list_move_after() { + local l + l=$(container_List) + + $l push_back 3 + $l push_back 5 + $l push_back 10 + + local e1 + local e2 + local e3 + local v + + e1=$($l front) + e2=$($e1 next) + e3=$($e2 next) + + $l move_after "$e3" "$e1" || assert_fail + [ "$($l len)" = 3 ] || assert_fail + + e2=$($e1 next) + v=$($e2 value) + [ "${v}" = 10 ] || assert_fail +} +readonly -f test_container_list_move_after + +function test_container_list_move_after_error() { + local l + l=$(container_List) + + $l move_after "$NULL" "$NULL" + + return 0 +} +readonly -f test_container_list_move_after_error + +function test_container_list_push_back_list() { + local l1 + l1=$(container_List) + $l1 push_back 2 + $l1 push_back 3 + + local l2 + l2=$(container_List) + $l2 push_back 10 + $l2 push_back 20 + + $l1 push_back_list "$l2" || assert_fail + [ "$($l1 len)" -eq 4 ] || assert_fail + + local e + local v + + e=$($l1 front) + v=$($e value) + [ "${v}" -eq 2 ] || assert_fail + + e=$($l1 back) + v=$($e value) + [ "${v}" -eq 20 ] || assert_fail +} +readonly -f test_container_list_push_back_list + +function test_container_list_push_back_list_error() { + local l1 + l1=$(container_List) + + $l1 push_back_list "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_push_back_list_error + +function test_container_list_push_front_list() { + local l1 + l1=$(container_List) + $l1 push_back 2 + $l1 push_back 3 + + local l2 + l2=$(container_List) + $l2 push_back 10 + $l2 push_back 20 + + $l1 push_front_list "$l2" || assert_fail + [ "$($l1 len)" -eq 4 ] || assert_fail + + local e + local v + + e=$($l1 front) + v=$($e value) + [ "${v}" -eq 10 ] || assert_fail + + e=$($l1 back) + v=$($e value) + [ "${v}" -eq 3 ] || assert_fail +} +readonly -f test_container_list_push_front_list + +function test_container_list_push_front_list_error() { + local l1 + l1=$(container_List) + + $l1 push_front_list "$NULL" && assert_fail + + return 0 +} +readonly -f test_container_list_push_front_list_error diff --git a/src/container/p.sh b/src/container/p.sh index 20663ca..97294b8 100644 --- a/src/container/p.sh +++ b/src/container/p.sh @@ -8,3 +8,4 @@ if [ -n "${CONTAINER_PACKAGE:-}" ]; then return 0; fi readonly CONTAINER_PACKAGE=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) . ${CONTAINER_PACKAGE}/ring.sh +. ${CONTAINER_PACKAGE}/list.sh From f5c191074c31be15f54a49620de4656892124935 Mon Sep 17 00:00:00 2001 From: Milos Gligoric Date: Wed, 10 Jan 2024 11:58:55 -0600 Subject: [PATCH 3/3] Add support for mac --- src/lang/bool.sh | 23 +++++++++++++++++++++++ src/lang/runtime.sh | 23 +++++++++++++++-------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/lang/bool.sh b/src/lang/bool.sh index 6104cfc..ed02d08 100644 --- a/src/lang/bool.sh +++ b/src/lang/bool.sh @@ -9,6 +9,7 @@ readonly BOOL_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) . ${BOOL_MOD}/bash.sh . ${BOOL_MOD}/core.sh +. ${BOOL_MOD}/os.sh # ---------- @@ -255,3 +256,25 @@ function is_bash5() { [ $(bash_version_major $ctx) = "5" ] } + +function is_linux() { + # Return true/0 if linux. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } + shift 0 || { ctx_wn $ctx; return $EC; } + + local name + name=$(os_name $ctx) + [ "${name}" = "${OS_LINUX}" ] +} + +function is_mac() { + # Return true/0 if mac. + local ctx; is_ctx "${1}" && ctx="${1}" && shift + [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } + shift 0 || { ctx_wn $ctx; return $EC; } + + local name + name=$(os_name $ctx) + [ "${name}" = "${OS_MAC}" ] +} diff --git a/src/lang/runtime.sh b/src/lang/runtime.sh index a2e32f6..6775b5a 100644 --- a/src/lang/runtime.sh +++ b/src/lang/runtime.sh @@ -8,6 +8,7 @@ if [ -n "${LANG_RUNTIME_MOD:-}" ]; then return 0; fi readonly LANG_RUNTIME_MOD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) . ${LANG_RUNTIME_MOD}/core.sh +. ${LANG_RUNTIME_MOD}/bool.sh # ---------- @@ -19,10 +20,13 @@ function runtime_num_cpu() { [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } shift 0 || { ctx_wn $ctx; return $EC; } - [ ! -f "/proc/cpuinfo" ] && \ - { ctx_w $ctx "no cpuinfo"; return $EC; } - - cat /proc/cpuinfo | grep 'processor' | wc -l + if is_mac; then + sysctl -n hw.logicalcpu_max + else + [ ! -f "/proc/cpuinfo" ] && \ + { ctx_w $ctx "no cpuinfo"; return $EC; } + cat /proc/cpuinfo | grep 'processor' | wc -l + fi } function runtime_num_physical_cpu() { @@ -31,8 +35,11 @@ function runtime_num_physical_cpu() { [ $# -ne 0 ] && { ctx_wn $ctx; return $EC; } shift 0 || { ctx_wn $ctx; return $EC; } - [ ! -f "/proc/cpuinfo" ] && \ - { ctx_w $ctx "no cpuinfo"; return $EC; } - - cat /proc/cpuinfo | grep 'core id' | sort -u | wc -l + if is_mac; then + sysctl -n hw.physicalcpu_max + else + [ ! -f "/proc/cpuinfo" ] && \ + { ctx_w $ctx "no cpuinfo"; return $EC; } + cat /proc/cpuinfo | grep 'core id' | sort -u | wc -l + fi }