Skip to content

Library host: reference parameters, and integers past the top of a long - #8

Merged
RandomChirp merged 3 commits into
FoxDevCommunity:mainfrom
jefflroberts:fll-references
Oct 5, 2026
Merged

RandomChirp merged 3 commits into
FoxDevCommunity:mainfrom
jefflroberts:fll-references

Conversation

@jefflroberts

Copy link
Copy Markdown
Collaborator

Found running a CodeMine application (Shutter Ace), whose codemine.fll reads the
registry with cmRegGetValue(nRoot, cKey, @cvalue), declared "I,C,R". Measured
in Visual FoxPro 9 against a library of our own, tests/fll/refparm.c, which
scripts/build-fllhost.mjs builds beside the two API samples.

  • A number past the top of a signed long wraps into an 'I' parameter as the
    product wraps it: HKEY_LOCAL_MACHINE, written 2147483650, was reaching the
    library as 0x80000000 (HKEY_CLASSES_ROOT), because casting a double that
    large is undefined and this compiler makes it that.
  • A variable passed with @ to a parameter declared 'R' is handed to the
    library as a Locator. The library reads and writes it through _Load and
    _Store (thunks 30 and 29 in winapims.lib), and what it stored comes back
    with the answer and is written into the variable. A value where 'R' was
    declared is refused before the function runs, with error 9.

The wire protocol gains an 'R' tag in front of a referenced argument and a
list of stored values at the end of a call's reply; a host built before this
simply ends its reply sooner.

Builds on the @var-as-a-reference work in the class run-time pull request.

Verification. Two new cases in tests/fll/samples.test.ts against refparm.fll, whose expectations vfp9.exe gave with the same build of it. The FLL, runtime and reference tests pass on this branch.

Depends on #6, whose @var-as-a-reference work this uses: until #6 is merged this pull request's diff includes it too. Only the last commit is new here.

🤖 Generated with Claude Code

@RandomChirp RandomChirp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The library host side is sound: _Load and _Store against a Locator per reference parameter, the stored values travelling back after the error fields so an older host's reply still parses, the R marker in the call frame, and the wrap of a number between 2^31 and 2^32 to what the product hands an I parameter (2147483650 to 0x80000002 is exactly the registry-root case). refparm.c builds here beside the two Microsoft samples, and cargo test -p foxvm is green on a merge with main.

This branch contains #6, so it inherits the two points I left there: the Error-method rule that also skips errors inside a runtime-called Error method, which the product does not, and the dead Instr::DoDefault. Once #6 is settled this one only needs the same rebase.

The refparm expectations (swap old new, bump .T. 6 N, set .T. 42 N, err 9, byval kept, and the INTOF rows) can only be confirmed by a run against vfp9.exe with the built .fll; the test says they were, and the values are consistent with the API, so I have not repeated that measurement.

Review generated with Claude Code (Claude Fable 5.1), run against vfp9.exe and the test suites on a merge with main.

jefflroberts and others added 3 commits September 24, 2026 18:08
…arch

Found running a 60,000-line CodeMine application (Shutter Ace); each behaviour
measured in Visual FoxPro 9 first.

- DODEFAULT() runs the parent class's code. The importer keeps an overridden
  .vcx method's ancestors' versions as Name#1, Name#2 (nearest first), each
  compiled with its own class's header; the session runs the next one up, or
  walks DEFINE CLASS parents from the class whose code is running, and
  answers .T. past the last. A program class inherits the methods it does not
  override, and answers Class in proper case.
- An error raised inside an object's Error method - called directly or reached
  through DODEFAULT() - is dropped and the method carries on, and ERROR() and
  MESSAGE() there see the error that sent it (the session's last error).
- @var passed to an object's method is the variable: it crosses as
  {"$ref", "$val"} and a method of FoxPro code writes the caller's variable.
  @m.x is a reference too.
- The run-time class library search looks in the project's class-library
  folders before the Foundation Classes, SET CLASSLIB finds a project library
  by name, and a parent library that cannot be found is reported instead of
  silently dropping what the class inherits.
- A non-visual class (a Custom) can be added to a container as a member.
- Importer: a middle class's dotted overrides (pgfSteps.Page2.Name) reach the
  member an older ancestor made, so a third class keeps the pages and what is
  on them; a class's own property written in parentheses is an expression
  worked out when the object is made (nHkeyMachineRoot = ((2^31) + 2)).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ult instruction

Review on FoxDevCommunity#6 (measured in vfp9.exe): an error inside an Error method is skipped only
when the program called the method, or reached an ancestor's with DODEFAULT() from
there. When the runtime called Error because a method of the object failed, the error
goes to the default handler - the dialog - and ON ERROR is not asked. in_class_error
already holds the object in that case, so the skip is gated on it.

DODEFAULT is a builtin now, so Instr::DoDefault, its handler and the compiler block
that emitted it were unreachable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found running a CodeMine application (Shutter Ace), whose codemine.fll reads the
registry with cmRegGetValue(nRoot, cKey, @cvalue), declared "I,C,R". Measured
in Visual FoxPro 9 against a library of our own, tests/fll/refparm.c, which
scripts/build-fllhost.mjs builds beside the two API samples.

- A number past the top of a signed long wraps into an 'I' parameter as the
  product wraps it: HKEY_LOCAL_MACHINE, written 2147483650, was reaching the
  library as 0x80000000 (HKEY_CLASSES_ROOT), because casting a double that
  large is undefined and this compiler makes it that.
- A variable passed with @ to a parameter declared 'R' is handed to the
  library as a Locator. The library reads and writes it through _Load and
  _Store (thunks 30 and 29 in winapims.lib), and what it stored comes back
  with the answer and is written into the variable. A value where 'R' was
  declared is refused before the function runs, with error 9.

The wire protocol gains an 'R' tag in front of a referenced argument and a
list of stored values at the end of a call's reply; a host built before this
simply ends its reply sooner.

Builds on the @var-as-a-reference work in the class run-time pull request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jefflroberts

Copy link
Copy Markdown
Collaborator Author

Rebased on the updated #6, so it now carries the Error-method fix and the Instr::DoDefault removal from there. Nothing in the library host changed. cargo test -p foxvm and the vitest suite are green, including the refparm tests with the host and .fll built.

@RandomChirp
RandomChirp merged commit 33542a4 into FoxDevCommunity:main Oct 5, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants