Files
hakorune/src/interpreter/box_methods.rs

269 lines
9.7 KiB
Rust
Raw Normal View History

/*!
* Box Method Handlers Module
*
* Extracted from interpreter.rs lines 1389-2515 (1,126 lines)
* Contains Box type-specific method implementations:
*
* MOVED TO methods/basic_methods.rs:
* - execute_string_method (StringBox)
* - execute_integer_method (IntegerBox)
* - execute_bool_method (BoolBox) - NEW
* - execute_float_method (FloatBox) - NEW
*
* MOVED TO methods/collection_methods.rs:
* - execute_array_method (ArrayBox)
* - execute_map_method (MapBox)
*
* MOVED TO methods/io_methods.rs:
* - execute_file_method (FileBox)
* - execute_result_method (ResultBox)
*
* MOVED TO methods/math_methods.rs:
* - execute_math_method (MathBox)
* - execute_random_method (RandomBox)
*
* MOVED TO system_methods.rs:
* - execute_time_method (TimeBox)
* - execute_datetime_method (DateTimeBox)
* - execute_timer_method (TimerBox)
* - execute_debug_method (DebugBox)
*
* MOVED TO async_methods.rs:
* - execute_future_method (FutureBox)
* - execute_channel_method (ChannelBox)
*
* MOVED TO web_methods.rs:
* - execute_web_display_method (WebDisplayBox)
* - execute_web_console_method (WebConsoleBox)
* - execute_web_canvas_method (WebCanvasBox)
*
* MOVED TO special_methods.rs:
* - execute_sound_method (SoundBox)
* - execute_method_box_method (MethodBox)
*
* REMAINING IN THIS MODULE:
* - execute_console_method
* - execute_null_method
*/
use super::*;
use crate::boxes::NullBox;
impl NyashInterpreter {
// StringBox methods moved to methods/basic_methods.rs
// IntegerBox methods moved to methods/basic_methods.rs
// ArrayBox methods moved to methods/collection_methods.rs
// FileBox methods moved to methods/io_methods.rs
// ResultBox methods moved to methods/io_methods.rs
// FutureBox methods moved to async_methods.rs
// ChannelBox methods moved to async_methods.rs
// MathBox methods moved to methods/math_methods.rs
/// NullBoxのメソッド呼び出しを実行
pub(super) fn execute_null_method(&mut self, _null_box: &NullBox, method: &str, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 引数を評価
let mut arg_values = Vec::new();
for arg in arguments {
arg_values.push(self.execute_expression(arg)?);
}
// メソッドを実行
match method {
"is_null" => {
if !arg_values.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("is_null() expects 0 arguments, got {}", arg_values.len()),
});
}
Ok(Box::new(BoolBox::new(true)))
}
"is_not_null" => {
if !arg_values.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("is_not_null() expects 0 arguments, got {}", arg_values.len()),
});
}
Ok(Box::new(BoolBox::new(false)))
}
"equals" => {
if arg_values.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("equals() expects 1 argument, got {}", arg_values.len()),
});
}
let other = &arg_values[0];
// NullBoxは他のNullBoxとのみ等しい
let is_equal = other.as_any().downcast_ref::<NullBox>().is_some();
Ok(Box::new(BoolBox::new(is_equal)))
}
"get_or_default" => {
if arg_values.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("get_or_default() expects 1 argument, got {}", arg_values.len()),
});
}
// nullの場合はデフォルト値を返す
Ok(arg_values[0].clone_box())
}
_ => {
Err(RuntimeError::InvalidOperation {
message: format!("Unknown NullBox method: {}", method),
})
}
}
}
// TimeBox methods moved to system_methods.rs
// DateTimeBox methods moved to system_methods.rs
// TimerBox methods moved to system_methods.rs
// MapBox methods moved to methods/collection_methods.rs
// RandomBox methods moved to methods/math_methods.rs
// SoundBox methods moved to special_methods.rs
// DebugBox methods moved to system_methods.rs
🎨 feat: EguiBox GUI開発基盤完成 + パーサー無限ループバグ修正 ## 🚀 主要機能追加 ### EguiBox - GUI開発基盤 - Windows版GUIメモ帳アプリ (simple_notepad.rs, nyash_notepad_jp.rs) - 日本語フォント対応 (NotoSansJP-VariableFont_wght.ttf) - BMPアイコン表示システム (c_drive_icon.bmp) - Windowsエクスプローラー風アプリ (nyash_explorer.rs) - アイコン抽出システム (test_icon_extraction.rs) ### ビジュアルプログラミング準備 - NyashFlow プロジェクト設計完成 (NYASHFLOW_PROJECT_HANDOVER.md) - ビジュアルノードプロトタイプ基盤 - WebAssembly対応準備 ## 🔧 重大バグ修正 ### パーサー無限ループ問題 (3引数メソッド呼び出し) - 原因: メソッドパラメータ解析ループの予約語処理不備 - 修正: src/parser/mod.rs - 非IDENTIFIERトークンのエラーハンドリング追加 - 効果: "from"等の予約語で適切なエラー報告、ハング→瞬時エラー ### MapBoxハング問題調査 - MapBox+3引数メソッド呼び出し組み合わせ問題特定 - バグレポート作成 (MAPBOX_HANG_BUG_REPORT.md) - 事前評価vs必要時評価の設計問題明確化 ## 🧹 コード品質向上 - box_methods.rs を8モジュールに機能分離 - 一時デバッグコード全削除 (eprintln\!, unsafe等) - 構文チェック通過確認済み ## 📝 ドキュメント整備 - CLAUDE.md にGUI開発セクション追加 - Gemini/ChatGPT先生相談ログ保存 (sessions/) - 段階的デバッグ手法確立 ## 🎯 次の目標 - must_advance\!マクロ実装 (無限ループ早期検出) - コマンド引数でデバッグ制御 (--debug-fuel) - MapBox問題の根本修正 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-10 07:54:03 +09:00
/// EguiBoxのメソッド呼び出しを実行非WASM環境のみ
#[cfg(not(target_arch = "wasm32"))]
pub(super) fn execute_egui_method(&mut self, _egui_box: &crate::boxes::EguiBox, method: &str, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 引数を評価
let mut arg_values = Vec::new();
for arg in arguments {
arg_values.push(self.execute_expression(arg)?);
}
// メソッドを実行
match method {
"setTitle" => {
if arg_values.len() != 1 {
return Err(RuntimeError::InvalidOperation {
message: format!("setTitle expects 1 argument, got {}", arg_values.len()),
});
}
// EguiBoxは不変参照なので、新しいインスタンスを返す必要がある
// 実際のGUIアプリではstateを共有するが、今はシンプルに
Ok(Box::new(VoidBox::new()))
}
"setSize" => {
if arg_values.len() != 2 {
return Err(RuntimeError::InvalidOperation {
message: format!("setSize expects 2 arguments, got {}", arg_values.len()),
});
}
Ok(Box::new(VoidBox::new()))
}
"run" => {
if !arg_values.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("run expects 0 arguments, got {}", arg_values.len()),
});
}
// run()は実際のGUIアプリケーションを起動するため、
// ここでは実行できない(メインスレッドブロッキング)
Err(RuntimeError::InvalidOperation {
message: "EguiBox.run() must be called from main thread".to_string(),
})
}
_ => {
Err(RuntimeError::InvalidOperation {
message: format!("Unknown method '{}' for EguiBox", method),
})
}
}
}
/// ConsoleBoxのメソッド呼び出しを実行
pub(super) fn execute_console_method(&mut self, console_box: &crate::boxes::console_box::ConsoleBox, method: &str, arguments: &[ASTNode])
-> Result<Box<dyn NyashBox>, RuntimeError> {
// 引数を評価
let mut arg_values = Vec::new();
for arg in arguments {
arg_values.push(self.execute_expression(arg)?);
}
// メソッドを実行
match method {
"log" => {
if arg_values.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: "console.log() requires at least 1 argument".to_string(),
});
}
// 引数をすべて文字列に変換
let messages: Vec<String> = arg_values.iter()
.map(|arg| arg.to_string_box().value)
.collect();
let combined_message = messages.join(" ");
console_box.log(&combined_message);
Ok(Box::new(VoidBox::new()))
}
"warn" => {
if arg_values.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: "console.warn() requires at least 1 argument".to_string(),
});
}
let messages: Vec<String> = arg_values.iter()
.map(|arg| arg.to_string_box().value)
.collect();
let combined_message = messages.join(" ");
console_box.warn(&combined_message);
Ok(Box::new(VoidBox::new()))
}
"error" => {
if arg_values.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: "console.error() requires at least 1 argument".to_string(),
});
}
let messages: Vec<String> = arg_values.iter()
.map(|arg| arg.to_string_box().value)
.collect();
let combined_message = messages.join(" ");
console_box.error(&combined_message);
Ok(Box::new(VoidBox::new()))
}
"clear" => {
if !arg_values.is_empty() {
return Err(RuntimeError::InvalidOperation {
message: format!("console.clear() expects 0 arguments, got {}", arg_values.len()),
});
}
console_box.clear();
Ok(Box::new(VoidBox::new()))
}
_ => {
Err(RuntimeError::InvalidOperation {
message: format!("Unknown ConsoleBox method: {}", method),
})
}
}
}
// MethodBox methods moved to special_methods.rs
// Web methods moved to web_methods.rs
}