Skip to content

Add extending to classes#67

Merged
cyteon merged 4 commits intomainfrom
better-oop
Mar 25, 2026
Merged

Add extending to classes#67
cyteon merged 4 commits intomainfrom
better-oop

Conversation

@cyteon
Copy link
Copy Markdown
Owner

@cyteon cyteon commented Mar 25, 2026

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 extends and super (new bytecode instructions Extend and GetSuper).
  • 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.

Comment on lines +237 to +243
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);
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

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).

Copilot uses AI. Check for mistakes.
Comment on lines 214 to +224
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())),
}
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
@cyteon cyteon merged commit df5465f into main Mar 25, 2026
10 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