Skip to content

feat: attr_accessor/attr_reader/attr_writer サポート #545

@takaokouji

Description

@takaokouji

Goal

attr_accessorattr_readerattr_writer をサポートし、インスタンス変数のアクセサメソッド経由での読み書きをブロックに変換できるようにする。

Background

TryRuby レッスン 470 で attr_accessor が使われている。スモウルビーではインスタンス変数 (@foo) は Scratch 変数として既にサポートされているが、attr_accessor による getter/setter メソッド構文(foo, self.foo, self.foo = val)は未対応。

Ruby の仕様

メソッド 効果
attr_accessor :foo getter (foo / self.foo) + setter (self.foo = val)
attr_reader :foo getter のみ
attr_writer :foo setter のみ
複数指定 attr_accessor :hp, :name で複数同時定義

ブロック変換

class Sprite1 < Sprite
  attr_accessor :hp, :name

  when_flag_clicked do
    self.hp = 100       # → data_setvariableto(@hp, 100)
    self.name = "hero"  # → data_setvariableto(@name, "hero")
    say(hp)             # → looks_say(@hp) ← @hp の data_variable
    say(self.name)      # → looks_say(@name)
  end
end

Implementation Steps

Phase 1: コンバーター — attr_accessor/reader/writer の解析

  • class-visitor.js でクラス本体トップレベルの attr_accessor :foo, :bar を認識
  • 各シンボルに対応するインスタンス変数 @foo, @bar を作成
  • アクセサ情報をコンテキストに保存(getter/setter の区別)
  • @ruby:attr_accessor:foo / @ruby:attr_reader:foo / @ruby:attr_writer:foo コメントをマーカーブロックに付与(ラウンドトリップ用)
  • ユニットテスト (RED → GREEN)

Phase 2: コンバーター — getter/setter の変換

  • foo (レシーバーなし CallNode、クラス内) → アクセサ登録済みなら @foo 変数参照に変換
  • self.foo → 同上
  • self.foo = val (CallOperatorWriteNode or LocalVariableWriteNode) → @foo = val 変数代入に変換
  • アクセサ未登録のメソッド呼び出しは従来通りエラーまたは ruby_statement
  • ユニットテスト

Phase 3: ジェネレーター — ラウンドトリップ

  • @ruby:attr_accessor:foo コメント付き変数定義 → attr_accessor :foo を出力
  • クラス内の @foo 読み取り → foo として出力(アクセサ登録済みの場合)
  • クラス内の @foo = val 書き込み → self.foo = val として出力(アクセサ登録済みの場合)
  • 複数アクセサの結合: 同じ種類の連続するアクセサを attr_accessor :hp, :name にまとめる
  • ユニットテスト

Phase 4: ブラウザ確認

  • Playwright MCP でラウンドトリップ確認

Definition of Done

  • ユニットテスト pass
  • lint pass
  • CI green
  • ブラウザ確認:
    • attr_accessor :hp + self.hp = 100 + say(hp) のラウンドトリップ
    • attr_reader :name で setter (self.name = "x") がエラーにならない(ruby_statement にフォールバック)
    • 複数アクセサ attr_accessor :hp, :name のラウンドトリップ

Affected Files

  • packages/scratch-gui/src/lib/ruby-to-blocks-converter/class-visitor.js — attr_accessor 解析
  • packages/scratch-gui/src/lib/ruby-to-blocks-converter/ast-handlers/expressions.js — getter 変換
  • packages/scratch-gui/src/lib/ruby-to-blocks-converter/ast-handlers/assignments.js — setter 変換
  • packages/scratch-gui/src/lib/ruby-generator/class-wrapper.js — attr_accessor 出力
  • packages/scratch-gui/src/lib/ruby-generator/data.js — アクセサ変数の出力変換
  • packages/scratch-gui/test/unit/lib/ruby-roundtrip/ — テスト追加

Risks & Open Questions

  • attr_reader で setter を使った場合の挙動: エラーにするか ruby_statement にフォールバックするか → フォールバックが安全
  • ジェネレーター側で @foofoo に変換する際、アクセサ情報をどこに保持するか → コメントマーカーで管理

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions