cpyte 4.3.0__tar.gz → 4.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {cpyte-4.3.0/source/cpyte.egg-info → cpyte-4.3.2}/PKG-INFO +1 -1
  2. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/__init__.py +1 -1
  3. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/bytecoding.py +10 -19
  4. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/compiling.py +48 -21
  5. cpyte-4.3.2/source/cpyte/elf2sef.py +832 -0
  6. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/mainpie.py +192 -13
  7. cpyte-4.3.2/source/cpyte/mksef.py +134 -0
  8. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/sef.py +310 -21
  9. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/semantic_analasis.py +7 -9
  10. {cpyte-4.3.0 → cpyte-4.3.2/source/cpyte.egg-info}/PKG-INFO +1 -1
  11. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte.egg-info/SOURCES.txt +4 -1
  12. cpyte-4.3.2/test/test_sef_tools.py +221 -0
  13. {cpyte-4.3.0 → cpyte-4.3.2}/MANIFEST.in +0 -0
  14. {cpyte-4.3.0 → cpyte-4.3.2}/pyproject.toml +0 -0
  15. {cpyte-4.3.0 → cpyte-4.3.2}/readme.md +0 -0
  16. {cpyte-4.3.0 → cpyte-4.3.2}/setup.cfg +0 -0
  17. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/__main__.py +0 -0
  18. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/_bignum_bc.py +0 -0
  19. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/_runtime_bc.py +0 -0
  20. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/astparse.py +0 -0
  21. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/bignum.c +0 -0
  22. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/clib.py +0 -0
  23. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/extension_hooks.py +0 -0
  24. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/formatter.py +0 -0
  25. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/gc_runtime.c +0 -0
  26. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/generate_bc.py +0 -0
  27. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/lexar.py +0 -0
  28. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/linker.py +0 -0
  29. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/lsp_server.py +0 -0
  30. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/optimizations.py +0 -0
  31. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/package_manifest.py +0 -0
  32. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/runtime.c +0 -0
  33. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/runtime_scorpion.c +0 -0
  34. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/ugc.h +0 -0
  35. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/ui.py +0 -0
  36. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/update_check.py +0 -0
  37. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/winjit_patch.py +0 -0
  38. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte/winjit_stubs.c +0 -0
  39. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte.egg-info/dependency_links.txt +0 -0
  40. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte.egg-info/entry_points.txt +0 -0
  41. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte.egg-info/requires.txt +0 -0
  42. {cpyte-4.3.0 → cpyte-4.3.2}/source/cpyte.egg-info/top_level.txt +0 -0
  43. {cpyte-4.3.0 → cpyte-4.3.2}/test/test_bignum_jit.py +0 -0
  44. {cpyte-4.3.0 → cpyte-4.3.2}/test/test_fuzz_del_has.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cpyte
3
- Version: 4.3.0
3
+ Version: 4.3.2
4
4
  Summary: The Cpyte programming language compiler
5
5
  Author: Hoang Duy Tung
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- __version__ = "4.3.0"
1
+ __version__ = "4.3.2"
2
2
 
3
3
  # ---------------------------------------------------------------------------
4
4
  # Public library API.
@@ -2,7 +2,7 @@ import hashlib
2
2
  import hmac
3
3
  import os
4
4
  from traceback import print_exception
5
- from typing import Any, Optional, Protocol
5
+ from typing import Any, Protocol
6
6
 
7
7
  from llvmlite import binding, ir
8
8
  from llvmlite.ir import instructions
@@ -253,9 +253,7 @@ class LLVM:
253
253
  t = _bc_array_norm(t)
254
254
  if t == "int":
255
255
  result = ir.IntType(32)
256
- elif t == "int64":
257
- result = ir.IntType(64)
258
- elif t == "uint64":
256
+ elif t == "int64" or t == "uint64":
259
257
  result = ir.IntType(64)
260
258
  elif t == "size_t":
261
259
  # Pointer-sized unsigned integer (i64 on every 64-bit cpyte target,
@@ -273,11 +271,7 @@ class LLVM:
273
271
  result = ir.PointerType(ir.IntType(8))
274
272
  elif t == "char":
275
273
  result = ir.IntType(8)
276
- elif t == "void*":
277
- result = ir.PointerType(ir.IntType(8))
278
- elif t == "big":
279
- result = ir.PointerType(ir.IntType(8))
280
- elif t == "ubig":
274
+ elif t == "void*" or t == "big" or t == "ubig":
281
275
  result = ir.PointerType(ir.IntType(8))
282
276
  elif t == "dynamic":
283
277
  # A runtime-typed value: (kind, data) tag pair. Mirrors DynValue.
@@ -288,10 +282,7 @@ class LLVM:
288
282
  elif t.endswith("[]"):
289
283
  base = self.llvm_type(t[:-2])
290
284
  result = ir.PointerType(base)
291
- elif t.endswith("*"):
292
- base = self.llvm_type(t[:-1])
293
- result = ir.PointerType(base)
294
- elif t.endswith("&"):
285
+ elif t.endswith("*") or t.endswith("&"):
295
286
  base = self.llvm_type(t[:-1])
296
287
  result = ir.PointerType(base)
297
288
  elif t in self.structs:
@@ -1656,7 +1647,7 @@ class LLVM:
1656
1647
  for table in (self.locals, self.local_types, self.ssa_values):
1657
1648
  table.pop(name, None)
1658
1649
  self.const_vars.pop(name, None)
1659
- return None
1650
+ return
1660
1651
  if kind == "dynamic":
1661
1652
  name = target.name
1662
1653
  if name in self.locals and getattr(
@@ -1679,15 +1670,15 @@ class LLVM:
1679
1670
  ir.Constant(_i64, 0),
1680
1671
  ],
1681
1672
  )
1682
- return None
1673
+ return
1683
1674
  if kind == "heap":
1684
1675
  self._emit_builtin_free(target)
1685
- return None
1676
+ return
1686
1677
  if kind == "slot":
1687
1678
  slot = self._emit_lvalue(target)
1688
1679
  if isinstance(slot.type, ir.PointerType) and slot.type.pointee is not None:
1689
1680
  self.builder.store(ir.Constant(slot.type.pointee, None), slot)
1690
- return None
1681
+ return
1691
1682
  raise Exception(
1692
1683
  f"unhandled del_kind {kind!r} at L{node._token.line}:{node._token.column}"
1693
1684
  )
@@ -6409,7 +6400,7 @@ class LLVM:
6409
6400
  slot = self._emit_lvalue(target)
6410
6401
  cur = self.builder.load(slot, "append.cur")
6411
6402
 
6412
- elem_t = arr_t[:-2] if arr_t.endswith("[]") else arr_t
6403
+ elem_t = arr_t.removesuffix("[]")
6413
6404
  if arr_t == "dynamic":
6414
6405
  # Element slot holds a DynValue; its i64 data is the inner list ptr.
6415
6406
  elem_llvm = _DynValue
@@ -6778,7 +6769,7 @@ class LLVM:
6778
6769
  def _is_const_var(self, name: str) -> bool:
6779
6770
  return name in self._const_prop
6780
6771
 
6781
- def _const_var_value(self, name: str) -> Optional[int]:
6772
+ def _const_var_value(self, name: str) -> int | None:
6782
6773
  return self._const_prop.get(name)
6783
6774
 
6784
6775
  def _try_unroll_counted_loop(self, node: While, pending_ivs: dict) -> bool:
@@ -1806,8 +1806,33 @@ def _find_scorpion_tool(name, fallback):
1806
1806
  return fallback
1807
1807
 
1808
1808
 
1809
+ def _scorpion_tool(name):
1810
+ """Locate a bundled Scorpion converter script (elf2sef.py / mksef.py).
1811
+
1812
+ Prefers the copy shipped inside the cpyte package so the installed wheel
1813
+ works standalone; falls back to the WEW-scorpion sibling checkout for
1814
+ source-tree development.
1815
+ """
1816
+ bundled = os.path.join(os.path.dirname(__file__), name)
1817
+ if os.path.isfile(bundled):
1818
+ return bundled
1819
+ sibling = os.path.join(
1820
+ os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(_RUNTIME_SCORPION_C)))),
1821
+ "WEW-scorpion",
1822
+ "tools" if name == "elf2sef.py" else "user",
1823
+ name,
1824
+ )
1825
+ return sibling
1826
+
1827
+
1809
1828
  def run_scorpion(
1810
- module, output="program.sef", opt_level=3, src_files=None, pic=False, exports=None
1829
+ module,
1830
+ output="program.sef",
1831
+ opt_level=3,
1832
+ src_files=None,
1833
+ pic=False,
1834
+ exports=None,
1835
+ auto_exports=None,
1811
1836
  ):
1812
1837
  """Compile a Cpyte module for Scorpion (RV32 bare-metal) producing a SEF file.
1813
1838
  Please use it good! :):)
@@ -1815,7 +1840,11 @@ def run_scorpion(
1815
1840
  With pic=True the module is compiled with -fPIC and the final ELF is linked
1816
1841
  with --emit-relocs so it can be converted to a dynamic (SEF v2) image via
1817
1842
  WEW-scorpion/tools/elf2sef.py. `exports` names the symbols to mark as
1818
- exported for dynamic linking (libraries).
1843
+ exported for dynamic linking (libraries). `auto_exports` are additional
1844
+ candidates discovered automatically (top-level `public` functions); only
1845
+ those that actually resolve to a defined symbol in the emitted module are
1846
+ added (elf2sef refuses unknown names). Returns (elf_file, [final exports])
1847
+ so callers can report exactly what was published.
1819
1848
  """
1820
1849
  from llvmlite import binding
1821
1850
 
@@ -1829,6 +1858,18 @@ def run_scorpion(
1829
1858
  optimize(mod, opt_level)
1830
1859
  mod.verify()
1831
1860
 
1861
+ defined = {
1862
+ f.name for f in mod.functions if not getattr(f, "is_declaration", True)
1863
+ }
1864
+ final_exports = list(exports or [])
1865
+ seen = set(final_exports)
1866
+ if auto_exports:
1867
+ for name in auto_exports:
1868
+ if name in seen or name not in defined:
1869
+ continue
1870
+ seen.add(name)
1871
+ final_exports.append(name)
1872
+
1832
1873
  target = binding.Target.from_triple("riscv32-unknown-elf")
1833
1874
  if pic:
1834
1875
  target_machine = target.create_target_machine(reloc="pic")
@@ -1895,17 +1936,10 @@ def run_scorpion(
1895
1936
 
1896
1937
  if pic:
1897
1938
  # Dynamic SEF v2: relocation + import/export records
1898
- elf2sef = os.path.join(
1899
- os.path.dirname(os.path.dirname(_RUNTIME_SCORPION_C)),
1900
- "..",
1901
- "..",
1902
- "WEW-scorpion",
1903
- "tools",
1904
- "elf2sef.py",
1905
- )
1939
+ elf2sef = _scorpion_tool("elf2sef.py")
1906
1940
  cmd = [sys.executable, elf2sef, elf_file, output]
1907
- if exports:
1908
- for name in exports:
1941
+ if final_exports:
1942
+ for name in final_exports:
1909
1943
  cmd += ["--export", name]
1910
1944
  r = subprocess.run(cmd, capture_output=True, text=True)
1911
1945
  if r.returncode != 0:
@@ -1913,14 +1947,7 @@ def run_scorpion(
1913
1947
  raise SystemExit(1)
1914
1948
  else:
1915
1949
  # Static SEF v1 via mksef.py
1916
- mksef = os.path.join(
1917
- os.path.dirname(os.path.dirname(_RUNTIME_SCORPION_C)),
1918
- "..",
1919
- "..",
1920
- "WEW-scorpion",
1921
- "user",
1922
- "mksef.py",
1923
- )
1950
+ mksef = _scorpion_tool("mksef.py")
1924
1951
  if not os.path.isfile(mksef):
1925
1952
  # Fallback: inline SEF generation using objdump/objcopy
1926
1953
  _elf_to_sef(elf_file, output, 0)
@@ -1935,7 +1962,7 @@ def run_scorpion(
1935
1962
  raise SystemExit(1)
1936
1963
 
1937
1964
  print_ok(f"Wrote {os.path.getsize(output)} bytes to {output}")
1938
- return elf_file
1965
+ return elf_file, final_exports
1939
1966
 
1940
1967
 
1941
1968
  def _elf_to_sef(elf_path, sef_output, flags=0):