## Major Features Added
### Field Visibility System
- Added `private { ... }` and `public { ... }` blocks in box declarations
- Default visibility is now handled explicitly (fields must be in either block)
- Visibility checks enforced at both interpreter and VM levels
### Parser Enhancements
- Extended AST with public_fields and private_fields vectors
- Added parsing for visibility blocks in box definitions
- Maintained backward compatibility with existing `init { ... }` syntax
### Interpreter Implementation
- Added visibility checks in field access (get_field/set_field)
- External access to private fields now throws appropriate errors
- Internal access (within methods) always allowed
### VM Implementation
- Extended VM with object_class tracking for visibility checks
- RefGet/RefSet instructions now enforce field visibility
- Fixed nested box declaration collection (boxes defined inside methods)
### Test Examples Added
- docs/examples/visibility_ok.nyash - demonstrates correct usage
- docs/examples/visibility_error.nyash - tests private field access errors
## Technical Details
### Error Messages
- Interpreter: "Field 'X' is private in Y"
- VM: Same error message for consistency
### Current Limitations
- All RefGet/RefSet treated as external access in VM (internal flag future work)
- Legacy `init { ... }` fields treated as having unspecified visibility
## Test Results
✅ Interpreter: Both test cases pass correctly
✅ VM: Both test cases pass correctly after nested declaration fix
This implements the foundation for proper encapsulation in Nyash,
following the "explicit is better than implicit" philosophy.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
37 lines
934 B
Plaintext
37 lines
934 B
Plaintext
static box Main {
|
||
init { console }
|
||
|
||
main() {
|
||
me.console = new ConsoleBox()
|
||
|
||
box User {
|
||
private { age, passwordHash }
|
||
public { name }
|
||
|
||
init { name, age }
|
||
|
||
birth(n, a) {
|
||
me.name = n
|
||
me.age = a
|
||
}
|
||
|
||
setAge(a) {
|
||
me.age = a # private だが内部からなのでOK
|
||
}
|
||
|
||
getAge() {
|
||
return me.age # private を内部参照(OK)
|
||
}
|
||
}
|
||
|
||
local u = new User("Alice", 20)
|
||
me.console.log("name(public)=" + u.name) # OK: public
|
||
u.name = "Bob" # OK: public set
|
||
|
||
me.console.log("age(private, internal)=" + u.getAge()) # OK: 内部アクセス
|
||
u.setAge(21) # OK: 内部でprivate set
|
||
me.console.log("done")
|
||
}
|
||
}
|
||
|