Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions py2v_transpiler/tests/input/transpile/test_classes_inheritance.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
module main

// @line: test_classes_inheritance.py:1:0
pub struct Animal {
name string
}
// @line: test_classes_inheritance.py:11:0
pub struct Dog {
Animal
breed string
}
// @line: test_classes_inheritance.py:22:0
pub struct Cat {
Animal
lives int
}
// @line: test_classes_inheritance.py:46:0
pub struct Vehicle {
brand string
}
// @line: test_classes_inheritance.py:52:0
pub struct Car {
Vehicle
model string
}

pub const Animal_new_animal__annotations__ = { 'name': 'string' }
pub const Animal_speak__annotations__ = { 'return': 'string' }
pub const Animal_info__annotations__ = { 'return': 'string' }
pub const Dog_new_dog__annotations__ = { 'name': 'string', 'breed': 'string' }
pub const Dog_speak__annotations__ = { 'return': 'string' }
pub const Dog_fetch__annotations__ = { 'return': 'string' }
pub const Cat_new_cat__annotations__ = { 'name': 'string' }
pub const Cat_speak__annotations__ = { 'return': 'string' }
pub const Cat_climb__annotations__ = { 'return': 'string' }
pub const Vehicle_new_vehicle__annotations__ = { 'brand': 'string' }
pub const Car_new_car__annotations__ = { 'brand': 'string', 'model': 'string' }
pub const Car_description__annotations__ = { 'return': 'string' }

// @line: test_classes_inheritance.py:2:4
pub fn new_animal(name string) Animal {
mut self := Animal{}
self.name = name
return self
}
// @line: test_classes_inheritance.py:5:4
pub fn (self Animal) speak() string {
return 'Some sound'
}
// @line: test_classes_inheritance.py:8:4
pub fn (self Animal) info() string {
return 'I am ${self.name}'
}
// @line: test_classes_inheritance.py:12:4
pub fn new_dog(name string, breed string) Dog {
mut self := Dog{}
self.Animal = new_animal(name)
self.breed = breed
return self
}
// @line: test_classes_inheritance.py:16:4
pub fn (self Dog) speak() string {
return 'Woof!'
}
// @line: test_classes_inheritance.py:19:4
pub fn (self Dog) fetch() string {
return '${self.name} is fetching'
}
// @line: test_classes_inheritance.py:23:4
pub fn new_cat(name string) Cat {
mut self := Cat{}
self.Animal = new_animal(name)
self.lives = 9
return self
}
// @line: test_classes_inheritance.py:27:4
pub fn (self Cat) speak() string {
return 'Meow!'
}
// @line: test_classes_inheritance.py:30:4
pub fn (self Cat) climb() string {
return '${self.name} is climbing'
}
// @line: test_classes_inheritance.py:33:0
pub fn test_basic_inheritance() {
mut dog := new_dog('Buddy', 'Golden')
println('${dog.name}')
println('${dog.breed}')
println('${dog.speak()}')
println('${dog.info()}')
println('${dog.fetch()}')
}
// @line: test_classes_inheritance.py:41:0
pub fn test_polymorphism() {
animals := [new_dog('Rex', 'Shepherd'), new_cat('Whiskers')]
for animal in animals {
println('${animal.name} says: ${animal.speak()}')
}
}
// @line: test_classes_inheritance.py:49:4
pub fn new_vehicle(brand string) Vehicle {
mut self := Vehicle{}
self.brand = brand
return self
}
// @line: test_classes_inheritance.py:53:4
pub fn new_car(brand string, model string) Car {
mut self := Car{}
self.Vehicle = new_vehicle(brand)
self.model = model
return self
}
// @line: test_classes_inheritance.py:57:4
pub fn (self Car) description() string {
return '${self.brand} ${self.model}'
}
// @line: test_classes_inheritance.py:60:0
pub fn test_class_variables() {
car := new_car('Toyota', 'Camry')
println('Car: ${car.description()}')
println('Wheels: ${car.wheels}')
println('Class wheels: ${Vehicle.wheels}')
}
// @line: test_classes_inheritance.py:66:0
pub fn test_isinstance_issubclass() {
mut dog := new_dog('Spot', 'Labrador')
println('dog is Animal: ${dog is Animal}')
println('dog is Dog: ${dog is dog}')
println('dog is Cat: ${dog is Cat}')
println('Dog is subclass of Animal: ${issubclass(dog, Animal)}')
println('Cat is subclass of Animal: ${issubclass(Cat, Animal)}')
println('Dog is subclass of Cat: ${issubclass(dog, Cat)}')
}
// @line: test_classes_inheritance.py:77:0
pub fn test() {
test_basic_inheritance()
test_polymorphism()
test_class_variables()
test_isinstance_issubclass()
}

fn main() {
// @line: test_classes_inheritance.py:83:0
// if __name__ == '__main__':
test()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
module main

pub struct NoneType {}

pub fn (n NoneType) str() string {
return 'None'
}

pub struct Interpolation {
pub:
value Any
expression string
conversion string
format_spec string
}

pub struct Template {
pub:
strings []string
interpolations []Interpolation
}

pub fn (t Template) values() []Any {
mut res := []Any{cap: t.interpolations.len}
for i in t.interpolations {
res << i.value
}
return res
}

pub fn (t1 Template) + (t2 Template) Template {
if t1.strings.len == 0 { return t2 }
if t2.strings.len == 0 { return t1 }
mut new_strings := t1.strings[..t1.strings.len - 1].clone()
new_strings << t1.strings.last() + t2.strings[0]
if t2.strings.len > 1 {
new_strings << t2.strings[1..]
}
mut new_interpolations := t1.interpolations.clone()
new_interpolations << t2.interpolations
return Template{
strings: new_strings
interpolations: new_interpolations
}
}

pub type Any = Interpolation | NoneType | Template | []Any | []u8 | bool | f64 | i64 | int | map[string]Any | string

pub enum PyAnnotationFormat { value forwardref string }

pub fn py_get_type_hints[T]() map[string]string {
mut hints := map[string]string{}
$for field in T.fields {
hints[field.name] = field.typ
}
return hints
}

pub fn py_get_type_hints_generic(obj Any) map[string]string {
return map[string]string{}
}

struct PyGeneratorInput {
val Any
is_exc bool
exc_msg string
}
struct PyGenerator[T] {
mut:
out chan T
in_ chan PyGeneratorInput
open bool = true
}

fn (mut g PyGenerator[T]) next() ?T {
if !g.open { return none }
g.in_ <- PyGeneratorInput{val: 0} // Send dummy value
res := <-g.out
if res == none { g.open = false }
return res
}
fn (mut g PyGenerator[T]) send(val Any) ?T {
if !g.open { panic('StopIteration') }
g.in_ <- PyGeneratorInput{val: val}
res := <-g.out
if res == none { g.open = false }
return res
}
fn (mut g PyGenerator[T]) throw(msg string) ?T {
if !g.open { panic('StopIteration') }
g.in_ <- PyGeneratorInput{is_exc: true, exc_msg: msg}
res := <-g.out
if res == none { g.open = false }
return res
}
fn (mut g PyGenerator[T]) close() {
g.open = false
g.in_.close()
// g.out will be closed by the generator function loop when it detects in_ closed or panic
}
fn py_yield[T](ch_out chan T, ch_in chan PyGeneratorInput, val T) Any {
ch_out <- val
inp := <-ch_in
if inp.is_exc {
panic(inp.exc_msg)
}
return inp.val
}
//##LLM@@ String formatting for bytes is stubbed and might be incorrect. Please implement proper bytes formatting or use V string interpolation.
fn py_bytes_format(fmt []u8, args Any) []u8 {
// Simplistic implementation for b'%s' % b'val'
// Converts bytes to string, formats, and converts back.
// This is not efficient or correct for non-ASCII bytes but works for simple cases.
fmt_str := fmt.bytestr()
// TODO: handle args properly. V's string interpolation/formatting expects distinct args.
// If args is []u8, treat as string.
arg_str := if args is []u8 { args.bytestr() } else { '${args}' }

// Manual substitution of %s
// V does not have sprintf for runtime strings easily available in core without C interop.
// Simple replace for %s
res := fmt_str.replace('%s', arg_str)
return res.bytes()
}
Loading
Loading