
Very messy due to multiple characters in symbols, multiple spaces in a row and the lack of propper array in POSIX sh.
182 lines
5.0 KiB
Bash
Executable File
182 lines
5.0 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
heap_init() {
|
|
heap_max=0
|
|
}
|
|
|
|
alloc_cons_ptr_ptr_unit() {
|
|
# args: $1 must be an heap pointer (non-negative integer)
|
|
# $2 must be an heap pointer (non-negative integer)
|
|
# input: heap_max
|
|
# output: heap_max++ heap_type_$heap_max heap_car_$heap_max heap_cdr_$heap_max
|
|
# clobbers: none
|
|
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
|
|
|
|
# heap_max++
|
|
heap_max=$((heap_max+1))
|
|
# heap_type[heap_max] = C
|
|
eval heap_type_$heap_max=C
|
|
# heap_car[heap_max] = $1
|
|
eval heap_car_$heap_max='"'$1'"'
|
|
# heap_cdr[heap_max] = $2
|
|
eval heap_cdr_$heap_max='"'$2'"'
|
|
}
|
|
|
|
alloc_primitive_hex_unit() {
|
|
# args: $1 must be a hexadecimal string
|
|
# input: heap_max
|
|
# output: heap_max++ heap_type_$heap_max heap_value_$heap_max
|
|
# clobbers: none
|
|
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
|
|
|
|
# heap_max++
|
|
heap_max=$((heap_max+1))
|
|
# heap_type[heap_max] = P
|
|
eval heap_type_$heap_max=P
|
|
# heap_value[heap_max] = $1
|
|
eval heap_value_$heap_max='"'$1'"'
|
|
}
|
|
|
|
car() {
|
|
eval 'printf %s "$heap_car_'$1'"'
|
|
}
|
|
|
|
cdr() {
|
|
eval 'printf %s "$heap_cdr_'$1'"'
|
|
}
|
|
|
|
value() {
|
|
eval 'printf %s "$heap_value_'$1'"'
|
|
}
|
|
|
|
debug_print() {
|
|
eval 'tmpdebug=$heap_type_'"$1"
|
|
if test $tmpdebug = C; then
|
|
printf '('
|
|
eval 'tmpdebugb=$heap_car_'$1
|
|
(debug_print $tmpdebugb)
|
|
printf ' . '
|
|
eval 'tmpdebugb=$heap_cdr_'$1
|
|
(debug_print $tmpdebugb)
|
|
printf ')'
|
|
else
|
|
eval 'printf "[%s]" "$heap_value_'$1'"'
|
|
fi
|
|
}
|
|
|
|
stack_init_name_unit() {
|
|
eval "stacklast_${1}=0"
|
|
}
|
|
|
|
stack_push_name_hex_unit() {
|
|
# args: $1 must be an [a-z]+ name
|
|
# $2 must be a hexadecimal string
|
|
# input: stacklast_$1
|
|
# output: stacklast_$1 stack_$1_${!stacklast_$1+1}
|
|
# clobbers: stacklast
|
|
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
|
|
eval stacklast='${'stacklast_${1}'}'
|
|
stacklast=$((${stacklast}+1))
|
|
echo stack_${1}_${stacklast}='"'${2}'"'
|
|
eval stack_${1}_${stacklast}='"'${2}'"'
|
|
eval stacklast_${1}=${stacklast}
|
|
}
|
|
|
|
stack_len_name_int() {
|
|
# args: $1 must be an [a-z]+ name
|
|
# input: stacklast_$1
|
|
# output: stdout=${!stacklast_$1}
|
|
# clobbers: nothing
|
|
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
|
|
eval 'printf %s ${'stacklast_${1}'}'
|
|
}
|
|
|
|
stack_pop_name_result_unit() {
|
|
# args: $1 must be an [a-z]+ name
|
|
# input: stacklast_$1
|
|
# output: stacklast_$1 stack_$1_${!stacklast_$1}
|
|
# clobbers: stacklast
|
|
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
|
|
eval stacklast='${'stacklast_${1}'}'
|
|
eval $2'="${'stack_${1}_${stacklast}'}"'
|
|
stacklast=$((${stacklast}-1))
|
|
eval stacklast_${1}=${stacklast}
|
|
}
|
|
|
|
stack_peek_name_hex() {
|
|
# args: $1 must be an [a-z]+ name
|
|
# input: stacklast_$1 stack_$1_${!stacklast_$1}
|
|
# output: stdout
|
|
# clobbers: stacklast
|
|
# warning: does no attempt to escape ", \, $, space and so on in any of the inputs or outputs.
|
|
eval stacklast='${'stacklast_${1}'}'
|
|
eval 'printf %s "${'stack_${1}_${stacklast}'}"'
|
|
}
|
|
|
|
stack_init_name_unit parse_stack
|
|
stack_push_name_hex_unit parse ''
|
|
|
|
heap_init
|
|
alloc_primitive_hex_unit "Int 42"
|
|
alloc_primitive_hex_unit "Sym toto"
|
|
alloc_cons_ptr_ptr_unit 1 $heap_max
|
|
|
|
printf '(+ 1 ( + 22 345 ))' | \
|
|
od -v -A n -t x1 | sed -e 's/^ //' | tr ' ' \\n | (while read c; do
|
|
case "$c" in
|
|
# Open paren
|
|
28) if test "x$(stack_peek_name_hex parse)" = 'x'; then
|
|
stack_pop_name_result_unit parse current
|
|
fi
|
|
stack_push_name_hex_unit parse 2028
|
|
stack_push_name_hex_unit parse '';;
|
|
# Close paren
|
|
29) if test "x$(stack_peek_name_hex parse)" = 'x'; then
|
|
stack_pop_name_result_unit parse current
|
|
else
|
|
stack_pop_name_result_unit parse current
|
|
alloc_primitive_hex_unit "Sym $current"
|
|
stack_push_name_hex_unit parse $heap_max
|
|
fi
|
|
alloc_primitive_hex_unit "Nil"
|
|
cdr=$heap_max
|
|
while test "x$(stack_peek_name_hex parse)" != 'x2028'; do
|
|
stack_pop_name_result_unit parse current
|
|
car=$current
|
|
alloc_cons_ptr_ptr_unit $car $cdr
|
|
cdr=$heap_max
|
|
done
|
|
stack_pop_name_result_unit parse current
|
|
stack_push_name_hex_unit parse $cdr;;
|
|
# Space
|
|
20) if test "x$(stack_peek_name_hex parse)" != 'x'; then
|
|
stack_pop_name_result_unit parse current
|
|
alloc_primitive_hex_unit "Sym $current"
|
|
stack_push_name_hex_unit parse $heap_max
|
|
stack_push_name_hex_unit parse ''
|
|
fi;;
|
|
# identifier character
|
|
*) stack_pop_name_result_unit parse current
|
|
stack_push_name_hex_unit parse "$current$c";;
|
|
esac
|
|
done
|
|
|
|
echo stack:
|
|
|
|
while test "x$(stack_len_name_int parse)" != 'x0'; do
|
|
stack_pop_name_result_unit parse tmp
|
|
echo "$tmp"
|
|
done | tac
|
|
|
|
echo heap:
|
|
|
|
for i in `seq $heap_max`; do
|
|
eval "echo $i \$heap_type_$i \$heap_car_$i \$heap_cdr_$i \$heap_value_$i"
|
|
done
|
|
|
|
#echo $(value $(cdr $heap_max))
|
|
|
|
debug_print $heap_max
|
|
echo
|
|
)
|