chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -137,4 +137,4 @@ impl Display for AddBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,4 +76,4 @@ impl CompareBox {
|
||||
let right_str = right.to_string_box();
|
||||
BoolBox::new(left_str.value >= right_str.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,4 +124,4 @@ impl Display for DivideBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,19 +13,19 @@
|
||||
|
||||
// Individual arithmetic operation implementations
|
||||
mod add_box;
|
||||
mod subtract_box;
|
||||
mod multiply_box;
|
||||
mod compare_box;
|
||||
mod divide_box;
|
||||
mod modulo_box;
|
||||
mod compare_box;
|
||||
mod multiply_box;
|
||||
mod subtract_box;
|
||||
|
||||
// Re-export all arithmetic box types
|
||||
pub use add_box::AddBox;
|
||||
pub use subtract_box::SubtractBox;
|
||||
pub use multiply_box::MultiplyBox;
|
||||
pub use compare_box::CompareBox;
|
||||
pub use divide_box::DivideBox;
|
||||
pub use modulo_box::ModuloBox;
|
||||
pub use compare_box::CompareBox;
|
||||
pub use multiply_box::MultiplyBox;
|
||||
pub use subtract_box::SubtractBox;
|
||||
|
||||
// Re-export for convenience - common pattern in arithmetic operations
|
||||
pub use crate::box_trait::{BoolBox, IntegerBox, NyashBox, StringBox};
|
||||
@ -125,4 +125,4 @@ mod tests {
|
||||
assert_eq!(CompareBox::greater(&left, &right).value, false);
|
||||
assert_eq!(CompareBox::equals(&left, &right).value, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,4 +115,4 @@ impl Display for MultiplyBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,4 +116,4 @@ impl Display for SubtractBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,11 +42,11 @@ impl ArrayBox {
|
||||
None => {
|
||||
let strict = std::env::var("HAKO_OOB_STRICT")
|
||||
.ok()
|
||||
.map(|v| matches!(v.as_str(), "1"|"true"|"on"))
|
||||
.map(|v| matches!(v.as_str(), "1" | "true" | "on"))
|
||||
.unwrap_or(false)
|
||||
|| std::env::var("NYASH_OOB_STRICT")
|
||||
.ok()
|
||||
.map(|v| matches!(v.as_str(), "1"|"true"|"on"))
|
||||
.map(|v| matches!(v.as_str(), "1" | "true" | "on"))
|
||||
.unwrap_or(false);
|
||||
if strict {
|
||||
Box::new(StringBox::new("[array/empty/pop] empty array"))
|
||||
@ -92,11 +92,11 @@ impl ArrayBox {
|
||||
None => {
|
||||
let strict = std::env::var("HAKO_OOB_STRICT")
|
||||
.ok()
|
||||
.map(|v| matches!(v.as_str(), "1"|"true"|"on"))
|
||||
.map(|v| matches!(v.as_str(), "1" | "true" | "on"))
|
||||
.unwrap_or(false)
|
||||
|| std::env::var("NYASH_OOB_STRICT")
|
||||
.ok()
|
||||
.map(|v| matches!(v.as_str(), "1"|"true"|"on"))
|
||||
.map(|v| matches!(v.as_str(), "1" | "true" | "on"))
|
||||
.unwrap_or(false);
|
||||
if strict {
|
||||
// Mark OOB occurrence for runner policies (Gate‑C strict fail, etc.)
|
||||
@ -127,11 +127,11 @@ impl ArrayBox {
|
||||
} else {
|
||||
let strict = std::env::var("HAKO_OOB_STRICT")
|
||||
.ok()
|
||||
.map(|v| matches!(v.as_str(), "1"|"true"|"on"))
|
||||
.map(|v| matches!(v.as_str(), "1" | "true" | "on"))
|
||||
.unwrap_or(false)
|
||||
|| std::env::var("NYASH_OOB_STRICT")
|
||||
.ok()
|
||||
.map(|v| matches!(v.as_str(), "1"|"true"|"on"))
|
||||
.map(|v| matches!(v.as_str(), "1" | "true" | "on"))
|
||||
.unwrap_or(false);
|
||||
if strict {
|
||||
crate::runtime::observe::mark_oob();
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! Implements the core BoolBox type for true/false values.
|
||||
|
||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase, StringBox};
|
||||
use crate::box_trait::{BoxBase, BoxCore, NyashBox, StringBox};
|
||||
use std::any::Any;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
@ -83,4 +83,4 @@ impl Display for BoolBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! Implements the ErrorBox type for representing error information.
|
||||
|
||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase, StringBox, BoolBox};
|
||||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox};
|
||||
use std::any::Any;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
@ -79,4 +79,4 @@ impl Display for ErrorBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,4 +9,4 @@
|
||||
)]
|
||||
|
||||
// Re-export the new FileBox implementation for backward compatibility
|
||||
pub use crate::boxes::file::FileBox;
|
||||
pub use crate::boxes::file::FileBox;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! Implements the core IntegerBox type for 64-bit signed integers.
|
||||
|
||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase, StringBox, BoolBox};
|
||||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox};
|
||||
use std::any::Any;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
@ -79,4 +79,4 @@ impl Display for IntegerBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,17 +4,17 @@
|
||||
//! fundamental data types in Nyash: String, Integer, Boolean, Void, File, and Error.
|
||||
|
||||
// Individual basic box implementations
|
||||
mod string_box;
|
||||
mod integer_box;
|
||||
mod bool_box;
|
||||
mod void_box;
|
||||
mod file_box;
|
||||
mod error_box;
|
||||
mod file_box;
|
||||
mod integer_box;
|
||||
mod string_box;
|
||||
mod void_box;
|
||||
|
||||
// Re-export all basic box types
|
||||
pub use string_box::StringBox;
|
||||
pub use integer_box::IntegerBox;
|
||||
pub use bool_box::BoolBox;
|
||||
pub use void_box::VoidBox;
|
||||
pub use error_box::ErrorBox;
|
||||
pub use file_box::FileBox;
|
||||
pub use error_box::ErrorBox;
|
||||
pub use integer_box::IntegerBox;
|
||||
pub use string_box::StringBox;
|
||||
pub use void_box::VoidBox;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! Implements the core StringBox type with all string manipulation methods.
|
||||
|
||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase};
|
||||
use crate::box_trait::{BoxBase, BoxCore, NyashBox};
|
||||
use crate::boxes::ArrayBox;
|
||||
use std::any::Any;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! Implements the core VoidBox type representing empty or null results.
|
||||
|
||||
use crate::box_trait::{NyashBox, BoxCore, BoxBase, StringBox, BoolBox};
|
||||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox};
|
||||
use std::any::Any;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
@ -75,4 +75,4 @@ impl Display for VoidBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,9 +99,9 @@
|
||||
* - call stackは直近100件まで自動保持
|
||||
*/
|
||||
|
||||
use crate::box_factory::RuntimeError;
|
||||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox, VoidBox};
|
||||
use crate::instance_v2::InstanceBox;
|
||||
use crate::box_factory::RuntimeError;
|
||||
use chrono::Local;
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -33,8 +33,8 @@
|
||||
* - `run()`はブロッキング動作(アプリ終了まで制御を返さない)
|
||||
*/
|
||||
|
||||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox};
|
||||
use crate::box_factory::RuntimeError;
|
||||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox};
|
||||
use eframe::{self, egui, epaint::Vec2};
|
||||
use std::any::Any;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
//! Thin FileBox shim that delegates to a selected provider.
|
||||
//! Not wired into the registry yet (safe placeholder).
|
||||
|
||||
use super::provider::{FileCaps, FileIo, FileResult};
|
||||
use std::sync::Arc;
|
||||
use super::provider::{FileIo, FileCaps, FileResult};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct FileBoxShim {
|
||||
@ -16,9 +16,16 @@ impl FileBoxShim {
|
||||
let caps = provider.caps();
|
||||
Self { provider, caps }
|
||||
}
|
||||
pub fn open(&self, path: &str) -> FileResult<()> { self.provider.open(path) }
|
||||
pub fn read(&self) -> FileResult<String> { self.provider.read() }
|
||||
pub fn close(&self) -> FileResult<()> { self.provider.close() }
|
||||
pub fn caps(&self) -> FileCaps { self.caps }
|
||||
pub fn open(&self, path: &str) -> FileResult<()> {
|
||||
self.provider.open(path)
|
||||
}
|
||||
pub fn read(&self) -> FileResult<String> {
|
||||
self.provider.read()
|
||||
}
|
||||
pub fn close(&self) -> FileResult<()> {
|
||||
self.provider.close()
|
||||
}
|
||||
pub fn caps(&self) -> FileCaps {
|
||||
self.caps
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,10 +3,12 @@
|
||||
//! Provides ProviderFactory implementation for the builtin FileBox (core-ro).
|
||||
//! This is auto-registered when feature "builtin-filebox" is enabled.
|
||||
|
||||
use std::sync::Arc;
|
||||
use crate::boxes::file::provider::FileIo;
|
||||
use crate::boxes::file::core_ro::CoreRoFileIo;
|
||||
use crate::runner::modes::common_util::provider_registry::{ProviderFactory, register_provider_factory};
|
||||
use crate::boxes::file::provider::FileIo;
|
||||
use crate::runner::modes::common_util::provider_registry::{
|
||||
register_provider_factory, ProviderFactory,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Builtin FileBox factory (static registration)
|
||||
pub struct BuiltinFileBoxFactory;
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
// 参考: 既存Boxの設計思想
|
||||
|
||||
// SSOT provider design (ring‑0/1) — modules are currently placeholders
|
||||
pub mod provider; // trait FileIo / FileCaps / FileError
|
||||
pub mod core_ro; // Core read‑only provider
|
||||
pub mod box_shim; // Thin delegating shim
|
||||
pub mod builtin_factory; // Builtin FileBox ProviderFactory
|
||||
pub mod box_shim; // Thin delegating shim
|
||||
pub mod builtin_factory;
|
||||
pub mod core_ro; // Core read‑only provider
|
||||
pub mod provider; // trait FileIo / FileCaps / FileError // Builtin FileBox ProviderFactory
|
||||
|
||||
use crate::box_trait::{BoolBox, BoxBase, BoxCore, NyashBox, StringBox};
|
||||
use crate::runtime::provider_lock;
|
||||
@ -64,7 +64,8 @@ impl FileBox {
|
||||
.ok_or("FileBox provider not initialized")?
|
||||
.clone();
|
||||
|
||||
provider.open(path)
|
||||
provider
|
||||
.open(path)
|
||||
.map_err(|e| format!("Failed to open: {}", e))?;
|
||||
|
||||
Ok(FileBox {
|
||||
@ -76,8 +77,7 @@ impl FileBox {
|
||||
|
||||
pub fn read_to_string(&self) -> Result<String, String> {
|
||||
if let Some(ref provider) = self.provider {
|
||||
provider.read()
|
||||
.map_err(|e| format!("Read failed: {}", e))
|
||||
provider.read().map_err(|e| format!("Read failed: {}", e))
|
||||
} else {
|
||||
Err("No provider available".to_string())
|
||||
}
|
||||
@ -85,7 +85,8 @@ impl FileBox {
|
||||
|
||||
pub fn write_all(&self, _buf: &[u8]) -> Result<(), String> {
|
||||
// Fail-Fast by capability: consult provider caps
|
||||
let caps = self.provider
|
||||
let caps = self
|
||||
.provider
|
||||
.as_ref()
|
||||
.map(|p| p.caps())
|
||||
.or_else(|| provider_lock::get_filebox_caps())
|
||||
@ -107,15 +108,20 @@ impl FileBox {
|
||||
|
||||
/// ファイルに内容を書き込む
|
||||
pub fn write(&self, _content: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
let caps = self.provider
|
||||
let caps = self
|
||||
.provider
|
||||
.as_ref()
|
||||
.map(|p| p.caps())
|
||||
.or_else(|| provider_lock::get_filebox_caps())
|
||||
.unwrap_or_else(|| provider::FileCaps::read_only());
|
||||
if !caps.write {
|
||||
return Box::new(StringBox::new("Error: write unsupported by provider (read-only)"));
|
||||
return Box::new(StringBox::new(
|
||||
"Error: write unsupported by provider (read-only)",
|
||||
));
|
||||
}
|
||||
Box::new(StringBox::new("Error: write supported but not implemented in this build"))
|
||||
Box::new(StringBox::new(
|
||||
"Error: write supported but not implemented in this build",
|
||||
))
|
||||
}
|
||||
|
||||
/// ファイルが存在するかチェック
|
||||
@ -126,28 +132,38 @@ impl FileBox {
|
||||
|
||||
/// ファイルを削除
|
||||
pub fn delete(&self) -> Box<dyn NyashBox> {
|
||||
let caps = self.provider
|
||||
let caps = self
|
||||
.provider
|
||||
.as_ref()
|
||||
.map(|p| p.caps())
|
||||
.or_else(|| provider_lock::get_filebox_caps())
|
||||
.unwrap_or_else(|| provider::FileCaps::read_only());
|
||||
if !caps.write {
|
||||
return Box::new(StringBox::new("Error: delete unsupported by provider (read-only)"));
|
||||
return Box::new(StringBox::new(
|
||||
"Error: delete unsupported by provider (read-only)",
|
||||
));
|
||||
}
|
||||
Box::new(StringBox::new("Error: delete supported but not implemented in this build"))
|
||||
Box::new(StringBox::new(
|
||||
"Error: delete supported but not implemented in this build",
|
||||
))
|
||||
}
|
||||
|
||||
/// ファイルをコピー
|
||||
pub fn copy(&self, _dest: &str) -> Box<dyn NyashBox> {
|
||||
let caps = self.provider
|
||||
let caps = self
|
||||
.provider
|
||||
.as_ref()
|
||||
.map(|p| p.caps())
|
||||
.or_else(|| provider_lock::get_filebox_caps())
|
||||
.unwrap_or_else(|| provider::FileCaps::read_only());
|
||||
if !caps.write {
|
||||
return Box::new(StringBox::new("Error: copy unsupported by provider (read-only)"));
|
||||
return Box::new(StringBox::new(
|
||||
"Error: copy unsupported by provider (read-only)",
|
||||
));
|
||||
}
|
||||
Box::new(StringBox::new("Error: copy supported but not implemented in this build"))
|
||||
Box::new(StringBox::new(
|
||||
"Error: copy supported but not implemented in this build",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,12 @@ pub struct FileCaps {
|
||||
}
|
||||
|
||||
impl FileCaps {
|
||||
pub const fn read_only() -> Self { Self { read: true, write: false } }
|
||||
pub const fn read_only() -> Self {
|
||||
Self {
|
||||
read: true,
|
||||
write: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Unified error type (thin placeholder for now)
|
||||
@ -40,9 +45,10 @@ pub trait FileIo: Send + Sync {
|
||||
pub fn normalize_newlines(s: &str) -> String {
|
||||
let mut out = String::with_capacity(s.len());
|
||||
for b in s.as_bytes() {
|
||||
if *b == b'\r' { continue; }
|
||||
if *b == b'\r' {
|
||||
continue;
|
||||
}
|
||||
out.push(*b as char);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
|
||||
@ -279,7 +279,11 @@ impl HTTPResponseBox {
|
||||
}
|
||||
|
||||
/// ステータスコード・メッセージ設定
|
||||
pub fn set_status(&self, code: Box<dyn NyashBox>, message: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
pub fn set_status(
|
||||
&self,
|
||||
code: Box<dyn NyashBox>,
|
||||
message: Box<dyn NyashBox>,
|
||||
) -> Box<dyn NyashBox> {
|
||||
let code_val = code.to_string_box().value.parse::<i32>().unwrap_or(200);
|
||||
let message_val = message.to_string_box().value;
|
||||
*self.status_code.lock().unwrap() = code_val;
|
||||
@ -288,7 +292,11 @@ impl HTTPResponseBox {
|
||||
}
|
||||
|
||||
/// ヘッダー設定
|
||||
pub fn set_header(&self, name: Box<dyn NyashBox>, value: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
pub fn set_header(
|
||||
&self,
|
||||
name: Box<dyn NyashBox>,
|
||||
value: Box<dyn NyashBox>,
|
||||
) -> Box<dyn NyashBox> {
|
||||
let name_str = name.to_string_box().value;
|
||||
let value_str = value.to_string_box().value;
|
||||
self.headers.lock().unwrap().insert(name_str, value_str);
|
||||
@ -326,7 +334,10 @@ impl HTTPResponseBox {
|
||||
let version = self.http_version.lock().unwrap().clone();
|
||||
let status_code = *self.status_code.lock().unwrap();
|
||||
let status_message = self.status_message.lock().unwrap().clone();
|
||||
response.push_str(&format!("{} {} {}\r\n", version, status_code, status_message));
|
||||
response.push_str(&format!(
|
||||
"{} {} {}\r\n",
|
||||
version, status_code, status_message
|
||||
));
|
||||
|
||||
// Headers
|
||||
for (name, value) in self.headers.lock().unwrap().iter() {
|
||||
@ -335,7 +346,8 @@ impl HTTPResponseBox {
|
||||
|
||||
// Content-Length if not already set
|
||||
let body_len = { self.body.lock().unwrap().len() };
|
||||
let need_len = { !self.headers.lock().unwrap().contains_key("content-length") && body_len > 0 };
|
||||
let need_len =
|
||||
{ !self.headers.lock().unwrap().contains_key("content-length") && body_len > 0 };
|
||||
if need_len {
|
||||
response.push_str(&format!("Content-Length: {}\r\n", body_len));
|
||||
}
|
||||
@ -367,10 +379,11 @@ impl HTTPResponseBox {
|
||||
let response = HTTPResponseBox::new();
|
||||
*response.status_code.lock().unwrap() = 200;
|
||||
*response.status_message.lock().unwrap() = "OK".to_string();
|
||||
response.headers.lock().unwrap().insert(
|
||||
"Content-Type".to_string(),
|
||||
"application/json".to_string(),
|
||||
);
|
||||
response
|
||||
.headers
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert("Content-Type".to_string(), "application/json".to_string());
|
||||
*response.body.lock().unwrap() = content.to_string_box().value;
|
||||
response
|
||||
}
|
||||
@ -384,7 +397,8 @@ impl HTTPResponseBox {
|
||||
"Content-Type".to_string(),
|
||||
"text/html; charset=utf-8".to_string(),
|
||||
);
|
||||
*response.body.lock().unwrap() = "<html><body><h1>404 - Not Found</h1></body></html>".to_string();
|
||||
*response.body.lock().unwrap() =
|
||||
"<html><body><h1>404 - Not Found</h1></body></html>".to_string();
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,7 +161,10 @@ impl MapBox {
|
||||
}
|
||||
value.clone_box()
|
||||
}
|
||||
None => Box::new(StringBox::new(&format!("[map/missing] Key not found: {}", key_str))),
|
||||
None => Box::new(StringBox::new(&format!(
|
||||
"[map/missing] Key not found: {}",
|
||||
key_str
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +205,10 @@ impl MapBox {
|
||||
.unwrap()
|
||||
.values()
|
||||
.map(|v| {
|
||||
if v.as_any().downcast_ref::<crate::instance_v2::InstanceBox>().is_some() {
|
||||
if v.as_any()
|
||||
.downcast_ref::<crate::instance_v2::InstanceBox>()
|
||||
.is_some()
|
||||
{
|
||||
v.share_box()
|
||||
} else {
|
||||
v.clone_box()
|
||||
|
||||
@ -16,28 +16,48 @@ pub struct MissingBox {
|
||||
|
||||
impl MissingBox {
|
||||
pub fn new() -> Self {
|
||||
Self { base: BoxBase::new() }
|
||||
Self {
|
||||
base: BoxBase::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_missing(&self) -> bool { true }
|
||||
pub fn is_missing(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl BoxCore for MissingBox {
|
||||
fn box_id(&self) -> u64 { self.base.id }
|
||||
fn parent_type_id(&self) -> Option<std::any::TypeId> { self.base.parent_type_id }
|
||||
fn box_id(&self) -> u64 {
|
||||
self.base.id
|
||||
}
|
||||
fn parent_type_id(&self) -> Option<std::any::TypeId> {
|
||||
self.base.parent_type_id
|
||||
}
|
||||
fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
// 開発時の可視性向上のための文字列表現。prod では基本的に表面化させない想定。
|
||||
write!(f, "(missing)")
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any { self }
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any { self }
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl NyashBox for MissingBox {
|
||||
fn type_name(&self) -> &'static str { "MissingBox" }
|
||||
fn to_string_box(&self) -> StringBox { StringBox::new("(missing)") }
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> { Box::new(self.clone()) }
|
||||
fn share_box(&self) -> Box<dyn NyashBox> { self.clone_box() }
|
||||
fn type_name(&self) -> &'static str {
|
||||
"MissingBox"
|
||||
}
|
||||
fn to_string_box(&self) -> StringBox {
|
||||
StringBox::new("(missing)")
|
||||
}
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
fn share_box(&self) -> Box<dyn NyashBox> {
|
||||
self.clone_box()
|
||||
}
|
||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||
// 欠損どうしは論理同値とみなすが、通常の等価比較は境界で禁止される想定。
|
||||
BoolBox::new(other.as_any().downcast_ref::<MissingBox>().is_some())
|
||||
@ -45,6 +65,7 @@ impl NyashBox for MissingBox {
|
||||
}
|
||||
|
||||
impl Display for MissingBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.fmt_box(f) }
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -145,8 +145,8 @@ pub use egui_box::EguiBox;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub use web::{WebCanvasBox, WebConsoleBox, WebDisplayBox};
|
||||
|
||||
pub mod null_box;
|
||||
pub mod missing_box;
|
||||
pub mod null_box;
|
||||
|
||||
// High-priority Box types
|
||||
pub mod array;
|
||||
@ -168,8 +168,8 @@ pub mod intent_box;
|
||||
pub mod p2p_box;
|
||||
|
||||
// null関数も再エクスポート
|
||||
pub use null_box::{null, NullBox};
|
||||
pub use missing_box::MissingBox;
|
||||
pub use null_box::{null, NullBox};
|
||||
|
||||
// High-priority Box types re-export
|
||||
pub use array::ArrayBox;
|
||||
|
||||
Reference in New Issue
Block a user