Skip to content

Migrate binary_tree module to Conductor#790

Open
Akshay-2007-1 wants to merge 3 commits into
conductor-migrationfrom
feat/migrate-binary-tree
Open

Migrate binary_tree module to Conductor#790
Akshay-2007-1 wants to merge 3 commits into
conductor-migrationfrom
feat/migrate-binary-tree

Conversation

@Akshay-2007-1

@Akshay-2007-1 Akshay-2007-1 commented Jul 11, 2026

Copy link
Copy Markdown

Description

Fixes #768

Migrates the binary_tree module to be Conductor-ready, following the pattern established by the repeat module (#698). binary_tree has no tab/visualization component, so this is scoped entirely to src/bundles/binary_tree/.

  • functions.ts is rewritten against Conductor's IDataHandler (pair_make/pair_head/pair_tail) instead of js-slang's stdlib/list, so tree structure is built from real Conductor Pairs rather than native JS arrays.
  • index.ts is now a BaseModulePlugin subclass with each exported function as a @moduleMethod-decorated closure, mirroring repeat.
  • The stored tree entry value is declared DataType.OPAQUE at the module boundary (arbitrary Source/Python values aren't representable as a single concrete DataType).
  • is_tree/is_empty_tree declare no argument type, since they're predicates that must accept a value of any type and answer false rather than throw — a declared type would mean the FFI boundary type-asserts and throws before the predicate body ever runs.
  • tsconfig.json picked up the same experimentalDecorators/emitDecoratorMetadata overrides repeat already has (this bundle was missing them, which breaks the moduleMethod decorator under TS's native Stage-3 decorators).

Testing

  • yarn workspace @sourceacademy/bundle-binary_tree run tsc — passes
  • yarn workspace @sourceacademy/bundle-binary_tree run lint — passes
  • yarn workspace @sourceacademy/bundle-binary_tree run test — 16/16 passing, against @sourceacademy/modules-testplugin's TestDataHandler
  • yarn workspace @sourceacademy/bundle-binary_tree run build — produces build/bundles/binary_tree.js
  • End-to-end: loaded the built bundle into py-slang's PyCseEvaluator (via py-slang#217's module loader work) and drove make_tree/entry/left_branch/right_branch/is_tree from real Python-shaped values through the actual pythonToModule/moduleToPython conversion code — all round-trip correctly.

Notes for reviewers

Getting the end-to-end test working surfaced two bugs upstream of this PR, not fixable within binary_tree itself:

  • BaseModulePlugin.initialise() in conductor registers each exported method as a detached function reference (this[name]) without binding it to the instance, so this is undefined inside any exported method body once a real evaluator calls it. This breaks every Conductor module that uses ordinary class methods (i.e. all of them), not just this one. Filing a fix against conductor separately.
  • moduleToPython/pythonToModule in py-slang#217 flatten a returned DataType.PAIR into a Python list and convert Python lists back to DataType.ARRAY, which loses identity for any function returning a Pair that's meant to be passed back into another module call (e.g. left_branch(t)). Flagging this on that PR directly since the affected file is new there.

Rewrites the binary_tree bundle as a Conductor BaseModulePlugin, backed
by IDataHandler pair/list primitives instead of js-slang's stdlib. Tree
entries are stored as OPAQUE values at the module boundary; is_tree and
is_empty_tree declare no arg type so they can accept any DataType and
answer false rather than throw, matching their predicate semantics.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the binary_tree bundle from js-slang to @sourceacademy/conductor, refactoring the tree operations, types, and tests to utilize Conductor's IDataHandler and TypedValue system, and exporting the module via a new BinaryTreeModulePlugin class. The review feedback suggests enhancing robustness by adding null/undefined checks for the value parameter in is_tree, is_empty_tree, and assertNonEmptyTree to prevent runtime crashes. Additionally, it is recommended to throw EvaluatorRuntimeError instead of generic Error objects for arity mismatches in the module plugin methods.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/bundles/binary_tree/src/functions.ts
Comment thread src/bundles/binary_tree/src/functions.ts
Comment thread src/bundles/binary_tree/src/functions.ts
Comment thread src/bundles/binary_tree/src/index.ts Outdated
Comment thread src/bundles/binary_tree/src/index.ts
Comment thread src/bundles/binary_tree/src/index.ts
@Akshay-2007-1 Akshay-2007-1 self-assigned this Jul 11, 2026
@Akshay-2007-1 Akshay-2007-1 marked this pull request as draft July 11, 2026 12:11
is_tree/is_empty_tree/assertNonEmptyTree now guard against a
missing/undefined value instead of crashing with a raw TypeError, and
the plugin's arity-check throws now use EvaluatorRuntimeError (already
used elsewhere in this module) instead of a generic Error.

Also adds the same __bindExportedMethods() workaround repeat/rune use
for the unbound-method issue in BaseModulePlugin.initialise()
(conductor#41), since this fix isn't merged upstream yet.
@Akshay-2007-1 Akshay-2007-1 marked this pull request as ready for review July 11, 2026 14:09
@Akshay-2007-1

Copy link
Copy Markdown
Author

@coderabbitai, any review comments?

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

@Akshay-2007-1 Sure thing — I'll kick off a full review of the changes in this PR now. You'll see my review comments shortly, covering functions.ts, index.ts, and the tsconfig.json update in src/bundles/binary_tree/.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0331d85f-4198-4185-99f3-31065bad8d16

📥 Commits

Reviewing files that changed from the base of the PR and between 7c75a40 and 2a97432.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (6)
  • src/bundles/binary_tree/package.json
  • src/bundles/binary_tree/src/__tests__/index.test.ts
  • src/bundles/binary_tree/src/functions.ts
  • src/bundles/binary_tree/src/index.ts
  • src/bundles/binary_tree/src/types.ts
  • src/bundles/binary_tree/tsconfig.json

Walkthrough

The binary tree module is migrated from synchronous native structures to Conductor TypedValue representations. Operations now use asynchronous evaluator calls, exports are provided through BinaryTreeModulePlugin, and tests use typed handler-generated fixtures.

Changes

Binary Tree Conductor Migration

Layer / File(s) Summary
Typed tree representation
src/bundles/binary_tree/src/types.ts, src/bundles/binary_tree/src/functions.ts
Tree aliases and empty-tree construction now use Conductor typed values.
Evaluator-based tree operations
src/bundles/binary_tree/src/functions.ts
Construction, validation, error handling, and branch access use asynchronous evaluator operations.
Conductor module plugin surface
src/bundles/binary_tree/src/index.ts, src/bundles/binary_tree/tsconfig.json, src/bundles/binary_tree/package.json
The module now exposes decorated, evaluator-aware plugin methods with updated compilation and development settings.
Typed async test coverage
src/bundles/binary_tree/src/__tests__/index.test.ts
Tests build typed trees and validate asynchronous predicates, accessors, errors, and opaque values.

Estimated code review effort: 4 (Complex) | ~45 minutes

Poem

I’m a rabbit with a typed tree to tend,
Pair by pair, where branches bend.
Async carrots hop through the stream,
Opaque numbers join the dream.
The plugin blooms—what a leafy scheme!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: migrating the binary_tree module to Conductor.
Description check ✅ Passed It covers the issue fixed, change summary, motivation/context, and testing; only the checklist template section is missing.
Linked Issues check ✅ Passed The PR implements the requested Conductor migration for binary_tree in #768.
Out of Scope Changes check ✅ Passed No clear out-of-scope changes are evident; the package, tests, and tsconfig updates support the Conductor migration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/migrate-binary-tree

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

master's binary_tree gained this validation while conductor-migration
was diverging (make_tree(0, 0, null) previously constructed a
malformed tree silently instead of throwing). Ports the same check,
using EvaluatorTypeError to match this module's existing Conductor
error style rather than modules-lib's InvalidParameterTypeError, which
doesn't apply here since this module no longer goes through js-slang.

@AaravMalani AaravMalani left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yep, LGTM. The only thing left is documentation, but since that's still pending as per #765, I'm approving it in advance

export function is_empty_tree(value: BinaryTree): value is EmptyBinaryTree {
return value === null;
export function is_empty_tree(value: TypedValue<DataType>): value is TypedValue<DataType.EMPTY_LIST> {
return value?.type === DataType.EMPTY_LIST;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Out of curiosity, when would value be nullish?

// function (which is how every evaluator calls closures) gets `this === undefined` inside the
// method body. Same workaround as repeat/rune until the upstream fix in conductor lands
// (source-academy/conductor#41).
private __bindExportedMethods() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yep, can be removed now

return await make_tree_func(this.evaluator, value, left, right);
}

// No declared arg type: is_tree is a predicate that must accept a value of any

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm, for this I think we should add a DataType.ANY which just accepts all values. Thoughts @Akshay-2007-1 @martin-henz?

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