2025-08-15 06:18:09 +00:00
|
|
|
// ✏️ Enhanced Kilo Text Editor - Phase 10.4
|
|
|
|
|
// Memory efficiency monitoring and "accidental full copy" detection
|
|
|
|
|
|
|
|
|
|
// Enhanced TextBuffer with memory monitoring
|
|
|
|
|
box EnhancedTextBuffer {
|
|
|
|
|
init { lines, undo_stack, initial_memory, operation_count }
|
|
|
|
|
|
2025-08-16 17:39:04 +09:00
|
|
|
birth() {
|
2025-08-15 06:18:09 +00:00
|
|
|
me.lines = new ArrayBox()
|
|
|
|
|
me.undo_stack = new ArrayBox()
|
|
|
|
|
me.operation_count = 0
|
|
|
|
|
|
|
|
|
|
// Start with one empty line
|
|
|
|
|
me.lines.push("")
|
|
|
|
|
|
|
|
|
|
// Record initial memory footprint
|
|
|
|
|
me.initial_memory = me.memory_footprint()
|
|
|
|
|
print("📊 Initial memory footprint: " + me.initial_memory + " bytes")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ⭐ Phase 10: Memory efficiency monitoring
|
|
|
|
|
memory_footprint() {
|
|
|
|
|
// Calculate total memory usage
|
|
|
|
|
local total_memory = 100 // Base TextBuffer overhead
|
2025-08-15 07:36:00 +00:00
|
|
|
local line_count_box = me.lines.length()
|
|
|
|
|
|
|
|
|
|
// Convert to integer for loop usage
|
|
|
|
|
local line_count = 0
|
|
|
|
|
if line_count_box != null {
|
|
|
|
|
line_count = line_count_box.toString().toInteger()
|
|
|
|
|
}
|
2025-08-15 06:18:09 +00:00
|
|
|
|
|
|
|
|
// Add memory for each line
|
|
|
|
|
local i = 0
|
|
|
|
|
loop(i < line_count) {
|
|
|
|
|
local line = me.lines.get(i)
|
2025-08-15 07:36:00 +00:00
|
|
|
if line != null {
|
|
|
|
|
total_memory = total_memory + line.toString().length() + 20 // String overhead
|
|
|
|
|
}
|
2025-08-15 06:18:09 +00:00
|
|
|
i = i + 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add undo stack memory
|
2025-08-15 07:36:00 +00:00
|
|
|
local undo_count_box = me.undo_stack.length()
|
|
|
|
|
local undo_count = 0
|
|
|
|
|
if undo_count_box != null {
|
|
|
|
|
undo_count = undo_count_box.toString().toInteger()
|
|
|
|
|
}
|
2025-08-15 06:18:09 +00:00
|
|
|
total_memory = total_memory + (undo_count * 50) // Estimate for undo operations
|
|
|
|
|
|
|
|
|
|
return total_memory
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ⭐ Phase 10: "Accidental full copy" detection
|
|
|
|
|
insert_char(row, col, char) {
|
|
|
|
|
local old_memory = me.memory_footprint()
|
|
|
|
|
me.operation_count = me.operation_count + 1
|
|
|
|
|
|
|
|
|
|
// Get current line
|
|
|
|
|
local current_line = me.lines.get(row)
|
|
|
|
|
local line_str = current_line.toString()
|
|
|
|
|
|
|
|
|
|
// Insert character
|
|
|
|
|
local left_part = line_str.substring(0, col)
|
|
|
|
|
local right_part = line_str.substring(col, line_str.length())
|
|
|
|
|
local new_line = left_part + char + right_part
|
|
|
|
|
|
|
|
|
|
// Replace line
|
|
|
|
|
me.lines.set(row, new_line)
|
|
|
|
|
|
|
|
|
|
// Save to undo stack
|
|
|
|
|
local undo_op = "insert_char:" + row + ":" + col + ":" + char
|
|
|
|
|
me.undo_stack.push(undo_op)
|
|
|
|
|
|
|
|
|
|
// Check for accidental full copy
|
|
|
|
|
local new_memory = me.memory_footprint()
|
|
|
|
|
local memory_diff = new_memory - old_memory
|
|
|
|
|
|
|
|
|
|
print("💾 Memory change: " + memory_diff + " bytes for operation " + me.operation_count)
|
|
|
|
|
|
|
|
|
|
// ⭐ Alert if memory increase is suspicious
|
|
|
|
|
if (memory_diff > 100) { // 1 character should not increase memory by 100+ bytes
|
|
|
|
|
print("🚨 INEFFICIENT COPY DETECTED!")
|
|
|
|
|
print(" Expected: ~20 bytes, Actual: " + memory_diff + " bytes")
|
|
|
|
|
print(" Operation: Insert '" + char + "' at (" + row + ", " + col + ")")
|
|
|
|
|
me.log_memory_leak_warning()
|
|
|
|
|
} else if (memory_diff > 0) {
|
|
|
|
|
print("✅ Normal memory usage: " + memory_diff + " bytes")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete_char(row, col) {
|
|
|
|
|
if (col <= 0) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local old_memory = me.memory_footprint()
|
|
|
|
|
me.operation_count = me.operation_count + 1
|
|
|
|
|
|
|
|
|
|
// Get current line and remove character
|
|
|
|
|
local current_line = me.lines.get(row)
|
|
|
|
|
local line_str = current_line.toString()
|
|
|
|
|
|
|
|
|
|
local left_part = line_str.substring(0, col - 1)
|
|
|
|
|
local right_part = line_str.substring(col, line_str.length())
|
|
|
|
|
local new_line = left_part + right_part
|
|
|
|
|
|
|
|
|
|
me.lines.set(row, new_line)
|
|
|
|
|
|
|
|
|
|
// Save to undo stack
|
|
|
|
|
local undo_op = "delete_char:" + row + ":" + col
|
|
|
|
|
me.undo_stack.push(undo_op)
|
|
|
|
|
|
|
|
|
|
local new_memory = me.memory_footprint()
|
|
|
|
|
local memory_diff = new_memory - old_memory
|
|
|
|
|
|
|
|
|
|
print("💾 Memory change: " + memory_diff + " bytes (deletion)")
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Search and replace with efficiency monitoring
|
|
|
|
|
search_and_replace(pattern, replacement) {
|
|
|
|
|
local initial_memory = me.memory_footprint()
|
|
|
|
|
local matches_found = 0
|
|
|
|
|
|
|
|
|
|
print("🔍 Starting search and replace: '" + pattern + "' -> '" + replacement + "'")
|
|
|
|
|
|
2025-08-15 07:36:00 +00:00
|
|
|
local line_count_box = me.lines.length()
|
|
|
|
|
local line_count = 0
|
|
|
|
|
if line_count_box != null {
|
|
|
|
|
line_count = line_count_box.toString().toInteger()
|
|
|
|
|
}
|
2025-08-15 06:18:09 +00:00
|
|
|
local i = 0
|
|
|
|
|
loop(i < line_count) {
|
|
|
|
|
local line = me.lines.get(i)
|
|
|
|
|
local line_str = line.toString()
|
|
|
|
|
|
|
|
|
|
// Simple search and replace (contains check)
|
|
|
|
|
if (line_str.indexOf(pattern) >= 0) {
|
|
|
|
|
// For simplicity, just append replacement to demonstrate memory monitoring
|
|
|
|
|
local new_line = line_str + " [REPLACED: " + pattern + " -> " + replacement + "]"
|
|
|
|
|
me.lines.set(i, new_line)
|
|
|
|
|
matches_found = matches_found + 1
|
|
|
|
|
}
|
|
|
|
|
i = i + 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local final_memory = me.memory_footprint()
|
|
|
|
|
local memory_ratio = final_memory / initial_memory
|
|
|
|
|
|
|
|
|
|
print("🔍 Search complete: " + matches_found + " matches")
|
|
|
|
|
print("📊 Memory usage: " + initial_memory + " -> " + final_memory + " bytes")
|
|
|
|
|
print("📈 Memory ratio: " + memory_ratio)
|
|
|
|
|
|
|
|
|
|
// Check for memory doubling (inefficient algorithm)
|
|
|
|
|
if (memory_ratio > 2) {
|
|
|
|
|
print("⚠️ Memory usage doubled during replace operation!")
|
|
|
|
|
print(" This may indicate inefficient string handling")
|
|
|
|
|
} else {
|
|
|
|
|
print("✅ Memory usage within reasonable bounds")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return matches_found
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_memory_leak_warning() {
|
|
|
|
|
print("⚠️ MEMORY EFFICIENCY WARNING")
|
|
|
|
|
print(" Current total memory: " + me.memory_footprint())
|
|
|
|
|
print(" Operations performed: " + me.operation_count)
|
|
|
|
|
print(" Average memory per operation: " + (me.memory_footprint() / me.operation_count))
|
|
|
|
|
print(" Consider optimizing string operations")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get_stats() {
|
|
|
|
|
local current_memory = me.memory_footprint()
|
|
|
|
|
local line_count = me.lines.length()
|
|
|
|
|
local undo_count = me.undo_stack.length()
|
|
|
|
|
|
2025-08-15 07:36:00 +00:00
|
|
|
return "Lines: " + line_count.toString() + ", Undo: " + undo_count.toString() + ", Memory: " + current_memory + "B, Ops: " + me.operation_count
|
2025-08-15 06:18:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Enhanced Kilo Editor
|
|
|
|
|
box EnhancedKiloEditor {
|
|
|
|
|
init { buffer, cursor_row, cursor_col, filename }
|
|
|
|
|
|
2025-08-16 17:39:04 +09:00
|
|
|
birth(file_name) {
|
2025-08-15 06:18:09 +00:00
|
|
|
me.buffer = new EnhancedTextBuffer()
|
|
|
|
|
me.cursor_row = 0
|
|
|
|
|
me.cursor_col = 0
|
|
|
|
|
me.filename = file_name
|
|
|
|
|
print("📝 Enhanced Kilo Editor initialized: " + me.filename)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
insert_text(text) {
|
|
|
|
|
local i = 0
|
|
|
|
|
local text_len = text.length()
|
|
|
|
|
|
|
|
|
|
loop(i < text_len) {
|
|
|
|
|
local char = text.substring(i, i + 1)
|
|
|
|
|
me.buffer.insert_char(me.cursor_row, me.cursor_col, char)
|
|
|
|
|
me.cursor_col = me.cursor_col + 1
|
|
|
|
|
i = i + 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_line() {
|
|
|
|
|
// Insert new line at current position
|
|
|
|
|
me.cursor_row = me.cursor_row + 1
|
|
|
|
|
me.cursor_col = 0
|
|
|
|
|
me.buffer.lines.insert(me.cursor_row, "")
|
|
|
|
|
print("↩️ New line inserted at row " + me.cursor_row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
backspace() {
|
|
|
|
|
if (me.cursor_col > 0) {
|
|
|
|
|
me.buffer.delete_char(me.cursor_row, me.cursor_col)
|
|
|
|
|
me.cursor_col = me.cursor_col - 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
show_stats() {
|
|
|
|
|
print("📊 Editor Stats: " + me.buffer.get_stats())
|
|
|
|
|
print("📍 Cursor: (" + me.cursor_row + ", " + me.cursor_col + ")")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test suite for memory efficiency
|
|
|
|
|
static box Main {
|
|
|
|
|
init { console }
|
|
|
|
|
|
|
|
|
|
main() {
|
|
|
|
|
me.console = new ConsoleBox()
|
|
|
|
|
me.console.log("✏️ Phase 10.4: Enhanced Kilo Editor - Memory Efficiency Testing")
|
|
|
|
|
|
|
|
|
|
local editor = new EnhancedKiloEditor("test_document.txt")
|
|
|
|
|
|
|
|
|
|
// Test 1: Normal character insertion
|
|
|
|
|
me.console.log("Test 1: Inserting characters normally")
|
|
|
|
|
editor.insert_text("Hello World")
|
|
|
|
|
editor.show_stats()
|
|
|
|
|
|
|
|
|
|
// Test 2: Large text insertion (potential memory stress)
|
|
|
|
|
me.console.log("Test 2: Large text insertion")
|
|
|
|
|
editor.new_line()
|
|
|
|
|
editor.insert_text("This is a longer line of text to test memory efficiency monitoring")
|
|
|
|
|
editor.show_stats()
|
|
|
|
|
|
|
|
|
|
// Test 3: Search and replace (memory doubling test)
|
|
|
|
|
me.console.log("Test 3: Search and replace operation")
|
|
|
|
|
local matches = editor.buffer.search_and_replace("test", "TEST")
|
|
|
|
|
editor.show_stats()
|
|
|
|
|
|
|
|
|
|
// Test 4: Memory stress test
|
|
|
|
|
me.console.log("Test 4: Memory stress test - rapid insertions")
|
|
|
|
|
local stress_count = 0
|
|
|
|
|
loop(stress_count < 10) {
|
|
|
|
|
editor.insert_text("X")
|
|
|
|
|
stress_count = stress_count + 1
|
|
|
|
|
}
|
|
|
|
|
editor.show_stats()
|
|
|
|
|
|
|
|
|
|
// Final memory report
|
|
|
|
|
me.console.log("Final memory footprint: " + editor.buffer.memory_footprint() + " bytes")
|
|
|
|
|
me.console.log("Total operations: " + editor.buffer.operation_count)
|
|
|
|
|
|
|
|
|
|
return "Enhanced Kilo Editor test complete"
|
|
|
|
|
}
|
|
|
|
|
}
|