Files
herolib/libarchive/rhai/verify.v
2025-05-04 08:23:34 +03:00

85 lines
3.8 KiB
V

module rhai
import freeflowuniverse.herolib.core.texttools
// import strings // No longer needed directly here
import freeflowuniverse.herolib.lang.rust
import os
// Helper to extract the primary struct name from declarations
fn get_primary_struct_name(struct_declarations []string) string {
if struct_declarations.len == 0 {
return ''
}
// Simple extraction: assumes first line is `pub struct Name {` or `struct Name {`
first_line := struct_declarations[0].trim_space()
if first_line.starts_with('pub struct ') {
name_part := first_line.all_after('pub struct ')
return name_part.all_before('{').trim_space()
} else if first_line.starts_with('struct ') {
name_part := first_line.all_after('struct ')
return name_part.all_before('{').trim_space()
}
return '' // Couldn't determine name
}
// verify_rhai_wrapper checks if the AI-generated output contains a plausible Rhai wrapper.
// It now uses the struct declarations to check for correct method naming.
fn verify_rhai_wrapper(rust_fn_signature string, struct_declarations []string, generated_output string) ! {
// 1. Extract Rust code block (same as before)
mut code_block := ''
if generated_output.contains('```rust') { // Use contains() for strings
start_index := generated_output.index('```rust') or { -1 }
end_index := generated_output.index_after('```', start_index + 7) or { -1 }
if start_index != -1 && end_index != -1 {
code_block = generated_output[start_index + 7..end_index].trim_space()
} else {
code_block = generated_output.trim_space()
}
} else {
code_block = generated_output.trim_space()
}
assert code_block.len > 0, 'Could not extract code block from generated output: \n`${generated_output}`'
// 2. Determine Original Function Name and Expected Wrapper Name
// Ideally, use rust module parsing here, but for now, simple string parsing:
is_method := rust_fn_signature.contains('&self') || rust_fn_signature.contains('&mut self')
mut original_fn_name := ''
sig_parts := rust_fn_signature.split('(')
if sig_parts.len > 0 {
name_parts := sig_parts[0].split(' ')
if name_parts.len > 0 {
original_fn_name = name_parts.last()
}
}
assert original_fn_name != '', 'Could not extract function name from signature: ${rust_fn_signature}'
expected_wrapper_fn_name := if is_method {
struct_name := get_primary_struct_name(struct_declarations)
assert struct_name != '', 'Could not determine struct name for method: ${rust_fn_signature}'
'${texttools.snake_case(struct_name)}_${original_fn_name}' // e.g., mystruct_get_name
} else {
original_fn_name // Standalone function uses the same name
}
// 3. Basic Signature Check (using expected_wrapper_fn_name)
expected_sig_start := 'pub fn ${expected_wrapper_fn_name}'
expected_sig_end := '-> Result<'
expected_sig_very_end := 'Box<EvalAltResult>>'
assert code_block.contains(expected_sig_start), 'Wrapper missing signature start: `${expected_sig_start}` in\n${code_block}'
assert code_block.contains(expected_sig_end), 'Wrapper missing signature end: `${expected_sig_end}` in\n${code_block}'
assert code_block.contains(expected_sig_very_end), 'Wrapper missing signature very end: `${expected_sig_very_end}` in\n${code_block}'
// 4. Basic Body Check (Check for call to the *original* function name)
body_start := code_block.index('{') or { -1 }
body_end := code_block.last_index('}') or { -1 }
if body_start != -1 && body_end != -1 && body_start < body_end {
body := code_block[body_start + 1..body_end]
// Check for call like `original_fn_name(...)` or `receiver.original_fn_name(...)`
assert body.contains(original_fn_name + '(') || body.contains('.' + original_fn_name + '('), 'Wrapper body does not appear to call original function `${original_fn_name}` in\n${body}'
} else {
assert false, 'Could not find function body `{...}` in wrapper:\n${code_block}'
}
// If all checks pass, do nothing (implicitly ok)
}