feat(package): hemar: antlr grammar, but still does not work

This commit is contained in:
2025-11-26 14:48:51 +00:00
parent 8a08272f68
commit 777d48bf3d
16 changed files with 282 additions and 7 deletions

View File

@@ -0,0 +1,38 @@
{ dash, hectic, symlinkJoin }:
let
shell = "${dash}/bin/dash";
bashOptions = [
"errexit"
"nounset"
];
test = hectic.writeShellApplication {
inherit shell bashOptions;
name = "hemar-test";
runtimeInputs = [ ];
text = ''
# shellcheck disable=SC2034
WORKSPACE=${./.}
${builtins.readFile hectic.helpers.posix-shell.log}
${builtins.readFile ./test.sh}
'';
};
hemar = hectic.writeShellApplication {
inherit shell bashOptions;
name = "hemar";
runtimeInputs = [ ];
text = ''
# shellcheck disable=SC2034
WORKSPACE=${./.}
${builtins.readFile hectic.helpers.posix-shell.log}
${builtins.readFile ./hemar.sh}
'';
};
in
symlinkJoin {
name = "hemar";
paths = [ hemar test ];
}

View File

@@ -0,0 +1,472 @@
#!/bin/dash
log notice "running"
# Syntax scheme:
#
# hemar
# elements
#
# elements
# element
# element ws elements
#
# element
# tag
# text
#
# text
# text-item
# text-item text
#
# text-item
# '0020' . '10FFFF' - '{'
# nopatern
#
# tag
# '{[' ws path ws ']}'
# '{[' ws loop-statement ws ']}'
# '{[' ws include-header ws ']}'
# '{[' ws "end" ws ']}'
# '{[' ws function ws ']}'
# '{[' ws '{[' ws ']}'
#
# # loop tag
# loop-statemant
# "for" string "in" path
#
# # include tag
# include-header
# "include" path
#
# # fucntion tag
# function
# "compute" language function-body
# "compute" - function-body
#
# language
# "dash"
# "plpgsql"
#
# function-body
# ""
# '0020' . '10FFFF', function-body
#
# function-character
# '0020' . '10FFFF' - ']'
# ncpatern
#
# # path
# path
# "."
# segmented-path
#
# segmented-path
# segment
# segment "." segmented-path
#
# segment
# string
# index
#
# index
# '\' digit
# '\' onenine digits
# '\' '-' digit
# '\' '-' onenine digits
#
# # types
# string
# character
# character string
#
# character
# '0020' . '10FFFF' - '"' - '\' - '.' - ']'
# '\' escape
# ncpatern
#
# escape
# '.'
# ']}'
# '"'
# '\'
# '/'
# 'b'
# 'f'
# 'n'
# 'r'
# 't'
# 'u' hex hex hex hex
# ws
#
# hex
# digit
# 'A' . 'F'
# 'a' . 'f'
#
# digits
# digit
# digit digits
#
# digit
# '0'
# onenine
#
# onenine
# '1' . '9'
#
# # paterns
# ws
# ""
# '\x20' ws
# '\x0a' ws
# '\x0d' ws
# '\x09' ws
#
# nopatern
# '{' '0020' . '10FFFF' - '['
#
# ncpatern
# ']' '0020' . '10FFFF' - '}'
# AST Plex:
#
# Type = 0..=5
#
# Text = string # just a text body
#
# Interpolation = string # path to variable
#
# Include = string # path to include data
#
# Section = {
# v = string # item variable name for loop
# p = string # path to array for iteration
# b = [Element] # section body
#
# }
#
# End = null
#
# Compute = {
# l = string # programing language
# b = string # function body
# }
#
# Element = {
# t = Type # element type
# b = Text # element body
# | Interpolation
# | Section
# | End
# | Include
# | Compute
# }
#
# AbstarctSyntaxTree (ATS) = {
# e = [Element] # elements array
# }
AST=$(mktemp)
AST_key='.'
trap 'rm -f "$AST"' EXIT INT HUP
yq -o j -i '.' "$AST"
log debug "AST path: ${WHITE}${AST}"
# 0 - text
# 1 - deside tag type
# 2 - interpolation
# 3 - section
# 4 - include
# 5 - compute
STAGE=0
# is_ws(char) -> bool
is_ws() {
ord=$(printf '%d' "'$1")
case $ord in
32|10|13|9) # <-> \x20 | \x0a | \x0d | \x09 <-> space | \n | \r | \t
return 0
;;
esac
return 1
}
# remove_last_double_quote(text) -> text
remove_last_double_quote() {
printf '%s' "$1" | sed 's/\(.*\)"\(.*\)/\1\2/'
}
#buf_read(buf?) -> text
buf_read() {
local buf
if [ ${1+x} ]; then
buf=${1}
else
buf=${CURRENT_STAGE_BUFFER}
fi
cat "$buf"
}
#buf_next()
buf_next() {
case "$CURRENT_STAGE_BUFFER" in
"$STAGE_BUFFER_1")
CURRENT_STAGE_BUFFER="$STAGE_BUFFER_2"
;;
"$STAGE_BUFFER_2")
CURRENT_STAGE_BUFFER="$STAGE_BUFFER_3"
;;
"$STAGE_BUFFER_3")
CURRENT_STAGE_BUFFER="$STAGE_BUFFER_4"
;;
"$STAGE_BUFFER_4")
CURRENT_STAGE_BUFFER="$STAGE_BUFFER_1"
;;
esac
}
buf_reset() {
: > "$STAGE_BUFFER_1"
: > "$STAGE_BUFFER_2"
: > "$STAGE_BUFFER_3"
: > "$STAGE_BUFFER_4"
CURRENT_STAGE_BUFFER="$STAGE_BUFFER_1"
}
STAGE_BUFFER_1="$(mktemp)"
STAGE_BUFFER_2="$(mktemp)"
STAGE_BUFFER_3="$(mktemp)"
STAGE_BUFFER_4="$(mktemp)"
CURRENT_STAGE_BUFFER=$STAGE_BUFFER_1
trap 'rm -f "$STAGE_BUFFER_1" "$STAGE_BUFFER_2" "$STAGE_BUFFER_3" "$STAGE_BUFFER_4"' EXIT INT HUP
log debug "stage buffer 1: ${WHITE}$STAGE_BUFFER_1"
log debug "stage buffer 2: ${WHITE}$STAGE_BUFFER_2"
log debug "stage buffer 3: ${WHITE}$STAGE_BUFFER_3"
log debug "stage buffer 4: ${WHITE}$STAGE_BUFFER_4"
# json_escape(value) -> str
json_escape() {
# TODO: escape functionality
printf '%s' "${1}" | sed 's/"/\\"/g'
}
# finds close pattern and store the char to the stage buffers separating by spaces
find_close_pattern() {
local buf char="${1:?}"
regular_char() {
[ ${TAG_ws_started+x} ] && {
unset TAG_ws_started
if [ "${TAG_first_ws_handled+x}" ]; then
buf_next
else
TAG_first_ws_handled=1
fi
}
printf '%s' "$1" >> "$CURRENT_STAGE_BUFFER"
}
if [ ! "${TAG_close_tag_flag+x}" ] && [ "$char" = ']' ]; then
TAG_close_tag_flag=1
elif [ "${TAG_close_tag_flag+x}" ]; then
unset TAG_close_tag_flag
if [ "$char" = '}' ]; then
log debug "cur buf: $WHITE$(cat "$STAGE_BUFFER_1")"
# removes first and last white spaces from the buffer
sed -i 's/[[:space:]]$//g' "$CURRENT_STAGE_BUFFER"
sed -i 's/^[[:space:]]//g' "$CURRENT_STAGE_BUFFER"
return 0
else
regular_char ']'"$char"
fi
else
# shellcheck disable=SC1003
case "$char" in
'"')
if [ "${TAG_escape_flag+x}" ]; then
unset TAG_escape_flag
else
if [ ${TAG_double_quote_flag+x} ]; then
unset TAG_double_quote_flag
return 1
else
TAG_double_quote_flag=1
return 1
fi
fi
;;
'\')
if [ "${TAG_escape_flag+x}" ]; then
unset TAG_escape_flag
else
TAG_escape_flag=1
return 1
fi
;;
*)
if [ "${TAG_escape_flag+x}" ]; then
if is_ws "$char"; then
unset TAG_escape_flag
else
log error "unexpected char \`$char\` after escape symbol"
exit 1
fi
elif is_ws "$char" && ! [ "${TAG_double_quote_flag+x}" ]; then
TAG_ws_started=1
return 1
fi
;;
esac
regular_char "$char"
fi
return 1
}
# finds open pattern and stores the char to the STAGE_BUFFER_1
find_open_pattern() {
local char="${1:?}"
if [ ! "${open_tag_flag+x}" ] && [ "$char" = '{' ]; then
open_tag_flag=1
elif [ "${open_tag_flag+x}" ]; then
unset open_tag_flag
if [ "$char" = '[' ]; then
return 0
else
printf '{%s' "$char" >> "$CURRENT_STAGE_BUFFER"
fi
else
printf '%s' "$char" >> "$CURRENT_STAGE_BUFFER"
fi
return 1
}
parse() {
char="$1"
case "$STAGE" in
# Text Stage - save char in STAGE_BUFFER_1 until next tag opens
0)
if find_open_pattern "$char"; then
log debug "open pattern founded"
buf=$(cat "$CURRENT_STAGE_BUFFER")
yq -o j -i "$AST_key += [{
\"type\": \"text\",
\"value\": \"$(json_escape "$buf")\"
}]" "$AST"
buf_reset
STAGE=1
fi
;;
1)
if find_close_pattern "$char"; then
case "$(cat "$STAGE_BUFFER_1")" in
compute)
log error 'compute unimplemented'
;;
include)
log error 'include unimplemented'
;;
for)
path=$STAGE_BUFFER_2
log error 'for unimplemented'
;;
end)
log error 'end unimplemented'
;;
'{[')
yq -o j -i "$AST_key += [{
\"type\": \"text\",
\"value\": \"{[\"
}]" "$AST"
;;
*) # interpolation tag
buf=$(cat "$STAGE_BUFFER_1")
yq -o j -i "$AST_key += [{
\"type\": \"interpolation\",
\"path\": \"$(json_escape "$buf")\"
}]" "$AST"
;;
esac
# zero-initialization
unset TAG_ws_started TAG_double_quote_flag TAG_escape_flag TAG_first_ws_handled TAG_close_tag_flag
buf_reset
STAGE=1
fi
;;
2)
;;
3)
;;
4)
;;
*)
log error "error: ${WHITE}impossible stage"
exit 13
;;
esac
}
while [ $# -gt 0 ]; do
case $1 in
-c|--compact-output)
OUTPUT_ARGS="${OUTPUT_ARGS+$OUTPUT_ARGS }-I=0"
shift
;;
--*|-*)
log error "argument $1 does not exists"
exit 9
;;
*)
log error "subcommand $1 does not exists"
exit 9
;;
esac
done
# Using dd to read one character at a time
input=$(cat)
i=1
while :; do
#log trace "loop"
char=$(printf '%s' "$input" | dd bs=1 skip=$((i-1)) count=1 2>/dev/null)
[ -z "$char" ] && break
parse "$char"
i=$((i+1))
done
# finish TEXT tag if file ends on it
if [ "$STAGE" -eq 0 ]; then
if [ "${open_tag_flag+x}" ]; then
unset open_tag_flag
printf '{' >> "$STAGE_BUFFER_1"
fi
buf=$(cat "$STAGE_BUFFER_1")
yq -o j -i "$AST_key += [{
\"type\": \"text\",
\"value\": \"$(json_escape "$buf")\"
}]" "$AST"
fi
# return the output
# shellcheck disable=SC2086
yq ${OUTPUT_ARGS:-} -o j "$AST"

View File

@@ -0,0 +1,70 @@
#!/bin/dash
plex_set() {
local structname key val regex base esc_key regex esc temp
structname=$1 key=$2 val=$3
# construct regex for ancestors
regex="^$key="
base=$key
while expr "$base" : '.*\.' >/dev/null; do
base=$(printf '%s\n' "$base" | sed 's/\.[^.]*$//')
esc=$(printf '%s\n' "$base" | sed 's/\./\\./g')
regex="$regex|^$esc="
done
# add descendants
esc_key="$(printf '%s\n' "$key" | sed 's/\./\\./g')"
regex="$regex|^${esc_key}\."
# remove old
# <plex>=$(printf '%s\n' "$<plex>" | grep -v -E "$regex")
temp="$(eval "printf '%s\\n' \"\$$structname\"" | grep -v -E "$regex")"
eval "$structname=\"\$temp\""
# add new
eval "$structname=\$(printf '%s\\n%s=%s\\n' \"\$$structname\" \"\$key\" \"\$val\")"
}
plex_child() {
local structname prefix
structname=$1 prefix=$2
eval printf '%s\\n' \"\$"$structname"\" \
| grep "^$prefix\." \
| sed "s|^$prefix\.||"
}
plex_val() {
local structname key
structname=$1 key=$2
eval printf '%s\n' \"\$"$structname"\" | grep "^$key=" | cut -d= -f2-
}
plex_fetch() {
local structname key
structname=$1 key=$2
if eval printf '%s\\n' \"\$"$structname"\" | grep -q "^$key="; then
eval printf '%s\\n' \"\$"$structname"\" | grep "^$key=" | cut -d= -f2-
else
eval printf '%s\\n' \"\$"$structname"\" | grep "^$key\." | sed "s|^$key\.||"
fi
}
plex_push() {
local structname prefix val max idx newidx kv
structname=${1:?}
prefix=${2:?}
val=${3:?}
# find max index
max=0
for kv in $(plex_fetch "$structname" "$prefix"); do
idx=${kv%%=*}
[ "$idx" -gt "$max" ] 2>/dev/null && max=$idx
done
newidx=$((max + 1))
plex_set "$structname" "$prefix.$newidx" "$val"
}

View File

@@ -0,0 +1,50 @@
#!/bin/dash
PLEX_TEMP="$(mktemp -d)"
#plex_set(name, key, value)
plex_set() {
local plexfile key val regex base esc_key esc
plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}" val="${3:?}"
find PLEX_
}
plex_child() {
local plexfile key
plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}"
grep "^$key\." "" | sed "s|^$key\.||"
}
plex_val() {
local plexfile key
plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}"
grep "^$key=" | cut -d= -f2- "$plexfile"
}
plex_fetch() {
local plexfile key temp
plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}"
if temp="$(grep "^$key=" | cut -d= -f2- "$plexfile")"; then
printf '%s' "$temp"
else
grep "^$key\." "" | sed "s|^$key\.||"
fi
}
plex_push() {
local plex prefix val max idx newidx kv
plex="${1:?}" prefix="${2:?}" val="${3:?}"
# find max index
max=0
for kv in $(plex_fetch "$plex" "$prefix"); do
idx=${kv%%=*}
[ "$idx" -gt "$max" ] 2>/dev/null && max=$idx
done
newidx=$((max + 1))
plex_set "$plex" "$prefix.$newidx" "$val"
}

View File

@@ -0,0 +1,40 @@
#!/bin/dash
PLEX_TEMP="$(mktemp -d)"
trap 'rm -rf $PLEX_TEMP' EXIT
#plex_set(name, key, value)
plex_set() {
local plexfile key val
plexfile="${PLEX_TEMP:?}/${1:?}.json" key="${2:?}" val="${3:?}"
touch "$plexfile"
yq -i ".$key = \"$val\"" "$plexfile"
}
#plex_child(name, key)
plex_child() {
plex_fetch "${1:?}" "${2:?}"
}
#plex_val(name, key)
plex_val() {
plex_fetch "${1:?}" "${2:?}"
}
#plex_val(name, key)
plex_fetch() {
local plexfile key
plexfile="${PLEX_TEMP:?}/${1:?}.json" key="${2:?}"
yq -r ".$key" "$plexfile"
}
#plex_push(name, prefix, val)
plex_push() {
local plexfile prefix val
plexfile="${PLEX_TEMP:?}/${1:?}.json" prefix="${2:?}" val="${3:?}"
yq -i ".$prefix += [\"$val\"]" "$plexfile"
}

View File

@@ -0,0 +1,21 @@
#!/bin/dash
init_plex() {
local backend
backend=${1:?}
case "$backend" in
env)
. ${WORKSPACE}/src/plex/backend/env_var.sh
;;
file)
. ${WORKSPACE}/src/plex/backend/file.sh
;;
yq-go)
. ${WORKSPACE}/src/plex/backend/yq-go.sh
;;
*)
exit 1
;;
esac
}

View File

@@ -0,0 +1,6 @@
#!/bin/dash
# shellcheck disable=SC1091
#. "${WORKSPACE:?}/test/plex/jq_backend_time.sh"
#. "${WORKSPACE:?}/test/plex/env_backend_time.sh"
. "${WORKSPACE:?}/test/plex/jq_backend.sh"

View File

@@ -0,0 +1,112 @@
#!/bin/dash
. "${WORKSPACE:?}/src/plex/plex.sh"
init_plex env
MY_STRUCT=''
math() {
awk "BEGIN {print $1}"
}
elapsed() {
local task time count decrease avg
task=$1
time=$2
count=$3
decrease=${4:-0}
avg=$(math "$time/$count-$decrease")
printf '\n[%s]\nelapsed %s seconds\n%s per second\n' \
"$task" "$avg" "$(math "1/$avg")" >&2
printf '%s' "$avg"
}
set_word_length() {
local length
length=${1:?}
# shellcheck disable=SC2183
__WORD_OFFSET_PATERN="$(printf '%*s' "$length" | tr ' ' '?')"
}
UNIQ_8_WORDS_COUNT=1000
DEFAULT_WORD_LENGTH=8
set_word_length "$DEFAULT_WORD_LENGTH"
randomword() {
local length
length=${1:-$DEFAULT_WORD_LENGTH}
LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c "$length"
}
WORDS=$(randomword $((8 * UNIQ_8_WORDS_COUNT)))
new_word() {
local prefix
prefix=${WORDS%"${WORDS#"$__WORD_OFFSET_PATERN"}"}
WORDS=${WORDS#"$__WORD_OFFSET_PATERN"}$prefix
printf '%s' "$prefix"
}
bench_set() {
local task depth count wordtime i start key d end
task=$1
depth=$2
count=$3
wordtime=$4
i=0
start=$(date +%s)
while [ "$i" -lt "$count" ]; do
key=$(new_word)
if [ "$depth" -gt 1 ]; then
d=1
while [ "$d" -lt "$depth" ]; do
key="$key.$(new_word)"
d=$((d + 1))
done
fi
plex_set 'MY_STRUCT' "$key" "$i"
i=$((i + 1))
done
end=$(date +%s)
elapsed "$task" "$((end - start))" "$count" "$(math "$wordtime*$depth")" >/dev/null
}
DEFAULT_TRIES=1000
ACCURATE_TRIES=10000
SUPPER_ACCURATE_TRIES=100000
WORD_CREATE_ACCURACY="$ACCURATE_TRIES"
BENCH_ACCURACY="$DEFAULT_TRIES"
count="$WORD_CREATE_ACCURACY"
set_word_length 8
i=0
start=$(date +%s)
while [ "$i" -lt "${count:?}" ]; do
new_word >/dev/null
i=$((i + 1))
done
end=$(date +%s)
wordtime=$(elapsed 'Word creation' "$((end - start))" "$count")
bench_set 'Set element with depth 1 length 8' 1 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 2 length 8' 2 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 3 length 8' 3 "$BENCH_ACCURACY" "$wordtime"
count="$WORD_CREATE_ACCURACY"
set_word_length 2
i=0
start=$(date +%s)
while [ "$i" -lt "${count:?}" ]; do
new_word >/dev/null
i=$((i + 1))
done
end=$(date +%s)
wordtime=$(elapsed 'Word creation' "$((end - start))" "$count")
bench_set 'Set element with depth 1 length 2' 1 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 2 length 2' 2 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 3 length 2' 3 "$BENCH_ACCURACY" "$wordtime"

View File

@@ -0,0 +1,19 @@
. "${WORKSPACE:?}/src/plex/plex.sh"
init_plex yq-go
plex_set ZALUPA zalupa apulaz
log error "struct:\n$WHITE$(yq . "$PLEX_TEMP/ZALUPA.json")$NC"
plex_set ZALUPA kek.zalupa apulaz
log error "struct:\n$WHITE$(yq . "$PLEX_TEMP/ZALUPA.json")$NC"
plex_set ZALUPA zalupa apulaz
log error "struct:\n$WHITE$(yq . "$PLEX_TEMP/ZALUPA.json")$NC"
plex_val ZALUPA zalupa
plex_child ZALUPA kek
plex_fetch ZALUPA kek

View File

@@ -0,0 +1,128 @@
#!/bin/dash
# shellcheck disable=SC1091
. "${WORKSPACE:?}/src/plex/plex.sh"
init_plex yq-go
math() {
awk "BEGIN {print $1}"
}
elapsed() {
local task time count decrease avg
task=$1
time=$2
count=$3
decrease=${4:-0}
avg=$(math "$time/$count-$decrease")
if [ "$time" -eq 0 ]; then
log info "\n[$WHITE${task}$NC]\ninstant\n"
else
log info "\n[$WHITE${task}$NC]\nelapsed $WHITE${avg}$NC seconds\n$WHITE$(math "1/$avg")$NC per second\n"
fi
printf '%s' "$avg"
}
set_word_length() {
local length
length=${1:?}
# shellcheck disable=SC2183
__WORD_OFFSET_PATERN="$(printf '%*s' "$length" | tr ' ' '?')"
}
UNIQ_8_WORDS_COUNT=1000
DEFAULT_WORD_LENGTH=8
set_word_length "$DEFAULT_WORD_LENGTH"
randomword() {
local length
length=${1:-$DEFAULT_WORD_LENGTH}
LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c "$length"
}
WORDS=$(randomword $((8 * UNIQ_8_WORDS_COUNT)))
WORDS=0123456789abcdefg
new_word() {
local prefix
# shellcheck disable=SC2295
prefix=${WORDS%"${WORDS#${__WORD_OFFSET_PATERN:?}}"}
# shellcheck disable=SC2295
WORDS=${WORDS#${__WORD_OFFSET_PATERN:?}}$prefix
printf '%s' "$prefix"
}
bench_set() {
local task depth count wordtime i start key d end
task=$1
depth=$2
count=$3
wordtime=$4
i=0
start=$(date +%s)
while [ "$i" -lt "$count" ]; do
key=$(new_word)
if [ "$depth" -gt 1 ]; then
d=1
while [ "$d" -lt "$depth" ]; do
key="$key.$(new_word)"
d=$((d + 1))
done
fi
set +e
plex_set 'MY_STRUCT' "$key" "$i"
error_code=$?
set -e
if [ $error_code != 0 ]; then
log error "key: $WHITE$key$NC, i: $WHITE$i$NC, struct: $WHITE$(jq . "$PLEX_TEMP/MY_STRUCT")$NC"
exit 1
fi
i=$((i + 1))
done
end=$(date +%s)
elapsed "$task" "$((end - start))" "$count" "$(math "$wordtime*$depth")" >/dev/null
}
DEFAULT_TRIES=1000
ACCURATE_TRIES=10000
SUPPER_ACCURATE_TRIES=100000
WORD_CREATE_ACCURACY="$SUPPER_ACCURATE_TRIES"
BENCH_ACCURACY="$DEFAULT_TRIES"
count="$WORD_CREATE_ACCURACY"
set_word_length 8
i=0
start=$(date +%s)
while [ "$i" -lt "${count:?}" ]; do
new_word >/dev/null
i=$((i + 1))
done
end=$(date +%s)
time=$((end - start))
log debug "word creation time: $time"
wordtime=$(elapsed 'Word creation' "$time" "$count")
bench_set 'Set element with depth 1 length 8' 1 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 2 length 8' 2 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 3 length 8' 3 "$BENCH_ACCURACY" "$wordtime"
log notice -
count="$WORD_CREATE_ACCURACY"
set_word_length 2
i=0
start=$(date +%s)
while [ "$i" -lt "${count:?}" ]; do
new_word >/dev/null
i=$((i + 1))
done
end=$(date +%s)
wordtime=$(elapsed 'Word creation' "$((end - start))" "$count")
bench_set 'Set element with depth 1 length 2' 1 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 2 length 2' 2 "$BENCH_ACCURACY" "$wordtime"
bench_set 'Set element with depth 3 length 2' 3 "$BENCH_ACCURACY" "$wordtime"