""" Core Primitives - Always available, minimal essential set. These are the primitives that form the foundation of the language. They cannot be overridden by libraries. """ # Arithmetic def prim_add(*args): if len(args) == 0: return 0 result = args[0] for arg in args[1:]: result = result + arg return result def prim_sub(a, b=None): if b is None: return -a return a - b def prim_mul(*args): if len(args) == 0: return 1 result = args[0] for arg in args[1:]: result = result * arg return result def prim_div(a, b): return a / b def prim_mod(a, b): return a % b def prim_abs(x): return abs(x) def prim_min(*args): return min(args) def prim_max(*args): return max(args) def prim_round(x): return round(x) def prim_floor(x): import math return math.floor(x) def prim_ceil(x): import math return math.ceil(x) # Comparison def prim_lt(a, b): return a < b def prim_gt(a, b): return a > b def prim_le(a, b): return a <= b def prim_ge(a, b): return a >= b def prim_eq(a, b): if isinstance(a, float) or isinstance(b, float): return abs(a - b) < 1e-9 return a == b def prim_ne(a, b): return not prim_eq(a, b) # Logic def prim_not(x): return not x def prim_and(*args): for a in args: if not a: return False return True def prim_or(*args): for a in args: if a: return True return False # Basic data access def prim_get(obj, key, default=None): """Get value from dict or list.""" if isinstance(obj, dict): return obj.get(key, default) elif isinstance(obj, (list, tuple)): try: return obj[int(key)] except (IndexError, ValueError): return default return default def prim_nth(seq, i): i = int(i) if 0 <= i < len(seq): return seq[i] return None def prim_first(seq): return seq[0] if seq else None def prim_length(seq): return len(seq) def prim_list(*args): return list(args) # Type checking def prim_is_number(x): return isinstance(x, (int, float)) def prim_is_string(x): return isinstance(x, str) def prim_is_list(x): return isinstance(x, (list, tuple)) def prim_is_dict(x): return isinstance(x, dict) def prim_is_nil(x): return x is None # Higher-order / iteration def prim_reduce(seq, init, fn): """(reduce seq init fn) — fold left: fn(fn(fn(init, s0), s1), s2) ...""" acc = init for item in seq: acc = fn(acc, item) return acc def prim_map(seq, fn): """(map seq fn) — apply fn to each element, return new list.""" return [fn(item) for item in seq] def prim_range(*args): """(range end), (range start end), or (range start end step) — integer range.""" if len(args) == 1: return list(range(int(args[0]))) elif len(args) == 2: return list(range(int(args[0]), int(args[1]))) elif len(args) >= 3: return list(range(int(args[0]), int(args[1]), int(args[2]))) return [] # Random import random _rng = random.Random() def prim_rand(): """Return random float in [0, 1).""" return _rng.random() def prim_rand_int(lo, hi): """Return random integer in [lo, hi].""" return _rng.randint(int(lo), int(hi)) def prim_rand_range(lo, hi): """Return random float in [lo, hi).""" return lo + _rng.random() * (hi - lo) def prim_map_range(val, from_lo, from_hi, to_lo, to_hi): """Map value from one range to another.""" if from_hi == from_lo: return to_lo t = (val - from_lo) / (from_hi - from_lo) return to_lo + t * (to_hi - to_lo) # Core primitives dict PRIMITIVES = { # Arithmetic '+': prim_add, '-': prim_sub, '*': prim_mul, '/': prim_div, 'mod': prim_mod, 'abs': prim_abs, 'min': prim_min, 'max': prim_max, 'round': prim_round, 'floor': prim_floor, 'ceil': prim_ceil, # Comparison '<': prim_lt, '>': prim_gt, '<=': prim_le, '>=': prim_ge, '=': prim_eq, '!=': prim_ne, # Logic 'not': prim_not, 'and': prim_and, 'or': prim_or, # Data access 'get': prim_get, 'nth': prim_nth, 'first': prim_first, 'length': prim_length, 'len': prim_length, 'list': prim_list, # Type predicates 'number?': prim_is_number, 'string?': prim_is_string, 'list?': prim_is_list, 'dict?': prim_is_dict, 'nil?': prim_is_nil, 'is-nil': prim_is_nil, # Higher-order / iteration 'reduce': prim_reduce, 'fold': prim_reduce, 'map': prim_map, 'range': prim_range, # Random 'rand': prim_rand, 'rand-int': prim_rand_int, 'rand-range': prim_rand_range, 'map-range': prim_map_range, }