Repository navigation
Merged
Conversation
… needs the dumpout method, a str is a symbol Plan 9.0 asks Max what the design of tap.python rests on before any of 9.1 onward is built. This is the spike, run on a Mac (Max 9.1.5), with the answers written into docs/TAP-PYTHON-PLAN.md under 9.0; Windows is still to run. - tap.python_spike.cpp (throwaway, -DTAP_PYTHON_SPIKE=ON, off by default, the external only): a plain SDK class, tap.python, registered by tap.python~'s own ext_main after min's — a dumpout in the obex, value outlets changed between dynlet_begin and dynlet_end, an instance attribute and methods, a class attribute, a class-level anything, and messages that ask Max things — plus the same class without its dumpout method, and a recorder that posts every message with its atom types. With the option off, tap.python_tilde.cpp is MIN_EXTERNAL(python) as before. - init/tap.python.txt (max objectfile tap.python tap.python~;), shipped by scripts/assemble-package.py. - runtime-tests/spike/: a patcher per question, generated; run_spike.py, which opens each in a fresh Max through run.py's harness and collects Max's log; the Mac's results; and how to run it by hand on Windows. What Max said: the init/ mapping finds [tap.python] in a fresh Max (and without it, No such object), both objects load in either order; outlet_insert_after keeps the dumpout last and every cord that stays; get<attr> is dropped silently unless the class registers object_obex_dumpout as its dumpout method, as the SDK's examples do; instance attributes and methods win over a class-level anything, but int, float, bang and list never reach it; object_getmethod() still answers unknown names with method_false(), so 1.0.2's guard stands; a metro message runs on the main, scheduler or audio thread as the plan said, and systhread_isaudiothread() tells; and a str return is output as symbol <s> — as the message it names, list, int, float, symbol, bang and "" are not data. The plan's Ports, anything, guard, reserved names, output table and 9.3-9.5 follow, and CLAUDE.md's guard note is corrected: an object's own messages do not answer object_getmethod(), only its attributes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plan item 9.0 (
docs/TAP-PYTHON-PLAN.md): before any of 9.1 onward is built, ask a real Max whattap.python's design rests on. This runs the spike on a Mac (Max 9.1.5, macOS 15.7.9, x86_64) and writes every answer into the plan under 9.0, as verified in Max with the version. Windows is still to run, so 9.0 stays unticked. Nothing is tagged.What is in it
The spike class (
source/projects/tap.python_tilde/tap.python_spike.cpp, throwaway). It is a plain SDK class,tap.python(class_new/class_addmethod/class_register, no min, no Python), registered bytap.python~'s ownext_mainafter min'swrap_as_max_external(), in the same binary (D11). It has:outlets nchanges between the box'sdynlet_beginanddynlet_end;anything;describe,fire,probe,thread,outmsg/outsym,getdump,attrmethod;dumpoutmethod, and a recorder that posts each message it receives with its atom types.It builds only with
-DTAP_PYTHON_SPIKE=ON, which is off by default and affects the external only (the mock-kernel test compilestap.python_tilde.cppwithout it). With the option off,ext_mainisMIN_EXTERNAL(python)exactly as before.init/tap.python.txt(max objectfile tap.python tap.python~;).scripts/assemble-package.pynow shipsinit/; I checked that an assembled macOS package carries it.runtime-tests/spike/:run_spike.py, which opens each patcher in a fresh Max throughrun.py's harness and reads Max's own log. It turns "Restore Windows on Launch" off for the run and restores the preference files after;results/macos.txt, the evidence;The plan:
anything, the guard, reserved names, thestrrow of the output table, and 9.3–9.5;PRODUCTION-PLAN.mdnotes the Mac run.CLAUDE.md: a pointer to the spike, and one correction (below).
What Max said (Mac)
[tap.python]loads it through theinit/mapping. With the file moved aside, Max saysNo such object. Both objects load and work in one patch, whichever is created first. No stub external is needed.outlet_insert_after(the last value outlet) puts the new outlet before the dumpout. The dumpout's cord moves with it and every other cord stays.outlet_deleteremoves exactly the outlets it is given, with their cords.get<attr>needs the class'sdumpoutmethod. The class must registerclass_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0), as Cycling '74's SDK examples do. Without it,get<attr>is dropped silently: no getter call, no output, no error. The plan's Ports did not have this. In passing:object_attr_getdump()wants theget…message name, not the attribute name its header documents.anything, and an instance method wins over a class method of the same name,bangincluded.int,float,bangandlistnever reachanything. So the forwarder also needs class-level methods for those four.object_getmethod()still answers an unknown name withmethod_false()on such a class, so 1.0.2's guard stands.dumpoutjoins the reserved names.systhread_isaudiothread()detects that last case. Both settings were put back.strreturn →symbol <s>(the maintainer left this to the spike).listis dropped.intandfloatraise "missing arguments" in every receiver.bangbecomes a real bang.symboland""misbehave too.symbol <s>, every string arrives as itself, and Max's own text objects output single symbols the same way.[route C]won't match it (use[sel C]), and[prepend]keeps the wordsymbol. A list still names a message:["start"].docs/, and anextras/patcher as the package's. I could not look at the Documentation window or the Extras menu: the Mac's screen was locked for the whole session.CLAUDE.md correction: it said an object's own messages answer their names through
object_getmethod(), as its attributes do. The probes show only attributes do. Messages added withobject_addmethod()answer as unknown, ontap.python~too. The guard leaves both out, so nothing changes in behaviour. The matching comment onanswered_by_max()is left for 9.2's move, since this PR doesn't touch shipped source.Still to do, by hand
runtime-tests/spike/README.md):init/mapping, and the first Windows (DLL) build of the second class, in either order (Q1);dumpoutmethod registered through an imported function's address, which is an import thunk on Windows (Q3);anything(Q4);Checked
cmake --buildandctestpass with the option off (build) and on (build-spike), on this Mac.clang-format(pre-commit, the pinned version) passes.clang-tidy-18, run asstyle.ymldoes, is clean ontap.python_tilde.cppwith and without-DTAP_PYTHON_SPIKE, and on the spike TU.🤖 Generated with Claude Code
https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz