- amiga_gfx
fill/ Flood TmpRas:Flood()requires a chipTmpRason the draw RastPort.open_screen/open_windownowAllocRaster+InitTmpRasand attach it; close/shutdown frees it before Window/Screen.filluses Flood mode 1 and no-ops ifTmpRasis missing (was mode 0 with NULL TmpRas → crash). - Amiga sibling imports:
py68_set_script_dirkept volume/assign names without the trailing colon (PROGDIR→PROGDIR/myclass.py). It now preservesPROGDIR:/DH0:soimportfinds modules next to the script. Also, joining with script_dir/sys.path.no longer yields./file.py(invalid on AmigaDOS); barepythonami test1.pyfrom the script drawer works.
- Amiga OS custom-screen graphics plugin:
ext/amiga_gfx/amiga_gfx.py68k(OpenScreen / Workbenchopen_window/ SetRGB4 / RastPort draw / blit / soft BOBs with optional background save/bob_drawrestore / SimpleSprites / IDCMP keyboard+mouse /lowleveljoystick). Layer 2:lib/amiga_gfx.py. Docs:docs/amiga-os-gfx.md. Fixtures:test_amiga_gfx*, blit+sprites, WB window, BOB. Host--checksmokes. - Amiga GUI installer foundation:
examples/installer/pluslib/install_*.py(install.ami/uninstall.ami, LHA extract vialha, User-Startup upsert, safe uninstall that opensed S:User-Startup). Plugins: extendedgui_intuition(progress + label/enable/redraw) and newext/asl(ask_drawer). Doc: docs/amiga-gui-installer.md. Host check:examples/test_install_ami.py. - AmigaDOS runtime install scripts:
scripts/Installnow installs underSYS:Python68kand copiesscripts/Uninstall. Uninstall removes the runtime, itslibdrawer, and current-session Assign/Path entries; manually addedS:User-Startuplines must still be removed by the user.
- Language Level 0.8: classes and instances with single inheritance.
class Name:/class Name(Base):at module level; restricted class body (pass, simple assignment,def); per-instance__dict__;__init__; bound user methods;isinstance/issubclass/object/type(obj). - Builtin exceptions are real type objects under
BaseException/Exception.except Exceptionmatches by single-inheritance subtype. InternalPy68ErrorKindtags remain for C raise paths and logging; user exception subclasses use catchablePY68_ERROR_EXCEPTIONplus a type pointer (D-0049, D-0050). __build_class__builtin builds types from a namespace dict.- Multiple inheritance, metaclasses, descriptors,
super(), operator dunders, nested classes, and closures remain out of scope.
- Extension ABI (D-0048):
Py68ExtServicesonPy68Runtimelets LoadSeg plugins build ownedstr/listresults without linking the interpreter. - New Amiga plugin
ext/gui_intuition/gui_intuition.py68k— Layer 1 Intuition dialog API for guicreator-exported forms (make amiga-ext). Behavioral reference: HASlib/gui_intuition.s; not linked from that object. - Pure-Python
lib/gui_dialog.pyLayer 2 helper (run_modal/run_modal_fields). - Owner Amiga fixture:
tests/integration/amiga/test_gui_intuition.*. - Host unit test:
tests/unit/test_ext_services.c. - gui_intuition close path matches HAS/RKM
CloseWindowSafely(drain beforeModifyIDCMP(0)); button/string borders match HAS bevels (GFLG_GADGHNONE, recessed edit frame with −2 inset) to fix close crashes and white/missing frames.
- Module identity: direct scripts and
-ccommands expose__name__as"__main__"; imported modules expose their canonical import name, including when accessed through an alias. - Version string
Python68K 0.7.1.
-
Language Level 0.7: generators.
yieldin a module-leveldefmakes the function a generator factory; calling it builds aPY68_OBJECT_GENERATORand runs no body code.for,iter, andnextresume generators, and an exhausted generator iterates as empty (D-0045).send,throw,close(), andyield fromare not implemented. -
Generator state lives in the generator object (locals, private operand stack sized once to
maximum_stack, try stack, resume IP), so suspending never allocates and resuming never uses C recursion. Dropping the last reference frees locals and saved operands without running userfinallyblocks (D-0045). -
New
OP_YIELD_VALUE(0x3C) andPy68Code.is_generator; the verifier rejectsOP_YIELD_VALUEoutside a code object marked as a generator. -
Generator expressions
(elt for x in iterable if cond), including the unparenthesized form as a call's only argument (sum(x for x in range(5))); alongside another argument it is a syntax error, as in CPython. They compile to a synthetic nested generator code object; the outermost iterable is evaluated eagerly and free variables of an enclosing function are snapshotted as hidden arguments, so later rebinding is not observed (D-0046, a documented divergence from CPython closures). -
list,tuple,set,sorted,sum,all, andanydrain a generator argument into a list inside the VM before the native callback runs, so no builtin re-enters the interpreter (D-0047).min,max,len, andindo not accept generators. -
A builtin called with the wrong number of arguments now raises a catchable
TypeErrornaming the builtin and its accepted count; it previously failed with a blankException:line. -
I/O failures report as
OSError(Python 3);IOErrorremains an accepted alias for the same catchable kind (D-0044). -
Restricted f-strings:
f"...{expr}...{expr!r}...{expr:04d}..."with!s/!r/!a, literal format specs matchingformat(), and{{/}}escapes (D-0043). Nested f-strings, raw/bytes prefixes, andstr.formatmethods remain deferred. -
Builtins
iter(x)/next(it[, default])over the existingPy68Rangecursor used byfor; catchableStopIteration(D-0042).enumerate/reversedstill deferred;forbytecode unchanged. -
Builtin
sum(iterable[, start])for list/tuple of numbers; optional numericstartdefaults to0. Checked int overflow; float promotion matches+(D-0041). -
Conditional expressions:
then if condition else else(PY68_AST_IF_EXP). Evaluates the condition, then exactly one branch. Lower precedence thanor/and/comparisons; else-chains are right-associative (a if c1 else b if c2 else c). Compiles toJUMP_IF_FALSE/JUMP(D-0040). Comprehensionfor/ifclauses stayor_testfilters. Statementif/elif/elseis unchanged. -
Fixed-count unpacking / multiple assignment:
a, b = (1, 2),a, b = [1, 2],a, b = 1, 2,for a, b in pairs:, and string unpacka, b = "ab".OP_UNPACK(0x0F). Length mismatch isValueError; non-sequence isTypeError. Assignment RHS is an expression list (D-0038). Starred and nested unpacking remain unsupported. D-0015 still requires parentheses for tuples outside assignment (return a, bis still a syntax error). -
Identity operators
is/is not(OP_IS/OP_IS_NOT). Immediate None/bool/int/float values compare by type and payload; heap objects compare by pointer (D-0037).is notis one comparison operator, notisplus unarynot. -
Membership operators
in/not in(OP_CONTAINS/OP_NOT_CONTAINS) for str substring, list/tuple equality scan, dict keys, and set members. -
for/ comprehensions iterate strings as successive one-character strings. -
Example
examples/wordcount.pyfixed for Level APIs (OSError,fread). -
freadallocates from remaining file size (Seek/ftell), not the full count, so large “read all” counts work on Amiga without multi-GiB pre-allocation. -
Amiga LoadSeg extensions:
load_library(path)loads*.py68kplugins with a public export ABI (include/py68k_ext.h); sampleext/demo_add(vbcc C + vasm) viamake amiga-ext(D-0027). -
Version string
Python68K 0.7.0.
- Language Level 0.6: list, set, and dict comprehensions with nested
forclauses andiffilters. Targets bind in the enclosing function or module scope, matchingfor(D-0026). Generator expressions remain rejected. - Comprehension bytecode uses
OP_LIST_APPEND/OP_SET_ADD/OP_MAP_ADDwith existingRANGE_INIT/RANGE_NEXTloops; no nested functions. - Amiga: avoid calling
ErrorOutput()on dos.library < V47 (fixes--debug/ stderr Guru on Kickstart 2.x–3.1); usepr_CESorOutput()instead. - String methods (ASCII/8-bit): case, search, trim, split/join, replace, align,
expandtabs, translate, classifiers; bound via
attr.c. - Text builtins:
ord,chr,repr,ascii,all,any,format(minimal int specs),maketrans(returns dict). Literal escapes\\ \' \" \n \r \t \xHHdecoded at load. See D-0024 / D-0025. - Version string
Python68K 0.6.0.
- Language Level 0.3: tuple, dict, set, limited attributes, bound methods, value equality/hash, IEEE-754 binary32 float,
/true divide vs//floor divide. - Language Level 0.4: catchable exception objects,
try/except/finally/raise,with fopen(...) as f. - Language Level 0.5:
import/from/as, module objects, loader cache, builtinsys(path,modules,argv). - Targeted diagnostics for remaining unsupported keywords (
class,lambda, …). - Version string
Python68K 0.5.0.
- File builtins:
fopen/fclose/fread/freadline/fwrite/exists/remove/renamewith modesr/w/a/rb/wb/ab(AmigaDOSOpenon target; stdio on host). - Console
input([prompt])via stdin / AmigaDOSInput(). - Host environment:
getenv/setenv/unsetenv. - Amiga DOS assigns:
assign_get/assign_add/assign_remove(AssignPath/AssignLock/Lock+NameFromLock). PY68_OBJECT_FILEwith close-on-release; host unit + language fixtures.- Version string
Python68K 0.2.0.
- Language Level 0.1 runtime: tokenize → parse → symbols → compile → verify → stack VM.
- Scalars, arithmetic, comparisons, control flow, lists/strings, functions, builtins.
- Host GCC build (
make host) and Amiga vbcc build (make amiga). - Host unit tests and language fixture suite (
make test). - Copyright preamble on all C/H sources: 2026 Piotr Rozentreter (Rozsoft).