Repository navigation
Access and Assign methods, _SCREEN and _VFP, released forms, FOR EACH over Forms - #7
Conversation
RandomChirp
left a comment
There was a problem hiding this comment.
Every measured claim in the new tests holds in vfp9.exe: _SCREEN.Forms is topmost first with a Custom left out, FOR EACH walks it, Forms(n) past the end and a read of Forms as a value are both 1924, a released form is .NULL. (VARTYPE X) to a variable and to a property holding it, Release() answers .T., PEMSTATUS(o, "DataEnvironment", 5) is .F. for CREATEOBJECT("form") and for a Form subclass, an event called as a method with no code answers .T., PageOrder is the page's place, _VFP.Height takes a write and _VFP.Foo is 1426, _SCREEN.cNothing is 1734, _SCREEN.AddObject makes the object and names it in capitals, and the Access/Assign program prints read 10, after write 60, inner 60, flag .F., flag2 .T., calls 3 5/1. cargo test -p foxvm is green on a merge with main.
The ubuntu check failed only on the stale instructions.json guard, which main no longer has; a rebase clears it.
One note, not a blocker: after this change every property read makes a host call (has_code_method, a Reflect::get plus a JS call) and every load of an object value another (released). FoxPro code reads THIS.x constantly, so it is worth timing a property-heavy loop before and after. If it shows, the answer is probably a per-object flag the host sets once (has any _ACCESS or _ASSIGN method at all) rather than a call per read.
Review generated with Claude Code (Claude Fable 5.1), run against vfp9.exe and the test suites on a merge with main.
RandomChirp
left a comment
There was a problem hiding this comment.
Withdrawing the approval: on a merge with main this branch stops one of the forms Visual FoxPro ships with from opening. tests/vfp/samplesRun.test.ts (which needs the product installed, so CI does not run it) passes on main and fails with this branch:
Solution/Tahoe/aa_fun.scx: Error 31 in FRMTRACK.INIT line 4: Invalid subscript reference.
That form is the Access/Assign sample. Its Init reads THIS.myButtons[1] where myButtons is an array property with a myButtons_Access method that takes the subscript. The branch calls the Access method with no argument on every read of the property, and then subscripts what it returned.
Measured in vfp9.exe with an array property myButtons[3] and this Access method:
PROCEDURE myButtons_Access
LPARAMETERS nIndex
? "access got", VARTYPE(nIndex), nIndex
IF VARTYPE(nIndex) = "N"
RETURN THIS.myButtons[nIndex]
ENDIF
RETURN "whole"
ENDPROC
- o.myButtons[1] calls the Access method with N 1, and o.myButtons[2] with N 2; the method's own THIS.myButtons[nIndex] reads the element without calling itself again.
- o.myButtons("x") calls it with C x.
- VARTYPE(o.myButtons), the whole array named with no subscript, calls it with N 1.
- o.myButtons[1] = 5 does not call it (an Assign method would be the one called); a read after it calls Access with 1 and gets 5.
- ALEN(o.myButtons) does not call it and answers 3; DIMENSION o.myButtons[4] works on the array itself.
- A read of THIS.myButtons[1] from another method of the object calls it, as a read from outside does.
So for an array property the subscript is the Access method's argument, and a write, ALEN and DIMENSION bypass it. With this branch every one of those reads calls Access with nothing and then fails with error 31 on the result, which is what the sample's Init hits.
The second failure the run reported, foxmedia.scx, was my environment (no COM addon in the worktree) and is not this branch's.
Review generated with Claude Code (Claude Fable 5.1), run against vfp9.exe and the test suites on a merge with main.
… over Forms Found running a CodeMine application (Shutter Ace); each behaviour measured in Visual FoxPro 9 first, and in tests/runtime/formsAndAccessors.test.ts. - Prop_Access and Prop_Assign stand in for reading and writing a property; inside either one, THIS.Prop is the property itself. The parser no longer warns that they are not honoured. - _SCREEN holds what a program writes to it and what AddProperty gives it, and _SCREEN.AddObject makes its object as CREATEOBJECT would - a program's class included (CodeMine keeps its global object manager there). _SCREEN.HWnd answers 0. - FOR EACH walks _SCREEN.Forms (and a formset's Forms) through a new optional host read, enumerate(); _SCREEN.Forms(n) counts from the topmost form and is 1924 past either end; FormCount leaves Custom objects out. - A released form reads as .NULL. from every variable, array element and property still holding it; Release() answers .T. - A form made from a class has no DataEnvironment; only a form file's does. - An event called as a method with no code behind it answers .T. - Name set by a program is what Name reads back; a page answers PageOrder with its place in the pageframe. - _VFP takes property writes, and an unknown name is 1426. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review on FoxDevCommunity#7: Solution/Tahoe/aa_fun.scx stopped opening with error 31, because THIS.myButtons[1] called myButtons_Access with nothing and then subscripted what it returned. Measured in vfp9.exe with an array property myButtons[3]: - obj.aProp[n] and obj.aProp("x") call the Access method with the subscript; the method's own THIS.aProp[n] reads the element without calling itself again - the array named whole, VARTYPE(obj.aProp), calls it with 1 - a write to an element, ALEN(obj.aProp) and DIMENSION obj.aProp[4] do not call it obj.aProp[n] now compiles to one instruction, GetMemberIndex, instead of a member read and then a subscript; ALEN's array argument is read with GetProp, which passes over the Access method; a method call on a property with an Access method goes to it. The member read that GetMember and the a.b path of LoadField each spelt out is one helper, read_member. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
b5b2962 to
0a36240
Compare
|
Thanks for catching this, and for measuring the array cases. I've rebased on main and pushed a fix. On the performance note: I haven't changed the per-read |
Found running a CodeMine application (Shutter Ace); each behaviour measured in
Visual FoxPro 9 first, and in tests/runtime/formsAndAccessors.test.ts.
inside either one, THIS.Prop is the property itself. The parser no longer
warns that they are not honoured.
and _SCREEN.AddObject makes its object as CREATEOBJECT would - a program's
class included (CodeMine keeps its global object manager there).
_SCREEN.HWnd answers 0.
host read, enumerate(); _SCREEN.Forms(n) counts from the topmost form and is
1924 past either end; FormCount leaves Custom objects out.
property still holding it; Release() answers .T.
with its place in the pageframe.
Verification. New
tests/runtime/formsAndAccessors.test.ts, each case mirroring a probe run invfp9.exe, plus a_SCREENcase intests/runtime/objectModel.test.ts. The full VM suite and the runtime, shared and vfp TypeScript tests pass on this branch.One of several pull requests split out of work on a CodeMine application (Shutter Ace); each stands on main on its own except where it says otherwise.
🤖 Generated with Claude Code