🚀 MAJOR: Multi-Delegation Syntax Implementation Complete!

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-12 08:29:25 +00:00
parent 7aa257872f
commit 6abcf94d6f
7 changed files with 97 additions and 44 deletions

View File

@ -105,7 +105,7 @@ pub enum StructureNode {
constructors: Vec<ASTNode>, constructors: Vec<ASTNode>,
init_fields: Vec<String>, init_fields: Vec<String>,
is_interface: bool, is_interface: bool,
extends: Option<String>, extends: Vec<String>, // 🚀 Multi-delegation: Changed from Option<String> to Vec<String>
implements: Vec<String>, implements: Vec<String>,
/// 🔥 ジェネリクス型パラメータ (例: ["T", "U"]) /// 🔥 ジェネリクス型パラメータ (例: ["T", "U"])
type_parameters: Vec<String>, type_parameters: Vec<String>,
@ -450,7 +450,7 @@ pub enum ASTNode {
constructors: HashMap<String, ASTNode>, // constructor_key -> FunctionDeclaration constructors: HashMap<String, ASTNode>, // constructor_key -> FunctionDeclaration
init_fields: Vec<String>, // initブロック内のフィールド定義 init_fields: Vec<String>, // initブロック内のフィールド定義
is_interface: bool, // interface box かどうか is_interface: bool, // interface box かどうか
extends: Option<String>, // 継承元のBox名 extends: Vec<String>, // 🚀 Multi-delegation: Changed from Option<String> to Vec<String>
implements: Vec<String>, // 実装するinterface名のリスト implements: Vec<String>, // 実装するinterface名のリスト
type_parameters: Vec<String>, // 🔥 ジェネリクス型パラメータ (例: ["T", "U"]) type_parameters: Vec<String>, // 🔥 ジェネリクス型パラメータ (例: ["T", "U"])
/// 🔥 Static boxかどうかのフラグ /// 🔥 Static boxかどうかのフラグ
@ -714,8 +714,8 @@ impl ASTNode {
format!("BoxDeclaration({}, {} fields, {} methods, {} constructors", name, fields.len(), methods.len(), constructors.len()) format!("BoxDeclaration({}, {} fields, {} methods, {} constructors", name, fields.len(), methods.len(), constructors.len())
}; };
if let Some(parent) = extends { if !extends.is_empty() {
desc.push_str(&format!(", extends {}", parent)); desc.push_str(&format!(", extends [{}]", extends.join(", ")));
} }
if !implements.is_empty() { if !implements.is_empty() {
@ -936,7 +936,7 @@ mod tests {
constructors: HashMap::new(), constructors: HashMap::new(),
init_fields: vec![], init_fields: vec![],
is_interface: false, is_interface: false,
extends: None, extends: vec![], // 🚀 Multi-delegation: Changed from None to vec![]
implements: vec![], implements: vec![],
span: Span::unknown(), span: Span::unknown(),
}; };

View File

@ -565,7 +565,7 @@ impl NyashInterpreter {
methods: HashMap<String, ASTNode>, methods: HashMap<String, ASTNode>,
init_fields: Vec<String>, init_fields: Vec<String>,
static_init: Option<Vec<ASTNode>>, static_init: Option<Vec<ASTNode>>,
extends: Option<String>, extends: Vec<String>, // 🚀 Multi-delegation: Changed from Option<String> to Vec<String>
implements: Vec<String>, implements: Vec<String>,
type_parameters: Vec<String> type_parameters: Vec<String>
) -> Result<(), RuntimeError> { ) -> Result<(), RuntimeError> {

View File

@ -745,8 +745,8 @@ impl NyashInterpreter {
name: current_class.clone() name: current_class.clone()
})?; })?;
// extendsまたはimplementsでparentが指定されているか確認 // extendsまたはimplementsでparentが指定されているか確認 (Multi-delegation) 🚀
let is_valid_delegation = current_box_decl.extends.as_ref().map(|s| s.as_str()) == Some(parent) || let is_valid_delegation = current_box_decl.extends.contains(&parent.to_string()) ||
current_box_decl.implements.contains(&parent.to_string()); current_box_decl.implements.contains(&parent.to_string());
if !is_valid_delegation { if !is_valid_delegation {

View File

@ -68,7 +68,7 @@ pub struct BoxDeclaration {
pub constructors: HashMap<String, ASTNode>, pub constructors: HashMap<String, ASTNode>,
pub init_fields: Vec<String>, pub init_fields: Vec<String>,
pub is_interface: bool, pub is_interface: bool,
pub extends: Option<String>, pub extends: Vec<String>, // 🚀 Multi-delegation: Changed from Option<String> to Vec<String>
pub implements: Vec<String>, pub implements: Vec<String>,
pub type_parameters: Vec<String>, // 🔥 ジェネリクス型パラメータ pub type_parameters: Vec<String>, // 🔥 ジェネリクス型パラメータ
} }
@ -81,7 +81,7 @@ pub struct StaticBoxDefinition {
pub methods: HashMap<String, ASTNode>, pub methods: HashMap<String, ASTNode>,
pub init_fields: Vec<String>, pub init_fields: Vec<String>,
pub static_init: Option<Vec<ASTNode>>, // static { } ブロック pub static_init: Option<Vec<ASTNode>>, // static { } ブロック
pub extends: Option<String>, pub extends: Vec<String>, // 🚀 Multi-delegation: Changed from Option<String> to Vec<String>
pub implements: Vec<String>, pub implements: Vec<String>,
pub type_parameters: Vec<String>, pub type_parameters: Vec<String>,
/// 初期化状態 /// 初期化状態

View File

@ -720,7 +720,7 @@ impl NyashInterpreter {
let old_context = self.current_constructor_context.clone(); let old_context = self.current_constructor_context.clone();
self.current_constructor_context = Some(ConstructorContext { self.current_constructor_context = Some(ConstructorContext {
class_name: box_decl.name.clone(), class_name: box_decl.name.clone(),
parent_class: box_decl.extends.clone(), parent_class: box_decl.extends.first().cloned(), // Use first parent for context
}); });
// コンストラクタを実行 // コンストラクタを実行
@ -753,7 +753,7 @@ impl NyashInterpreter {
constructors: HashMap<String, ASTNode>, constructors: HashMap<String, ASTNode>,
init_fields: Vec<String>, init_fields: Vec<String>,
is_interface: bool, is_interface: bool,
extends: Option<String>, extends: Vec<String>, // 🚀 Multi-delegation: Changed from Option<String> to Vec<String>
implements: Vec<String>, implements: Vec<String>,
type_parameters: Vec<String> // 🔥 ジェネリクス型パラメータ追加 type_parameters: Vec<String> // 🔥 ジェネリクス型パラメータ追加
) -> Result<(), RuntimeError> { ) -> Result<(), RuntimeError> {
@ -905,8 +905,8 @@ impl NyashInterpreter {
let mut all_fields = Vec::new(); let mut all_fields = Vec::new();
let mut all_methods = HashMap::new(); let mut all_methods = HashMap::new();
// 親クラスの継承チェーンを再帰的に解決 // 親クラスの継承チェーンを再帰的に解決 (Multi-delegation) 🚀
if let Some(parent_name) = &box_decl.extends { for parent_name in &box_decl.extends {
// 🔥 ビルトインBoxかチェック // 🔥 ビルトインBoxかチェック
let is_builtin = matches!(parent_name.as_str(), let is_builtin = matches!(parent_name.as_str(),
"IntegerBox" | "StringBox" | "BoolBox" | "ArrayBox" | "MapBox" | "IntegerBox" | "StringBox" | "BoolBox" | "ArrayBox" | "MapBox" |

View File

@ -205,14 +205,22 @@ impl NyashParser {
Vec::new() Vec::new()
}; };
// from句のパースデリゲーション) // from句のパースMulti-delegation🚀
let extends = if self.match_token(&TokenType::FROM) { let extends = if self.match_token(&TokenType::FROM) {
self.advance(); // consume 'from' self.advance(); // consume 'from'
let mut parent_list = Vec::new();
loop {
if let TokenType::IDENTIFIER(parent_name) = &self.current_token().token_type { if let TokenType::IDENTIFIER(parent_name) = &self.current_token().token_type {
let parent_name = parent_name.clone(); parent_list.push(parent_name.clone());
self.advance(); self.advance();
Some(parent_name)
if self.match_token(&TokenType::COMMA) {
self.advance(); // consume ','
} else {
break;
}
} else { } else {
let line = self.current_token().line; let line = self.current_token().line;
return Err(ParseError::UnexpectedToken { return Err(ParseError::UnexpectedToken {
@ -221,8 +229,11 @@ impl NyashParser {
line, line,
}); });
} }
}
parent_list
} else { } else {
None Vec::new()
}; };
// interface句のパースインターフェース実装 // interface句のパースインターフェース実装
@ -564,9 +575,12 @@ impl NyashParser {
self.consume(TokenType::RBRACE)?; self.consume(TokenType::RBRACE)?;
// 🔍 デリゲーションメソッドチェック親Boxに存在しないメソッドのoverride検出 // 🔍 デリゲーションメソッドチェック親Boxに存在しないメソッドのoverride検出
if let Some(ref parent_name) = extends { if !extends.is_empty() {
// For multi-delegation, validate against all parents
for parent_name in &extends {
self.validate_override_methods(&name, parent_name, &methods)?; self.validate_override_methods(&name, parent_name, &methods)?;
} }
}
Ok(ASTNode::BoxDeclaration { Ok(ASTNode::BoxDeclaration {
name, name,
@ -672,7 +686,7 @@ impl NyashParser {
constructors: HashMap::new(), // インターフェースにコンストラクタなし constructors: HashMap::new(), // インターフェースにコンストラクタなし
init_fields: vec![], // インターフェースにinitブロックなし init_fields: vec![], // インターフェースにinitブロックなし
is_interface: true, // インターフェースフラグ is_interface: true, // インターフェースフラグ
extends: None, extends: vec![], // 🚀 Multi-delegation: Changed from None to vec![]
implements: vec![], implements: vec![],
type_parameters: Vec::new(), // 🔥 インターフェースではジェネリクス未対応 type_parameters: Vec::new(), // 🔥 インターフェースではジェネリクス未対応
is_static: false, // インターフェースは非static is_static: false, // インターフェースは非static
@ -926,14 +940,22 @@ impl NyashParser {
Vec::new() Vec::new()
}; };
// from句のパースデリゲーション- static boxでもデリゲーション可能 // from句のパースMulti-delegation- static boxでもデリゲーション可能 🚀
let extends = if self.match_token(&TokenType::FROM) { let extends = if self.match_token(&TokenType::FROM) {
self.advance(); // consume 'from' self.advance(); // consume 'from'
let mut parent_list = Vec::new();
loop {
if let TokenType::IDENTIFIER(parent_name) = &self.current_token().token_type { if let TokenType::IDENTIFIER(parent_name) = &self.current_token().token_type {
let parent_name = parent_name.clone(); parent_list.push(parent_name.clone());
self.advance(); self.advance();
Some(parent_name)
if self.match_token(&TokenType::COMMA) {
self.advance(); // consume ','
} else {
break;
}
} else { } else {
let line = self.current_token().line; let line = self.current_token().line;
return Err(ParseError::UnexpectedToken { return Err(ParseError::UnexpectedToken {
@ -942,11 +964,14 @@ impl NyashParser {
line, line,
}); });
} }
}
parent_list
} else { } else {
None Vec::new()
}; };
// interface句のパースインターフェース実装 // interface句のパースインターフェース実装- static boxでもinterface実装可能
let implements = if self.match_token(&TokenType::INTERFACE) { let implements = if self.match_token(&TokenType::INTERFACE) {
self.advance(); // consume 'interface' self.advance(); // consume 'interface'

View File

@ -0,0 +1,28 @@
// Test Multi-Delegation Syntax (Phase 2 Implementation)
// This should test the new `box Child from ParentA, ParentB` syntax
local console = new ConsoleBox()
console.log("=== Testing Multi-Delegation Syntax ===")
// Test 1: Simple multi-delegation syntax parsing
console.log("Testing multi-delegation syntax...")
box MultiChild from StringBox, IntegerBox {
init { textValue, numValue }
pack(text, num) {
me.textValue = text
me.numValue = num
}
getCombined() {
return me.textValue + ": " + me.numValue
}
}
console.log("Multi-delegation box declared successfully!")
// Test if the parser accepted the syntax
local multi = new MultiChild("Count", 123)
console.log("Multi delegation instance: " + multi.getCombined())
console.log("=== Multi-Delegation Test Complete ===")