Advertisement
copyleft7212

reticulated.cweb

Mar 22nd, 2025
498
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.17 KB | Cybersecurity | 0 0
  1. @* T81Lang Runtime Engine.
  2. This CWEB document implements an optimized, standalone runtime engine for T81Lang, a scripting language
  3. supporting base-81 arithmetic with three types: `bigint81` (arbitrary-precision integers), `float81`
  4. (floating-point numbers), and `frac81` (rational numbers). It features a parser and evaluator written
  5. in Python 3, supporting interactive scripting and arithmetic execution of base-81 expressions. All
  6. dependencies are self-contained, with optimizations for performance and robustness.
  7.  
  8. @*1 Imports.
  9. We use only standard Python modules: `re` for parsing and `typing` for type hints.
  10.  
  11. @c
  12. import re
  13. from typing import Any, Dict, List, Tuple, Optional
  14.  
  15. @*2 Base-81 Arithmetic Types and Operations.
  16. Here we define the core types and their arithmetic operations, optimized for base-81.
  17.  
  18. @*2.1 T81BigInt Definition.
  19. `T81BigInt` is an arbitrary-precision integer in base-81, stored as a list of digits (080) in
  20. little-endian order.
  21.  
  22. @c
  23. class T81BigInt:
  24.     """Arbitrary-precision integer in base-81."""
  25.     def __init__(self, digits: List[int], sign: int = 0):
  26.         self.sign = sign  # 0 = positive, 1 = negative
  27.         self.digits = digits  # Little-endian digits (0–80)
  28.         self.trim()  # Remove leading zeros
  29.  
  30.     def trim(self):
  31.         """Remove leading zeros from digits."""
  32.         while len(self.digits) > 1 and self.digits[-1] == 0:
  33.             self.digits.pop()
  34.         if not self.digits:
  35.             self.digits = [0]
  36.             self.sign = 0
  37.  
  38.     def __str__(self) -> str:
  39.         """Convert to string representation."""
  40.         return ("-" if self.sign else "") + "".join(map(str, reversed(self.digits)))
  41.  
  42. @*2.2 T81Float Definition.
  43. `T81Float` represents a floating-point number as `mantissa * 81^exponent`.
  44.  
  45. @c
  46. class T81Float:
  47.     """Floating-point number in base-81."""
  48.     def __init__(self, mantissa: T81BigInt, exponent: int, sign: int = 0):
  49.         self.mantissa = mantissa  # Base-81 mantissa
  50.         self.exponent = exponent  # Exponent for base-81
  51.         self.sign = sign  # 0 = positive, 1 = negative
  52.         self.normalize()  # Adjust mantissa and exponent
  53.  
  54.     def normalize(self):
  55.         """Normalize by removing leading/trailing zeros and adjusting exponent."""
  56.         mant = self.mantissa.digits
  57.         while len(mant) > 1 and mant[-1] == 0:
  58.             mant.pop()
  59.         leading_zeros = 0
  60.         for d in mant:
  61.             if d != 0:
  62.                 break
  63.             leading_zeros += 1
  64.         if leading_zeros == len(mant):
  65.             self.mantissa = T81BigInt([0])
  66.             self.exponent = 0
  67.             self.sign = 0
  68.         elif leading_zeros > 0:
  69.             self.mantissa.digits = mant[leading_zeros:]
  70.             self.exponent -= leading_zeros
  71.             self.mantissa.trim()
  72.  
  73.     def __str__(self) -> str:
  74.         """Format as string."""
  75.         return f"(mantissa) {self.mantissa}, exponent: {self.exponent}"
  76.  
  77. @*2.3 T81Fraction Definition.
  78. `T81Fraction` represents a rational number as `numerator / denominator`.
  79.  
  80. @c
  81. class T81Fraction:
  82.     """Rational number in base-81."""
  83.     def __init__(self, numerator: T81BigInt, denominator: T81BigInt):
  84.         if denominator.digits == [0]:
  85.             raise ValueError("Denominator cannot be zero")
  86.         self.numerator = numerator
  87.         self.denominator = denominator
  88.         self.reduce()  # Simplify fraction
  89.  
  90.     def reduce(self):
  91.         """Simplify fraction using GCD."""
  92.         gcd = self._gcd(self.numerator, self.denominator)
  93.         if gcd.digits != [1]:
  94.             self.numerator = self._divide(self.numerator, gcd)[0]
  95.             self.denominator = self._divide(self.denominator, gcd)[0]
  96.         if self.denominator.sign:
  97.             self.numerator.sign ^= 1
  98.             self.denominator.sign = 0
  99.  
  100.     def __str__(self) -> str:
  101.         """Format as string."""
  102.         return f"{self.numerator}/{self.denominator}"
  103.  
  104. @*2.4 Arithmetic Operations.
  105. Optimized base-81 arithmetic functions for the types above.
  106.  
  107. @c
  108. def parse_trit_string(value: str) -> T81BigInt:
  109.     """Parse a base-81 string into a T81BigInt."""
  110.     sign = 1 if value.startswith('-') else 0
  111.     value = value.lstrip('-')
  112.     digits = [int(d) for d in reversed(value) if 0 <= int(d) <= 80]
  113.     return T81BigInt(digits or [0], sign)
  114.  
  115. def add_big(A: T81BigInt, B: T81BigInt) -> T81BigInt:
  116.     """Add two T81BigInts digit-by-digit."""
  117.     if A.sign != B.sign:
  118.         return subtract_big(A, T81BigInt(B.digits, not B.sign))
  119.     digits = []
  120.     carry = 0
  121.     max_len = max(len(A.digits), len(B.digits))
  122.     a_digits = A.digits + [0] * (max_len - len(A.digits))
  123.     b_digits = B.digits + [0] * (max_len - len(B.digits))
  124.     for a, b in zip(a_digits, b_digits):
  125.         total = a + b + carry
  126.         digits.append(total % 81)
  127.         carry = total // 81
  128.     if carry:
  129.         digits.append(carry)
  130.     return T81BigInt(digits, A.sign)
  131.  
  132. def subtract_big(A: T81BigInt, B: T81BigInt) -> T81BigInt:
  133.     """Subtract B from A digit-by-digit."""
  134.     if A.sign != B.sign:
  135.         return add_big(A, T81BigInt(B.digits, not B.sign))
  136.     if compare_big(A, B) < 0:
  137.         result = subtract_big(B, A)
  138.         result.sign = 1
  139.         return result
  140.     digits = []
  141.     borrow = 0
  142.     max_len = max(len(A.digits), len(B.digits))
  143.     a_digits = A.digits + [0] * (max_len - len(A.digits))
  144.     b_digits = B.digits + [0] * (max_len - len(B.digits))
  145.     for a, b in zip(a_digits, b_digits):
  146.         diff = a - b - borrow
  147.         if diff < 0:
  148.             diff += 81
  149.             borrow = 1
  150.         else:
  151.             borrow = 0
  152.         digits.append(diff)
  153.     result = T81BigInt(digits, A.sign)
  154.     result.trim()
  155.     return result
  156.  
  157. def multiply_big(A: T81BigInt, B: T81BigInt) -> T81BigInt:
  158.     """Multiply two T81BigInts digit-by-digit."""
  159.     digits = [0] * (len(A.digits) + len(B.digits))
  160.     for i, a in enumerate(A.digits):
  161.         carry = 0
  162.         for j, b in enumerate(B.digits):
  163.             temp = a * b + digits[i + j] + carry
  164.             digits[i + j] = temp % 81
  165.             carry = temp // 81
  166.         digits[i + len(B.digits)] += carry
  167.     return T81BigInt(digits, A.sign != B.sign)
  168.  
  169. def divide_big(A: T81BigInt, B: T81BigInt) -> Tuple[T81BigInt, T81BigInt]:
  170.     """Divide A by B iteratively, returning (quotient, remainder)."""
  171.     if B.digits == [0]:
  172.         raise ValueError("Division by zero")
  173.     if compare_big(A, B) < 0:
  174.         return T81BigInt([0]), A
  175.     quotient_digits = []
  176.     remainder = T81BigInt(A.digits[:], A.sign)
  177.     divisor = T81BigInt(B.digits[:], 0)
  178.     for i in range(len(A.digits) - 1, -1, -1):
  179.         temp = T81BigInt(remainder.digits[i:], 0)
  180.         q = 0
  181.         while compare_big(temp, divisor) >= 0:
  182.             temp = subtract_big(temp, divisor)
  183.             q += 1
  184.         quotient_digits.append(q)
  185.         remainder.digits[i:] = temp.digits
  186.     quotient = T81BigInt(list(reversed(quotient_digits)), A.sign != B.sign)
  187.     quotient.trim()
  188.     remainder.trim()
  189.     return quotient, remainder
  190.  
  191. def compare_big(A: T81BigInt, B: T81BigInt) -> int:
  192.     """Compare two T81BigInts: 1 if A > B, -1 if A < B, 0 if equal."""
  193.     if A.sign != B.sign:
  194.         return -1 if A.sign else 1
  195.     if len(A.digits) > len(B.digits):
  196.         return 1 if not A.sign else -1
  197.     if len(A.digits) < len(B.digits):
  198.         return -1 if not A.sign else 1
  199.     for a, b in zip(reversed(A.digits), reversed(B.digits)):
  200.         if a > b:
  201.             return 1 if not A.sign else -1
  202.         if a < b:
  203.             return -1 if not A.sign else 1
  204.     return 0
  205.  
  206. def float_multiply(A: T81Float, B: T81Float) -> T81Float:
  207.     """Multiply two T81Floats."""
  208.     mantissa = multiply_big(A.mantissa, B.mantissa)
  209.     exponent = A.exponent + B.exponent
  210.     sign = A.sign != B.sign
  211.     return T81Float(mantissa, exponent, sign)
  212.  
  213. def float_divide(A: T81Float, B: T81Float) -> T81Float:
  214.     """Divide A by B."""
  215.     quotient, _ = divide_big(A.mantissa, B.mantissa)
  216.     exponent = A.exponent - B.exponent
  217.     sign = A.sign != B.sign
  218.     return T81Float(quotient, exponent, sign)
  219.  
  220. def T81Fraction._gcd(self, A: T81BigInt, B: T81BigInt) -> T81BigInt:
  221.     """Compute GCD using Euclidean algorithm."""
  222.     a, b = T81BigInt(A.digits[:], 0), T81BigInt(B.digits[:], 0)
  223.     while b.digits != [0]:
  224.         a, b = b, divide_big(a, b)[1]
  225.     return a
  226.  
  227. def T81Fraction._divide(self, A: T81BigInt, B: T81BigInt) -> Tuple[T81BigInt, T81BigInt]:
  228.     """Wrapper for divide_big in T81Fraction."""
  229.     return divide_big(A, B)
  230.  
  231. @*3 Runtime Environment.
  232. Stores variables during script execution.
  233.  
  234. @c
  235. class RuntimeEnv:
  236.     """Environment for storing script variables."""
  237.     def __init__(self):
  238.         self.variables: Dict[str, Any] = {}
  239.  
  240.     def set_var(self, name: str, value: Any):
  241.         """Store a variable."""
  242.         self.variables[name] = value
  243.  
  244.     def get_var(self, name: str) -> Any:
  245.         """Retrieve a variable."""
  246.         return self.variables.get(name)
  247.  
  248. @*4 Reticulated Parser with Optimized Expression Handling.
  249. Parses and evaluates T81Lang scripts with a recursive descent parser for expressions.
  250.  
  251. @c
  252. class ReticulatedParser:
  253.     """Parser and evaluator for T81Lang."""
  254.     def __init__(self, env: RuntimeEnv):
  255.         self.env = env
  256.  
  257.     def parse_line(self, line: str):
  258.         """Process a single script line."""
  259.         line = line.strip()
  260.         if line.startswith("let"):
  261.             self._parse_let(line)
  262.         elif line.startswith("print"):
  263.             self._parse_print(line)
  264.  
  265.     def _parse_let(self, line: str):
  266.         """Parse a 'let' statement."""
  267.         match = re.match(r'let (\w+): (\w+) = "?([\d]+)"?(?:, (\d+))?', line)
  268.         if not match:
  269.             raise SyntaxError(f"Invalid let statement: {line}")
  270.         name, typ, val, exp = match.groups()
  271.         if typ == "bigint81":
  272.             val_obj = parse_trit_string(val)
  273.         elif typ == "float81":
  274.             mantissa = parse_trit_string(val)
  275.             exponent = int(exp or 0)
  276.             val_obj = T81Float(mantissa, exponent)
  277.         elif typ == "frac81":
  278.             num = parse_trit_string(val)
  279.             denom = parse_trit_string(exp or "1")
  280.             val_obj = T81Fraction(num, denom)
  281.         else:
  282.             raise TypeError(f"Unknown type: {typ}")
  283.         self.env.set_var(name, val_obj)
  284.  
  285.     def _parse_print(self, line: str):
  286.         """Parse a 'print' statement."""
  287.         match = re.match(r'print\((.+)\)', line)
  288.         if not match:
  289.             raise SyntaxError(f"Invalid print statement: {line}")
  290.         expr = match.group(1).strip()
  291.         result = self._eval_expr(expr)
  292.         print(self._format_result(result))
  293.  
  294.     def _eval_expr(self, expr: str) -> Any:
  295.         """Evaluate an expression with precedence."""
  296.         tokens = self._tokenize(expr)
  297.         return self._parse_expression(tokens)
  298.  
  299.     def _tokenize(self, expr: str) -> List[str]:
  300.         """Tokenize an expression into variables and operators."""
  301.         tokens = []
  302.         current = ""
  303.         for char in expr:
  304.             if char in "+-*/()":
  305.                 if current:
  306.                     tokens.append(current.strip())
  307.                     current = ""
  308.                 tokens.append(char)
  309.             elif char.isspace():
  310.                 if current:
  311.                     tokens.append(current.strip())
  312.                     current = ""
  313.             else:
  314.                 current += char
  315.         if current:
  316.             tokens.append(current.strip())
  317.         return tokens
  318.  
  319.     def _parse_expression(self, tokens: List[str], pos: int = 0) -> Tuple[Any, int]:
  320.         """Parse expression with precedence (multiplication/division before addition/subtraction)."""
  321.         result, pos = self._parse_term(tokens, pos)
  322.         while pos < len(tokens) and tokens[pos] in "+-":
  323.             op = tokens[pos]
  324.             pos += 1
  325.             right, new_pos = self._parse_term(tokens, pos)
  326.             if op == "+":
  327.                 result = self._binary_op(result, right, "+")
  328.             elif op == "-":
  329.                 result = self._binary_op(result, right, "-")
  330.             pos = new_pos
  331.         return result, pos
  332.  
  333.     def _parse_term(self, tokens: List[str], pos: int) -> Tuple[Any, int]:
  334.         """Parse multiplication and division terms."""
  335.         result, pos = self._parse_factor(tokens, pos)
  336.         while pos < len(tokens) and tokens[pos] in "*/":
  337.             op = tokens[pos]
  338.             pos += 1
  339.             right, new_pos = self._parse_factor(tokens, pos)
  340.             if op == "*":
  341.                 result = self._binary_op(result, right, "*")
  342.             elif op == "/":
  343.                 result = self._binary_op(result, right, "/")
  344.             pos = new_pos
  345.         return result, pos
  346.  
  347.     def _parse_factor(self, tokens: List[str], pos: int) -> Tuple[Any, int]:
  348.         """Parse a single factor (variable or parenthesized expression)."""
  349.         if pos >= len(tokens):
  350.             raise SyntaxError("Unexpected end of expression")
  351.         token = tokens[pos]
  352.         if token == "(":
  353.             pos += 1
  354.             result, pos = self._parse_expression(tokens, pos)
  355.             if pos >= len(tokens) or tokens[pos] != ")":
  356.                 raise SyntaxError("Missing closing parenthesis")
  357.             return result, pos + 1
  358.         value = self.env.get_var(token)
  359.         if value is None:
  360.             raise NameError(f"Undefined variable: {token}")
  361.         return value, pos + 1
  362.  
  363.     def _binary_op(self, A: Any, B: Any, op: str) -> Any:
  364.         """Perform binary operation based on types."""
  365.         if isinstance(A, T81BigInt) and isinstance(B, T81BigInt):
  366.             if op == "+": return add_big(A, B)
  367.             elif op == "-": return subtract_big(A, B)
  368.             elif op == "*": return multiply_big(A, B)
  369.             elif op == "/": return divide_big(A, B)[0]
  370.         elif isinstance(A, T81Float) and isinstance(B, T81Float):
  371.             if op == "*": return float_multiply(A, B)
  372.             elif op == "/": return float_divide(A, B)
  373.         elif isinstance(A, T81Fraction) and isinstance(B, T81Fraction):
  374.             if op == "+":
  375.                 num = add_big(multiply_big(A.numerator, B.denominator),
  376.                               multiply_big(B.numerator, A.denominator))
  377.                 denom = multiply_big(A.denominator, B.denominator)
  378.                 return T81Fraction(num, denom)
  379.             elif op == "-":
  380.                 num = subtract_big(multiply_big(A.numerator, B.denominator),
  381.                                   multiply_big(B.numerator, A.denominator))
  382.                 denom = multiply_big(A.denominator, B.denominator)
  383.                 return T81Fraction(num, denom)
  384.             elif op == "*":
  385.                 return T81Fraction(multiply_big(A.numerator, B.numerator),
  386.                                   multiply_big(A.denominator, B.denominator))
  387.             elif op == "/":
  388.                 return T81Fraction(multiply_big(A.numerator, B.denominator),
  389.                                   multiply_big(A.denominator, B.numerator))
  390.         raise TypeError(f"Unsupported operation {op} for types {type(A)}, {type(B)}")
  391.  
  392.     def _format_result(self, value: Any) -> str:
  393.         """Format result for display."""
  394.         return str(value)
  395.  
  396. @*5 Script Execution.
  397. Runs the T81Lang script.
  398.  
  399. @c
  400. def run_script(script: str):
  401.     """Execute a T81Lang script."""
  402.     env = RuntimeEnv()
  403.     parser = ReticulatedParser(env)
  404.     for line in script.strip().split('\n'):
  405.         if line and not line.strip().startswith('#'):
  406.             parser.parse_line(line)
  407.  
  408. @*6 Main Execution and Example.
  409. Runs a test script if executed directly.
  410.  
  411. @c
  412. if __name__ == "__main__":
  413.     code = """
  414.    let a: bigint81 = "102"      # 102 in base-81
  415.    let b: bigint81 = "21"       # 21 in base-81
  416.    print(a + b)                 # Should print 123
  417.    print(a + b * b)             # Tests precedence: 102 + (21 * 21)
  418.  
  419.    let f1: float81 = "102", 0   # 102 * 81^0
  420.    let f2: float81 = "21", 0    # 21 * 81^0
  421.    print(f1 * f2)               # Should print (mantissa) 2142, exponent: 0
  422.    print(f1 / f2)               # Should print approx. 4
  423.  
  424.    let r1: frac81 = "7", 3      # 7/3 in base-81
  425.    let r2: frac81 = "5", 9      # 5/9 in base-81
  426.    print(r1 + r2)               # Should print 26/27
  427.    print(r1 * r2)               # Should print 35/27
  428.    """
  429.     run_script(code)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement