Adds tagged bignum support alongside the existing 48-bit fixnum on the C tier. Tag 6 = bignum, heap struct sign-magnitude with u64 little-endian limbs. Reader emits bignums for any literal past the fixnum range; +, -, *, quotient, remainder, modulo, expt, =, <, >, abs, odd?, even?, integer?, exact?, number->string, string->number all promote fixnum → bignum on overflow & demote back when results fit. Boehm GC owns every allocation. Schoolbook O(n²) mul + shift-subtract divmod is sufficient at our 4-limb / 256-bit scale. Before: (expt 2 48) = 0, (expt 2 256) = 0, secp256k1-p = -4294968273. After: all three return their exact arbitrary-precision values, matching Python tier byte-for-byte. Validated: - c/test.c — 85/85 pass (+2 new bignum unit tests). - tests/functional.lsp — 205/205 pass on both C & Python tiers. - tests/bignum-cross-tier.lsp — 33/33 pass byte-identical on both tiers (diff produces no output). - ecdsa/runs/lumbda-sweep-003/c-tier-bignum-probe.lsp — all four assertions now match the Python oracle. - ecdsa Phase B byte-identity sweep inside QEMU guest: n+1=9 p=251 sha256 c668bbe3... — matches Python oracle. n+1=18 p=131071 sha256 8a031f96... — matches Python oracle. n+1=33 p=2³²-5 sha256 0bc56905... — matches Python oracle. Previously the n+1=33 C tier emitted sha256 b024d6d9... (26,078 fewer Toffolis due to silent fixnum wrap). Bignums close that gate. secp256k1 production-width emit (n+1=257) is now structurally unblocked on C tier; downstream agent (#55) drives that next-step on the ecdsa side. Asm tier inherits in a follow-up port.
46 lines
1.3 KiB
Makefile
46 lines
1.3 KiB
Makefile
# Makefile for lumbda C interpreter
|
|
# Targets: all, test, bench, clean
|
|
|
|
CC = gcc
|
|
CFLAGS = -O2 -Wall -Wextra -Wno-unused-parameter -std=c11 -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE
|
|
LDFLAGS = -lm
|
|
|
|
# Boehm GC autodetect — enable when /usr/include/gc.h is present.
|
|
# Without GC, every allocation leaks (ul_free is a no-op in our header);
|
|
# small REPL snippets work but anything iterating past a few thousand
|
|
# allocations OOMs the process. The named-let + per-iteration user-fn
|
|
# call pattern in tests/regression/named-let-gc.lsp pins this down.
|
|
# Override with USE_GC=0 to force the malloc-only path for diagnostics.
|
|
USE_GC ?= $(shell test -f /usr/include/gc.h && echo 1 || echo 0)
|
|
ifeq ($(USE_GC),1)
|
|
CFLAGS += -DUSE_BOEHM_GC
|
|
LDFLAGS += -lgc
|
|
endif
|
|
|
|
SRCS = types.c bignum.c reader.c printer.c eval.c builtins.c vm.c jit.c portal.c
|
|
OBJS = $(SRCS:.c=.o)
|
|
|
|
.PHONY: all clean test bench
|
|
|
|
all: lumbda
|
|
|
|
lumbda: main.o $(OBJS)
|
|
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
|
|
|
test: test_runner
|
|
./test_runner
|
|
|
|
test_runner: test.c $(OBJS)
|
|
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
|
|
|
bench: bench_runner lumbda
|
|
ulimit -s 65536 && ./bench_runner
|
|
|
|
bench_runner: bench.c $(OBJS)
|
|
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
|
|
|
%.o: %.c lumbda.h
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
clean:
|
|
rm -f *.o lumbda test_runner bench_runner
|