diff --git a/apps/tinyproxy_nyash/proxy_server.nyash b/apps/tinyproxy_nyash/proxy_server.nyash index d52429ce..8bfa522f 100644 --- a/apps/tinyproxy_nyash/proxy_server.nyash +++ b/apps/tinyproxy_nyash/proxy_server.nyash @@ -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" diff --git a/src/ast.rs b/src/ast.rs index a597db1c..d2a40d54 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -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::() { Some(LiteralValue::Bool(bool_box.value)) + } else if box_val.as_any().downcast_ref::().is_some() { + Some(LiteralValue::Null) } else if box_val.as_any().downcast_ref::().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"), } } diff --git a/src/box_arithmetic.rs b/src/box_arithmetic.rs index 009f3709..bfafc2ec 100644 --- a/src/box_arithmetic.rs +++ b/src/box_arithmetic.rs @@ -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 { diff --git a/src/parser/expressions.rs b/src/parser/expressions.rs index b834083d..091dce6d 100644 --- a/src/parser/expressions.rs +++ b/src/parser/expressions.rs @@ -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() }) diff --git a/src/tokenizer.rs b/src/tokenizer.rs index aa8e04a9..06b96100 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -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), } } diff --git a/test_array_length_fix.nyash b/test_array_length_fix.nyash new file mode 100644 index 00000000..152fc0a8 --- /dev/null +++ b/test_array_length_fix.nyash @@ -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" + } +} \ No newline at end of file diff --git a/test_modulo_operator_fix.nyash b/test_modulo_operator_fix.nyash new file mode 100644 index 00000000..897b4793 --- /dev/null +++ b/test_modulo_operator_fix.nyash @@ -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" + } +} \ No newline at end of file diff --git a/test_null_literal_support.nyash b/test_null_literal_support.nyash new file mode 100644 index 00000000..0fe71f11 --- /dev/null +++ b/test_null_literal_support.nyash @@ -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" + } +} \ No newline at end of file diff --git a/test_static_box_patterns.nyash b/test_static_box_patterns.nyash new file mode 100644 index 00000000..ed69cc66 --- /dev/null +++ b/test_static_box_patterns.nyash @@ -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" + } +} \ No newline at end of file