Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds single-inheritance support to the Modu language via class Child extends Parent and enables calling parent implementations through super.<method>(...), with accompanying docs, tests, and editor syntax updates.
Changes:
- Add lexer/parser/AST/compiler/VM support for
extendsandsuper(new bytecode instructionsExtendandGetSuper). - Expand OOP test coverage and examples to validate inheritance and
super.init(...). - Update documentation and editor syntax highlighting (REPL, VS Code, Zed) for the new keywords.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/lib/tour/pages/classes.md | Updates the tour page example to demonstrate extends and super.init(). |
| lang/tests/cases/oop.modu | Adds an inheritance test case (xCounter extends Counter) using super.init. |
| lang/tests/cases/oop.expected | Updates expected output to include results from the new inheritance test. |
| lang/src/vm/vm.rs | Implements Extend and GetSuper execution and threads parent_methods through instances/classes. |
| lang/src/vm/value.rs | Extends Value::Class / Value::Instance with parent_methods and updates equality behavior. |
| lang/src/vm/instruction.rs | Adds new VM instructions: Extend and GetSuper. |
| lang/src/parser.rs | Parses class ... extends ... and tokenizes super into the expression stream. |
| lang/src/lexer.rs | Adds extends and super keywords to the lexer. |
| lang/src/compiler/compiler.rs | Emits bytecode for inheritance (Extend) and compiles super.<method> to GetSuper. |
| lang/src/cli/repl.rs | Updates REPL syntax highlighting regex to include extends and super. |
| lang/src/ast.rs | Extends Expr::Class with an optional parent field. |
| lang/examples/oop.modu | Updates the example program to demonstrate inheritance and super. |
| extensions/zed/languages/modu/highlights.scm | Adds highlighting for extends and super. |
| extensions/zed/extension.toml | Updates the pinned tree-sitter-modu grammar revision. |
| extensions/vscode/syntaxes/modu.tmLanguage.json | Adds extends and super to VS Code keyword highlighting. |
| extensions/vscode/package.json | Bumps VS Code extension version and updates install script to match. |
| extensions/vscode/modu-lang-1.10.0.vsix | Adds a packaged VS Code extension artifact to the repo. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if matches!(&object.node, Expr::Identifier(n) if n == "super") { | ||
| self.emit(Instruction::LoadLocal(0), span); | ||
| self.emit(Instruction::GetSuper(property.clone()), span); | ||
| } else { | ||
| self.compile_expr(*object.clone())?; | ||
| self.emit(Instruction::GetProperty(property.clone()), span); | ||
| } |
There was a problem hiding this comment.
super property access compiles to LoadLocal(0) unconditionally. If super is used outside a class method (e.g. top-level or a normal fn without locals), the VM will try to read stack slot 0 and panic (out-of-bounds) before GetSuper can raise a friendly runtime error. Please gate this at compile-time (e.g. ensure self is defined at local slot 0 / you’re inside a class method) and otherwise return a compile error like "super can only be used inside class methods" (or compile to a safe runtime error without LoadLocal).
| if let Expr::PropertyAccess { object, property: _ } = &callee.node { | ||
| let (target_local, target_global) = match &object.node { | ||
| Expr::Identifier(name) => { | ||
| match self.scope.resolve(name) { | ||
| Variable::Local(index) => (Some(index), None), | ||
| Variable::Global(_) => (None, Some(name.to_string())), | ||
| } | ||
| if name == "super" { | ||
| (Some(0), None) | ||
| } else { | ||
| match self.scope.resolve(name) { | ||
| Variable::Local(index) => (Some(index), None), | ||
| Variable::Global(_) => (None, Some(name.to_string())), | ||
| } | ||
| } |
There was a problem hiding this comment.
For super.method() calls, the compiler hard-codes target_local = Some(0). Outside a class method this slot may not exist or won’t be the receiver being invoked, which can lead to incorrect self_target replacement behavior on return. Consider reusing the same compile-time validation as for super property access (only allow in methods where local 0 is self) and otherwise emit a compile error.
No description provided.