# Hop — a packet-pipeline language, and Denis Lemire's prime.c rewritten in it.
#
# Declarative-ish targets in the spirit of the GitOps workflows Denis runs:
# describe what you want, then `make` it.

HOP        := bin/hop
REF        := bin/prime_ref
NATIVE     := bin/prime
PRIME      := examples/prime.hop
REF_SRC    := examples/reference/prime.c
EXPECTED   := examples/reference/prime.expected.txt
# candidates to emit for bounded targets
LIMIT      ?= 100

# verify uses bash process substitution
SHELL      := /bin/bash

.PHONY: all build test vet fmt run demo factorial verify reference \
        native emit-c verify-native debug check clean

all: build test vet

## build: compile the hop interpreter to bin/hop
build:
	@mkdir -p bin
	go build -o $(HOP) ./cmd/hop

## test: run the Go test suite (prime fidelity, general-purpose, error handling)
test:
	go test ./...

## vet: static checks
vet:
	go vet ./...

## fmt: gofmt the tree
fmt:
	go fmt ./...

## run: run the prime scanner forever, like the original prime.c (Ctrl-C to stop)
run: build
	$(HOP) run $(PRIME) --metrics

## demo: a short, bounded showcase — primes + live metrics + the other example
demo: build
	@echo "== prime pipeline (first $(LIMIT) candidates) =="
	$(HOP) run $(PRIME) --limit $(LIMIT) --metrics
	@echo
	@echo "== factorial (proof the language is general purpose) =="
	$(HOP) run examples/factorial.hop

## factorial: run the second example on its own
factorial: build
	$(HOP) run examples/factorial.hop

## reference: build the original C as an oracle, regenerate the golden prime lines
reference:
	@mkdir -p bin
	cc -O2 -o $(REF) $(REF_SRC)
	$(REF) | grep --line-buffered "is prime" | head -n 30 > $(EXPECTED)
	@echo "wrote $(EXPECTED)"

## verify: prove Hop's prime lines match the compiled C oracle exactly
verify: build
	@diff <(cat $(EXPECTED)) <($(HOP) run $(PRIME) --limit 200 | grep "is prime" | head -n 30) \
		&& echo "OK: Hop output is identical to the reference prime.c"

## native: compile examples/prime.hop to a native, debuggable binary (bin/prime)
## The generated C is kept at bin/prime.c so gdb/lldb can show source.
native: build
	$(HOP) build $(PRIME) -o $(NATIVE)

## emit-c: print the C the compiler would generate for the prime pipeline
emit-c: build
	@$(HOP) emit $(PRIME)

## verify-native: compile prime.hop to a binary and diff ITS output against prime.c
verify-native: build
	@$(HOP) build $(PRIME) -o $(NATIVE) 2>/dev/null
	@diff <(cat $(EXPECTED)) <($(NATIVE) 2>/dev/null | grep "is prime" | head -n 30) \
		&& echo "OK: the compiled Hop binary is identical to the reference prime.c"

## debug: build the native prime binary and open it in lldb (falls back to gdb)
debug: native
	@echo "Generated C: $(NATIVE).c"
	@echo "Try: (lldb) b is_prime  /  b acl_in  /  b probe_in  /  b ticker_start  -> run -> bt"
	@command -v lldb >/dev/null 2>&1 && exec lldb $(NATIVE) || exec gdb $(NATIVE)

## check: the full gate — build, test, vet, and both interpreter & native verifies
check: all verify verify-native

clean:
	rm -rf bin
