#!/usr/bin/env bash # interactive build and run menu, with the same commands as tinyvm.bat. set -u tinyvm_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) || exit 1 tinyvm_caller=$PWD cd -- "$tinyvm_root" || exit 1 usage() { cat <<'HELP' usage: tinyvm.sh [command] build [all|core|micro|tools|lsp] build executables run FILE.zc run on the native VM run-micro FILE.zc run on the portable microcore js FILE.zc run on the JavaScript VM lsp FILE.zc check a source file test [test options] run the full test suite check run the minimal test suite genome rebuild the compiler and verify the fixpoint repl start the resident compiler REPL clean remove generated build output help show this help with no command, open the interactive menu. HELP } build() { case "${1:-all}" in all) make ;; core) make bin/zy ;; micro) make bin/zym ;; tools) make bin/zc0 bin/mkgenome bin/genmap ;; lsp) make lsp ;; *) printf 'Unknown build target: %s\n' "$1" >&2; return 2 ;; esac } source_path() { local input=$1 if [[ $input != /* ]]; then input="$tinyvm_caller/$input"; fi [[ -f $input ]] || { printf 'Source file not found: %s\n' "$input" >&2; return 2; } printf '%s\n' "$input" } run_file() { local mode=$1 input exe [[ $# == 2 ]] || { printf 'Usage: tinyvm.sh %s FILE.zc\n' "$mode" >&2; return 2; } input=$(source_path "$2") || return case $mode in run) exe=bin/zy ;; run-micro) exe=bin/zym ;; lsp) exe=bin/zclsp ;; js) command -v node >/dev/null || { echo 'node.js is required.' >&2; return 1; }; make js || return; node src/js/tinyvm.js "$input"; return ;; esac make "$exe" || return "$exe" < "$input" } repl() { make bin/zy || return echo 'Enter statements or fn definitions, ending each chunk with a backtick. Ctrl-D exits.' { cat examples/repl.zc; printf '`'; cat; } | bin/zy } dispatch() { local action=${1:-help} [[ $# == 0 ]] || shift case $action in build) build "$@" ;; run|run-micro|js|lsp) run_file "$action" "$@" ;; test) bash tests/test.sh "$@" ;; check) make check ;; genome) make genome ;; repl) repl ;; clean) make clean ;; help|-h|--help) usage ;; *) printf 'Unknown command: %s\n' "$action" >&2; usage >&2; return 2 ;; esac } menu() { local choice input status while true; do printf '\nTinyVM — build and run\n' printf ' 1 build everything\n 2 run a .zc file\n 3 run on the microcore\n 4 run in JavaScript\n 5 check with the language server\n 6 run tests\n 7 rebuild genome\n R REPL\n C clean build output\n Q quit\n' read -r -p 'select an option: ' choice || return 0 status=0 case $choice in 1) build || status=$? ;; 2|3|4|5) read -r -p 'source file: ' input || return 0 case $choice in 2) choice=run ;; 3) choice=run-micro ;; 4) choice=js ;; 5) choice=lsp ;; esac run_file "$choice" "$input" || status=$? ;; 6) dispatch test || status=$? ;; 7) dispatch genome || status=$? ;; r|R) repl || status=$? ;; c|C) dispatch clean || status=$? ;; q|Q) return 0 ;; *) echo 'Invalid option.'; continue ;; esac [[ $status == 0 ]] || printf 'Command failed with status %d.\n' "$status" >&2 done } if [[ $# == 0 ]]; then menu; else dispatch "$@"; fi