Skip to content

Instance call support: @ separator, void-returns-Any, hybrid field type system, and class method emission#664

Merged
joehendrix merged 2 commits intomainfrom
jhx/instance-call-core
Mar 27, 2026
Merged

Instance call support: @ separator, void-returns-Any, hybrid field type system, and class method emission#664
joehendrix merged 2 commits intomainfrom
jhx/instance-call-core

Conversation

@joehendrix
Copy link
Copy Markdown
Contributor

@joehendrix joehendrix commented Mar 25, 2026

Summary

Three interrelated changes to the Python→Laurel→Core pipeline that enable correct handling of instance methods, void procedures, and user-defined class fields:

  1. Unambiguous @ separator for instance methodsStorage@put_item instead of Storage_put_item, eliminating collisions with underscored names
  2. Void procedures return Any — all PySpec procedures now have exactly one output (void returns Any via from_none), removing special-case void handling at call sites
  3. Hybrid two-kind field type system — builtin types (int, str, bool, float) become Any on Composite fields; class types (PySpec services, user classes) stay Composite, matching parameter semantics at call boundaries
  4. User-defined class method emission — class method definitions (Counter@__init__, Counter@increment) are now included in the Laurel program as static procedures

PythonToLaurel changes

  • @ separator applied across PythonToLaurel, PythonToCore, PySpecPipeline, and Specs/ToLaurel
  • New translateFieldType helper maps builtins→Any, composites→Composite for field declarations
  • self parameter typed as Composite (not Any) in __init__ and user methods
  • Removed wrapFieldInAny for self.field reads in method bodies — builtin fields are already Any-typed
  • unsupportedConstruct error thrown when Composite→Any coercion is attempted (e.g., returning a Storage field as str)

LaurelToCoreTranslator changes

  • Statement-position calls now synthesize throwaway $unused_N variables to match output count, fixing Core arity checks for void-returns-Any procedures
  • Single-target Assign with StaticCall also synthesizes extra LHS variables for multi-output procedures

Testing

  • New dispatch tests for void assign/init, non-void discard, instance call result, user class construct, class field assign, and class method return
  • Two negative tests for Composite↔Any kind mismatches: test_class_composite_as_any (Composite field returned as Any) and test_class_any_as_composite (Any value assigned to Composite field). The latter requires explicit pyspec paths since IdentifyOverloads resolves modules from complete programs with main, not isolated class snippets.
  • 7 regenerated expected_laurel files reflecting the new field type system

Known limitations

  • Composite→Any coercion (e.g., returning a Storage field as str) is explicitly rejected with a user-facing error. Coercion functions are being developed separately.
  • Procedure names used as type annotations (e.g., Storage_put_item as a type) silently fall through to Any instead of producing an error or warning.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

@joehendrix joehendrix requested a review from a team March 25, 2026 22:54
@joehendrix joehendrix marked this pull request as draft March 26, 2026 07:04
@joehendrix joehendrix changed the title Replace InstanceCall with StaticCall and fix void procedure assignment Use @ separator for instance methods, make void procedures return Any, and emit user class definitions Mar 26, 2026
@joehendrix joehendrix force-pushed the jhx/instance-call-core branch from acca015 to 4c6b6b3 Compare March 26, 2026 15:22
@joehendrix joehendrix changed the title Use @ separator for instance methods, make void procedures return Any, and emit user class definitions Instance call support: @ separator, void-returns-Any, hybrid field type system, and class method emission Mar 26, 2026
@joehendrix joehendrix force-pushed the jhx/instance-call-core branch 6 times, most recently from 21fdd05 to 58208e4 Compare March 26, 2026 21:07
@joehendrix joehendrix marked this pull request as ready for review March 26, 2026 21:08
@joehendrix joehendrix force-pushed the jhx/instance-call-core branch 5 times, most recently from 9bf553e to 080c937 Compare March 26, 2026 22:47
@joehendrix joehendrix enabled auto-merge March 26, 2026 22:58
shigoel
shigoel previously approved these changes Mar 27, 2026
joscoh
joscoh previously approved these changes Mar 27, 2026
Copy link
Copy Markdown
Contributor

@joscoh joscoh left a comment

Choose a reason for hiding this comment

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

Not necessarily blocking, but the ... ++ "@" pattern appears 9 times throughout the code. If we ever want to change the naming convention, it would be better to have this in a separate function.

…pe system, and class method emission

- Use @ as class-method separator (e.g., Storage@put_item) to avoid
  ambiguity with underscored names
- Void PySpec procedures now return Any (via from_none), eliminating
  special-case void handling at call sites
- Add translateFieldType: builtins become Any on Composite fields,
  class types stay Composite (hybrid two-kind system)
- Self parameter typed as Composite in __init__/methods
- Throw unsupportedConstruct for Composite→Any coercion attempts
- Synthesize throwaway LHS variables in LaurelToCoreTranslator for
  statement-position calls to void-returns-Any procedures
- Emit user-defined class method definitions as static procedures
- Add positive and negative dispatch tests, regenerate expected files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@joehendrix joehendrix dismissed stale reviews from joscoh and shigoel via 2b7a538 March 27, 2026 01:22
@joehendrix joehendrix force-pushed the jhx/instance-call-core branch from 080c937 to 2b7a538 Compare March 27, 2026 01:22
mkInstanceMethodCall now returns Hole for Any-typed receivers,
consistent with how other unknown method calls on Any are handled.
This fixes the type checking error for `with open(...) as f:` where
the context manager type is Any.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@joehendrix joehendrix added this pull request to the merge queue Mar 27, 2026
Merged via the queue into main with commit 3f9a5a0 Mar 27, 2026
15 checks passed
@joehendrix joehendrix deleted the jhx/instance-call-core branch March 27, 2026 02:11
olivier-aws pushed a commit that referenced this pull request Mar 30, 2026
…pe system, and class method emission (#664)

## Summary

Three interrelated changes to the Python→Laurel→Core pipeline that
enable correct handling of instance methods, void procedures, and
user-defined class fields:

1. **Unambiguous `@` separator for instance methods** —
`Storage@put_item` instead of `Storage_put_item`, eliminating collisions
with underscored names
2. **Void procedures return Any** — all PySpec procedures now have
exactly one output (void returns `Any` via `from_none`), removing
special-case void handling at call sites
3. **Hybrid two-kind field type system** — builtin types (int, str,
bool, float) become `Any` on Composite fields; class types (PySpec
services, user classes) stay `Composite`, matching parameter semantics
at call boundaries
4. **User-defined class method emission** — class method definitions
(`Counter@__init__`, `Counter@increment`) are now included in the Laurel
program as static procedures

## PythonToLaurel changes

- `@` separator applied across PythonToLaurel, PythonToCore,
PySpecPipeline, and Specs/ToLaurel
- New `translateFieldType` helper maps builtins→Any,
composites→Composite for field declarations
- `self` parameter typed as `Composite` (not `Any`) in `__init__` and
user methods
- Removed `wrapFieldInAny` for `self.field` reads in method bodies —
builtin fields are already Any-typed
- `unsupportedConstruct` error thrown when Composite→Any coercion is
attempted (e.g., returning a Storage field as str)

## LaurelToCoreTranslator changes

- Statement-position calls now synthesize throwaway `$unused_N`
variables to match output count, fixing Core arity checks for
void-returns-Any procedures
- Single-target `Assign` with `StaticCall` also synthesizes extra LHS
variables for multi-output procedures

## Testing

- New dispatch tests for void assign/init, non-void discard, instance
call result, user class construct, class field assign, and class method
return
- Two negative tests for Composite↔Any kind mismatches:
`test_class_composite_as_any` (Composite field returned as Any) and
`test_class_any_as_composite` (Any value assigned to Composite field).
The latter requires explicit pyspec paths since `IdentifyOverloads`
resolves modules from complete programs with `main`, not isolated class
snippets.
- 7 regenerated expected_laurel files reflecting the new field type
system

## Known limitations

- Composite→Any coercion (e.g., returning a `Storage` field as `str`) is
explicitly rejected with a user-facing error. Coercion functions are
being developed separately.
- Procedure names used as type annotations (e.g., `Storage_put_item` as
a type) silently fall through to `Any` instead of producing an error or
warning.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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.

4 participants