🚀 MAJOR: Multi-Delegation Syntax Implementation Complete!
Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
10
src/ast.rs
10
src/ast.rs
@ -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(),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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>,
|
||||||
/// 初期化状態
|
/// 初期化状態
|
||||||
|
|||||||
@ -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" |
|
||||||
|
|||||||
@ -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'
|
||||||
|
|
||||||
|
|||||||
28
test_multi_delegation.nyash
Normal file
28
test_multi_delegation.nyash
Normal 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 ===")
|
||||||
Reference in New Issue
Block a user