Skip to content

Scope transpiled class attributes in a function instead of an object - #725

Open
AlexECX wants to merge 2 commits into
TranscryptOrg:dev_fall_2019from
AlexECX:master
Open

Scope transpiled class attributes in a function instead of an object#725
AlexECX wants to merge 2 commits into
TranscryptOrg:dev_fall_2019from
AlexECX:master

Conversation

@AlexECX

@AlexECXAlexECX commented May 14, 2020

Copy link
Copy Markdown

Change Summary

Currently, the transpiled attributes of a class are scoped in an object as key/value pairs. This is problematic when trying to handle class scoped operation, for example:

classA:
print("hello from A")
A=1B=A+1

The main objective of this PR is to facilitate the implementation of class scoped operations.

Secondary changes:

  • Add support for class variable operations.
  • Add support for class scoped expressions.
  • Handle 'assignationless' annotated class variable.

Related issue number

Related to #630 and #663.

PR Checklist

  • Adapted tests
  • Passes tests
  • Documented changes
  • Compatibility with __iter__
  • Compatibility with __next__
  • Compatibility with dataclass class decorator
  • Compatibility with user and built-in decorators
  • Compatibility with nested classes

Sample before/after

Python source:

classA:
print("hello from A")
z: stra: str=""b=1c=b+1def__iter__(self):
returniter([1])
def__next__(self):
returnnext(iter([1]))
deffunc(self, arg):
returnarg@decordefdecorated_func(self, arg):
returnarg@staticmethoddefstatic_func(arg):
returnarg@classmethoddefclassmethod_func(cls, arg):
returnarg@propertydefproperty_func(self):
return1

Before:

exportvarA=__class__('A',[object],{__module__: __name__,// no print()// z: str causes an error at transpile timea: '',b: 1,c: b+1,// causes an error at JS runtimeget__iter__(){return__get__(this,function(self){returnpy_iter([1]);});},[Symbol.iterator](){returnthis.__iter__()},get__next__(){return__get__(this,function(self){returnpy_next(py_iter([1]));});},next: __jsUsePyNext__,getfunc(){return__get__(this,function(self,arg){returnarg;});},getdecorated_func(){return__get__(this,decor(function(self,arg){returnarg;}));},getstatic_func(){returnfunction(arg){returnarg;};},getclassmethod_func(){return__getcm__(this,function(cls,arg){returnarg;});},get_get_property_func(){return__get__(this,function(self){return1;});}});Object.defineProperty(A,'property_func',property.call(A,A._get_property_func));;

After:

exportvarA=__class__('A',[object],(()=>{letcls={};cls.__module__=__name__;print("hello from A");varz=cls.z;vara=cls.a='';varb=cls.b=1;varc=cls.c=b+1;__def__(cls,function__iter__(){return__get__(this,function(self){returnpy_iter([1]);});});cls[Symbol.iterator]=()=>cls.__iter__();__def__(cls,function__next__(){return__get__(this,function(self){returnpy_next(py_iter([1]));});});cls.next=__jsUsePyNext__;__def__(cls,functionfunc(){return__get__(this,function(self,arg){returnarg;});});__def__(cls,functiondecorated_func(){return__get__(this,decor(function(self,arg){returnarg;}));});__def__(cls,functionstatic_func(){returnfunction(arg){returnarg;};});__def__(cls,functionclassmethod_func(){return__getcm__(this,function(cls,arg){returnarg;});});__def__(cls,function_get_property_func(){return__get__(this,function(self){return1;});});returncls;})());Object.defineProperty(A,'property_func',property.call(A,A._get_property_func));;

@AlexECX
AlexECX changed the base branch from master to dev_fall_2019May 14, 2020 18:39
@faerot

Copy link
Copy Markdown

It creates major problems like creating unnecessary scope when class attributes will overshadow global variables with the same name. If you have global name a and want to use it inside method, you will access var a in this class function instead.

@AlexECX

Copy link
Copy Markdown
Author

I haven't been able to work on this, and probably won't unless I take a deeper dive into compiler.py.

Given:

class A:
z: str
a: str = ""
b = 1
c = b + 1

need a way to get

export var A = __class__ ('A', [object], (() => {
let cls = {};
cls.__module__ = __name__;
cls.z = undefined;
cls.a = '';
cls.b = 1;
cls.c = cls.b + 1;
};

instead of my current

export var A = __class__ ('A', [object], (() => {
let cls = {};
cls.__module__ = __name__;
var z = cls.z;
var a = cls.a = '';
var b = cls.b = 1;
var c = cls.c = b + 1;
};

the difficult part being to replace cls.c = b + 1 by cls.c = cls.b + 1.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AlexECX@faerot