# Semana 9: direccionamiento abierto, Swiss Tables y dict de CPython. Se usa dentro del entorno.
#
#   make             compila los programas de la clase en build/
#   make lab         compila el laboratorio en build/lab/
#   make test        corre las pruebas de los ejemplos y de los apuntes
#   make test-table  prueba solo la tabla (sesión 1 del laboratorio)
#   make test-spell  prueba solo el corrector (sesión 2 del laboratorio)
#   make test-lab    prueba todo su laboratorio; falla hasta que lo terminen
#   make bench       mide el corrector con cuatro diseños, con -O2 y sin sanitizers
#   make clean       borra lo generado
#
# Los programas de errors/ tienen errores a propósito. No se compilan con make: los compilan las
# pruebas, y ustedes, con los comandos de los apuntes.

CXX = g++
CXXFLAGS = -Wall -Wextra -std=c++20 -g -fsanitize=address,undefined
BENCHFLAGS = -Wall -Wextra -std=c++20 -O2
LAB_DIR ?= lab
BUILD = build
DATA ?= ../../data
PROGRAMS = probe_trace probe_order compact_dict group_match test_demos
BENCHES = probing_counts tombstone_counts swiss_counts layout_bench
COMMON_HEADERS = bench.h mini_swiss.h demo_tables.h
LAB_HEADERS = $(LAB_DIR)/probing_hash_map.h $(LAB_DIR)/hash_map.h $(LAB_DIR)/churn_test.h \
	$(LAB_DIR)/dictionaries.h $(LAB_DIR)/spell_checker.h lab/utf8.h lab/load_words.h lab/not_implemented.h

.PHONY: all lab test test-table test-spell test-lab bench clean

all: $(PROGRAMS:%=$(BUILD)/%) $(BENCHES:%=$(BUILD)/%)

$(PROGRAMS:%=$(BUILD)/%): $(BUILD)/%: %.cpp $(COMMON_HEADERS) | $(BUILD)
	$(CXX) $(CXXFLAGS) $< -o $@

# Las mediciones van con -O2 y sin sanitizers.
$(BENCHES:%=$(BUILD)/%): $(BUILD)/%: %.cpp $(COMMON_HEADERS) | $(BUILD)
	$(CXX) $(BENCHFLAGS) $< -o $@

# LAB_DIR va primero: así las pruebas toman el código de esa carpeta.
$(BUILD)/$(LAB_DIR)/map_tests: lab/tests/map_tests.cpp lab/tests/map_suite.h $(LAB_HEADERS) | $(BUILD)/$(LAB_DIR)
	$(CXX) $(CXXFLAGS) -I$(LAB_DIR) -Ilab -Ilab/tests -I. $< -o $@

$(BUILD)/$(LAB_DIR)/spell_tests: lab/tests/spell_tests.cpp $(LAB_HEADERS) | $(BUILD)/$(LAB_DIR)
	$(CXX) $(CXXFLAGS) -I$(LAB_DIR) -Ilab -Ilab/tests -I. $< -o $@

$(BUILD)/$(LAB_DIR)/spell: lab/tests/spell.cpp $(LAB_HEADERS) | $(BUILD)/$(LAB_DIR)
	$(CXX) $(BENCHFLAGS) -I$(LAB_DIR) -Ilab -I. $< -o $@

$(BUILD)/$(LAB_DIR)/bench_spell: lab/tests/bench_spell.cpp lab/tests/bytes_counter.h $(LAB_HEADERS) bench.h | $(BUILD)/$(LAB_DIR)
	$(CXX) $(BENCHFLAGS) -I$(LAB_DIR) -Ilab -Ilab/tests -I. $< -o $@

$(BUILD) $(BUILD)/$(LAB_DIR):
	mkdir -p $@

lab: $(BUILD)/$(LAB_DIR)/map_tests $(BUILD)/$(LAB_DIR)/spell_tests $(BUILD)/$(LAB_DIR)/spell $(BUILD)/$(LAB_DIR)/bench_spell

# Si existe solution/, también se comprueba la solución del laboratorio.
test: all
	@if [ -d solution ]; then $(MAKE) --no-print-directory LAB_DIR=solution lab; fi
	DATA=$(DATA) python3 -m unittest discover -p 'test_*.py'

test-table: all lab
	LAB_DIR=$(LAB_DIR) DATA=$(DATA) python3 -m unittest -v test_lab.TestTable

test-spell: all lab
	LAB_DIR=$(LAB_DIR) DATA=$(DATA) python3 -m unittest -v test_lab.TestSpell

test-lab: all lab
	LAB_DIR=$(LAB_DIR) DATA=$(DATA) python3 -m unittest -v test_lab

bench: $(BUILD)/$(LAB_DIR)/bench_spell
	$< $(DATA)/palabras.txt $(DATA)/tradiciones.txt

clean:
	rm -rf $(BUILD) __pycache__
