#!/usr/bin/env bash set -euo pipefail # Nyash self-hosting dev loop helper # Goals: # - Avoid repeated Rust builds; iterate on .nyash scripts only # - One-time ensure binary exists; then run with VM (default) or MIR # - Optional watch mode that re-runs on file changes (uses entr/inotifywait if available) ROOT_DIR=$(cd "$(dirname "$0")/.." && pwd) BIN="$ROOT_DIR/target/release/nyash" SCRIPT="apps/selfhost-minimal/main.nyash" BACKEND="vm" WATCH=0 LOAD_STD=0 VERBOSE=0 EXTRA_ARGS=() usage() { cat < interpreter|mir|vm (default: vm) --std Load Ny std scripts from nyash.toml ([ny_plugins]) -v, --verbose Verbose CLI output -h, --help Show this help Examples: # One-off run (VM), minimal selfhost sample tools/dev_selfhost_loop.sh apps/selfhost-minimal/main.nyash # Watch mode with Ny std libs loaded tools/dev_selfhost_loop.sh --watch --std lang/src/compiler/entry/compiler_stageb.hako EOF } while [[ $# -gt 0 ]]; do case "$1" in --watch) WATCH=1; shift ;; --backend) BACKEND="$2"; shift 2 ;; --std) LOAD_STD=1; shift ;; -v|--verbose) VERBOSE=1; shift ;; -h|--help) usage; exit 0 ;; --) shift; EXTRA_ARGS=("${@}"); break ;; *.nyash) SCRIPT="$1"; shift ;; *) EXTRA_ARGS+=("$1"); shift ;; esac done if [[ ! -f "$BIN" ]]; then echo "[dev] nyash binary not found; building release (one-time)..." (cd "$ROOT_DIR" && cargo build --release --features cranelift-jit) fi run_once() { local envs=("NYASH_DISABLE_PLUGINS=1") if [[ "$LOAD_STD" -eq 1 ]]; then envs+=("NYASH_LOAD_NY_PLUGINS=1") fi if [[ "$VERBOSE" -eq 1 ]]; then envs+=("NYASH_CLI_VERBOSE=1") fi echo "[dev] running: ${envs[*]} $BIN --backend $BACKEND $SCRIPT ${EXTRA_ARGS[*]}" (cd "$ROOT_DIR" && \ env ${envs[@]} "$BIN" --backend "$BACKEND" "$SCRIPT" "${EXTRA_ARGS[@]}" ) } if [[ "$WATCH" -eq 0 ]]; then run_once exit $? fi # Watch mode echo "[dev] watch mode ON (backend=$BACKEND, std=$LOAD_STD)" FILES_CMD="rg --files --glob 'apps/**/*.nyash'" if command -v entr >/dev/null 2>&1; then # Use entr for reliable cross-platform watching echo "[dev] using 'entr' for file watching" # Feed a stable, sorted file list to entr; rerun on any change eval "$FILES_CMD" | sort | entr -rs "bash -lc '$(printf %q "$ROOT_DIR")/tools/dev_selfhost_loop.sh --backend $(printf %q "$BACKEND") $( ((LOAD_STD)) && echo --std ) $( ((VERBOSE)) && echo -v ) $(printf %q "$SCRIPT") ${EXTRA_ARGS:+-- ${EXTRA_ARGS[*]@Q}}'" exit $? fi if command -v inotifywait >/dev/null 2>&1; then echo "[dev] using 'inotifywait' for file watching" while true; do run_once || true # Block until any .nyash under apps changes inotifywait -qq -r -e close_write,create,delete,move "$ROOT_DIR/apps" || true done exit 0 fi # Fallback: naive polling on mtime hash every 1s echo "[dev] no watcher found; falling back to 1s polling" prev_hash="" while true; do cur_hash=$( (cd "$ROOT_DIR" && eval "$FILES_CMD" | xargs -r stat -c '%Y %n' 2>/dev/null | md5sum | awk '{print $1}') ) if [[ "$cur_hash" != "$prev_hash" ]]; then prev_hash="$cur_hash" run_once || true fi sleep 1 done