Skip to content

Commit

Permalink
py2many: Fix type inference for methods
Browse files Browse the repository at this point in the history
Allows classes.py to pass on many targets

Related to: py2many#400
  • Loading branch information
adsharma committed Aug 24, 2021
1 parent e9ad025 commit ef52617
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,8 @@ path = "tests/expected/sealed.rs"
name = "import_tests"
test = true
path = "tests/expected/import_tests.rs"

[[bin]]
name = "classes"
test = true
path = "tests/expected/classes.rs"
5 changes: 5 additions & 0 deletions py2many/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,11 @@ def visit_Attribute(self, node):
def visit_Call(self, node):
fname = get_id(node.func)
if fname is not None:
# Handle methods calls by looking up the method name
# without the prefix
# TODO: use remove suffix
if fname.startswith("self."):
fname = fname.split(".", 1)[1]
fn = node.scopes.find(fname)
if isinstance(fn, ast.ClassDef):
self._annotate(node, fn.name)
Expand Down
4 changes: 4 additions & 0 deletions pyrs/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,10 @@ def visit_ClassDef(self, node) -> str:
index += 1
fields.append(f"pub {declaration}: {typename},")

for b in node.body:
if isinstance(b, ast.FunctionDef):
b.self_type = node.name

extension = "#[pyclass]\n" if self.extension else ""
struct_def = "pub struct {0} {{\n{1}\n}}\n\n".format(
node.name, "\n".join(fields)
Expand Down
13 changes: 13 additions & 0 deletions tests/cases/classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Foo:
def bar(self):
return self.baz()

def baz(self) -> int:
return 10


if __name__ == "__main__":
f = Foo()
b = f.bar()
print(b)
assert b == 10
20 changes: 20 additions & 0 deletions tests/expected/classes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <cassert> // NOLINT(build/include_order)
#include <iostream> // NOLINT(build/include_order)

#include "pycpp/runtime/builtins.h" // NOLINT(build/include_order)
#include "pycpp/runtime/sys.h" // NOLINT(build/include_order)
class Foo {
public:
inline int bar() { return this->baz(); }

inline int baz() { return 10; }
};

int main(int argc, char** argv) {
pycpp::sys::argv = std::vector<std::string>(argv, argv + argc);
Foo f = Foo();
auto b = f.bar();
std::cout << b;
std::cout << std::endl;
assert(b == 10);
}
19 changes: 19 additions & 0 deletions tests/expected/classes.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// @dart=2.9
import 'package:sprintf/sprintf.dart';

class Foo {
int bar() {
return baz();
}

int baz() {
return 10;
}
}

main(List<String> argv) {
final Foo f = Foo();
final b = f.bar();
print(sprintf("%s", [b]));
assert(b == 10);
}
25 changes: 25 additions & 0 deletions tests/expected/classes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"fmt"
)

type Foo struct {
}

func bar(self Foo) int {
return baz(self)
}

func baz(self Foo) int {
return 10
}

func main() {
var f Foo = Foo{}
b := bar(f)
fmt.Printf("%v\n", b)
if !(b == 10) {
panic("assert")
}
}
20 changes: 20 additions & 0 deletions tests/expected/classes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
struct Foo

end

function bar(self::Foo)::Int64
return baz(self)
end

function baz(self::Foo)::Int64
return 10
end

function main()
f = Foo()
b = bar(f)
println(join([b], " "))
@assert(b == 10)
end

main()
17 changes: 17 additions & 0 deletions tests/expected/classes.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Foo {

fun bar(): Int {
return baz()
}

fun baz(): Int {
return 10
}
}

fun main(argv: Array<String>) {
val f = Foo()
val b = f.bar()
println("$b")
assert(b == 10)
}
19 changes: 19 additions & 0 deletions tests/expected/classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from typing import Callable, Dict, List, Set, Optional
from ctypes import c_int8 as i8, c_int16 as i16, c_int32 as i32, c_int64 as i64
from ctypes import c_uint8 as u8, c_uint16 as u16, c_uint32 as u32, c_uint64 as u64
import sys


class Foo:
def bar(self) -> int:
return self.baz()

def baz(self) -> int:
return 10


if __name__ == "__main__":
f: Foo = Foo()
b = f.bar()
print(b)
assert b == 10
45 changes: 45 additions & 0 deletions tests/expected/classes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! ```cargo
//! [package]
//! edition = "2018"
//! [dependencies]
//! anyhow = "*"
//! ```
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::double_parens)] // https://github.com/adsharma/py2many/issues/17
#![allow(clippy::map_identity)]
#![allow(clippy::needless_return)]
#![allow(clippy::print_literal)]
#![allow(clippy::ptr_arg)]
#![allow(clippy::redundant_static_lifetimes)] // https://github.com/adsharma/py2many/issues/266
#![allow(clippy::unnecessary_cast)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::useless_vec)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(unused_imports)]
#![allow(unused_mut)]
#![allow(unused_parens)]

extern crate anyhow;
use anyhow::Result;

pub struct Foo {}

impl Foo {
pub fn bar(&self) -> i32 {
return self.baz();
}

pub fn baz(&self) -> i32 {
return 10;
}
}
pub fn main() -> Result<()> {
let f: Foo = Foo {};
let b = f.bar();
println!("{}", b);
assert!((b as i32) == 10);
Ok(())
}

0 comments on commit ef52617

Please sign in to comment.