Fix ModuloBox E0046 error and add null literal support

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-15 07:29:52 +00:00
parent 426571db5e
commit aae81ec4d5
9 changed files with 205 additions and 1 deletions

View File

@ -166,7 +166,7 @@ static box Main {
me.console = new ConsoleBox()
me.console.log("🚀 Starting Tinyproxy Nyash - Phase 10.1")
local result = statics.ProxyServer.main()
local result = ProxyServer.main()
me.console.log("🏁 Proxy result: " + result)
return "Phase 10.1 Complete"

View File

@ -250,6 +250,7 @@ pub enum LiteralValue {
Integer(i64),
Float(f64), // 浮動小数点数サポート追加
Bool(bool),
Null, // null値
Void,
}
@ -264,6 +265,7 @@ impl LiteralValue {
LiteralValue::Integer(i) => Box::new(IntegerBox::new(*i)),
LiteralValue::Float(f) => Box::new(FloatBox::new(*f)),
LiteralValue::Bool(b) => Box::new(BoolBox::new(*b)),
LiteralValue::Null => Box::new(crate::boxes::null_box::NullBox::new()),
LiteralValue::Void => Box::new(VoidBox::new()),
}
}
@ -283,6 +285,8 @@ impl LiteralValue {
Some(LiteralValue::Float(float_box.value))
} else if let Some(bool_box) = box_val.as_any().downcast_ref::<BoolBox>() {
Some(LiteralValue::Bool(bool_box.value))
} else if box_val.as_any().downcast_ref::<crate::boxes::null_box::NullBox>().is_some() {
Some(LiteralValue::Null)
} else if box_val.as_any().downcast_ref::<VoidBox>().is_some() {
Some(LiteralValue::Void)
} else {
@ -298,6 +302,7 @@ impl fmt::Display for LiteralValue {
LiteralValue::Integer(i) => write!(f, "{}", i),
LiteralValue::Float(fl) => write!(f, "{}", fl),
LiteralValue::Bool(b) => write!(f, "{}", b),
LiteralValue::Null => write!(f, "null"),
LiteralValue::Void => write!(f, "void"),
}
}

View File

@ -513,6 +513,14 @@ impl BoxCore for ModuloBox {
fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "ModuloBox[{}]", self.box_id())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
impl NyashBox for ModuloBox {

View File

@ -357,6 +357,14 @@ impl NyashParser {
})
}
TokenType::NULL => {
self.advance();
Ok(ASTNode::Literal {
value: LiteralValue::Null,
span: Span::unknown(),
})
}
TokenType::THIS => {
self.advance();
Ok(ASTNode::This { span: Span::unknown() })

View File

@ -16,6 +16,7 @@ pub enum TokenType {
FLOAT(f64), // 浮動小数点数サポート追加
TRUE,
FALSE,
NULL, // null リテラル
// キーワード
BOX,
@ -417,6 +418,7 @@ impl NyashTokenizer {
"or" => TokenType::OR,
"true" => TokenType::TRUE,
"false" => TokenType::FALSE,
"null" => TokenType::NULL,
_ => TokenType::IDENTIFIER(identifier),
}
}

View File

@ -0,0 +1,43 @@
// Test for ArrayBox.length() functionality
static box ArrayLengthTest {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("🧪 Testing ArrayBox.length() functionality")
// Test 1: Empty array
local empty_array = new ArrayBox()
local empty_length = empty_array.length()
me.console.log("Empty array length: " + empty_length) // Expected: 0
// Test 2: Array with elements
local test_array = new ArrayBox()
test_array.push("first")
test_array.push("second")
test_array.push("third")
local length_after_push = test_array.length()
me.console.log("Array length after 3 pushes: " + length_after_push) // Expected: 3
// Test 3: Array after pop
local popped = test_array.pop()
me.console.log("Popped element: " + popped)
local length_after_pop = test_array.length()
me.console.log("Array length after pop: " + length_after_pop) // Expected: 2
// Test 4: Verify elements are still accessible
local first_element = test_array.get(0)
local second_element = test_array.get(1)
me.console.log("Element at index 0: " + first_element)
me.console.log("Element at index 1: " + second_element)
// Test 5: Edge case - accessing beyond length
local beyond_length = test_array.get(5)
me.console.log("Element beyond length: " + beyond_length) // Expected: null
me.console.log("✅ ArrayBox.length() tests completed")
return "ArrayBox functionality verified"
}
}

View File

@ -0,0 +1,31 @@
// Test % operator functionality after ModuloBox fix
static box ModuloTest {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("🧪 Testing % operator after ModuloBox fix")
// Test 1: Basic modulo operation
local result1 = 10 % 3
me.console.log("10 % 3 = " + result1) // Expected: 1
// Test 2: Chip-8 style operations
local result2 = 4096 % 4096
me.console.log("4096 % 4096 = " + result2) // Expected: 0
local result3 = 256 % 16
me.console.log("256 % 16 = " + result3) // Expected: 0
// Test 3: Common modulo patterns
local result4 = 17 % 5
me.console.log("17 % 5 = " + result4) // Expected: 2
// Test 4: Zero check (should not crash)
local result5 = 42 % 1
me.console.log("42 % 1 = " + result5) // Expected: 0
me.console.log("✅ Modulo operator tests completed")
return "ModuloBox fix verified"
}
}

View File

@ -0,0 +1,36 @@
// Test null literal support
static box NullLiteralTest {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("🧪 Testing null literal support")
// Test 1: Basic null assignment
local null_value = null
me.console.log("Null value: " + null_value)
// Test 2: Null comparison
if null_value == null {
me.console.log("✅ Null comparison works")
} else {
me.console.log("❌ Null comparison failed")
}
// Test 3: Null vs non-null
local non_null = "not null"
if non_null != null {
me.console.log("✅ Non-null comparison works")
} else {
me.console.log("❌ Non-null comparison failed")
}
// Test 4: Null in conditions
if null_value == null {
me.console.log("✅ Null condition evaluation works")
}
me.console.log("✅ Null literal tests completed")
return "Null literal support verified"
}
}

View File

@ -0,0 +1,71 @@
// Test for proper static box usage patterns
static box StaticBoxTest {
init { console, test_result }
main() {
me.console = new ConsoleBox()
me.console.log("🧪 Testing proper static box patterns")
// ✅ Correct: Call static method directly
local result = StaticBoxTest.test_static_method()
me.console.log("Static method result: " + result)
// ✅ Correct: Access static box fields through me
me.test_result = "Static box initialization successful"
me.console.log("Static field access: " + me.test_result)
me.console.log("✅ Static box pattern tests completed")
return "Static box usage verified"
}
test_static_method() {
return "Static method executed successfully"
}
}
// Test proxy server pattern (simplified)
static box SimpleProxyTest {
init { console, port, running }
main() {
me.console = new ConsoleBox()
me.console.log("🌐 Testing simplified proxy server pattern")
// ✅ Correct: Initialize static box fields
me.port = 8080
me.running = true
me.console.log("Proxy configured on port: " + me.port)
me.console.log("Proxy running status: " + me.running)
// ✅ Correct: Call other static methods
local startup_result = SimpleProxyTest.simulate_startup()
me.console.log("Startup result: " + startup_result)
return "Proxy simulation complete"
}
simulate_startup() {
return "Proxy server simulation started successfully"
}
}
// Entry point
static box Main {
init { console }
main() {
me.console = new ConsoleBox()
me.console.log("🚀 Testing Static Box Patterns")
// Test both static box patterns
local test1_result = StaticBoxTest.main()
me.console.log("Test 1: " + test1_result)
local test2_result = SimpleProxyTest.main()
me.console.log("Test 2: " + test2_result)
me.console.log("✅ All static box pattern tests passed")
return "Static box tests complete"
}
}