- test_features.py
- test_more_features.py
- test_misc_features.py
- test_final_features.py
- test_even_more_features.py
- test_advenced.py
- test_function_annotations.py
- test_type_annotations.py
- test_string_literals.py
- test_none_type.py
- test_transpile.py
- repro_iterators.py
- generics_monomorphization.py
File: test_more_features.py
Python code:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before call")
result = func(*args, **kwargs)
print("After call")
return result
return wrapper
@my_decorator
def greet(name: str):
print(f"Hello, {name}!")
return nameGenerated V code:
pub fn my_decorator(func fn (...Any) Any) Any {
mut wrapper := fn [func] (args ...int, kwargs map[string]string) Any {
println('Before call')
result := func(...args, kwargs)
println('After call')
return result
}
return wrapper
}Problems:
- The closure syntax
fn [func] (...)is not valid V syntax for capturing variables. - The variadic parameter
args ...intmust be the last parameter in V, butkwargs map[string]stringfollows it. func(...args, kwargs)- V does not support passing a map as a separate positional argument after variadic args.- The
@my_decoratorannotation is generated as a comment, but the decorator is not actually applied togreet. Thegreetfunction is generated as a standalone function without the decorator wrapper. - Warning issued:
Warning: Custom decorator 'my_decorator' at line 13 is not fully supported and might generate invalid code.
File: test_more_features.py
Python code:
async def fetch_data(id: int) -> str:
print(f"Fetching {id}...")
await asyncio.sleep(0.1)
return f"Data_{id}"
async def main_async():
data = await fetch_data(42)
print(data)Generated V code:
pub fn fetch_data(id int) string {
println('Fetching ${id}...')
/* await */ asyncio.sleep(0.1)
return 'Data_${id}'
}
pub fn main_async() {
data := /* await */ fetch_data(42)
println('${data}')
}Problems:
awaitis replaced with a comment/* await */instead of actual V async code.asyncio.sleep(0.1)andasyncio.run(main_async())are not valid V code.- V does not have built-in async/await support like Python. The transpiler should either use V's
goroutines or emit a clear error.
File: test_misc_features.py
Python code:
p = q = r = [1, 2, 3]
p.append(4)
print(f"q: {q}, r: {r}")Generated V code:
py_assign_tmp_0 := [1, 2, 3]
mut p := py_assign_tmp_0.clone()
q := py_assign_tmp_0
r := py_assign_tmp_0
p << 4
println('q: ${q}, r: ${r}')Problem:
- In Python,
p = q = r = [1, 2, 3]creates three references to the same list. Appending topalso affectsqandr. - In the generated V code,
pgets.clone()making it an independent copy, whileqandrshare the original. This changes the semantics - modifyingpdoes not affectqorr.
File: test_final_features.py
Python code:
counter = 0
def increment():
global counter
counter += 1
print(f"Counter: {counter}")Generated V code:
// To compile with globals, use: v -enable-globals .
__global counter int
pub fn increment() {
//##LLM@@ Python 'global' or 'nonlocal' scope modification detected. V heavily discourages global state and has strict mutability rules for closures. Please refactor state management, possibly by passing mutable parameters (mut) explicitly.
counter += 1
println('Counter: ${counter}')
}Problems:
- V requires the
-enable-globalsflag to compile code with global variables. - V discourages global state. The transpiler emits a warning comment but does not provide an alternative solution.
- The
init()function for initializing the global variable may not be called automatically in all contexts.
File: test_final_features.py
Python code:
class MyContext:
def __enter__(self):
print("Entering context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exiting context")
def process():
with MyContext() as ctx:
print("Inside context")
increment()Generated V code:
pub fn (self MyContext) enter() Any {
println('Entering context')
return self
}
pub fn (self MyContext) exit(exc_type Any, exc_val Any, exc_tb Any) {
println('Exiting context')
}
pub fn process() {
ctx_mgr_0 := MyContext{}
defer { ctx_mgr_0.exit(none, none, none) }
ctx := ctx_mgr_0.enter()
println('Inside context')
increment()
}Problems:
__enter__is renamed toenterand__exit__is renamed toexit. These are not standard V context manager methods.- The
enter()method returnsAnyinstead of the specific typeMyContext. - The
withstatement is translated usingdefer, which is functional but not idiomatic for V context management.
File: test_even_more_features.py
Python code:
@full_name.setter
def full_name(self, value: str):
parts = value.split(" ")
if len(parts) == 2:
self._first = parts[0]
self._last = parts[1]Generated V code:
pub fn (mut self User) set_full_name(value string) string {
parts := value.split(' ')
if parts.len == 2 {
self._first = py_subscript(parts, 0)
self._last = py_subscript(parts, 1)
}
}Problems:
- The setter function has return type
stringbut does not return a value. In V, this may cause a compilation error. - Python setters should not return a value. The transpiler should generate a function with no return type.
py_subscript(parts, 0)is used instead ofparts[0]. While this may work, it is not idiomatic V.
File: test_even_more_features.py
Python code:
def match_status(status: int | str):
match status:
case 200:
print("OK")
case 404:
print("Not Found")
case "error":
print("Server Error")
case _:
print("Unknown")
match_status(500) # This should work in PythonGenerated V code:
pub fn match_status(status SumType_IntString) {
py_match_subject_1 := status
py_match_subject_any_1 := Any(py_match_subject_1)
mut py_match_found_1 := false
if !py_match_found_1 && (py_match_subject_any_1 == 200) {
println('OK')
py_match_found_1 = true
}
// ... more cases
}
match_status(500) # This will fail in VProblems:
- The function signature requires
SumType_IntString, butmatch_status(500)passes a plainint. - In V, you cannot pass a plain
intto a function expectingSumType_IntStringwithout explicit wrapping. - The match statement is converted to a series of
ifblocks withAnycomparisons, which loses type safety.
File: test_function_annotations.py, test_type_annotations.py, test_string_literals.py
Python code:
x, y = coordsGenerated V code:
py_destruct_0 := coords
x := py_destruct_0[0]
y := py_destruct_0[1]Problem:
TupleStruct_IntIntdoes not support indexing via[]. V tuples use named fields like.it_0,.it_1or field names.- The generated code will not compile in V.
File: test_function_annotations.py
Python code:
def process(name: str, nums: Optional[List[int]] = None, multiplier: int = 1) -> List[int]:
if nums is None:
nums = []
return [x * multiplier for x in nums]
process("test") # Uses default None for numsGenerated V code:
pub fn process(name string, nums ?[]int, multiplier int) []int {
if nums == none {
nums = []int{}
}
mut py_comp_3 := []int{}
for x in nums {
py_comp_3 << x * multiplier
}
return py_comp_3
}
process('test', mut none, 1)Problems:
mut noneis not valid V syntax.- The default parameter handling is incorrect - instead of using V's default parameter syntax, the transpiler explicitly passes
mut noneat call sites. - V does not support default parameter values in the same way as Python.
File: test_type_annotations.py
Python code:
def complex_dict(data: Dict[str, List[int]]) -> List[int]:
result: List[int] = []
for key, values in data.items():
result.extend(values)
return resultGenerated V code:
pub fn complex_dict(data map[string][]int) []int {
mut result := []int{}
for key, values in data {
result << values
}
return result
}Problem:
result << valuesadds the entirevalueslist as a single element toresult, rather than extendingresultwith each element ofvalues.- In Python,
result.extend(values)adds each element individually. - The correct V code would need a nested loop or array spreading.
File: test_type_annotations.py
Python code:
def function_type(f: callable, x: int) -> int:
return f(x)
def apply_function(f: callable, values: List[int]) -> List[int]:
result: List[int] = []
for v in values:
result.append(f(v))
return resultGenerated V code:
pub fn function_type(f fn, x int) int {
return f(x)
}
pub fn apply_function(f fn, values []int) []int {
mut result := []int{}
for v in values {
result << f(v)
}
return result
}Problem:
fnwithout a signature is not type-safe in V.- The function
fcannot be called without knowing its parameter and return types. - V requires explicit function signatures like
fn (int) int.
File: test_string_literals.py
Python code:
data = {"name": "Bob", "age": 25}
result = "{name} is {age} years old".format_map(data)Generated V code:
data := {'name': Any('Bob'), 'age': Any(25)}
mut result := '{name} is {age} years old'.format_map(data)Problem:
- V strings do not have a
format_map()method. - The transpiler should either use V's string interpolation or a helper function.
File: test_none_type.py
Python code:
x = None
y = 10
x = y
y = NoneGenerated V code:
mut x := Any(NoneType{})
mut y := 10
x = y
y = noneProblems:
Any(NoneType{})is not valid V syntax.NoneType{}is not a valid V type or constructor.- Assigning
noneto anintvariable (y = none) will not compile in V.
File: test_none_type.py
Python code:
def no_return():
pass
result = no_return()
print(f"No return result: {result}")
print(f"Is None: {result is None}")Generated V code:
mut no_return := fn () {
}
mut result := no_return()
println('No return result: ${result}')
println('Is None: ${(result) is NoneType}')Problem:
- In V, a function without a return statement returns
void, notnone. - Assigning
voidto a variable and printing it is not valid in V. - The transpiler should either make the function return
?or handle this case differently.
File: test_none_type.py
Python code:
def get_value(x=None):
return "No value" if x is None else f"Value: {x}"Generated V code:
mut get_value := fn (mut x Any) Any {
return if (x) is NoneType { 'No value' } else { 'Value: ${x}' }
}Problem:
mutin function parameters is not idiomatic V for this use case.- The function parameter should not be mutable unless explicitly needed.
File: test_transpile.py
Python code:
class Data:
def __init__(self):
self.value: int | str = 0
d = Data()
d.value = "hello"
print(d.value.upper())
d.value = 123
print(d.value + 1)Generated V code:
pub struct Data {
value SumType_IntString
}
d := new_data()
d.value = 'hello'
println('${d.value.to_upper()}')
d.value = 123
println('${d.value + 1}')Problems:
d.value.to_upper()-SumType_IntStringdoes not have ato_upper()method. You must first narrow the type tostring.d.value + 1-SumType_IntStringdoes not support+withint. You must first narrow the type toint.- The transpiler should generate type narrowing checks before accessing type-specific methods or operators.
File: repro_iterators.py
Python code:
data = [1, 2, 3, 4, 5]
it = iter(data)
remaining = list(it)
print(f"Remaining: {remaining}")Generated V code:
it := py_iter(data)
remaining := py_list_from_iter<[]Any>(it)
println('Remaining: ${remaining}')Problem:
py_list_from_iter<[]Any>(it)may not work correctly with all iterator types.- The generic type
[]Anyloses type information from the originalList[int].
File: generics_monomorphization.py
Python code:
T = TypeVar("T")
class Box(Generic[T]):
def __init__(self, x: T):
self.x = xGenerated V code:
pub struct Box[T] {
x int
}
pub fn new_box[T](x T) Box[T] {
mut self := Box[T]{}
self.x = x
return self
}Problem:
- The struct field
xhas typeinthardcoded instead ofT. - When
Box[T]is used with different types (e.g.,Box[string]), the field typeintwill be incorrect. - The field should be
x Tto properly support generics.
These issues were already known before this analysis:
- Variadic parameter must be last in V: In V, the variadic parameter (
...Any) must be the last parameter in the argument list. - Cannot assign void function result: In V, you cannot assign the result of a function that returns nothing (
void). - Type mismatch in if/elif chains: Variables defined as
?intcannot be assigned string values like'A','B', etc. - C.try() for exceptions: The transpiler uses
if C.try() { ... } else { ... }for exception handling, which is not idiomatic V and may require thediv72.vexclibrary or C interop. - Limited decorator support: Custom decorators generate warnings and produce code that may not be valid V. The
@decoratorsyntax is not directly supported in V.
| # | Issue | Severity | Files Affected |
|---|---|---|---|
| 1 | Decorator closures with invalid V syntax | High | test_more_features.py |
| 2 | Async/Await not supported (comment-only) | High | test_more_features.py |
| 3 | Chained assignment .clone() changes semantics |
Medium | test_misc_features.py |
| 4 | Global variables require -enable-globals |
Medium | test_final_features.py |
| 5 | Context manager methods renamed | Low | test_final_features.py |
| 6 | Property setter has incorrect return type | Medium | test_even_more_features.py |
| 7 | Match/case Union type compatibility | High | test_even_more_features.py |
| 8 | Try/except requires external library | High | test_advenced.py |
| 9 | Tuple destructuring invalid indexing | High | test_function_annotations.py, test_type_annotations.py, test_string_literals.py |
| 10 | mut none invalid syntax |
High | test_function_annotations.py |
| 11 | extend() vs << semantic difference |
Medium | test_type_annotations.py |
| 12 | callable type untyped fn |
Medium | test_type_annotations.py |
| 13 | partition() invalid tuple indexing |
High | test_string_literals.py |
| 14 | format_map() not available in V |
Medium | test_string_literals.py |
| 15 | NoneType{} invalid syntax |
High | test_none_type.py |
| 16 | Void function assigned to variable | High | test_none_type.py |
| 17 | mut in function parameters |
Low | test_none_type.py |
| 18 | SumType methods without narrowing | High | test_transpile.py |
| 19 | py_list_from_iter type loss |
Low | repro_iterators.py |
| 20 | Generic field type hardcoded | High | generics_monomorphization.py |