LambLisp 01 Red Fox Alpha
From AI to Actuator
Loading...
Searching...
No Matches
LambLisp.h
1// Copyright 2026 by Frobenius Norm LLC 2026-05-16
2// Free for non-commercial use. Commercial use requires a license.
3#ifndef LL_LAMB_H
4#define LL_LAMB_H
5
6#include "ll_platform_generic.h"
7
17
20class LL_Port;
21typedef LL_Port Port_t;
22typedef Port_t *Portst_t;
24
26typedef void CPPDeleter(void *cpp_obj);
27typedef CPPDeleter *CPPDeleterPtr;
28
29class Cell; //forward
30typedef Cell *Sexpr_t;
31
49extern Cell _NIL_, _HASHT_, _HASHF_, _OBJ_EOF_, _OBJ_UNDEF_, _OBJ_VOID_, _OBJ_NOSLOT_, _OBJ_FREED_, _OBJ_SYSERROR_;
50
51class DatumLabels;
53enum class WriteMode { Simple, Cyclic, Shared };
55
66constexpr Sexpr_t NIL = &_NIL_;
67constexpr Sexpr_t HASHT = &_HASHT_;
68constexpr Sexpr_t HASHF = &_HASHF_;
69constexpr Sexpr_t OBJ_EOF = &_OBJ_EOF_;
70constexpr Sexpr_t OBJ_UNDEF = &_OBJ_UNDEF_;
71constexpr Sexpr_t OBJ_VOID = &_OBJ_VOID_;
72constexpr Sexpr_t OBJ_FREED = &_OBJ_FREED_;
73constexpr Sexpr_t OBJ_NOSLOT = &_OBJ_NOSLOT_;
84constexpr Sexpr_t OBJ_SYSERROR = &_OBJ_SYSERROR_;
86
118
142#ifndef SINT_CACHE_MIN_CFG
143 #define SINT_CACHE_MIN_CFG (-2048)
144#endif
145#ifndef SINT_CACHE_MAX_CFG
146 #define SINT_CACHE_MAX_CFG ( 4096)
147#endif
148static const LL_int32 SINT_CACHE_MIN = SINT_CACHE_MIN_CFG;
149static const LL_int32 SINT_CACHE_MAX = SINT_CACHE_MAX_CFG;
150static const LL_int32 SINT_CACHE_SIZE = SINT_CACHE_MAX - SINT_CACHE_MIN + 1;
151extern Cell *sint_cache_cells;
153
154#ifndef LL_FLOAT_PROFILE
155#define LL_FLOAT_PROFILE 0
156#endif
157#if LL_FLOAT_PROFILE
158#define LL_FLOAT_PROF_N 5
159#define LL_FLOAT_PROF_TOTAL 0
160#define LL_FLOAT_PROF_NAN 1
161#define LL_FLOAT_PROF_SPEC 2
162#define LL_FLOAT_PROF_SMALL 3
163#define LL_FLOAT_PROF_MISS 4
164extern LL_int64 ll_float_prof[LL_FLOAT_PROF_N];
165
169inline void ll_float_prof_note(double v)
170{
171 ll_float_prof[LL_FLOAT_PROF_TOTAL]++;
172 if (v != v) { ll_float_prof[LL_FLOAT_PROF_NAN]++; return; }
173 if (v == 1.0 / 0.0 || v == -1.0 / 0.0) { ll_float_prof[LL_FLOAT_PROF_SPEC]++; return; }
174 if (v == 0.0 && __builtin_signbit(v)) { ll_float_prof[LL_FLOAT_PROF_SPEC]++; return; }
175 if (v >= -16.0 && v <= 16.0) {
176 const int i = (int) v;
177 if ((double) i == v) { ll_float_prof[LL_FLOAT_PROF_SMALL]++; return; }
178 }
179 ll_float_prof[LL_FLOAT_PROF_MISS]++;
180}
181#endif
182
238class Cell {
239public:
247 Cell() {}
248
249 Cell(Word_t typ, Word_t w1, Word_t w2) { type(typ); rplaca(w1); rplacd(w2); }
250 Cell(Word_t typ, Sexpr_t w1, Sexpr_t w2) { type(typ); rplaca((Word_t) w1); rplacd((Word_t) w2); }
252
280 enum {
281 //Complex atoms first
297 // [B736] why this block exists: a healthy-vector dump misread as a wiped header
300
302
306 // [B317] the car's byte length is written but not read; see the entry before "fixing" strlen()
309
312
315
319
320 //Simple atoms next
327 //Interface atoms to C++ functions. No garbage collection finalization required.
330
331 //T_VOID and T_UNDEF are singletons
334
345 // Maintainer note, deliberately not published: moving these two above T_PAIR was tried and
346 // reverted -- it makes (car 1/2) answer 1, and Cell::features[] in ll_vm_cell.cpp is
347 // positional, so an enum reorder without a matching table reorder reads the wrong rows.
350
367
369 };
371
374 static const int F_GC01 = 0x01;
375 static const int F_GC02 = 0x02;
376 static const int F_GC04 = 0x04;
377 static const int F_TAIL = 0x08;
412 static const int F_SUBTYPE_MASK = 0xF0;
413
414 static const int F_CAR_IS_INT = 0x10;
415 static const int F_CAR_IS_FLOAT = 0x20;
416 static const int F_CDR_IS_INT = 0x40;
417 static const int F_CDR_IS_FLOAT = 0x80;
419 static const int GC_STATE_MASK = F_GC01 | F_GC02 | F_GC04;
421
430#define _type_ (_contents._byte[0])
431#define _flags_ (_contents._byte[1])
432#define _car_ (_contents._word[1])
433#define _cdr_ (_contents._word[2])
434#define _car_addr_ (&(_car_))
435#define _int_ptr_ ((LL_int32 *) _car_addr_)
436#define _real_ptr_ ((LL_float32 *) _car_addr_)
437#define _byte2_ptr_ (&(_contents._byte[2]))
438
439 void zero() { _contents._word[0] = _contents._word[1] = _contents._word[2] = 0; }
440 LL_int32 type(void) { return _type_; }
441 void type(LL_int32 t) { _type_ = t; }
442
443 LL_int32 flags(void) { return _flags_; }
444 void flags_set(LL_int32 f) { _flags_ |= f; }
445 void flags_clr(LL_int32 f) { _flags_ &= ~f; }
446
447 void rplaca(Word_t p) { _car_ = p; }
448 void rplacd(Word_t p) { _cdr_ = p; }
450
467
468 typedef struct {
469 LL_int32 typ;
470 bool is_any_pair, is_any_svec, is_any_svec2n, is_any_str, is_any_sym, is_any_bvec;
471 const char *type_name;
472 } CellFeatures;
473
474 static const CellFeatures features[Ntypes];
475
476 void init_static_data();
477
483 Bool_t is_atom(void) { return _type_ < T_PAIR; }
484 Bool_t is_pair(void) { return _type_ == T_PAIR; }
485
486 //Note sometimes faster to check the features, other times faster to check the type directly. For 3 checks the feature table wins, but for 2 it is not always obvious.
490 Bool_t is_any_pair(void) { return _type_ >= T_PAIR; }
491 Bool_t is_any_svec_atom() { return features[_type_].is_any_svec; }
492 Bool_t is_any_svec2n_atom() { return (_type_ == T_SVEC2N_HEAP) || (_type_ == T_SVEC_IMM); }
493 Bool_t is_any_str_atom(void) { return features[_type_].is_any_str; }
494 Bool_t is_any_sym_atom(void) { return (_type_ == T_SYM_HEAP) || (_type_ == T_GENSYM); }
495 Bool_t is_any_bvec_atom(void) { return features[_type_].is_any_bvec; }
496 Bool_t is_any_int(void) { return _type_ == T_INT32 || _type_ == T_INT64 || _type_ == T_BIGNUM; }
503 Bool_t is_integer_valued(void);
504 Bool_t is_bignum(void) { return _type_ == T_BIGNUM; }
505 Bool_t is_any_real(void) { return _type_ == T_FLOAT32 || _type_ == T_FLOAT64; }
506
512
525 bool is_slot_typed() const { return _type_ > T_NIL; }
526 bool car_is_int() const { return (_flags_ & F_CAR_IS_INT) != 0; }
527 bool car_is_float() const { return (_flags_ & F_CAR_IS_FLOAT) != 0; }
528 bool cdr_is_int() const { return (_flags_ & F_CDR_IS_INT) != 0; }
529 bool cdr_is_float() const { return (_flags_ & F_CDR_IS_FLOAT) != 0; }
530 bool car_is_embedded() const { return (_flags_ & (F_CAR_IS_INT | F_CAR_IS_FLOAT)) != 0; }
531 bool cdr_is_embedded() const { return (_flags_ & (F_CDR_IS_INT | F_CDR_IS_FLOAT)) != 0; }
535 bool car_is_ptr() const { return !car_is_embedded(); }
536 bool cdr_is_ptr() const { return !cdr_is_embedded(); }
538
548 LL_int32 car_int32() const { return (LL_int32) _car_; }
549 LL_float32 car_float32() const { return *(LL_float32*) &_car_; }
550 LL_int32 cdr_int32() const { return (LL_int32) _cdr_; }
551 LL_float32 cdr_float32() const { return *(LL_float32*) &_cdr_; }
553
555
574 enum { gcst_idle, gcst_issued, gcst_stacked, gcst_marked, gcst_free, Ngcstates };
575
576 LL_int32 gc_state(void) { return _flags_ & GC_STATE_MASK; }
577 Sexpr_t gc_state(LL_int32 st) { _flags_ = (_flags_ & ~GC_STATE_MASK) | (st & GC_STATE_MASK); return this; }
578 LL_int32 tail_state(void) { return _flags_ & F_TAIL; }
579 Sexpr_t tail_state_set(void) { _flags_ |= F_TAIL; return this; }
580 Sexpr_t tail_state_clr(void) { _flags_ &= ~F_TAIL; return this; }
581
582 static const int F_BC_VARIADIC = 0x01;
583 bool bytecode_is_variadic() const { return (_contents._byte[2] & F_BC_VARIADIC) != 0; }
584 void bytecode_set_variadic() { _contents._byte[2] |= F_BC_VARIADIC; }
586
589 Ptr_t get_car_addr() { return _car_addr_; }
590 Word_t get_car(void) { return _car_; }
591 Word_t get_cdr(void) { return _cdr_; }
592
612 Bool_t as_Bool_t() { return (Bool_t) _car_; }
613 Char_t as_Char_t() { return (Char_t) _car_; }
614 ll_codepoint_t as_codepoint() { return (ll_codepoint_t) _car_; }
615 LL_int32 as_int32() const { return (LL_int32) _car_; }
616 LL_int64 as_int64() const { return *(LL_int64*) &_car_; }
617 LL_float32 as_float32() const { return *(LL_float32*) &_car_; }
618 LL_float64 as_float64() const { return *(LL_float64*) &_car_; }
619
620 Ptr_t as_Ptr_t() { return (Ptr_t) _cdr_; }
621 Charst_t as_Charst_t() { return (Charst_t) as_Ptr_t(); }
622 Bytest_t as_Bytest_t() { return (Bytest_t) as_Ptr_t(); }
623 CharVec_t as_CharVec_t() { return (CharVec_t) as_Ptr_t(); }
624 ByteVec_t as_ByteVec_t() { return (ByteVec_t) as_Ptr_t(); }
625 Portst_t as_Portst_t() { return (Portst_t) as_Ptr_t(); }
626
628
637 LL_int32 hash_sexpr(void);
638 LL_int32 hash_contents(void);
639 LL_int32 hash(void) { return (type() == T_SYM_HEAP) ? prechecked_sym_heap_get_hash() : hash_sexpr(); }
641
644 Sexpr_t set(LL_int32 typ, Word_t w1, Word_t w2) { _type_ = typ; _car_ = w1; _cdr_ = w2; return this; }
645 Sexpr_t set(LL_int32 typ, LL_int32 a, Sexpr_t b) { _type_ = typ; _car_ = (Word_t) a; _cdr_ = (Word_t) b; return this; }
646 Sexpr_t set(LL_int32 typ, Word_t a, Sexpr_t b) { _type_ = typ; _car_ = a; _cdr_ = (Word_t) b; return this; }
647 Sexpr_t set(LL_int32 typ, Sexpr_t a, Sexpr_t b) { _type_ = typ; _car_ = (Word_t) a; _cdr_ = (Word_t) b; return this; }
648
649 Sexpr_t set(Bool_t b) { return set(T_BOOL, (Word_t) b, (Word_t) 0); }
650 Sexpr_t set(Char_t c) { return set(T_CHAR, (Word_t) c, (Word_t) 0); }
651 Sexpr_t set(LL_int32 i) { _type_ = T_INT32; _car_ = _cdr_ = 0; memcpy(&_car_, &i, 4); return this; }
652 Sexpr_t set(LL_int64 v) { _type_ = T_INT64; _car_ = _cdr_ = 0; memcpy(&_car_, &v, 8); return this; }
653 Sexpr_t set(LL_float32 r) { _type_ = T_FLOAT32; _car_ = _cdr_ = 0; memcpy(&_car_, &r, 4); return this; }
654 Sexpr_t set(LL_float64 d) { _type_ = T_FLOAT64; _car_ = _cdr_ = 0; memcpy(&_car_, &d, 8); return this; }
666 Sexpr_t set(LL_float32 r, LL_float32 i) { _type_ = T_COMPLEX; _car_ = _cdr_ = 0;
667 memcpy(&_car_, &r, 4); memcpy(&_cdr_, &i, 4);
668 _flags_ = (_flags_ & 0x0F) | F_CAR_IS_FLOAT | F_CDR_IS_FLOAT;
669 return this; }
670 LL_float32 cpx_real() const { return *(LL_float32*) &_car_; }
671 LL_float32 cpx_imag() const { return *(LL_float32*) &_cdr_; }
672 // ── T_RATIONAL: P70 per-slot P23 word-type components ────────────────────────────────────────
673 // car=numerator, cdr=denominator; each slot is either an EMBEDDED int32 (an embedded int32, common small
674 // case, no allocation, not GC-scanned) or a traced pointer to a boxed exact integer (T_INT32/T_INT64/
675 // T_BIGNUM). A component that overflows int32 boxes to T_INT64 then T_BIGNUM (int widening ladder)
676 // -- no float64 fallback, so rationals stay exact. as_numerator/as_denominator read a component as
677 // int64 (valid unless it is a boxed T_BIGNUM -- guard with rat_is_big() first).
678 Sexpr_t set(LL_int32 num, LL_int32 den) {
679 _type_ = T_RATIONAL; _car_ = _cdr_ = 0; memcpy(&_car_, &num, 4); memcpy(&_cdr_, &den, 4);
680 _flags_ = (_flags_ & 0x0F) | F_CAR_IS_INT | F_CDR_IS_INT;
681 return this;
682 }
683 void rat_set_car_i32(LL_int32 v) { _car_ = 0; memcpy(&_car_, &v, 4); _flags_ = (_flags_ & ~(F_CAR_IS_INT|F_CAR_IS_FLOAT)) | F_CAR_IS_INT; }
688 void rat_set_car_ptr(Sexpr_t p) { _car_ = (Word_t) p; _flags_ = _flags_ & ~(F_CAR_IS_INT|F_CAR_IS_FLOAT); }
689 void rat_set_cdr_i32(LL_int32 v) { _cdr_ = 0; memcpy(&_cdr_, &v, 4); _flags_ = (_flags_ & ~(F_CDR_IS_INT|F_CDR_IS_FLOAT)) | F_CDR_IS_INT; }
690 void rat_set_cdr_ptr(Sexpr_t p) { _cdr_ = (Word_t) p; _flags_ = _flags_ & ~(F_CDR_IS_INT|F_CDR_IS_FLOAT); }
691 LL_int64 int_as_i64() const { return _type_ == T_INT64 ? as_int64() : (LL_int64) as_int32(); }
692 Sexpr_t rat_car_ptr() const { return (Sexpr_t) _car_; }
693 Sexpr_t rat_cdr_ptr() const { return (Sexpr_t) _cdr_; }
694 bool rat_car_big() const { return car_is_ptr() && ((Cell*) _car_)->type() == T_BIGNUM; }
695 bool rat_cdr_big() const { return cdr_is_ptr() && ((Cell*) _cdr_)->type() == T_BIGNUM; }
696 bool rat_is_big() const { return _type_ == T_RATIONAL && (rat_car_big() || rat_cdr_big()); }
697 bool exact_is_big() const { return _type_ == T_BIGNUM || rat_is_big(); }
698 LL_int64 as_numerator() const { return car_is_int() ? (LL_int64) car_int32() : ((const Cell*) _car_)->int_as_i64(); }
699 LL_int64 as_denominator() const { return cdr_is_int() ? (LL_int64) cdr_int32() : ((const Cell*) _cdr_)->int_as_i64(); }
702 switch (_type_) {
703 case T_INT32: { LL_int32 v = as_int32(); return v > 0 ? 1 : v < 0 ? -1 : 0; }
704 case T_INT64: { LL_int64 v = as_int64(); return v > 0 ? 1 : v < 0 ? -1 : 0; }
705 case T_BIGNUM: { const int32_t *pay = (const int32_t *) as_ByteVec_t(); int n = pay[0] & 0x7fffffff; return n == 0 ? 0 : (((uint32_t) pay[0]) >> 31 ? -1 : 1); }
706 case T_RATIONAL:
707 if (car_is_int()) { LL_int32 v = car_int32(); return v > 0 ? 1 : v < 0 ? -1 : 0; }
708 return ((Cell*) _car_)->exact_sign();
709 default: return 0;
710 }
711 }
712 Sexpr_t set(Port_t &p) { return set(T_PORT_HEAP, (Word_t) 0, (Word_t) &p); }
713 //Sexpr_t set(Sexpr_t a, Sexpr_t b) { return set(T_PAIR, a, b); } //!<Set cell as pair
714
715 Sexpr_t set(LL_int32 typ, LL_int32 a, Charst_t b) { return set(typ, (Word_t) a, (Word_t) b); }
716 Sexpr_t set(LL_int32 typ, LL_int32 a, Bytest_t b) { return set(typ, (Word_t) a, (Word_t) b); }
717 Sexpr_t set(LL_int32 typ, LL_int32 a, CharVec_t b) { return set(typ, (Word_t) a, (Word_t) b); }
718 Sexpr_t set(LL_int32 typ, LL_int32 a, ByteVec_t b) { return set(typ, (Word_t) a, (Word_t) b); }
720
721 Sexpr_t mk_error(const char *fmt, ...) CHECKPRINTF_pos2;
722 Sexpr_t mk_error(Sexpr_t irritants, const char *fmt, ...) CHECKPRINTF_pos3;
723
729 Sexpr_t prechecked_anypair_get_car() { return (Sexpr_t) get_car(); }
730 Sexpr_t prechecked_anypair_get_cdr() { return (Sexpr_t) get_cdr(); }
731
732 LL_int32 prechecked_sym_heap_get_hash() { return as_int32(); }
733 Charst_t prechecked_sym_heap_get_chars() { return (Charst_t) as_Ptr_t(); }
734 void prechecked_sym_heap_get_info(LL_int32 &hsh, Charst_t &chars) { hsh = as_int32(); chars = (Charst_t) as_Ptr_t(); }
735
765 static const int LL_STR_HDR = (int) sizeof(LL_int32);
767 CharVec_t prechecked_str_heap_get_chars() { return (CharVec_t) ((char *) as_Ptr_t() + LL_STR_HDR); }
768 LL_int32 prechecked_str_heap_get_charlength() { LL_int32 n; memcpy(&n, as_Ptr_t(), sizeof(n)); return n; }
769 void prechecked_str_heap_set_charlength(LL_int32 n) { memcpy(as_Ptr_t(), &n, sizeof(n)); }
772 CharVec_t prechecked_str_imm_get_chars() { return (CharVec_t) _byte2_ptr_; }
773
774 void prechecked_bvec_imm_set_length(LL_int32 l) { _contents._byte[2] = l; }
775
791 static Char_t buf[32];
792 const String s = str();
793 Charst_t src = (Charst_t) s.c_str();
794 LL_int32 i = 0;
795 for (; src[i] && i < (LL_int32) (sizeof(buf) - 1); i++) buf[i] = src[i];
796 buf[i] = '\0';
797 return (Charst_t) buf;
798 }
799 void prechecked_gensym_get_info(LL_int32 &hsh, Charst_t &chars) { hsh = as_int32(); chars = prechecked_gensym_get_chars(); }
800
801 Sexpr_t prechecked_error_get_irritants() { return (Sexpr_t) get_cdr(); }
802 Sexpr_t prechecked_error_get_str() { return (Sexpr_t) get_car(); }
803 Charst_t prechecked_error_get_chars() { return prechecked_error_get_str()->any_str_get_chars(); }
805
810#define THROW_BAD_TYPE { throw mk_error("%s Bad type %s", me, dump().c_str()); }
812 Bool_t mustbe_Bool_t() { ME("Cell::mustbe_Bool_t()"); if (type() == T_BOOL) return as_Bool_t(); THROW_BAD_TYPE; }
813 Char_t mustbe_Char_t() { ME("Cell::mustbe_Char_t()"); if (type() == T_CHAR) return as_Char_t(); THROW_BAD_TYPE; }
814 ll_codepoint_t mustbe_codepoint() { ME("Cell::mustbe_codepoint()"); if (type() == T_CHAR) return as_codepoint(); THROW_BAD_TYPE; }
815 LL_int32 mustbe_int32() { ME("Cell::mustbe_int32()"); if (type() == T_INT32) return as_int32(); THROW_BAD_TYPE; }
816 LL_float32 mustbe_float32() { ME("Cell::mustbe_float32()"); if (type() == T_FLOAT32) return as_float32(); THROW_BAD_TYPE; }
817
818 Sexpr_t mustbe_any_str_t() { ME("Cell::mustbe_any_str_t()"); if (is_any_str_atom()) return this; THROW_BAD_TYPE; }
819 Sexpr_t mustbe_cppobj_t() { ME("Cell::mustbe_cppobj_t()"); if (type() == T_CPP_HEAP) return this; THROW_BAD_TYPE; }
820
821 CPPDeleterPtr prechecked_cppobj_get_deleter() { return (CPPDeleterPtr) _car_; }
822 Ptr_t prechecked_cppobj_get_ptr() { return as_Ptr_t(); }
823
824 CPPDeleterPtr any_cppobj_get_deleter() { return mustbe_cppobj_t()->prechecked_cppobj_get_deleter(); }
825 Ptr_t any_cppobj_get_ptr() { return mustbe_cppobj_t()->prechecked_cppobj_get_ptr(); }
826 void any_cppobj_get_info(CPPDeleterPtr &d, Ptr_t &p) { Sexpr_t o = mustbe_cppobj_t(); d = o->prechecked_cppobj_get_deleter(); p = o->prechecked_cppobj_get_ptr(); }
827
828 LL_float32 coerce_float32()
829 {
830 ME("Cell::coerce_float32()");
831 LL_int32 typ = type();
832 if (typ == T_FLOAT32) return as_float32();
833 else if (typ == T_INT32) return (LL_float32) as_int32();
834 else if (typ == T_INT64) return (LL_float32) as_int64();
835 else if (typ == T_FLOAT64) return (LL_float32) as_float64();
836 else if (typ == T_RATIONAL) {
837 LL_float64 n = (car_is_int()) ? (LL_float64) car_int32() : ((Cell*) _car_)->coerce_float64();
838 LL_float64 d = (cdr_is_int()) ? (LL_float64) cdr_int32() : ((Cell*) _cdr_)->coerce_float64();
839 return (LL_float32) (n / d);
840 }
841 else if (typ == T_BIGNUM) return (LL_float32) coerce_float64();
842 else if (typ == T_CHAR) return (LL_float32) as_codepoint();
843 THROW_BAD_TYPE;
844 }
845
846 LL_float64 coerce_float64()
847 {
848 ME("Cell::coerce_float64()");
849 LL_int32 typ = type();
850 if (typ == T_FLOAT64) return as_float64();
851 else if (typ == T_FLOAT32) return (LL_float64) as_float32();
852 else if (typ == T_INT32) return (LL_float64) as_int32();
853 else if (typ == T_INT64) return (LL_float64) as_int64();
854 else if (typ == T_RATIONAL) {
855 LL_float64 n = (car_is_int()) ? (LL_float64) car_int32() : ((Cell*) _car_)->coerce_float64();
856 LL_float64 d = (cdr_is_int()) ? (LL_float64) cdr_int32() : ((Cell*) _cdr_)->coerce_float64();
857 return n / d;
858 }
859 else if (typ == T_BIGNUM) {
860 // limb-by-limb: payload = [int32 sign_nlimbs][LL_int32 limb0 ... limbN-1], little-endian.
861 const int32_t *pay = (const int32_t *) as_ByteVec_t();
862 int n = (int)(pay[0] & 0x7fffffff);
863 int neg = (int)((uint32_t) pay[0] >> 31);
864 const LL_int32 *limbs = (const LL_int32 *)(pay + 1);
865 LL_float64 r = 0.0;
866 for (int i = n - 1; i >= 0; i--)
867 r = r * 4294967296.0 + (LL_float64)(uint32_t) limbs[i];
868 return neg ? -r : r;
869 }
870 THROW_BAD_TYPE;
871 }
872
873 LL_int32 coerce_int32()
874 {
875 ME("Cell::coerce_int32()");
876 LL_int32 typ = type();
877 if (typ == T_INT32) return as_int32();
878 else if (typ == T_INT64) return (LL_int32) as_int64();
879 else if (typ == T_FLOAT32) return (LL_int32) as_float32();
880 else if (typ == T_FLOAT64) return (LL_int32) as_float64();
881 else if (typ == T_RATIONAL) return (LL_int32) ((LL_float32) as_numerator() / (LL_float32) as_denominator());
882 else if (typ == T_CHAR) return (LL_int32) as_codepoint();
883 THROW_BAD_TYPE;
884 }
885
886 LL_int64 coerce_int64()
887 {
888 ME("Cell::coerce_int64()");
889 LL_int32 typ = type();
890 if (typ == T_INT64) return as_int64();
891 else if (typ == T_INT32) return (LL_int64) as_int32();
892 else if (typ == T_FLOAT32) return (LL_int64) as_float32();
893 else if (typ == T_FLOAT64) return (LL_int64) as_float64();
894 else if (typ == T_RATIONAL) return (LL_int64) ((LL_float64) as_numerator() / (LL_float64) as_denominator());
895 THROW_BAD_TYPE;
896 }
897
899 int exact_rank() const { switch (_type_) { case T_INT32: return 0; case T_INT64: return 1; case T_RATIONAL: return 2; case T_BIGNUM: return 3; default: return -1; } }
901 int inexact_rank() const { switch (_type_) { case T_FLOAT32: return 0; case T_FLOAT64: return 1; case T_COMPLEX: return 2; default: return -1; } }
902 bool is_exact() const { return exact_rank() >= 0; }
903 bool is_inexact() const { return inexact_rank() >= 0; }
904 bool is_complex() const { return _type_ == T_COMPLEX; }
906 int num_rank() const {
907 switch (_type_) {
908 case T_INT32: case T_INT64: case T_BIGNUM: return 0;
909 case T_FLOAT32: case T_FLOAT64: return 1;
910 case T_RATIONAL: return 2;
911 case T_COMPLEX: return 3;
912 default: return -1;
913 }
914 }
915 LL_int64 numerator64() const { if (_type_ == T_RATIONAL) return (LL_int64) as_numerator(); if (_type_ == T_INT64) return as_int64(); return (LL_int64) as_int32(); }
916 LL_int64 denominator64() const { return _type_ == T_RATIONAL ? (LL_int64) as_denominator() : (LL_int64) 1; }
917 LL_float64 coerce_cpx_real() { return _type_ == T_COMPLEX ? (LL_float64) cpx_real() : coerce_float64(); }
918 LL_float64 coerce_cpx_imag() { return _type_ == T_COMPLEX ? (LL_float64) cpx_imag() : 0.0; }
919
920 Sexpr_t error_get_str() { ME("Cell::error_get_str()"); if (_type_ == T_ERROR) return prechecked_error_get_str(); THROW_BAD_TYPE; }
921 Sexpr_t error_get_irritants() { ME("Cell::error_get_irritants()"); if (_type_ == T_ERROR) return prechecked_error_get_irritants(); THROW_BAD_TYPE; }
922 Charst_t error_get_chars() { ME("Cell::error_get_chars()"); if (_type_ == T_ERROR) return prechecked_error_get_chars(); THROW_BAD_TYPE; }
926 Sexpr_t any_error_get_str() { return (_type_ == T_ERROR) ? prechecked_error_get_str() : NIL; }
927 Sexpr_t any_error_get_irritants() { return (_type_ == T_ERROR) ? prechecked_error_get_irritants() : NIL; }
928
929 LL_int32 any_sym_get_hash() { ME("any_sym_get_hash()"); if (is_any_sym_atom()) return as_int32(); THROW_BAD_TYPE; }
930
931 Charst_t any_sym_get_chars() {
932 ME("Cell::any_sym_get_chars()");
933 if (_type_ == T_SYM_HEAP) return prechecked_sym_heap_get_chars();
934 else if (_type_ == T_GENSYM) return prechecked_gensym_get_chars();
935 else THROW_BAD_TYPE;
936 }
937
938 void any_sym_get_info(LL_int32 &hsh, Charst_t &chars) {
939 ME("Cell::any_sym_get_info()");
940 if (_type_ == T_SYM_HEAP) prechecked_sym_heap_get_info(hsh, chars);
941 else if (_type_ == T_GENSYM) prechecked_gensym_get_info(hsh, chars);
942 else THROW_BAD_TYPE;
943 }
944
946
958
960 CharVec_t any_str_get_chars() {
961 ME("Cell::anystring_get_chars()");
962 if (_type_ == T_STR_IMM) return prechecked_str_imm_get_chars();
963 else if (_type_ == T_STR_HEAP) return prechecked_str_heap_get_chars();
964 else if (_type_ == T_STR_EXT) return prechecked_str_ext_get_chars();
965 else THROW_BAD_TYPE;
966 }
967
987 if (_type_ == T_STR_HEAP) return (LL_int32) _car_;
988 return (LL_int32) strlen(any_str_get_chars());
989 }
990 void any_str_get_info(LL_int32 &len, CharVec_t &chars) {
991 chars = any_str_get_chars();
992 len = (_type_ == T_STR_HEAP) ? (LL_int32) _car_ : (LL_int32) strlen(chars);
993 }
996
1011
1022 if (_type_ != T_STR_HEAP) return ll_u8_strlen(any_str_get_chars());
1024 if (n == 0) {
1025 n = ll_u8_strlen_n(prechecked_str_heap_get_chars(), (LL_int32) _car_);
1027 }
1028 return n;
1029 }
1030
1031
1057
1059 void any_svec_get_info(LL_int32 &Nelems, Sexpr_t *&elems) {
1060 ME("Cell::any_svec_get_info()");
1061 LL_int32 typ = _type_;
1062 if (typ <= T_SVEC2N_HEAP) {
1063 Nelems = as_int32();
1064 elems = (Sexpr_t *) as_Ptr_t();
1065 }
1066 else if (typ == T_SVEC_IMM) { //could be 0, 1 or 2 elems
1067 Nelems = 2; //assume
1068 if (prechecked_anypair_get_cdr() == OBJ_NOSLOT) Nelems--;
1069 if (prechecked_anypair_get_car() == OBJ_NOSLOT) Nelems--;
1070 elems = (Sexpr_t *) _car_addr_;
1071 }
1072 else THROW_BAD_TYPE;
1073 }
1074
1075 Sexpr_t *any_svec_get_elems()
1076 {
1077 ME("Cell::any_svec_get_elems()");
1078 Sexpr_t *res = 0;
1079 LL_int32 typ = _type_;
1080
1081 if (typ <= T_SVEC2N_HEAP) res = (Sexpr_t *) as_Ptr_t();
1082 else if (typ == T_SVEC_IMM) res = (Sexpr_t *) _car_addr_;
1083 else THROW_BAD_TYPE;
1084
1085 return res;
1086 }
1087
1089 {
1090 ME("Cell::any_bvec_get_length()");
1091 LL_int32 Nelems = -1;
1092 if (_type_ == T_BVEC_IMM) {
1093 ByteVec_t b = (ByteVec_t) _byte2_ptr_;
1094 Nelems = b[0];
1095 }
1096 else if ((_type_ == T_BVEC_HEAP) || (_type_ == T_BVEC_EXT) || (_type_ == T_BIGNUM)) Nelems = as_int32();
1097 else if (is_any_str_atom()) Nelems = any_str_get_length();
1098 else THROW_BAD_TYPE;
1099
1100 return Nelems;
1101 }
1102
1133 {
1134 ME("Cell::any_bvec_get_elems()");
1135 ByteVec_t res = 0;
1136 if (_type_ == T_BVEC_IMM) {
1137 ByteVec_t b = (ByteVec_t) _byte2_ptr_;
1138 res = (ByteVec_t) &(b[1]);
1139 }
1140 else if ((_type_ == T_BVEC_HEAP) || (_type_ == T_BVEC_EXT) || (_type_ == T_BIGNUM)) res = as_ByteVec_t();
1141 else if (is_any_str_atom()) res = (ByteVec_t) any_str_get_chars();
1142 else THROW_BAD_TYPE;
1143 return res;
1144 }
1145
1146 void any_bvec_get_info(LL_int32 &Nelems, ByteVec_t &elems)
1147 {
1148 ME("Cell::any_bvec_get_info()");
1149 if (_type_ == T_BVEC_IMM) {
1150 ByteVec_t b = (ByteVec_t) _byte2_ptr_;
1151 Nelems = b[0];
1152 elems = (ByteVec_t) &(b[1]);
1153 }
1154 else if ((_type_ == T_BVEC_HEAP) || (_type_ == T_BVEC_EXT) || (_type_ == T_BIGNUM)) {
1155 Nelems = as_int32();
1156 elems = as_ByteVec_t();
1157 }
1158 else if (is_any_str_atom()) {
1159 CharVec_t s;
1160 any_str_get_info(Nelems, s);
1161 elems = (ByteVec_t) s;
1162 }
1163 else THROW_BAD_TYPE;
1164 }
1165
1184 LL_int32 bvec_elem_type(void) const { return _contents._byte[3]; }
1185 void bvec_set_elem_type(LL_int32 t) { _contents._byte[3] = (Byte_t)t; }
1187
1188#undef THROW_BAD_TYPE
1189#undef _type_
1190#undef _flags_
1191#undef _car_
1192#undef _cdr_
1193#undef _car_addr_
1194#undef _int_ptr_
1195#undef _real_ptr_
1196#undef _byte2_ptr_
1197
1204 String cell_name(void);
1205
1206 Charst_t type_name(LL_int32 typ);
1207 Charst_t type_name(void) { return type_name(this->type()); }
1208 Charst_t gcstate_name(void);
1209
1210 String dump();
1211
1212 // P138: the recursive core takes an external DatumLabels table (nullptr => Simple/legacy tree print).
1213 String str(Sexpr_t sx, Bool_t as_write_or_display, DatumLabels *lbl, LL_int32 max_depth);
1214 // Legacy 4-arg form kept for source compat: env_depth is now ignored (environments print via labels + max_depth backstop).
1215 String str(Sexpr_t sx, Bool_t as_write_or_display, LL_int32 env_depth, LL_int32 max_depth) { (void) env_depth; return str(sx, as_write_or_display, (DatumLabels *) 0, max_depth); }
1216 String str(Bool_t as_write_or_display, LL_int32 env_depth, LL_int32 max_depth) { (void) env_depth; return str(this, as_write_or_display, (DatumLabels *) 0, max_depth); }
1217 String str(Bool_t as_write_or_display, LL_int32 env_depth) { (void) env_depth; return str(this, as_write_or_display, (DatumLabels *) 0, 10); }
1218 String str(Bool_t as_write_or_display) { return str(this, as_write_or_display, (DatumLabels *) 0, 10); }
1219 String str(LL_int32 env_depth) { (void) env_depth; return str(this, true, (DatumLabels *) 0, 10); }
1220 String str(void) { return str(this, true, (DatumLabels *) 0, 10); }
1222
1223private:
1224 union {
1225 Byte_t _byte[3 * sizeof(Word_t)];
1226 Word_t _word[3];
1227 } _contents;
1228
1229};
1230
1231static_assert(sizeof(Cell) == 3*sizeof(Word_t), "Cell size != 3*Word_t size\n");
1232static_assert(sizeof(Cell) == 3*sizeof(Ptr_t), "Cell size != 3*Ptr_t size\n");
1233
1236extern Sexpr_t LAMB_INPUT;
1237extern Sexpr_t LAMB_OUTPUT;
1239
1240class LambMemoryManager;
1241struct NcgFrame;
1242
1243struct NcgErrJmp;
1244
1266
1278void ll_root_balance_report(const char *where, LL_int32 before, LL_int32 after,
1279 const void *fn = nullptr);
1280LL_int32 ll_root_balance_count();
1281void ll_root_balance_reset();
1282
1301#if LL_ROOT_BALANCE
1302#define LL_ROOT_BRACKET_FN(_l_, _where_, _offset_, _fn_, ...) __extension__({ \
1303 const LL_int32 _llrb_d0 = (_l_).gc_root_depth(); \
1304 Sexpr_t _llrb_res = (__VA_ARGS__); \
1305 const LL_int32 _llrb_d1 = (_l_).gc_root_depth(); \
1306 if (_llrb_d1 != _llrb_d0 + (_offset_)) \
1307 ll_root_balance_report((_where_), _llrb_d0 + (_offset_), _llrb_d1, (_fn_)); \
1308 _llrb_res; })
1309#else
1310#define LL_ROOT_BRACKET_FN(_l_, _where_, _offset_, _fn_, ...) (__VA_ARGS__)
1311#endif
1312#define LL_ROOT_BRACKET_AT(_l_, _where_, _offset_, ...) \
1313 LL_ROOT_BRACKET_FN((_l_), (_where_), (_offset_), nullptr, __VA_ARGS__)
1314#define LL_ROOT_BRACKET(_l_, _where_, ...) \
1315 LL_ROOT_BRACKET_FN((_l_), (_where_), 0, nullptr, __VA_ARGS__)
1316
1333#define LL_CALL_MOP3(lambref, func, args, env) __extension__({ \
1334 Lamb &_llcm_l = (lambref); \
1335 Sexpr_t _llcm_a = (args); \
1336 Sexpr_t _llcm_e = (env); \
1337 LL_int32 _llcm_top = _llcm_l.gc_root_depth(); \
1338 _llcm_l.gc_root_push(_llcm_a); \
1339 _llcm_l.gc_root_push(_llcm_e); \
1340 Sexpr_t _llcm_r = (func)(_llcm_l, _llcm_a, _llcm_e); \
1341 LL_ROOT_BALANCE_AFTER_MOP3(_llcm_l, _llcm_top, (func)); \
1342 _llcm_l.gc_root_setdepth(_llcm_top); \
1343 _llcm_r; })
1349#if LL_ROOT_BALANCE
1350#define LL_ROOT_BALANCE_AFTER_MOP3(_l_, _top_, _fn_) \
1351 do { const LL_int32 _llcm_d = (_l_).gc_root_depth(); \
1352 if (_llcm_d != (_top_) + 2) \
1353 ll_root_balance_report("mop3 (direct call)", (_top_) + 2, _llcm_d, \
1354 (const void *) (_fn_)); \
1355 } while (0)
1356#else
1357#define LL_ROOT_BALANCE_AFTER_MOP3(_l_, _top_, _fn_) do { } while (0)
1358#endif
1366
1367class Lamb {
1368public:
1369
1370 Lamb();
1371
1376 typedef Sexpr_t (*Mop3st_t)(Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec);
1377 typedef Sexpr_t (*Mop3st_argv_t)(Lamb &lamb, Sexpr_t *argv, int nargs, Sexpr_t env_exec);
1382
1385 Sexpr_t setup(void);
1386 Sexpr_t loop(void);
1387 void end(void);
1395
1398 void log(const char *fmt, ...) CHECKPRINTF_pos2;
1399 void printf(const char *fmt, ...) CHECKPRINTF_pos2;
1400 bool debug(void);
1401 void debug(bool onoff);
1403
1407 unsigned long build_version();
1408 unsigned long build_UTC();
1409 unsigned long build_pushUTC();
1410 const char *build_buildRelease();
1411 const char *build_buildDate();
1412 const char *build_pushDate();
1414
1421 void expand();
1438 Sexpr_t tcons(LL_int32 typ, Word_t a, Word_t b, Sexpr_t env_exec);
1439 Sexpr_t tcons(LL_int32 typ, Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1440
1441 Sexpr_t cons(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec) { return tcons(Cell::T_PAIR, a, b, env_exec); }
1442
1443 void gc_root_push(Sexpr_t p);
1444 Sexpr_t materialized(Sexpr_t box);
1445 void gc_root_pop(LL_int32 n=1);
1446 LL_int32 gc_root_depth();
1449#ifdef LL_GC_POISON
1450 LL_int32 gc_root_find(Sexpr_t s);
1451 LL_int32 gc_phase_now();
1452 LL_int32 gc_snapshot_nroots();
1453#endif
1454 void gc_root_setdepth(LL_int32 n);
1455 void gc_idle_task_us(LL_int32 us, Sexpr_t env_exec);
1456 void gc_collect(Sexpr_t env_exec);
1457
1474 uint32_t eval_progress() const;
1475 LL_int32 gc_Qm() const;
1476 void gc_pass_n(LL_int32 nsteps);
1477
1478 // ── P6 LambSettings accessors (delegate to LambMemoryManager) ────────────
1479 LL_int32 mem_cell_block_size();
1480 LL_int32 mem_n_cell_blocks();
1481 LL_int32 mem_total_cells();
1482 LL_int32 mem_ngc();
1483 LL_int32 mem_markstack_grows();
1484 LL_int32 mem_urgent_calls();
1485 LL_int32 mem_urgent_max_us();
1486 void mem_diag_quiet(Bool_t q);
1487 LL_int32 mem_startmark_max_us();
1488 LL_int32 mem_startmark_nroots();
1489 LL_int32 mem_extraroots_max_us();
1490 LL_int32 mem_extraroots_pushes();
1491 LL_int32 mem_nfree();
1492 LL_int32 mem_extension_block_size();
1493 void mem_set_extension_block_size(LL_int32 sz);
1494 void mem_expand_to_n_blocks(LL_int32 n, Sexpr_t env_exec);
1495 LL_int32 mem_max_cell_blocks();
1496 void mem_set_max_cell_blocks(LL_int32 n);
1497 LL_int32 mem_gc_budget_ns();
1498 LL_int32 mem_dbg_urgent_max_us();
1499 LL_int32 mem_dbg_urgent_calls();
1500 LL_int32 mem_dbg_urgent_bulk();
1501 unsigned long mem_dbg_t_gc_total_us();
1502 LL_int32 mem_dbg_nfree();
1504 LL_int32 mem_dbg_amax();
1505 LL_int32 mem_dbg_live_marked();
1506 unsigned long mem_dbg_n_idle();
1507 unsigned long mem_dbg_n_work();
1508 LL_int32 mem_dbg_t_mark_ns();
1509 LL_int32 mem_dbg_t_sweep_ns();
1510 LL_int32 mem_dbg_mark_q();
1511 LL_int32 mem_dbg_sweep_q();
1512 LL_int32 mem_dbg_yuasa_M();
1513 LL_int32 mem_dbg_yuasa_N();
1514 void mem_set_gc_budget_ns(LL_int32 ns);
1515 LL_int32 mem_gcload_target_pct();
1516 void mem_set_gcload_target_pct(LL_int32 pct);
1517 LL_int32 verbosity() { return _verbosity; }
1518 void set_verbosity(LL_int32 v){ _verbosity = v; }
1519
1524 // Maintainer note: declared here, defined beside the ll_term singleton that stores it -- a shipped
1525 // ll_xmop3_*.cpp must be
1526 // Maintainer note: a shipped ll_xmop3_*.cpp must be able to set this without including a header
1527 // that is stripped from customer packages -- doing otherwise made every package unbuildable.
1528 void set_repl_quiet(bool q);
1529 bool repl_quiet(void) const;
1531 void ncg_frame_pool_init(LL_int32 n);
1534
1537 Sexpr_t car(Sexpr_t l);
1538 Sexpr_t cdr(Sexpr_t l);
1539 Sexpr_t prechecked_anypair_get_car(Sexpr_t c);
1540 Sexpr_t prechecked_anypair_get_cdr(Sexpr_t c);
1541 Sexpr_t caar(Sexpr_t l) { return car(car(l)); }
1542 Sexpr_t cadr(Sexpr_t l) { return car(cdr(l)); }
1543
1595 int car_type(Sexpr_t c) { if (c->car_is_int()) return Cell::T_INT32;
1596 if (c->car_is_float()) return Cell::T_FLOAT32;
1597 return c->prechecked_anypair_get_car()->type(); }
1598 int cdr_type(Sexpr_t c) { if (c->cdr_is_int()) return Cell::T_INT32;
1599 if (c->cdr_is_float()) return Cell::T_FLOAT32;
1600 return c->prechecked_anypair_get_cdr()->type(); }
1601 LL_int32 car_mustbe_int32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR && c->car_is_int()) return c->car_int32(); return car(c)->mustbe_int32(); }
1602 LL_int32 cdr_mustbe_int32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR && c->cdr_is_int()) return c->cdr_int32(); return cdr(c)->mustbe_int32(); }
1603 LL_float32 car_mustbe_float32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR && c->car_is_float()) return c->car_float32(); return car(c)->mustbe_float32(); }
1604 LL_float32 cdr_mustbe_float32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR && c->cdr_is_float()) return c->cdr_float32(); return cdr(c)->mustbe_float32(); }
1605
1606 LL_int32 car_coerce_int32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->car_is_int()) return c->car_int32(); if (c->car_is_float()) return (LL_int32) c->car_float32(); } return car(c)->coerce_int32(); }
1607 LL_int32 cdr_coerce_int32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->cdr_is_int()) return c->cdr_int32(); if (c->cdr_is_float()) return (LL_int32) c->cdr_float32(); } return cdr(c)->coerce_int32(); }
1608 LL_int64 car_coerce_int64(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->car_is_int()) return (LL_int64) c->car_int32(); if (c->car_is_float()) return (LL_int64) c->car_float32(); } return car(c)->coerce_int64(); }
1609 LL_int64 cdr_coerce_int64(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->cdr_is_int()) return (LL_int64) c->cdr_int32(); if (c->cdr_is_float()) return (LL_int64) c->cdr_float32(); } return cdr(c)->coerce_int64(); }
1610 LL_float32 car_coerce_float32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->car_is_float()) return c->car_float32(); if (c->car_is_int()) return (LL_float32) c->car_int32(); } return car(c)->coerce_float32(); }
1611 LL_float32 cdr_coerce_float32(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->cdr_is_float()) return c->cdr_float32(); if (c->cdr_is_int()) return (LL_float32) c->cdr_int32(); } return cdr(c)->coerce_float32(); }
1612 LL_float64 car_coerce_float64(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->car_is_float()) return (LL_float64) c->car_float32(); if (c->car_is_int()) return (LL_float64) c->car_int32(); } return car(c)->coerce_float64(); }
1613 LL_float64 cdr_coerce_float64(Sexpr_t c) { if (c->type() >= Cell::T_PAIR) { if (c->cdr_is_float()) return (LL_float64) c->cdr_float32(); if (c->cdr_is_int()) return (LL_float64) c->cdr_int32(); } return cdr(c)->coerce_float64(); }
1615 Sexpr_t cdar(Sexpr_t l) { return cdr(car(l)); }
1616 Sexpr_t cddr(Sexpr_t l) { return cdr(cdr(l)); }
1617 Sexpr_t caddr(Sexpr_t l) { return car(cddr(l)); }
1618 Sexpr_t cdddr(Sexpr_t l) { return cdr(cddr(l)); }
1619 Sexpr_t cadddr(Sexpr_t l) { return car(cdddr(l)); }
1620 Sexpr_t cddddr(Sexpr_t l) { return cdr(cdddr(l)); }
1622
1625 void set_car_bang(Sexpr_t c, Sexpr_t val);
1626 void set_cdr_bang(Sexpr_t c, Sexpr_t val);
1627 void vector_set_bang(Sexpr_t vec, LL_int32 k, Sexpr_t val);
1628 Sexpr_t reverse_bang(Sexpr_t l);
1630
1633 Sexpr_t eq_q(Sexpr_t obj1, Sexpr_t obj2);
1634 Sexpr_t eqv_q(Sexpr_t obj1, Sexpr_t obj2);
1635 Sexpr_t equal_q(Sexpr_t obj1, Sexpr_t obj2);
1636 Sexpr_t assq(Sexpr_t obj, Sexpr_t alist);
1638
1658
1660 Sexpr_t oblist_query(Sexpr_t oblist, const char *identifier, Bool_t force, Sexpr_t env_exec);
1661 Sexpr_t oblist_test(Sexpr_t oblist, const char *identifier, Sexpr_t env_exec) { return oblist_query(oblist, identifier, false, env_exec); }
1662 Sexpr_t oblist_intern(Sexpr_t oblist, const char *identifier, Sexpr_t env_exec) { return oblist_query(oblist, identifier, true, env_exec); }
1663 Sexpr_t oblist_analyze(Sexpr_t oblist, LL_int32 verbosity, Sexpr_t env_exec);
1665
1672 Sexpr_t dict_new(LL_int32 framesize, Sexpr_t env_exec) { return dict_add_empty_frame(NIL, framesize, env_exec); }
1673 Sexpr_t dict_new(Sexpr_t env_exec) { return dict_add_empty_frame(NIL, 0, env_exec); }
1674
1678 Sexpr_t dict_add_empty_frame(Sexpr_t dict, LL_int32 framesize, Sexpr_t env_exec);
1679 Sexpr_t dict_add_empty_frame(Sexpr_t dict, Sexpr_t env_exec) { return dict_add_empty_frame(dict, 0, env_exec); }
1680
1681 Sexpr_t dict_add_keyval_frame(Sexpr_t dict, Sexpr_t keys, Sexpr_t vals, Sexpr_t env_exec);
1682 Sexpr_t dict_add_keyval_frame_argv(Sexpr_t dict, Sexpr_t keys, Sexpr_t *argv, int nargs, Sexpr_t env_exec);
1683 Sexpr_t dict_add_vector_frame(Sexpr_t parent, Sexpr_t names, Sexpr_t *vals, int ncaps, Sexpr_t env);
1684 Sexpr_t dict_add_alist_frame(Sexpr_t dict, Sexpr_t alist, Sexpr_t env_exec) { return mk_dict(alist, dict, env_exec); }
1685 Sexpr_t dict_append_bang(Sexpr_t d1, Sexpr_t d2, Sexpr_t env_exec);
1686 void dict_bind_bang(Sexpr_t dict, Sexpr_t key, Sexpr_t value, Sexpr_t env_exec);
1687 void dict_bind_local_bang(Sexpr_t dict, Sexpr_t key, Sexpr_t value, Sexpr_t env_exec);
1688 void dict_rebind_bang(Sexpr_t dict, Sexpr_t key, Sexpr_t value, Sexpr_t env_exec);
1689 void dict_bind_alist_bang(Sexpr_t dict, Sexpr_t alist, Sexpr_t env_exec);
1690 void dict_rebind_alist_bang(Sexpr_t dict, Sexpr_t alist, Sexpr_t env_exec);
1691
1692 Sexpr_t dict_ref_q(Sexpr_t dict, Sexpr_t key);
1693 Sexpr_t dict_ref(Sexpr_t dict, Sexpr_t key);
1694
1696 Sexpr_t dict_keys(Sexpr_t dict, Sexpr_t env_exec);
1697 Sexpr_t dict_values(Sexpr_t dict, Sexpr_t env_exec);
1698
1699 Sexpr_t dict_to_alist(Sexpr_t dict, Sexpr_t env_exec);
1700 Sexpr_t dict_to_2list(Sexpr_t dict, Sexpr_t env_exec);
1701 Sexpr_t alist_to_dict(Sexpr_t alist, Sexpr_t env_exec);
1702 Sexpr_t twolist_to_dict(Sexpr_t twolist, Sexpr_t env_exec);
1703
1704 Sexpr_t dict_analyze(Sexpr_t dict, LL_int32 verbosity = 0);
1705 Sexpr_t integrity_check(Sexpr_t env_exec, LL_int32 verbosity = 1);
1707
1710 Sexpr_t read(LL_Port &src, Sexpr_t env_exec) { return read_sexpr(src, env_exec, false); }
1711
1712 Sexpr_t write_or_display(Sexpr_t sexpr, Bool_t do_write, WriteMode mode = WriteMode::Cyclic);
1713 Sexpr_t write_simple(Sexpr_t sexpr);
1714
1721 String sprintf(Charst_t fmt, Sexpr_t args, Sexpr_t env_exec);
1722
1723 Sexpr_t printf(Sexpr_t args, LL_Port &outp);
1724 Sexpr_t printf(Sexpr_t args);
1726
1729 Sexpr_t eval(Sexpr_t sexpr, Sexpr_t env_exec);
1730 Sexpr_t eval_list(Sexpr_t args, Sexpr_t env_exec);
1731 Sexpr_t apply_proc_partial(Sexpr_t proc, Sexpr_t sexpr, Sexpr_t env_exec);
1732 Sexpr_t map_proc(Sexpr_t proc, Sexpr_t lists, Sexpr_t env_exec);
1734
1737 Sexpr_t r5_base_environment() { return _r5_base_environment; }
1738 Sexpr_t r5_interaction_environment() { return _r5_interaction_environment; }
1739 Sexpr_t lamb_oblist() { return _lamb_oblist; }
1740
1744 Sexpr_t current_input_port() { return (_r5_cur_in_cell != NIL) ? (Sexpr_t) _r5_cur_in_cell->get_cdr() : NIL; }
1745 Sexpr_t current_output_port() { return (_r5_cur_out_cell != NIL) ? (Sexpr_t) _r5_cur_out_cell->get_cdr() : NIL; }
1746 Sexpr_t current_error_port() { return (_r5_cur_err_cell != NIL) ? (Sexpr_t) _r5_cur_err_cell->get_cdr() : NIL; }
1747 void set_current_input_port(Sexpr_t p) { if (_r5_cur_in_cell != NIL) set_cdr_bang(_r5_cur_in_cell, p); }
1748 void set_current_output_port(Sexpr_t p) { if (_r5_cur_out_cell != NIL) set_cdr_bang(_r5_cur_out_cell, p); }
1749 void set_current_error_port(Sexpr_t p) { if (_r5_cur_err_cell != NIL) set_cdr_bang(_r5_cur_err_cell, p); }
1750
1751 bool reader_fold_case() { return _reader_fold_case; }
1752 void reader_fold_case_set(bool v) { _reader_fold_case = v; }
1754
1755 Sexpr_t load(Charst_t name, Sexpr_t env_exec, LL_int32 verbosity = 0);
1756
1759 Sexpr_t append(Sexpr_t sexpr, Sexpr_t env_exec);
1760 Sexpr_t append2(Sexpr_t lis, Sexpr_t obj, Sexpr_t env_exec);
1761 Sexpr_t list_copy(Sexpr_t sexpr, Sexpr_t env_exec);
1767 Sexpr_t list_analyze(Sexpr_t sexpr, Sexpr_t env_exec);
1768 Sexpr_t list_to_vector(Sexpr_t l, Sexpr_t env_exec);
1769 Sexpr_t vector_to_list(Sexpr_t v, Sexpr_t env_exec);
1770 Sexpr_t vector_copy(Sexpr_t from, Sexpr_t env_exec);
1772
1777 Sexpr_t vector_to_sparsevec(Sexpr_t vec, Sexpr_t skip, Sexpr_t env_exec);
1778 Sexpr_t sparsevec_to_vector(Sexpr_t alist, Sexpr_t fill, Sexpr_t env_exec);
1780
1787 Sexpr_t mk_error(Sexpr_t env_exec, Sexpr_t irritants, const char *fmt, ...) CHECKPRINTF_pos4;
1788 Sexpr_t mk_error(Sexpr_t env_exec, const char *fmt, ...) CHECKPRINTF_pos3;
1789 Sexpr_t mk_syserror(const char *fmt, ...) CHECKPRINTF_pos2;
1790 Sexpr_t tag_error(Sexpr_t err, const char *kind);
1791 Sexpr_t mk_syserror(Sexpr_t irritants, const char *fmt, ...) CHECKPRINTF_pos3;
1793
1804 Sexpr_t gensym(Sexpr_t env_exec);
1805 Sexpr_t mk_bool(Bool_t b, Sexpr_t env_exec) { return b? HASHT : HASHF; }
1806 Sexpr_t mk_character(ll_codepoint_t cp, Sexpr_t env_exec) { return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set(Cell::T_CHAR, (Word_t)cp, (Word_t)0); }
1813 Sexpr_t mk_integer(LL_int64 i, Sexpr_t env_exec) {
1814 if (i >= SINT_CACHE_MIN && i <= SINT_CACHE_MAX) return sint_cache_cells + (LL_int32)(i - SINT_CACHE_MIN);
1815 if (i >= INT32_MIN && i <= INT32_MAX) return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set((LL_int32) i);
1816 return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set(i);
1817 }
1818 Sexpr_t mk_int32(LL_int32 i, Sexpr_t env_exec) {
1819 if (i >= SINT_CACHE_MIN && i <= SINT_CACHE_MAX) return sint_cache_cells + (i - SINT_CACHE_MIN);
1820 return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set(i);
1821 }
1822 Sexpr_t mk_int64(LL_int64 i, Sexpr_t env_exec) { return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set(i); }
1827 // Maintainer note: a float cache was proposed; the branch is paid by the misses too, and measurement
1829 Sexpr_t mk_float32(LL_float32 r, Sexpr_t env_exec) {
1830#if LL_FLOAT_PROFILE
1831 ll_float_prof_note((double) r);
1832#endif
1833 return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set(r); }
1834 Sexpr_t mk_float64(LL_float64 d, Sexpr_t env_exec) {
1835#if LL_FLOAT_PROFILE
1836 ll_float_prof_note((double) d);
1837#endif
1838 return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set(d); }
1839 Sexpr_t mk_complex(LL_float32 r, LL_float32 i, Sexpr_t env_exec) { return tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec)->set(r, i); }
1841 void rat_store_i64(Sexpr_t c, bool is_num, LL_int64 v, Sexpr_t env_exec) {
1842 if (v >= (LL_int64) INT32_MIN && v <= (LL_int64) INT32_MAX) {
1843 if (is_num) c->rat_set_car_i32((LL_int32) v); else c->rat_set_cdr_i32((LL_int32) v);
1844 } else {
1845 Sexpr_t b = mk_int64(v, env_exec);
1846 if (is_num) c->rat_set_car_ptr(b); else c->rat_set_cdr_ptr(b);
1847 }
1848 }
1849
1852 Sexpr_t mk_rational(LL_int64 num, LL_int64 den, Sexpr_t env_exec) {
1853 if (den == 0) throw mk_syserror("rational: division by zero");
1854#if LL_RATIONAL
1855 if (den < 0) { num = -num; den = -den; }
1856 LL_int64 a = num < 0 ? -num : num, b = den;
1857 while (b) { LL_int64 r = a % b; a = b; b = r; }
1858 if (a > 0) { num /= a; den /= a; }
1859 if (den == 1) return mk_integer(num, env_exec);
1860 Sexpr_t c = tcons(Cell::T_PAIR, (Word_t) 0, (Word_t) 0, env_exec);
1861 c->set((LL_int32) 0, (LL_int32) 1);
1862 rat_store_i64(c, true, num, env_exec);
1863 rat_store_i64(c, false, den, env_exec);
1864 return c;
1865#else
1866 return mk_float64((LL_float64) num / (LL_float64) den, env_exec);
1867#endif
1868 }
1869#if LL_RATIONAL && LL_BIGNUM
1871 Sexpr_t mk_rational_big(Sexpr_t num, Sexpr_t den, Sexpr_t env_exec);
1872 Sexpr_t rat_num_cell(Sexpr_t x, Sexpr_t env_exec);
1873 Sexpr_t rat_den_cell(Sexpr_t x, Sexpr_t env_exec);
1874 void rat_store_cell(Sexpr_t c, bool is_num, Sexpr_t val);
1875 Sexpr_t rat_big_add2(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1876 Sexpr_t rat_big_sub2(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1877 Sexpr_t rat_big_mul2(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1878 Sexpr_t rat_big_div2(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1879 int rat_big_cmp2(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1880 Sexpr_t rat_big_floorlike(Sexpr_t x, int mode, Sexpr_t env_exec);
1881#endif
1882
1883 Sexpr_t mk_number(Charst_t str, Sexpr_t env_exec);
1884
1885 Sexpr_t mk_sharp_const(Charst_t name, Sexpr_t env_exec);
1886
1887#if LL_BIGNUM
1888 // P54.2 — T_BIGNUM methods
1889 Sexpr_t mk_bignum(int nlimbs, int sign, Sexpr_t env_exec);
1890 Sexpr_t bignum_normalize(Sexpr_t x, Sexpr_t env_exec);
1891 Sexpr_t bignum_add(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1892 Sexpr_t bignum_sub(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1893 Sexpr_t bignum_mul(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1894 Sexpr_t bignum_divmod(Sexpr_t a, Sexpr_t b, Sexpr_t *rem, Sexpr_t env_exec);
1895 Sexpr_t bignum_gcd(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1896 int bignum_cmp(Sexpr_t a, Sexpr_t b);
1900 int exact_int_cmp(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec);
1901 Sexpr_t bignum_shift(Sexpr_t a, int bits, Sexpr_t env_exec);
1902 Sexpr_t bignum_ashift(Sexpr_t n, int bits, Sexpr_t env_exec);
1903 Sexpr_t bignum_bitwise(Sexpr_t a, Sexpr_t b, char op, Sexpr_t env_exec);
1904 Sexpr_t bignum_modexp_sw(Sexpr_t base, Sexpr_t exp, Sexpr_t mod, Sexpr_t env_exec);
1905 Sexpr_t bignum_to_string(Sexpr_t x, int radix, Sexpr_t env_exec);
1906 Sexpr_t bignum_from_string(const char *s, int radix, Sexpr_t env_exec);
1907 Sexpr_t to_bignum(Sexpr_t x, Sexpr_t env_exec);
1908#endif
1910
1937
1953 Sexpr_t mk_string(Sexpr_t env_exec, const char *fmt, ...) CHECKPRINTF_pos3;
1970 void *payload_alloc(size_t nbytes, const char *who, Sexpr_t env_exec);
1971
1974 Sexpr_t mk_string(LL_int32 k, Charst_t src, Sexpr_t env_exec);
1975 Sexpr_t mk_string(String s, Sexpr_t env_exec) { return mk_string(s.length(), s.c_str(), env_exec); }
1976
1977 Sexpr_t mk_symbol_or_number(Charst_t str, Sexpr_t env_exec);
1978 Sexpr_t mk_symbol(Charst_t str, Sexpr_t env_exec) { return oblist_intern(_lamb_oblist, str, env_exec); }
1979
1980 Sexpr_t mk_bytevector(LL_int32 k, Sexpr_t env_exec);
1981 Sexpr_t mk_bytevector(LL_int32 k, Bytest_t src, Sexpr_t env_exec);
1982 Sexpr_t mk_bytevector(LL_int32 k, LL_int32 fill, Sexpr_t env_exec);
1983
1985 Sexpr_t mk_bytevector_ext(LL_int32 k, Bytest_t ext, Sexpr_t env_exec) { return tcons(Cell::T_BVEC_EXT, (Word_t) k, (Word_t) ext, env_exec); }
1986
1988 Sexpr_t mk_intvector(LL_int32 k, Sexpr_t env_exec);
1989 Sexpr_t mk_realvector(LL_int32 k, Sexpr_t env_exec);
1990 Sexpr_t mk_intvector(LL_int32 k, LL_int32 fill, Sexpr_t env_exec);
1991 Sexpr_t mk_realvector(LL_int32 k, LL_float32 fill, Sexpr_t env_exec);
1992
1993 Sexpr_t mk_vector(LL_int32 len, Sexpr_t fill, Sexpr_t env_exec);
1994 Sexpr_t mk_hashtbl(LL_int32 len, Sexpr_t fill, Sexpr_t env_exec);
1995
1996 Sexpr_t mk_serial_port(Sexpr_t env_exec);
1997 Sexpr_t mk_input_file_port(Charst_t name, Sexpr_t env_exec);
1998 Sexpr_t mk_output_file_port(Charst_t name, Sexpr_t env_exec);
1999
2026#if LL_NETWORK
2027 Sexpr_t mk_udp_port(unsigned local_port, Sexpr_t env_exec);
2028 Sexpr_t mk_tcp_client_port(Charst_t host, unsigned port, Sexpr_t env_exec);
2029 Sexpr_t mk_tcp_server_port(unsigned port, Sexpr_t env_exec);
2030 Sexpr_t server_accept_port(LL_Port *server, Sexpr_t env_exec);
2031#endif
2032#if LL_WIFI
2033 Sexpr_t mk_tls_client_port(Charst_t host, unsigned port, Charst_t ca_cert_pem, Sexpr_t env_exec);
2034 Sexpr_t mk_tls_server_port(unsigned port, Charst_t cert_pem, Charst_t key_pem, Sexpr_t env_exec);
2035#endif
2037
2038 Sexpr_t mk_input_string_port(Charst_t inp, Sexpr_t env_exec);
2039 Sexpr_t mk_output_string_port(Sexpr_t env_exec);
2040 Sexpr_t mk_input_bytevector_port(ByteVec_t src, LL_int32 n, Sexpr_t env_exec);
2041 Sexpr_t mk_output_bytevector_port(Sexpr_t env_exec);
2043
2046 Sexpr_t mk_Mop3_procst_t(Mop3st_t f, Sexpr_t env_exec) { return tcons(Cell::T_MOP3_PROC, (Word_t) 0, (Word_t) f, env_exec); }
2047 Sexpr_t mk_Mop3_procst_argv_t(Mop3st_t f, Mop3st_argv_t fa, Sexpr_t env_exec) { return tcons(Cell::T_MOP3_PROC, (Word_t) fa, (Word_t) f, env_exec); }
2048 Sexpr_t mk_Mop3_nprocst_t(Mop3st_t f, Sexpr_t env_exec) { return tcons(Cell::T_MOP3_NPROC, (Word_t) 0, (Word_t) f, env_exec); }
2049 Sexpr_t mk_cppobj(void *obj, CPPDeleterPtr deleter, Sexpr_t env_exec) { return tcons(Cell::T_CPP_HEAP, (Word_t) deleter, (Word_t) obj, env_exec); }
2051
2065 Sexpr_t mk_macro(Sexpr_t nlam, Sexpr_t env_nlam, Sexpr_t env_exec) { return tcons(Cell::T_MACRO, nlam, env_nlam, env_exec); }
2066 Sexpr_t mk_procedure(Sexpr_t formals, Sexpr_t body, Sexpr_t env_proc, Sexpr_t env_exec) { return tcons(Cell::T_PROC, cons(formals, body, env_proc), env_proc, env_exec); }
2067 Sexpr_t mk_nprocedure(Sexpr_t formals, Sexpr_t body, Sexpr_t env_nproc, Sexpr_t env_exec) { return tcons(Cell::T_NPROC, cons(formals, body, env_nproc), env_nproc, env_exec); }
2068 Sexpr_t mk_thunk_sexpr(Sexpr_t sexpr, Sexpr_t env_thunk, Sexpr_t env_exec) { return tcons(Cell::T_THUNK_SEXPR, sexpr, env_thunk, env_exec); }
2069 Sexpr_t mk_thunk_body(Sexpr_t body, Sexpr_t env_thunk, Sexpr_t env_exec) { return tcons(Cell::T_THUNK_BODY, body, env_thunk, env_exec); }
2070 Sexpr_t mk_dict(Sexpr_t frame, Sexpr_t base, Sexpr_t env_exec) { return tcons(Cell::T_DICT, frame, base, env_exec); }
2071 Sexpr_t mk_dict(LL_int32 framesize, Sexpr_t env_exec);
2073
2079 Sexpr_t macroexpand(Sexpr_t form, Sexpr_t env_exec);
2080 Sexpr_t macroexpand1(Sexpr_t form, Sexpr_t env_exec);
2081
2082 Sexpr_t macroexpand(Sexpr_t proc, Sexpr_t args, Sexpr_t env_exec);
2083 Sexpr_t macroexpand1(Sexpr_t proc, Sexpr_t args, Sexpr_t env_exec);
2085
2088 NcgFrame *ncg_frame_top = nullptr;
2089 NcgFrame *ncg_frame_pool_head = nullptr;
2091 NcgErrJmp *ncg_err_ctx = nullptr;
2092
2094 Sexpr_t ncg_eval(Sexpr_t bc, Sexpr_t args, Sexpr_t env_exec);
2095 Sexpr_t ncg_eval_argv(Sexpr_t bc, Sexpr_t *argv, int nargs, Sexpr_t env_exec);
2096 Sexpr_t ncg_compile(Sexpr_t bc, Sexpr_t env_exec, Sexpr_t captured_names = nullptr);
2097 void ncg_disassemble(Sexpr_t bc, Sexpr_t env_exec);
2098 void ncg_vector_set_ptr(Sexpr_t *data_ptr, LL_int32 k, Sexpr_t val);
2099 // P38 helpers -- fast vector-ref/set with write barrier; called by ncg_vector_ref/set_fast shims.
2100 Sexpr_t ncg_vref_fast(Sexpr_t vec, Sexpr_t idx);
2101 Sexpr_t ncg_vset_fast(Sexpr_t vec, Sexpr_t idx, Sexpr_t val);
2102 // P40 helper -- fast cons from free list, no gc_pass.
2103 Sexpr_t ncg_cons_fast(Sexpr_t a, Sexpr_t d);
2104 Sexpr_t ncg_box_fast(LL_int64 v);
2106
2122 const char *eval_stack_base_ = nullptr;
2123 size_t eval_stack_budget_ = LL_EVAL_STACK_BUDGET;
2124 LL_int32 eval_root_depth_max_ = LL_EVAL_ROOT_DEPTH_MAX;
2125
2126 void eval_recursion_overflow(const char *where);
2127 inline void eval_recursion_check(const char *where) {
2128 char _probe;
2129 const char *_sp = &_probe;
2130 if ((eval_stack_base_ == nullptr) || (_sp > eval_stack_base_)) eval_stack_base_ = _sp; // track outermost (highest)
2131 if ((size_t) (eval_stack_base_ - _sp) > eval_stack_budget_) eval_recursion_overflow(where); // C-stack guard page
2132 if (gc_root_depth() > eval_root_depth_max_) eval_recursion_overflow(where); // rootstack OOB write
2133 }
2134
2135
2138
2139 /* put this comment after the last documented member to start new page in doxygen detailed section.
2140 \latexonly \newpage \endlatexonly
2141 */
2142
2143private:
2144
2145 LambMemoryManager *mem;
2146
2147 bool _debug_in_progress;
2148 bool _reader_fold_case;
2149 LL_int32 _verbosity;
2150 LL_float32 ema_loop_ms = 4.0f;
2151 int ema_alpha_inv = 8;
2152
2153 //Symbols and bindings
2154 static const LL_int32 _lamb_oblist_size = 2048;
2155 static const LL_int32 _r5_base_frame_size = 1024;
2156 static const LL_int32 _r5_interaction_frame_size = 512;
2157
2158 Sexpr_t _lamb_oblist;
2159 Sexpr_t _r5_base_environment;
2160 Sexpr_t _r5_interaction_environment;
2161
2162 Sexpr_t _r5_cur_in_cell;
2163 Sexpr_t _r5_cur_out_cell;
2164 Sexpr_t _r5_cur_err_cell;
2165
2166 //Reader
2167 const char *DELIMITERS = "()\";\f\t\v\n\r ";
2168
2169 enum {
2170 TOK_EOF,
2171 TOK_LPAREN,
2172 TOK_RPAREN,
2173 TOK_DOT,
2174 TOK_ATOM,
2175 TOK_SQUOTE,
2176 TOK_DQUOTE,
2177 TOK_BQUOTE,
2178 TOK_COMMA,
2179 TOK_COMMA_AT,
2180 TOK_SHARP,
2181 TOK_SHARP_CONST,
2182 TOK_VECTOR,
2183 TOK_BVECTOR,
2184 TOK_DCOLON,
2185 Ntokens
2186 };
2187
2188 void report();
2189
2190 LL_int32 produce_token(LL_Port &src, Sexpr_t &env_exec);
2191 Sexpr_t consume_token(LL_int32 tok, LL_Port &src, Sexpr_t env_exec, bool quoted);
2192
2193 //Tokens that the reader recognizes and converts directly to symbols.
2194 Sexpr_t sym_squote; //single quote '
2195 Sexpr_t sym_qquote; //backquote `
2196 Sexpr_t sym_unquote; //comma ,
2197 Sexpr_t sym_uqsplice; //comma-at ,@
2198
2199 //Symbols inserted into the reader output to complete multi-step operations
2200 //e.g., a quoted vector '#(a b c) becomes (apply vector (quote (a b c)))
2201 Sexpr_t sym_apply;
2202 Sexpr_t sym_vector;
2203
2204 //Magic reader tokens that turn into magic symbols.
2205 Sexpr_t sym_colon_hook; //LL_float64 colon ::
2206 Sexpr_t sym_sharp_hook; //sharp # (not constant or vector)
2207
2208 Sexpr_t sym_ellipsis; //three dot ellipsis ...
2209 Sexpr_t sym_fatarrow; //aka "feed through" =>
2210
2211 //Loop-based control
2212 Sexpr_t sym_loop;
2213 Sexpr_t sym_loop_deadline_ms;
2214 Sexpr_t sym_gc_idle_strategy;
2215 Sexpr_t sym_gcis_auto;
2216 Sexpr_t sym_gcis_deadline;
2217 Sexpr_t sym_gcis_jitter;
2218 Sexpr_t sym_gcis_off;
2219
2220 Sexpr_t vector_eqv_q(Sexpr_t obj1, Sexpr_t obj2);
2221 Sexpr_t hashtbl_eqv_q(Sexpr_t obj1, Sexpr_t obj2);
2222 Sexpr_t bytevector_eqv_q(Sexpr_t obj1, Sexpr_t obj2);
2223
2224 //Bindings: Symbols, Variables and Environments
2225 Sexpr_t dump_frame(Sexpr_t frame);
2226 Sexpr_t dump_env_stack(Sexpr_t env_stack);
2227
2229 const char *token2name(LL_int32 tok);
2230
2231 // P138: datum-label read state (`#N=<datum>` / `#N#`). A placeholder cell is pre-registered
2232 // before its datum is read so an interior `#N#` resolves to the same (still-being-filled) cell,
2233 // reconstructing cycles. Placeholders are kept as GC roots for the whole top-level read.
2234 // (Plain arrays, not autobuf_t: ll_vm_util.h is not visible this early in the header.)
2235 LL_int32 *rd_lab_ids;
2236 Sexpr_t *rd_lab_cells;
2237 LL_int32 rd_lab_cap;
2238 LL_int32 rd_lab_n;
2239 LL_int32 rd_lab_depth;
2240 LL_int32 rd_lab_root_base;
2241 void rd_label_register(LL_int32 id, Sexpr_t cell);
2242 Sexpr_t rd_label_lookup(LL_int32 id);
2243
2244 Sexpr_t read_sexpr(LL_Port &src, Sexpr_t &env_exec, bool quoted);
2245 Sexpr_t read_atom(LL_Port &src, Sexpr_t &env_exec);
2246
2247 Sexpr_t read_any_quote(Sexpr_t symbol, LL_Port &src, Sexpr_t &env_exec);
2248 Sexpr_t read_squote(LL_Port &src, Sexpr_t env_exec) { return read_any_quote(sym_squote, src, env_exec); }
2249 Sexpr_t read_qquote(LL_Port &src, Sexpr_t env_exec) { return read_any_quote(sym_qquote, src, env_exec); }
2250 Sexpr_t read_unquote(LL_Port &src, Sexpr_t env_exec) { return read_any_quote(sym_unquote, src, env_exec); }
2251 Sexpr_t read_uqsplice(LL_Port &src, Sexpr_t env_exec) { return read_any_quote(sym_uqsplice, src, env_exec); }
2252
2253 Sexpr_t read_sharp_const(LL_Port &src, Sexpr_t &env_exec);
2254 Sexpr_t read_sharp(LL_Port &src, Sexpr_t &env_exec);
2255 Sexpr_t read_vector(LL_Port &src, Sexpr_t &env_exec);
2256 Sexpr_t read_bvector(LL_Port &src, Sexpr_t &env_exec);
2257 Sexpr_t read_quotedvector(LL_Port &src, Sexpr_t &env_exec);
2258 Sexpr_t read_list(LL_Port &src, Sexpr_t &env_exec, bool quoted);
2259 Sexpr_t read_string(LL_Port &src, Sexpr_t &env_exec);
2260 Sexpr_t read_bar_symbol(LL_Port &src, Sexpr_t &env_exec);
2261
2262};
2263
2264// Maintainer note: the frame idiom for the inline Lamb members below. `ll_gc_frame` is
2265// mem->rootpush-based and is NOT in scope here -- this header is included first in
2268//With error check, inlined for speed.
2276#ifdef LL_GC_POISON
2277void ll_poison_check_read(Sexpr_t c, const char *where);
2278#define LL_POISON_READ(c) ll_poison_check_read((c), me)
2279int ll_poison_check_list(Sexpr_t head, const char *what, const char *where);
2280#define LL_POISON_ARG(x) ll_poison_check_list((x), #x, me)
2281#define LL_POISON_AT(x, lbl) ll_poison_check_list((x), #x, (lbl))
2282#else
2283#define LL_POISON_READ(c) ((void) 0)
2284#endif
2285
2319inline Sexpr_t Lamb::materialized(Sexpr_t box)
2320{
2321 gc_root_push(box);
2322 return box;
2323}
2324
2325inline Sexpr_t Lamb::car(Sexpr_t c) {
2326 ME("Lamb::car()");
2327 LL_POISON_READ(c);
2328 if (c->type() >= Cell::T_PAIR) {
2329 if (c->car_is_embedded()) {
2330 if (c->car_is_int()) return materialized(mk_int32(c->car_int32(), NIL));
2331 if (c->car_is_float()) return materialized(mk_float32(c->car_float32(), NIL));
2332 }
2333 return c->prechecked_anypair_get_car();
2334 }
2335 embedded_debug_catcher();
2336 throw mk_syserror("%s Bad type %s", me, c->dump().c_str());
2337}
2338
2339inline Sexpr_t Lamb::prechecked_anypair_get_car(Sexpr_t c) {
2340 if (c->car_is_embedded()) {
2341 if (c->car_is_int()) return materialized(mk_int32(c->car_int32(), NIL));
2342 if (c->car_is_float()) return materialized(mk_float32(c->car_float32(), NIL));
2343 }
2344 return c->prechecked_anypair_get_car();
2345}
2346
2347inline Sexpr_t Lamb::prechecked_anypair_get_cdr(Sexpr_t c) {
2348 if (c->cdr_is_embedded()) {
2349 if (c->cdr_is_int()) return materialized(mk_int32(c->cdr_int32(), NIL));
2350 if (c->cdr_is_float()) return materialized(mk_float32(c->cdr_float32(), NIL));
2351 }
2352 return c->prechecked_anypair_get_cdr();
2353}
2354
2355inline Sexpr_t Lamb::cdr(Sexpr_t c) {
2356 ME("Lamb::cdr()");
2357 LL_POISON_READ(c);
2358 if (c->type() >= Cell::T_PAIR) {
2359 if (c->cdr_is_embedded()) {
2360 if (c->cdr_is_int()) return materialized(mk_int32(c->cdr_int32(), NIL));
2361 if (c->cdr_is_float()) return materialized(mk_float32(c->cdr_float32(), NIL));
2362 }
2363 return c->prechecked_anypair_get_cdr();
2364 }
2365 embedded_debug_catcher();
2366 throw mk_syserror("%s Bad type %s", me, c->dump().c_str());
2367}
2368
2369
2370// ---------------------------------------------------------------------------
2371// mop3 authoring macros. THESE LIVE HERE ON PURPOSE.
2372//
2373// They were in ll_vm_mop3.h until 2026-08-26. Every shipped ll_xmop3_*.cpp includes that header
2374// for these macros and for nothing else (zero references to apply_fast or anything NCG) -- but
2375// packaging strips `ll_vm_*` from customer src/, so from the day the include was added (acc66ea,
2376// 2026-05-04) NO customer package could be rebuilt from source: twelve extension modules failed
2377// with "fatal error: ll_vm_mop3.h: No such file or directory". It went unnoticed for four months
2378// because nobody builds a package the way a customer does.
2379//
2380// LambLisp.h already ships and every extension already includes it, so putting them here needs no
2381// new header and no new include. Anything that is genuinely VM-internal stays in ll_vm_mop3.h.
2382// If you add a macro that a shipped ll_xmop3_*.cpp needs, it belongs HERE, not there.
2383// ---------------------------------------------------------------------------
2384
2390#define mop3_gc_frame(...) \
2391 { LL_int32 __mop3_frame_top__ = lamb.gc_root_depth(); \
2392 __VA_ARGS__; \
2393 lamb.gc_root_setdepth(__mop3_frame_top__); } \
2394 //
2395//
2396#define mop3_gcroot_Sexpr_t(_id_, ...) \
2397 Sexpr_t _id_ = __VA_ARGS__; \
2398 lamb.gc_root_push(_id_)
2399
2400// GC protection macros for NCG shim functions (Lamb *lamb pointer form).
2401// Mirror the `lamb.` forms but use -> instead of dot.
2414#define lambp_gc_frame(...) \
2415 { LL_int32 __lambp_frame_top__ = lamb->gc_root_depth(); \
2416 __VA_ARGS__; \
2417 lamb->gc_root_setdepth(__lambp_frame_top__); } \
2418 //
2419
2426#define lambp_gcroot_Sexpr_t(_id_, ...) \
2427 Sexpr_t _id_ = __VA_ARGS__; \
2428 lamb->gc_root_push(_id_)
2429//
2431
2432
2434
2436
2439#define mop3_try \
2440 LL_int32 __gc_depth__ = lamb.gc_root_depth(); \
2441 try \
2442 //
2443//
2444
2445#define mop3_catch(__code_before_rethrow__) \
2446 catch (Sexpr_t __err__) { \
2447 if (__err__->type() != Cell::T_ERROR) \
2448 throw NIL->mk_error("mop3_catch() BUG in %s bad type %s", me, __err__->dump().c_str()); \
2449 lamb.gc_root_setdepth(__gc_depth__); \
2450 if (!LL_ERR_IS_USER_RAISE(__err__)) /* a user raise is control flow, not a fault */ \
2451 global_printf("\r[%d] %s mop3_catch(): %s\n", millis(), me, __err__->error_get_chars()); \
2452 ll_debug_catcher; \
2453 __code_before_rethrow__; \
2454 throw __err__; \
2455 } \
2456 //
2457//
2458
2459#endif
Definition LambLisp.h:238
static const int F_GC02
gc flag
Definition LambLisp.h:375
int exact_rank() const
Exact numeric rank: 0=T_INT32 1=T_INT64 2=T_RATIONAL 3=T_BIGNUM -1=not exact.
Definition LambLisp.h:899
LL_float32 mustbe_float32()
Return the value of this T_FLOAT32 cell as a real.
Definition LambLisp.h:816
Sexpr_t set(Bool_t b)
Set cell as boolean.
Definition LambLisp.h:649
Sexpr_t set(LL_int32 typ, LL_int32 a, CharVec_t b)
Set cell as a mutable string.
Definition LambLisp.h:717
Bool_t is_any_pair(void)
Definition LambLisp.h:490
LL_int64 as_denominator() const
Definition LambLisp.h:699
CharVec_t any_str_get_chars()
If the cell is any kind of string, return a pointer to the zero-terminated character array.
Definition LambLisp.h:960
Bool_t is_integer_valued(void)
static const int F_CAR_IS_FLOAT
PAIR subtype: car holds an embedded LL_float32 (not a traced pointer).
Definition LambLisp.h:415
bool car_is_embedded() const
True when the car holds an embedded value of either kind (one bitwise op).
Definition LambLisp.h:530
void rplaca(Word_t p)
Replace the cell car field. Called rplaca for historical reasons, and to distinguish it from set-car!...
Definition LambLisp.h:447
Sexpr_t mustbe_cppobj_t()
Return this cell if it is a CPP object.
Definition LambLisp.h:819
LL_int32 type(void)
Return the type of the cell as a small integer.
Definition LambLisp.h:440
static const int F_CAR_IS_INT
PAIR subtype: car holds an embedded LL_int32 (not a traced pointer).
Definition LambLisp.h:414
bool is_inexact() const
True for T_FLOAT32, T_FLOAT64, T_COMPLEX.
Definition LambLisp.h:903
LL_int64 numerator64() const
Numerator of any exact number as LL_int64.
Definition LambLisp.h:915
Bool_t is_any_str_atom(void)
Return true if the cell is any kind of string.
Definition LambLisp.h:493
CharVec_t prechecked_str_ext_get_chars()
Return a pointer to the character array located outside the heap.
Definition LambLisp.h:771
void prechecked_str_heap_set_charlength(LL_int32 n)
Write the character count into the block head.
Definition LambLisp.h:769
ByteVec_t as_ByteVec_t()
Return the value of this cell as a pointer to an array of bytes.
Definition LambLisp.h:624
Bool_t is_bignum(void)
Return true if the cell is T_BIGNUM.
Definition LambLisp.h:504
Sexpr_t rat_car_ptr() const
boxed numerator cell (valid when car_is_ptr())
Definition LambLisp.h:692
Bool_t is_any_svec2n_atom()
Return true if the cell is Sexpr_t vector of size 2^n.
Definition LambLisp.h:492
LL_int32 any_str_get_charlength()
Definition LambLisp.h:1021
Sexpr_t rat_cdr_ptr() const
boxed denominator cell (valid when cdr_is_ptr())
Definition LambLisp.h:693
String cell_name(void)
A convenience feature to produce a string name for cells which are "well known" like NIL....
void rat_set_cdr_ptr(Sexpr_t p)
boxed-int denominator ptr (a traced pointer)
Definition LambLisp.h:690
Sexpr_t set(LL_int32 i)
Set cell as T_INT32.
Definition LambLisp.h:651
Sexpr_t set(LL_int32 typ, LL_int32 a, Charst_t b)
Set cell as a immutable string.
Definition LambLisp.h:715
Word_t get_car(void)
Return the value of the cell car.
Definition LambLisp.h:590
Sexpr_t any_error_get_str()
Definition LambLisp.h:926
void rplacd(Word_t p)
Replace the cell cdr field. Called rplacd for historical reasons, and to distinguish it from set-cdr!...
Definition LambLisp.h:448
Sexpr_t gc_state(LL_int32 st)
Set the garbage collection state of this cell, and return the cell.
Definition LambLisp.h:577
Ptr_t get_car_addr()
Return the address of the cell car.
Definition LambLisp.h:589
bool car_is_float() const
True when the car slot holds an embedded LL_float32.
Definition LambLisp.h:527
int num_rank() const
Legacy scalar rank: 0=int 1=float 2=rational 3=complex -1=non-numeric.
Definition LambLisp.h:906
int inexact_rank() const
Inexact numeric rank: 0=T_FLOAT32 1=T_FLOAT64 2=T_COMPLEX -1=not inexact.
Definition LambLisp.h:901
static const int F_GC04
gc flag
Definition LambLisp.h:376
CharVec_t as_CharVec_t()
Return the value of this cell as a pointer to a zero-terminated character array.
Definition LambLisp.h:623
Char_t as_Char_t()
Return the value of this cell as a character.
Definition LambLisp.h:613
Char_t mustbe_Char_t()
Return the value of this cell as a character.
Definition LambLisp.h:813
LL_int32 gc_state(void)
Return the garbage-collection state of this cell.
Definition LambLisp.h:576
void any_bvec_get_info(LL_int32 &Nelems, ByteVec_t &elems)
Definition LambLisp.h:1146
Sexpr_t set(LL_float32 r)
Set cell as T_FLOAT32.
Definition LambLisp.h:653
Sexpr_t tail_state_set(void)
Set the tail state flag on this cell, and return the cell.
Definition LambLisp.h:579
Bool_t is_any_bvec_atom(void)
Return true if the cell is any kind of bytevector.
Definition LambLisp.h:495
Sexpr_t set(LL_float32 r, LL_float32 i)
Set cell as T_COMPLEX (single precision).
Definition LambLisp.h:666
LL_int32 any_bvec_get_length()
Definition LambLisp.h:1088
LL_int32 as_int32() const
T_INT32 cell value.
Definition LambLisp.h:615
LL_float64 coerce_cpx_real()
Real part: T_COMPLEX → cpx_real; others → coerce_float64.
Definition LambLisp.h:917
bool cdr_is_float() const
True when the cdr slot holds an embedded LL_float32.
Definition LambLisp.h:529
static const int GC_STATE_MASK
Mask for obtaining garbage collection state bits from Cell flag byte.
Definition LambLisp.h:419
Sexpr_t set(LL_int32 typ, Sexpr_t a, Sexpr_t b)
This is a convenience function for common cases.
Definition LambLisp.h:647
void type(LL_int32 t)
Set the type of this cell.
Definition LambLisp.h:441
Ptr_t as_Ptr_t()
Return the value of this cell as a generic pointer (i.e., void*).
Definition LambLisp.h:620
bool car_is_int() const
True when the car slot holds an embedded LL_int32.
Definition LambLisp.h:526
void rat_set_car_ptr(Sexpr_t p)
boxed-int numerator ptr (a traced pointer)
Definition LambLisp.h:688
LL_int32 bvec_elem_type(void) const
Get the array element-type tag from Cell byte 3. HEAP/EXT SHAPES ONLY – on T_BVEC_IMM this is element...
Definition LambLisp.h:1184
bool exact_is_big() const
does not fit the int64 fast path
Definition LambLisp.h:697
bool is_complex() const
Definition LambLisp.h:904
int exact_sign()
Sign (-1/0/+1) of any exact number; for a rational, the numerator's sign (denominator is positive).
Definition LambLisp.h:701
LL_float32 cdr_float32() const
Cdr word as a float32. Same caution as car_float32().
Definition LambLisp.h:551
Charst_t prechecked_gensym_get_chars()
Definition LambLisp.h:790
bool is_slot_typed() const
True when the collector traverses this cell's two slots.
Definition LambLisp.h:525
LL_float32 car_float32() const
Car word as a float32. ONLY meaningful when car_is_float().
Definition LambLisp.h:549
Bool_t is_atom(void)
Definition LambLisp.h:483
Bool_t as_Bool_t()
Return the value of this cell as a boolean.
Definition LambLisp.h:612
bool car_is_ptr() const
Definition LambLisp.h:535
Bool_t is_any_real(void)
Return true if the cell is any inexact real type (T_FLOAT32 or T_FLOAT64).
Definition LambLisp.h:505
bool cdr_is_int() const
True when the cdr slot holds an embedded LL_int32.
Definition LambLisp.h:528
Sexpr_t mustbe_any_str_t()
Return this cell if it is a string.
Definition LambLisp.h:818
Word_t get_cdr(void)
Return the value of the cell cdr.
Definition LambLisp.h:591
static const int F_CDR_IS_FLOAT
PAIR subtype: cdr holds an embedded LL_float32 (not a traced pointer).
Definition LambLisp.h:417
static const int F_GC01
gc flag
Definition LambLisp.h:374
LL_float64 as_float64() const
T_FLOAT64 cell value; spans car+cdr on ESP32.
Definition LambLisp.h:618
LL_float32 coerce_float32()
Definition LambLisp.h:828
Bool_t is_any_svec_atom()
Return true if the cell is any kind of Sexpr_t vector.
Definition LambLisp.h:491
static const int LL_STR_HDR
Bytes of block header before the characters.
Definition LambLisp.h:765
ll_codepoint_t mustbe_codepoint()
Return full codepoint; throw if not T_CHAR.
Definition LambLisp.h:814
Charst_t as_Charst_t()
Return the value of this cell as a pointer to a zero-terminated character array.
Definition LambLisp.h:621
LL_int32 mustbe_int32()
Return the value of this T_INT32 cell as int32.
Definition LambLisp.h:815
LL_int32 prechecked_str_heap_get_charlength()
Character count, read from the block head.
Definition LambLisp.h:768
Bool_t is_pair(void)
Return true if the cell is a cons pair.
Definition LambLisp.h:484
LL_int64 as_numerator() const
Numerator as int64 (guard rat_is_big()).
Definition LambLisp.h:698
LL_int64 denominator64() const
Denominator of any exact number as LL_int64 (1 for integer types).
Definition LambLisp.h:916
Sexpr_t set(LL_int32 num, LL_int32 den)
Definition LambLisp.h:678
void str_invalidate_charlength()
Mark a heap string's cached character count UNKNOWN. No-op for anything else.
Definition LambLisp.h:1008
LL_int64 int_as_i64() const
value of a boxed T_INT32/T_INT64 (NOT T_BIGNUM)
Definition LambLisp.h:691
LL_int32 flags(void)
Return the entire set of cell flags.
Definition LambLisp.h:443
Charst_t type_name(LL_int32 typ)
Return a pointer to the C string corresponding to the cell type.
CharVec_t prechecked_str_imm_get_chars()
Return a pointer to the character array embedded in this cell.
Definition LambLisp.h:772
void zero()
Set all cell bits to zero.
Definition LambLisp.h:439
LL_int32 any_str_get_length()
Definition LambLisp.h:986
Sexpr_t set(LL_int32 typ, Word_t a, Sexpr_t b)
a (Word_t,Sexpr_t) call formerly resolved to the (LL_int32,Sexpr_t) overload and SIGN-TRUNCATED the c...
Definition LambLisp.h:646
bool is_exact() const
True for T_INT32, T_INT64, T_RATIONAL, T_BIGNUM.
Definition LambLisp.h:902
@ T_STR_EXT
(reserved Charst_t) Same as T_STR_HEAP but externally allocated; the character array is not freed at ...
Definition LambLisp.h:314
@ T_FLOAT32
(LL_float32 reserved) Inexact 32-bit LL_float32; value in car via memcpy(4).
Definition LambLisp.h:325
@ T_ERROR
(Sexpr_t Sexpr_t) An error cell; car is a T_STRING, cdr is a pointer to irritants.
Definition LambLisp.h:363
@ T_CHAR
(Char_t reserved) Character atom
Definition LambLisp.h:322
@ T_NEEDS_FINALIZING
Any types less than or equal to this have data stored in the heap, and need specialized finalizing at...
Definition LambLisp.h:311
@ T_BVEC_IMM
Special format: type and flag bytes as usual, byte 2 is vector length, remaining bytes are vector ele...
Definition LambLisp.h:316
@ T_PORT_HEAP
(reserved Ptr_t) car is unused, cdr is ptr to underlying C++ port instance
Definition LambLisp.h:310
@ T_BVEC_EXT
(LL_int32 Bytest_t) Same as T_BYTEVEC but externally allocated; the byte array is not freed at GC tim...
Definition LambLisp.h:313
@ T_SVEC_HEAP
(LL_int32 Sexpr_t[]) A vector of Sexprs is a (len Sexpr_t*) pair.
Definition LambLisp.h:298
@ T_VOID
(don't care) VOID has its own type and a singleton instance OBJ_VOID
Definition LambLisp.h:332
@ T_PAIR
(slot Sexpr_t) Normal cons cell. EACH SLOT holds a reference to another cell OR an embedded LL_int32 ...
Definition LambLisp.h:355
@ T_GENSYM
Runtime symbol generation with no heap operations.
Definition LambLisp.h:318
@ T_INT64
(LL_int64 wide) Exact 64-bit integer; 8-byte value at &car (spans car+cdr on ESP32)....
Definition LambLisp.h:324
@ T_SVEC2N_HEAP
(LL_int32 Sexpr_t[]) Same as vector, but length must be a power of 2; useful for hash tables.
Definition LambLisp.h:299
@ T_MACRO
(Sexpr_t Sexpr_t) Macro; car is transformer (proc of 1 arg) and cdr is env.
Definition LambLisp.h:359
@ T_UNDEF
(ERROR ERROR) UNDEF has its own type and a singleton instance OBJ_UNDEF
Definition LambLisp.h:333
@ T_BYTECODE
(Sexpr_t Sexpr_t) Compiled bytecode procedure; car is T_SVEC_HEAP[bvec,arity,maxloc,...
Definition LambLisp.h:365
@ T_THUNK_SEXPR
(Sexpr_t Sexpr_t) S-expression thunk pair; car is sexpr, cdr is environment with all variable binding...
Definition LambLisp.h:361
@ T_FLOAT64
(LL_float64 wide) Inexact 64-bit LL_float64; 8-byte value at &car (spans car+cdr on ESP32)....
Definition LambLisp.h:326
@ T_VALUES
(Sexpr_t Sexpr_t) Multiple return values; car is first value, cdr is list of remaining values.
Definition LambLisp.h:364
@ T_CPP_HEAP
(ptr-to-cpp-deleter ptr-to-cpp-object) Deleter is a function void f(void *cpp_obj) of the appropriate...
Definition LambLisp.h:308
@ T_THUNK_BODY
(Sexpr_t Sexpr_t) Code body thunk pair; car is body (i.e., list of sexprs), cdr is environment with a...
Definition LambLisp.h:362
@ T_NIL
Definition LambLisp.h:339
@ T_BVEC_HEAP
(LL_int32 Bytest_t) Bytevector is a (len byte*) pair.
Definition LambLisp.h:304
@ T_STR_HEAP
(LL_int32 Charst_t) car=BYTE length, cdr=ptr to a payload allocated len+1 and ZEROED – EXACTLY the sh...
Definition LambLisp.h:307
@ T_SYM_HEAP
(LL_int32 Charst_t) Symbol is a (hash char*) pair.
Definition LambLisp.h:303
@ T_MOP3_NPROC
(reserved *Mop3st_t) pointer to native macro processor - args are not evaluated before calling
Definition LambLisp.h:329
@ Ntypes
Number of LambLisp virtual machine types.
Definition LambLisp.h:368
@ T_BYTECODE_N
(Sexpr_t Sexpr_t) Compiled bytecode nlambda (non-evaluating); same layout as T_BYTECODE,...
Definition LambLisp.h:366
@ T_COMPLEX
(slot-typed) Complex number atom; car=real part, cdr=imaginary part. EACH SLOT is an embedded LL_int3...
Definition LambLisp.h:348
@ T_SVEC_IMM
(Sexpr_t Sexpr_t) Vector of 0, 1 or 2 elements.
Definition LambLisp.h:356
@ T_INT32
(LL_int32 reserved) Exact 32-bit integer; value in car via memcpy(4).
Definition LambLisp.h:323
@ T_PROC
(Sexpr_t Sexpr_t) Procedure pair; car is lambda (formals + body containing free variables),...
Definition LambLisp.h:357
@ T_BOOL
(Bool_t reserved) Boolean atom
Definition LambLisp.h:321
@ T_DICT
(Sexpr_t Sexpr_t) Dictionary pair; car is local frame, cdr is list of parent frames,...
Definition LambLisp.h:360
@ T_ANY_HEAP_SVEC
Any types less than or equal to this are heap-stored vectors of S-expressions. They need specialized ...
Definition LambLisp.h:301
@ T_NPROC
(Sexpr_t Sexpr_t) Non-evaluating procedure pair; car is nlambda (formals + body containing free varia...
Definition LambLisp.h:358
@ T_MOP3_PROC
(reserved *Mop3st_t) pointer to native function - args are evaluated before calling
Definition LambLisp.h:328
@ T_BIGNUM
(LL_int32 Bytest_t) Arbitrary-precision integer; same layout as T_BVEC_HEAP: car=byte-length,...
Definition LambLisp.h:305
@ T_STR_IMM
Special format: type and flag bytes as usual, remaining bytes are 0-terminated string embedded in the...
Definition LambLisp.h:317
@ T_RATIONAL
(slot-typed) Exact rational atom; car=numerator, cdr=denominator (>=2, GCD-reduced)....
Definition LambLisp.h:349
bool bytecode_is_variadic() const
Ph9: true if T_BYTECODE with rest-arg.
Definition LambLisp.h:583
static const int F_TAIL
trampoline tail marker
Definition LambLisp.h:377
Bytest_t as_Bytest_t()
Return the value of this cell as a pointer to an array of bytes.
Definition LambLisp.h:622
Sexpr_t set(LL_int32 typ, LL_int32 a, Bytest_t b)
Set cell as a immutable bytevector.
Definition LambLisp.h:716
Ptr_t prechecked_cppobj_get_ptr()
Return a pointer to a C++ object obtained earlier.
Definition LambLisp.h:822
static const int F_CDR_IS_INT
PAIR subtype: cdr holds an embedded LL_int32 (not a traced pointer).
Definition LambLisp.h:416
bool cdr_is_embedded() const
Definition LambLisp.h:531
bool rat_is_big() const
a component is a T_BIGNUM
Definition LambLisp.h:696
void rat_set_car_i32(LL_int32 v)
Definition LambLisp.h:683
Bool_t is_any_sym_atom(void)
Return true if the cell is any kind of symbol.
Definition LambLisp.h:494
static const int F_BC_VARIADIC
byte 2 bit 0: final locals slot holds rest-arg list (T_BYTECODE only).
Definition LambLisp.h:582
Sexpr_t tail_state_clr(void)
Clear the tail state flag on this cell, and return the cell.
Definition LambLisp.h:580
static const int F_SUBTYPE_MASK
The subtype bits. Meaning is per top-level type; today only pairs use them.
Definition LambLisp.h:412
Ptr_t prechecked_str_heap_get_block()
The BLOCK base == the cdr == what payload_alloc returned. This is the only thing that may be freed.
Definition LambLisp.h:766
LL_float32 cpx_real() const
Real part of a T_COMPLEX cell.
Definition LambLisp.h:670
Sexpr_t set(LL_int32 typ, LL_int32 a, Sexpr_t b)
Convenience: car is a raw (sign-extended) int32. ATOMS only – never a pair type (a pair car must be a...
Definition LambLisp.h:645
Bool_t mustbe_Bool_t()
Return the value of this cell as a boolean.
Definition LambLisp.h:812
LL_float64 coerce_float64()
Definition LambLisp.h:846
Sexpr_t mk_error(const char *fmt,...) CHECKPRINTF_pos2
Fill and return OBJ_SYSERROR, the ONE statically allocated error cell. Allocates nothing,...
Portst_t as_Portst_t()
Return the value of this cell as a pointer to an instance of the system underlying "port" implementat...
Definition LambLisp.h:625
ll_codepoint_t as_codepoint()
Return full Unicode codepoint stored in T_CHAR cell.
Definition LambLisp.h:614
CPPDeleterPtr prechecked_cppobj_get_deleter()
Return the function to be called at garbage collection time to recycle the C++ object.
Definition LambLisp.h:821
LL_int32 hash_contents(void)
For symbols, the hash of its characters; for numbers, strings, vectors, and bytevectors,...
void flags_clr(LL_int32 f)
Clear the selected flags.
Definition LambLisp.h:445
Sexpr_t set(LL_float64 d)
Definition LambLisp.h:654
void any_svec_get_info(LL_int32 &Nelems, Sexpr_t *&elems)
Definition LambLisp.h:1059
Sexpr_t set(Char_t c)
Set cell as character.
Definition LambLisp.h:650
Sexpr_t set(LL_int32 typ, LL_int32 a, ByteVec_t b)
Set cell as a mutable bytevector.
Definition LambLisp.h:718
Bool_t is_any_int(void)
Definition LambLisp.h:496
LL_float64 coerce_cpx_imag()
Imaginary part: T_COMPLEX → cpx_imag; others → 0.
Definition LambLisp.h:918
LL_int32 hash_sexpr(void)
For symbols, the hash of its characters; for numbers, the hash of the number; otherwise the hash of t...
void bytecode_set_variadic()
Ph9: mark T_BYTECODE as variadic.
Definition LambLisp.h:584
void flags_set(LL_int32 f)
Set the selected flags.
Definition LambLisp.h:444
LL_float32 as_float32() const
T_FLOAT32 cell value.
Definition LambLisp.h:617
Sexpr_t set(Port_t &p)
Set cell as port.
Definition LambLisp.h:712
LL_int32 car_int32() const
Car word as a signed int32. ONLY meaningful when car_is_int(); on any other slot this returns the bit...
Definition LambLisp.h:548
Charst_t gcstate_name(void)
Return a pointer to a C string corresponding to the given GC state.
String dump()
Return a printable representation of the Cell internals.
void bvec_set_elem_type(LL_int32 t)
Set the array element-type tag in Cell byte 3. HEAP/EXT SHAPES ONLY – on T_BVEC_IMM this OVERWRITES e...
Definition LambLisp.h:1185
LL_int32 tail_state(void)
Return the tail-call state of this cell.
Definition LambLisp.h:578
Sexpr_t set(LL_int32 typ, Word_t w1, Word_t w2)
This is the lowest-level generic "set" function.
Definition LambLisp.h:644
ByteVec_t any_bvec_get_elems()
Definition LambLisp.h:1132
LL_int32 cdr_int32() const
Cdr word as a signed int32. Same caution as car_int32().
Definition LambLisp.h:550
CharVec_t prechecked_str_heap_get_chars()
The characters, LL_STR_HDR bytes into the block. INTERIOR POINTER – never free this.
Definition LambLisp.h:767
void rat_set_cdr_i32(LL_int32 v)
embedded int32 denominator (embedded)
Definition LambLisp.h:689
Sexpr_t set(LL_int64 v)
Set cell as T_INT64 (8 bytes at &car; spans cdr on ESP32).
Definition LambLisp.h:652
LL_int32 hash(void)
Return the hash value of this cell.
Definition LambLisp.h:639
LL_int64 as_int64() const
T_INT64 cell value; spans car+cdr on ESP32.
Definition LambLisp.h:616
LL_float32 cpx_imag() const
Imaginary part of a T_COMPLEX cell.
Definition LambLisp.h:671
LL_int32 gc_root_depth()
Return current rootstack depth (save before a try block).
LL_int32 cdr_coerce_int32(Sexpr_t c)
cdr(c)->coerce_int32() with no box.
Definition LambLisp.h:1607
Sexpr_t mk_sharp_const(Charst_t name, Sexpr_t env_exec)
Parse a #-prefixed constant name (e.g., "t", "f", "true", "false") and return the corresponding singl...
Sexpr_t oblist_analyze(Sexpr_t oblist, LL_int32 verbosity, Sexpr_t env_exec)
Report statistics on the oblist hash table (load factor, chain lengths, etc.) at the given verbosity ...
Sexpr_t mk_rational(LL_int64 num, LL_int64 den, Sexpr_t env_exec)
Definition LambLisp.h:1852
Sexpr_t oblist_test(Sexpr_t oblist, const char *identifier, Sexpr_t env_exec)
Return the interned symbol for identifier, or HASHF if not present.
Definition LambLisp.h:1661
NcgFrame * ncg_frame_top
linked list of live frames; head threaded through frame->prev
Definition LambLisp.h:2088
Sexpr_t apply_proc_partial(Sexpr_t proc, Sexpr_t sexpr, Sexpr_t env_exec)
Evaluate the function arguments and then apply the function to them. The result may be a tail requiri...
Sexpr_t sparsevec_to_vector(Sexpr_t alist, Sexpr_t fill, Sexpr_t env_exec)
Reconstruct a dense vector from a sparse (index . value) alist; positions not present in the alist ar...
LL_int64 car_coerce_int64(Sexpr_t c)
car(c)->coerce_int64() with no box.
Definition LambLisp.h:1608
Sexpr_t mk_bytevector_ext(LL_int32 k, Bytest_t ext, Sexpr_t env_exec)
Injection of externally allocated memory, which will not be freed at GC time.
Definition LambLisp.h:1985
Sexpr_t mk_bytevector(LL_int32 k, LL_int32 fill, Sexpr_t env_exec)
Heap allocation with initialization.
Sexpr_t oblist_query(Sexpr_t oblist, const char *identifier, Bool_t force, Sexpr_t env_exec)
Look up identifier in oblist. If force is true, intern the symbol (creating it if absent) and return ...
Sexpr_t assq(Sexpr_t obj, Sexpr_t alist)
Search an association list for a matching key, and return the (key . value) pair, or false if not fou...
String sprintf(Charst_t fmt, Sexpr_t args, Sexpr_t env_exec)
Sexpr_t mk_tls_server_port(unsigned port, Charst_t cert_pem, Charst_t key_pem, Sexpr_t env_exec)
Create a TLS server on port using PEM-encoded certificate cert_pem and private key key_pem....
Sexpr_t alist_to_dict(Sexpr_t alist, Sexpr_t env_exec)
Convert an alist into a dictionary. The resulting dictionary has no parent.
void set_current_output_port(Sexpr_t p)
for with-output-to-file
Definition LambLisp.h:1748
Sexpr_t(* Mop3st_argv_t)(Lamb &lamb, Sexpr_t *argv, int nargs, Sexpr_t env_exec)
Definition LambLisp.h:1377
Sexpr_t cadr(Sexpr_t l)
Composition: car(cdr(l)); returns the second element of a list.
Definition LambLisp.h:1542
Sexpr_t printf(Sexpr_t args)
Format and write to the current output port; args is (fmt-string val ...). See sprintf() for format s...
void gc_root_depth_max_reset()
Re-baseline the peak to the CURRENT depth, so one workload can be measured in isolation....
void set_current_input_port(Sexpr_t p)
for with-input-from-file
Definition LambLisp.h:1747
Sexpr_t(* Mop3st_t)(Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Definition LambLisp.h:1376
Sexpr_t mk_input_bytevector_port(ByteVec_t src, LL_int32 n, Sexpr_t env_exec)
Wrap n bytes of src as a binary input port.
const char * build_buildDate()
Return a pointer to a character array containing the build date.
Sexpr_t mk_int64(LL_int64 i, Sexpr_t env_exec)
Definition LambLisp.h:1822
Sexpr_t loop(void)
Run often to maintain control. The main responsibility of C++ Lamb::loop() is to call the LambLisp fu...
Sexpr_t gensym(Sexpr_t env_exec)
Produce a new unique symbol.
Sexpr_t eqv_q(Sexpr_t obj1, Sexpr_t obj2)
Return true if 1 cells are the same cell, or are atoms with the same value.
void printf(const char *fmt,...) CHECKPRINTF_pos2
C-level printf feature with a limit on the length of strings produced.
Sexpr_t printf(Sexpr_t args, LL_Port &outp)
Format and write to outp; args is (fmt-string val ...). See sprintf() for format specifier syntax....
Sexpr_t dict_add_vector_frame(Sexpr_t parent, Sexpr_t names, Sexpr_t *vals, int ncaps, Sexpr_t env)
compact kv-vec frame (T_SVEC_IMM for ncaps==1); alist fallback for ncaps>1.
Sexpr_t eq_q(Sexpr_t obj1, Sexpr_t obj2)
Return true if 2 cells are the same cell, or are atoms with the same value.
const char * eval_stack_base_
highest stack address seen at a recursion entry (== outermost frame)
Definition LambLisp.h:2122
Sexpr_t dict_add_keyval_frame_argv(Sexpr_t dict, Sexpr_t keys, Sexpr_t *argv, int nargs, Sexpr_t env_exec)
same as dict_add_keyval_frame but values come from argv[] instead of a cons list.
Sexpr_t oblist_intern(Sexpr_t oblist, const char *identifier, Sexpr_t env_exec)
Return the interned symbol for identifier, creating it if necessary.
Definition LambLisp.h:1662
LL_int32 eval_root_depth_max_
trip threshold: rootstack depth (cap is 65536); tunable at runtime
Definition LambLisp.h:2124
Sexpr_t macroexpand(Sexpr_t form, Sexpr_t env_exec)
Fully expand all macros in form, applying transformers repeatedly until no further expansion is possi...
Sexpr_t ncg_eval_argv(Sexpr_t bc, Sexpr_t *argv, int nargs, Sexpr_t env_exec)
Phase 6: direct NCG→NCG call; takes argv[] instead of list, skips apply_proc_partial.
Sexpr_t mk_number(Charst_t str, Sexpr_t env_exec)
Parse str as a number; returns T_INT32/T_INT64, T_FLOAT32/T_FLOAT64, T_RATIONAL, or T_COMPLEX as appr...
Sexpr_t cons(Sexpr_t a, Sexpr_t b, Sexpr_t env_exec)
Cell constructor for normal pairs.
Definition LambLisp.h:1441
Sexpr_t cdar(Sexpr_t l)
Composition: cdr(car(l)).
Definition LambLisp.h:1615
Sexpr_t caddr(Sexpr_t l)
Composition: car(cdr(cdr(l))); returns the third element of a list.
Definition LambLisp.h:1617
uint32_t eval_progress() const
Sexpr_t mk_udp_port(unsigned local_port, Sexpr_t env_exec)
open a UDP datagram socket.
Sexpr_t mk_hashtbl(LL_int32 len, Sexpr_t fill, Sexpr_t env_exec)
Allocate a T_SVEC2N_HEAP hash-table vector; actual size is rounded up to the next power of 2,...
Sexpr_t tcons(LL_int32 typ, Word_t a, Word_t b, Sexpr_t env_exec)
Generic cell constructor with no GC protection for its arguments.
Sexpr_t dict_values(Sexpr_t dict, Sexpr_t env_exec)
Return a list of all the values in this dictionary. If the dictionary has parents,...
Sexpr_t tag_error(Sexpr_t err, const char *kind)
Tag a fresh T_ERROR with a kind marker in its irritants (e.g. "%file-error"/"%read-error") so file-er...
Sexpr_t mk_symbol(Charst_t str, Sexpr_t env_exec)
Intern str in the oblist and return the symbol S-expression. Two calls with identical strings always ...
Definition LambLisp.h:1978
Sexpr_t mk_Mop3_procst_t(Mop3st_t f, Sexpr_t env_exec)
car=0 (no argv variant)
Definition LambLisp.h:2046
LL_int32 car_mustbe_int32(Sexpr_t c)
car(c)->mustbe_int32() with no box.
Definition LambLisp.h:1601
Sexpr_t list_copy(Sexpr_t sexpr, Sexpr_t env_exec)
Return a shallow copy of the list: new pair cells with the same elements in the same order.
Sexpr_t mk_output_string_port(Sexpr_t env_exec)
Create an output port that accumulates written characters; retrieve the result with Scheme get-output...
unsigned long build_version()
Return the build version as a long integer (implemented as a UTC time stamp).
Sexpr_t mk_thunk_sexpr(Sexpr_t sexpr, Sexpr_t env_thunk, Sexpr_t env_exec)
Allocate a T_THUNK_SEXPR trampoline cell: sexpr will be evaluated in env_thunk on the next trampoline...
Definition LambLisp.h:2068
Sexpr_t mk_float64(LL_float64 d, Sexpr_t env_exec)
T_FLOAT64 cell.
Definition LambLisp.h:1834
LL_float32 cdr_mustbe_float32(Sexpr_t c)
cdr(c)->mustbe_float32() with no box.
Definition LambLisp.h:1604
Sexpr_t reverse_bang(Sexpr_t l)
Reverse the list in-place and return the new list head (the former list tail).
void ncg_frame_pool_init(LL_int32 n)
Allocate n frames and push them onto the pool free list.
Sexpr_t mk_symbol_or_number(Charst_t str, Sexpr_t env_exec)
Try to parse str as a number; if that fails, intern it as a symbol. Used by the reader for unquoted t...
Sexpr_t ncg_cons_fast(Sexpr_t a, Sexpr_t d)
fast cons; returns nullptr if Nfree<=yuasa_M or sweeping.
Sexpr_t cddddr(Sexpr_t l)
Composition: cdr(cdr(cdr(cdr(l)))).
Definition LambLisp.h:1620
LL_int32 mem_dbg_nfree()
free cells right now (instantaneous)
LL_float64 cdr_coerce_float64(Sexpr_t c)
cdr(c)->coerce_float64() with no box.
Definition LambLisp.h:1613
Sexpr_t mk_bool(Bool_t b, Sexpr_t env_exec)
Return HASHT or HASHF.
Definition LambLisp.h:1805
Sexpr_t prechecked_anypair_get_car(Sexpr_t c)
Car of a known pair; handles embedded int32/float32; no type check.
Definition LambLisp.h:2339
LL_int32 ncg_frame_pool_n()
Frames currently in the free-list pool.
Definition LambLisp.h:1530
Sexpr_t mk_int32(LL_int32 i, Sexpr_t env_exec)
Definition LambLisp.h:1818
Sexpr_t list_analyze(Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t mk_output_file_port(Charst_t name, Sexpr_t env_exec)
Open the named filesystem file for writing; return a port. Throws if the file cannot be opened.
void ncg_vector_set_ptr(Sexpr_t *data_ptr, LL_int32 k, Sexpr_t val)
Write-barrier store for inlined NCG_STORE_LOCAL (Phase 1).
NcgErrJmp * ncg_err_ctx
innermost escape context; set by ncg_eval before JIT call
Definition LambLisp.h:2091
Sexpr_t mk_output_bytevector_port(Sexpr_t env_exec)
Create a binary output port that accumulates written bytes; retrieve the result with Scheme get-outpu...
Sexpr_t server_accept_port(LL_Port *server, Sexpr_t env_exec)
Accept one pending connection from server; returns a bidirectional client port, or HASHF (#f) if no c...
Sexpr_t mk_Mop3_procst_argv_t(Mop3st_t f, Mop3st_argv_t fa, Sexpr_t env_exec)
car=argv fn, cdr=standard fn
Definition LambLisp.h:2047
Sexpr_t append(Sexpr_t sexpr, Sexpr_t env_exec)
Concatenate a list of lists per R5RS append; the last element may be a non-list, producing an imprope...
const char * build_pushDate()
Return a pointer to a character array containing the date this repo was last pushed.
Sexpr_t mk_nprocedure(Sexpr_t formals, Sexpr_t body, Sexpr_t env_nproc, Sexpr_t env_exec)
As mk_procedure() but returns a T_NPROC cell; arguments are passed unevaluated at call time.
Definition LambLisp.h:2067
Sexpr_t mk_input_file_port(Charst_t name, Sexpr_t env_exec)
Open the named filesystem file for reading; return a port. Throws if the file cannot be opened.
Sexpr_t dict_new(LL_int32 framesize, Sexpr_t env_exec)
Return a new empty dictionary with the given top frame size.
Definition LambLisp.h:1672
Sexpr_t prechecked_anypair_get_cdr(Sexpr_t c)
Cdr of a known pair; handles embedded int32/float32; no type check.
Definition LambLisp.h:2347
Sexpr_t ncg_box_fast(LL_int64 v)
fast integer box; nullptr if Nfree<=yuasa_M or sweeping.
Sexpr_t mk_realvector(LL_int32 k, Sexpr_t env_exec)
Allocates a bytevector from the heap to ensure proper alignment (no IMM type).
LL_float64 car_coerce_float64(Sexpr_t c)
car(c)->coerce_float64() with no box.
Definition LambLisp.h:1612
void set_repl_quiet(bool q)
Sexpr_t mk_character(ll_codepoint_t cp, Sexpr_t env_exec)
Definition LambLisp.h:1806
Sexpr_t vector_copy(Sexpr_t from, Sexpr_t env_exec)
Return a shallow copy of the S-expression vector from.
Sexpr_t mk_tls_client_port(Charst_t host, unsigned port, Charst_t ca_cert_pem, Sexpr_t env_exec)
Open a TLS client connection to host:port. Pass a PEM CA certificate string in ca_cert_pem to verify ...
Sexpr_t mk_complex(LL_float32 r, LL_float32 i, Sexpr_t env_exec)
Definition LambLisp.h:1839
LL_float32 car_coerce_float32(Sexpr_t c)
car(c)->coerce_float32() with no box.
Definition LambLisp.h:1610
Sexpr_t mk_bytevector(LL_int32 k, Bytest_t src, Sexpr_t env_exec)
Heap allocation with initialization.
void * payload_alloc(size_t nbytes, const char *who, Sexpr_t env_exec)
Allocate a bulk PAYLOAD (string/bytevector/vector/bignum/bytecode body) with a DEFINED out-of-memory ...
Sexpr_t mk_float32(LL_float32 r, Sexpr_t env_exec)
is what decides whether it is worth it.
Definition LambLisp.h:1829
const char * build_buildRelease()
Return a pointer to a character array containing the release description.
void ncg_mark_frames()
Push all NCG live-frame values onto GC markstack; called from start_marking().
Sexpr_t dict_append_bang(Sexpr_t d1, Sexpr_t d2, Sexpr_t env_exec)
Append d2 as a parent dictionary of d1.
void set_cdr_bang(Sexpr_t c, Sexpr_t val)
Replace the cdr field in the cell with val. GC flags will be maintained as required.
Sexpr_t cdddr(Sexpr_t l)
Composition: cdr(cdr(cdr(l))).
Definition LambLisp.h:1618
Sexpr_t mk_string(Sexpr_t env_exec, const char *fmt,...) CHECKPRINTF_pos3
Build a string with PRINTF FORMATTING – fmt is a format, not content.
LL_int32 cdr_mustbe_int32(Sexpr_t c)
cdr(c)->mustbe_int32() with no box.
Definition LambLisp.h:1602
void gc_idle_task_us(LL_int32 us, Sexpr_t env_exec)
Run GC for up to us microseconds of spare time; bank extra quanta as credit to skip during later allo...
LL_float32 car_mustbe_float32(Sexpr_t c)
car(c)->mustbe_float32() with no box.
Definition LambLisp.h:1603
Sexpr_t mk_thunk_body(Sexpr_t body, Sexpr_t env_thunk, Sexpr_t env_exec)
Allocate a T_THUNK_BODY trampoline cell: body is a list of expressions evaluated in sequence in env_t...
Definition LambLisp.h:2069
Sexpr_t twolist_to_dict(Sexpr_t twolist, Sexpr_t env_exec)
Convert a list of 2-element lists into a dictionary. The resulting dictionary has no parent.
int car_type(Sexpr_t c)
The TYPE TAG of a pair's car, without materialising it. The missing member of this family: every othe...
Definition LambLisp.h:1595
Sexpr_t mk_macro(Sexpr_t nlam, Sexpr_t env_nlam, Sexpr_t env_exec)
Allocate a T_MACRO cell: nlam is the nlambda transformer, env_nlam is its definition environment....
Definition LambLisp.h:2065
Sexpr_t macroexpand1(Sexpr_t form, Sexpr_t env_exec)
Apply at most one macro expansion step to form. Returns the expansion if form is a macro call,...
void gc_root_setdepth(LL_int32 n)
Restore rootstack to saved depth, discarding entries above n (call in catch to drop orphaned roots wi...
Sexpr_t dict_to_2list(Sexpr_t dict, Sexpr_t env_exec)
Convert the dictionary to a list of 2-element lists, retaining only the top-level (key value) sublist...
Sexpr_t dict_add_empty_frame(Sexpr_t dict, Sexpr_t env_exec)
Returns a new dictionary with an empty alist top frame and dict as parent.
Definition LambLisp.h:1679
Sexpr_t mk_bytevector(LL_int32 k, Sexpr_t env_exec)
Simplest heap allocation with no initialization.
Sexpr_t equal_q(Sexpr_t obj1, Sexpr_t obj2)
Returns true when obj1 and obj2 are eqv?, and also all their descendants.
Sexpr_t dict_ref_q(Sexpr_t dict, Sexpr_t key)
Returns (key value) pair, or false if key is unbound.
Sexpr_t mk_tcp_server_port(unsigned port, Sexpr_t env_exec)
Create a TCP listener on port; return a server port. Scheme: (open-tcp-server-port port)....
Sexpr_t dict_add_empty_frame(Sexpr_t dict, LL_int32 framesize, Sexpr_t env_exec)
void gc_pass_n(LL_int32 nsteps)
run nsteps mark steps; no-op if not in marking phase.
unsigned long build_UTC()
Return the UTC time of this build.
Sexpr_t dict_to_alist(Sexpr_t dict, Sexpr_t env_exec)
Convert the dictionary to an alist, retaining only the top-level (key . value) pairs.
void expand()
Add another block of cells to the population.
Sexpr_t lamb_oblist()
Definition LambLisp.h:1739
Sexpr_t mk_syserror(const char *fmt,...) CHECKPRINTF_pos2
Fill and return the SHARED system error object (OBJ_SYSERROR). Allocates nothing; only one exists at ...
Sexpr_t ncg_vset_fast(Sexpr_t vec, Sexpr_t idx, Sexpr_t val)
fast vector-set (write-barrier inline).
Sexpr_t mk_input_string_port(Charst_t inp, Sexpr_t env_exec)
Wrap the C string inp as an input port; reading consumes characters left to right.
Sexpr_t dict_analyze(Sexpr_t dict, LL_int32 verbosity=0)
Internal integrity check.
Sexpr_t eval_list(Sexpr_t args, Sexpr_t env_exec)
Evaluate the list of S-expressions in the environment provided, and return a lkist of results.
Sexpr_t car(Sexpr_t l)
Return the first element (car) of a pair cell; throws if l is not a pair type.
Definition LambLisp.h:2325
void log(const char *fmt,...) CHECKPRINTF_pos2
C-level printf feature with a limit on the length of strings produced. Takes care of log prompt.
LL_int64 cdr_coerce_int64(Sexpr_t c)
cdr(c)->coerce_int64() with no box.
Definition LambLisp.h:1609
Sexpr_t mk_intvector(LL_int32 k, Sexpr_t env_exec)
Note that integer vectors and real vectors are just bytevectors underneath.
void end(void)
int ncg_frame_pool_count
frames currently available in the pool
Definition LambLisp.h:2090
bool debug(void)
Return the state of the Lamb internal debug flag.
void dict_bind_alist_bang(Sexpr_t dict, Sexpr_t alist, Sexpr_t env_exec)
Modify the target dictionary; binding keys in the alist to their corresponding values.
Sexpr_t dict_keys(Sexpr_t dict, Sexpr_t env_exec)
Note that keys and values are guaranteed to return in the corresponding order in dict_keys and dict_v...
Sexpr_t dict_add_alist_frame(Sexpr_t dict, Sexpr_t alist, Sexpr_t env_exec)
Returns a new dictionary with the alist bindings added in a new frame on top of the base dictionary.
Definition LambLisp.h:1684
Sexpr_t dict_ref(Sexpr_t dict, Sexpr_t key)
Returns the value associated with the key in the given dictionary; throws error if key is unbound.
LL_int32 gc_Qm() const
return current mark quantum size.
Sexpr_t macroexpand1(Sexpr_t proc, Sexpr_t args, Sexpr_t env_exec)
Apply one expansion step of macro proc to args.
void dict_rebind_alist_bang(Sexpr_t dict, Sexpr_t alist, Sexpr_t env_exec)
Modify the target dictionary; rebinding keys in the alist to their corresponding values.
void ncg_frame_pool_free()
release them; nothing did, so every instance leaked the pool.
LL_int32 gc_root_depth_max()
Peak rootstack depth since boot or the last reset. gc_root_depth() is instantaneous and cannot tell a...
Sexpr_t write_simple(Sexpr_t sexpr)
Write sexpr using write semantics without following shared structure. Returns OBJ_VOID.
Sexpr_t mk_procedure(Sexpr_t formals, Sexpr_t body, Sexpr_t env_proc, Sexpr_t env_exec)
Allocate a T_PROC closure: formals is the parameter list, body is the list of body expressions,...
Definition LambLisp.h:2066
Sexpr_t mk_serial_port(Sexpr_t env_exec)
Wrap the platform serial port (Arduino Serial or POSIX stdin/stdout) as a LambLisp port object.
Sexpr_t cddr(Sexpr_t l)
Composition: cdr(cdr(l)).
Definition LambLisp.h:1616
LL_float32 cdr_coerce_float32(Sexpr_t c)
cdr(c)->coerce_float32() with no box.
Definition LambLisp.h:1611
Sexpr_t mk_vector(LL_int32 len, Sexpr_t fill, Sexpr_t env_exec)
Allocate a T_SVEC_HEAP vector of len elements, all initialized to fill.
void rat_store_i64(Sexpr_t c, bool is_num, LL_int64 v, Sexpr_t env_exec)
Store an int64 exact value into a rational slot: embedded int32 if it fits, else a boxed T_INT64.
Definition LambLisp.h:1841
Sexpr_t mk_integer(LL_int64 i, Sexpr_t env_exec)
Definition LambLisp.h:1813
Sexpr_t materialized(Sexpr_t box)
Hand back an accessor's fresh box, ROOTED first – unconditional; see the definition.
Definition LambLisp.h:2319
Sexpr_t dict_new(Sexpr_t env_exec)
Return a new empty dictionary with alist top frame.
Definition LambLisp.h:1673
LL_int32 mem_dbg_total_cells()
total cells in the pool right now
void gc_root_pop(LL_int32 n=1)
Release the preserved cells for normal GC processing.
void dict_bind_bang(Sexpr_t dict, Sexpr_t key, Sexpr_t value, Sexpr_t env_exec)
Modify the target dictionary; value is re-assigned to key wherever first found in chain,...
void gc_root_push(Sexpr_t p)
Preserve the cell given from GC, until popped.
Sexpr_t vector_to_sparsevec(Sexpr_t vec, Sexpr_t skip, Sexpr_t env_exec)
Convert vec to a sorted (index . value) alist, omitting elements equal to skip.
Sexpr_t vector_to_list(Sexpr_t v, Sexpr_t env_exec)
Convert an S-expression vector to a proper list; element order is preserved.
Sexpr_t dict_add_keyval_frame(Sexpr_t dict, Sexpr_t keys, Sexpr_t vals, Sexpr_t env_exec)
Returns a new dictionary with a new top frame containing the keys bound to the values.
void dict_rebind_bang(Sexpr_t dict, Sexpr_t key, Sexpr_t value, Sexpr_t env_exec)
Modify the target dictionary; value is assigned to key wherever first found in env,...
Sexpr_t read(LL_Port &src, Sexpr_t env_exec)
Read one S-expression from src; returns OBJ_EOF at end of input.
Definition LambLisp.h:1710
void vector_set_bang(Sexpr_t vec, LL_int32 k, Sexpr_t val)
Replace the specified vector element with val. GC flags will be maintained as required.
Sexpr_t cdr(Sexpr_t l)
Return the second element (cdr) of a pair cell; throws if l is not a pair type.
Definition LambLisp.h:2355
Sexpr_t macroexpand(Sexpr_t proc, Sexpr_t args, Sexpr_t env_exec)
Fully expand the macro proc applied to args.
void eval_recursion_check(const char *where)
Definition LambLisp.h:2127
void diag_memory_report()
NOT #if LL_ESP32: the report is platform-independent now; a host answers "HEAP".
void ncg_disassemble(Sexpr_t bc, Sexpr_t env_exec)
Log basic info about an NCG-compiled proc.
void gc_collect(Sexpr_t env_exec)
Run one complete GC cycle (mark + sweep); leaves heap in idle phase with all unreachable cells freed.
unsigned long mem_dbg_t_gc_total_us()
monotonic total us in gc_pass – measured GC load
Sexpr_t eval(Sexpr_t sexpr, Sexpr_t env_exec)
Evaluate the S-expression in the environment provided.
unsigned long build_pushUTC()
Return the UTC time this repo was last pushed.
Sexpr_t integrity_check(Sexpr_t env_exec, LL_int32 verbosity=1)
GC heap integrity check; callable from mop3.
Sexpr_t mk_tcp_client_port(Charst_t host, unsigned port, Sexpr_t env_exec)
Open a TCP connection to host:port; return a bidirectional port. Scheme: (open-tcp-client-port host p...
LL_int32 car_coerce_int32(Sexpr_t c)
car(c)->coerce_int32() with no box; truncates an embedded float as the original does.
Definition LambLisp.h:1606
Sexpr_t append2(Sexpr_t lis, Sexpr_t obj, Sexpr_t env_exec)
Destructively attach obj to the end of lis, which must be a proper list.
Sexpr_t ncg_eval(Sexpr_t bc, Sexpr_t args, Sexpr_t env_exec)
Execute a T_BYTECODE cell that has been NCG-compiled.
Sexpr_t cadddr(Sexpr_t l)
Composition: car(cdr(cdr(cdr(l)))); returns the fourth element of a list.
Definition LambLisp.h:1619
bool build_isDebug()
Return true if this build is not checked in. This is unrelated to the runtime debug flag.
Sexpr_t mk_error(Sexpr_t env_exec, Sexpr_t irritants, const char *fmt,...) CHECKPRINTF_pos4
Allocate a NEW T_ERROR cell with these irritants. Unlike Cell::mk_error(), which reuses one shared ob...
Sexpr_t ncg_compile(Sexpr_t bc, Sexpr_t env_exec, Sexpr_t captured_names=nullptr)
Compile a T_BYTECODE cell to native code, and record it in the procedure's own native-code slot....
size_t eval_stack_budget_
trip threshold: bytes of C-stack growth below base; tunable at runtime
Definition LambLisp.h:2123
void eval_recursion_overflow(const char *where)
cold path: throws the catchable "recursion too deep" error
void set_car_bang(Sexpr_t c, Sexpr_t val)
Replace the car field in the cell with val. GC flags will be maintained as required.
NcgFrame * ncg_frame_pool_head
free-list head; recycled frames linked via frame->prev
Definition LambLisp.h:2089
Sexpr_t map_proc(Sexpr_t proc, Sexpr_t lists, Sexpr_t env_exec)
Apply the procecure to the lists per R5RS.
Sexpr_t setup(void)
Run once after base platform has started. In particular, Serial should be initialized before calling ...
Sexpr_t ncg_vref_fast(Sexpr_t vec, Sexpr_t idx)
fast vector-ref (T_SVEC + T_INT32 fast path).
Sexpr_t load(Charst_t name, Sexpr_t env_exec, LL_int32 verbosity=0)
Load and evaluate S-expressions from the named file.
Sexpr_t write_or_display(Sexpr_t sexpr, Bool_t do_write, WriteMode mode=WriteMode::Cyclic)
Write sexpr to the current output port. do_write true => write semantics (strings quoted,...
Sexpr_t list_to_vector(Sexpr_t l, Sexpr_t env_exec)
Convert a proper list to a heap-allocated S-expression vector (T_SVEC_HEAP); list order is preserved.
void dict_bind_local_bang(Sexpr_t dict, Sexpr_t key, Sexpr_t value, Sexpr_t env_exec)
Modify only the top frame of dict; update key if found there, else create it there....
Sexpr_t caar(Sexpr_t l)
Composition: car(car(l)).
Definition LambLisp.h:1541