Implement Phase 0: Stabilize CLI build with feature separation

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-13 05:06:43 +00:00
parent f6bd6ef39b
commit 079a095f5c
9 changed files with 144 additions and 32 deletions

View File

@ -9,50 +9,110 @@ repository = "https://github.com/user/nyash"
keywords = ["language", "interpreter", "box", "memory-safe", "rust"]
categories = ["development-tools::parsing", "interpreters"]
# Default features - minimal CLI only
[features]
default = ["cli"]
cli = []
gui = ["dep:egui", "dep:eframe", "dep:egui_extras", "dep:image"]
gui-examples = ["gui"]
all-examples = ["gui-examples"]
[lib]
name = "nyash_rust"
path = "src/lib.rs"
crate-type = ["cdylib", "rlib"]
# Main CLI binary - always available
[[bin]]
name = "nyash"
path = "src/main.rs"
# GUI examples - only built with gui-examples feature
[[bin]]
name = "simple_notepad"
path = "examples/simple_notepad.rs"
required-features = ["gui-examples"]
[[bin]]
name = "nyash_notepad"
path = "examples/simple_notepad_v2.rs"
required-features = ["gui-examples"]
[[bin]]
name = "nyash_notepad_ascii"
path = "examples/simple_notepad_ascii.rs"
required-features = ["gui-examples"]
[[bin]]
name = "debug_notepad"
path = "examples/debug_notepad.rs"
required-features = ["gui-examples"]
[[bin]]
name = "nyash_notepad_jp"
path = "examples/nyash_notepad_jp.rs"
required-features = ["gui-examples"]
[[bin]]
name = "nyash_explorer"
path = "examples/nyash_explorer.rs"
required-features = ["gui-examples"]
[[bin]]
name = "nyash_explorer_icons"
path = "examples/nyash_explorer_with_icons.rs"
[[example]]
name = "visual_node_prototype"
path = "development/egui_research/experiments/visual_node_prototype.rs"
required-features = ["gui-examples"]
[[bin]]
name = "test_icon_extraction"
path = "examples/test_icon_extraction.rs"
required-features = ["gui-examples"]
# Examples for development - only available as examples, not bins
[[example]]
name = "gui_simple_notepad"
path = "examples/simple_notepad.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_simple_notepad_v2"
path = "examples/simple_notepad_v2.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_simple_notepad_ascii"
path = "examples/simple_notepad_ascii.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_debug_notepad"
path = "examples/debug_notepad.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_nyash_notepad_jp"
path = "examples/nyash_notepad_jp.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_nyash_explorer"
path = "examples/nyash_explorer.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_nyash_explorer_with_icons"
path = "examples/nyash_explorer_with_icons.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_test_icon_extraction"
path = "examples/test_icon_extraction.rs"
required-features = ["gui-examples"]
[[example]]
name = "gui_visual_node_prototype"
path = "development/egui_research/experiments/visual_node_prototype.rs"
required-features = ["gui-examples"]
@ -90,11 +150,11 @@ wasm-bindgen = "0.2"
console_error_panic_hook = "0.1"
js-sys = "0.3"
# GUI フレームワーク
egui = "0.29"
eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"] }
egui_extras = { version = "0.29", features = ["image"] }
image = { version = "0.25", features = ["png", "ico"] }
# GUI フレームワーク - only when gui feature is enabled
egui = { version = "0.29", optional = true }
eframe = { version = "0.29", default-features = false, features = ["default_fonts", "glow"], optional = true }
egui_extras = { version = "0.29", features = ["image"], optional = true }
image = { version = "0.25", features = ["png", "ico"], optional = true }
# Windows API
[target.'cfg(windows)'.dependencies]

View File

@ -0,0 +1,13 @@
// Basic arithmetic test
local a, b, c, d, flag
a = 10
b = 20
c = a + b
print("10 + 20 = " + c)
d = c * 2
print("30 * 2 = " + d)
// Boolean test
flag = true
print("Flag is: " + flag)

View File

@ -0,0 +1,12 @@
// Simple Hello World test
print("Hello, Nyash!")
local greeting
greeting = new StringBox("Welcome to Nyash!")
print(greeting.toString())
local numbers
numbers = new IntegerBox(42)
local result
result = numbers + 8
print("42 + 8 = " + result)

View File

@ -0,0 +1,15 @@
// Static box Main pattern - current working syntax
static box Main {
init { console, result }
main() {
me.console = new ConsoleBox()
me.console.log("Hello from Static Main!")
local temp
temp = 42
me.result = temp
return "Main completed!"
}
}

View File

@ -1,3 +1,5 @@
#![cfg(feature = "gui")]
/*! 🖼️ EguiBox - デスクトップGUIアプリBox
* Everything is Box哲学によるGUIフレームワーク統合
* 「なんでもBoxにできる」化け物言語の第一歩

View File

@ -74,7 +74,7 @@ pub mod console_box;
pub mod web;
// GUI Box条件付きコンパイル
#[cfg(not(target_arch = "wasm32"))]
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
pub mod egui_box;
// 共通で使う型とトレイトを再エクスポート
@ -95,7 +95,7 @@ pub use map_box::MapBox;
pub use console_box::ConsoleBox;
// EguiBoxの再エクスポート非WASM環境のみ
#[cfg(not(target_arch = "wasm32"))]
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
pub use egui_box::EguiBox;
// Web Box群の再エクスポートWASM環境のみ

View File

@ -144,7 +144,7 @@ impl NyashInterpreter {
// DebugBox methods moved to system_methods.rs
/// EguiBoxのメソッド呼び出しを実行非WASM環境のみ
#[cfg(not(target_arch = "wasm32"))]
#[cfg(all(feature = "gui", 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> {
// 引数を評価

View File

@ -459,7 +459,7 @@ impl NyashInterpreter {
// }
// EguiBox method calls (非WASM環境のみ)
#[cfg(not(target_arch = "wasm32"))]
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
if let Some(egui_box) = obj_value.as_any().downcast_ref::<crate::boxes::EguiBox>() {
return self.execute_egui_method(egui_box, method, arguments);
}
@ -849,14 +849,19 @@ impl NyashInterpreter {
}
// 🔥 ビルトインBoxかチェック
let is_builtin = matches!(parent,
"IntegerBox" | "StringBox" | "BoolBox" | "ArrayBox" | "MapBox" |
"FileBox" | "ResultBox" | "FutureBox" | "ChannelBox" | "MathBox" |
"TimeBox" | "DateTimeBox" | "TimerBox" | "RandomBox" | "SoundBox" |
"DebugBox" | "MethodBox" | "NullBox" | "ConsoleBox" | "FloatBox" |
"BufferBox" | "RegexBox" | "JSONBox" | "StreamBox" | "HTTPClientBox" |
"IntentBox" | "P2PBox" | "EguiBox"
);
let mut builtin_boxes = vec![
"IntegerBox", "StringBox", "BoolBox", "ArrayBox", "MapBox",
"FileBox", "ResultBox", "FutureBox", "ChannelBox", "MathBox",
"TimeBox", "DateTimeBox", "TimerBox", "RandomBox", "SoundBox",
"DebugBox", "MethodBox", "NullBox", "ConsoleBox", "FloatBox",
"BufferBox", "RegexBox", "JSONBox", "StreamBox", "HTTPClientBox",
"IntentBox", "P2PBox"
];
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
builtin_boxes.push("EguiBox");
let is_builtin = builtin_boxes.contains(&parent);
if is_builtin {
// ビルトインBoxの場合、ロックを解放してからメソッド呼び出し

View File

@ -214,7 +214,7 @@ impl NyashInterpreter {
// let p2p_box = Box::new(crate::boxes::P2PBox::new(node_id, intent_box)) as Box<dyn NyashBox>;
// return Ok(p2p_box);
// }
#[cfg(not(target_arch = "wasm32"))]
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
"EguiBox" => {
// EguiBoxは引数なしで作成GUIアプリケーション用
if !arguments.is_empty() {
@ -860,9 +860,9 @@ impl NyashInterpreter {
let is_web_box = false;
// GUI専用Box非WASM環境のみ
#[cfg(not(target_arch = "wasm32"))]
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
let is_gui_box = matches!(type_name, "EguiBox");
#[cfg(target_arch = "wasm32")]
#[cfg(not(all(feature = "gui", not(target_arch = "wasm32"))))]
let is_gui_box = false;
is_builtin || is_web_box || is_gui_box ||
@ -916,14 +916,19 @@ impl NyashInterpreter {
// 親クラスの継承チェーンを再帰的に解決 (Multi-delegation) 🚀
for parent_name in &box_decl.extends {
// 🔥 ビルトインBoxかチェック
let is_builtin = matches!(parent_name.as_str(),
"IntegerBox" | "StringBox" | "BoolBox" | "ArrayBox" | "MapBox" |
"FileBox" | "ResultBox" | "FutureBox" | "ChannelBox" | "MathBox" |
"TimeBox" | "DateTimeBox" | "TimerBox" | "RandomBox" | "SoundBox" |
"DebugBox" | "MethodBox" | "NullBox" | "ConsoleBox" | "FloatBox" |
"BufferBox" | "RegexBox" | "JSONBox" | "StreamBox" | "HTTPClientBox" |
"IntentBox" | "P2PBox" | "EguiBox"
);
let mut builtin_boxes = vec![
"IntegerBox", "StringBox", "BoolBox", "ArrayBox", "MapBox",
"FileBox", "ResultBox", "FutureBox", "ChannelBox", "MathBox",
"TimeBox", "DateTimeBox", "TimerBox", "RandomBox", "SoundBox",
"DebugBox", "MethodBox", "NullBox", "ConsoleBox", "FloatBox",
"BufferBox", "RegexBox", "JSONBox", "StreamBox", "HTTPClientBox",
"IntentBox", "P2PBox"
];
#[cfg(all(feature = "gui", not(target_arch = "wasm32")))]
builtin_boxes.push("EguiBox");
let is_builtin = builtin_boxes.contains(&parent_name.as_str());
if is_builtin {
// ビルトインBoxの場合、フィールドやメソッドは継承しない