pxt-core 7.5.44 → 7.5.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/built/pxtpy.d.ts CHANGED
@@ -16,6 +16,7 @@ declare namespace pxt.py {
16
16
  pyAST?: AST;
17
17
  isProtected?: boolean;
18
18
  moduleTypeMarker?: {};
19
+ isStatic?: boolean;
19
20
  declared?: number;
20
21
  }
21
22
  interface TypeOptions {
@@ -170,7 +171,7 @@ declare namespace pxt.py {
170
171
  keywords: Keyword[];
171
172
  body: Stmt[];
172
173
  decorator_list: Expr[];
173
- baseClass?: ClassDef;
174
+ baseClass?: SymbolInfo;
174
175
  isEnum?: boolean;
175
176
  isNamespace?: boolean;
176
177
  }
package/built/pxtpy.js CHANGED
@@ -186,6 +186,7 @@ var pxt;
186
186
  return mkType({ primType: tp });
187
187
  }
188
188
  function getOrSetSymbolType(sym) {
189
+ var _a;
189
190
  if (!sym.pySymbolType) {
190
191
  currErrorCtx = sym.pyQName;
191
192
  if (sym.parameters) {
@@ -207,8 +208,24 @@ var pxt;
207
208
  sym.pyRetType = mkType({ moduleType: sym });
208
209
  }
209
210
  else {
210
- if (sym.retType)
211
- sym.pyRetType = mapTsType(sym.retType);
211
+ if (sym.retType) {
212
+ if (((_a = sym.qName) === null || _a === void 0 ? void 0 : _a.endsWith(".__constructor")) && sym.retType === "void") {
213
+ // This must be a TS class. Because python treats constructors as functions,
214
+ // set the return type to be the class instead of void
215
+ const classSym = lookupGlobalSymbol(sym.qName.substring(0, sym.qName.lastIndexOf(".")));
216
+ if (classSym) {
217
+ sym.pyRetType = mkType({
218
+ classType: classSym
219
+ });
220
+ }
221
+ else {
222
+ sym.pyRetType = mapTsType(sym.retType);
223
+ }
224
+ }
225
+ else {
226
+ sym.pyRetType = mapTsType(sym.retType);
227
+ }
228
+ }
212
229
  else if (sym.pyRetType) {
213
230
  // nothing to do
214
231
  }
@@ -241,11 +258,19 @@ var pxt;
241
258
  return pxt.U.lookup(internalApis, name) || pxt.U.lookup(externalApis, name);
242
259
  }
243
260
  function lookupGlobalSymbol(name) {
261
+ var _a;
244
262
  if (!name)
245
263
  return undefined;
246
264
  let sym = lookupApi(name);
247
265
  if (sym)
248
266
  getOrSetSymbolType(sym);
267
+ else if (name.indexOf(".") && !name.endsWith(".__constructor")) {
268
+ const base = name.substring(0, name.lastIndexOf("."));
269
+ const baseSymbol = lookupGlobalSymbol(base);
270
+ if ((baseSymbol === null || baseSymbol === void 0 ? void 0 : baseSymbol.kind) === 8 /* Class */ && ((_a = baseSymbol.extendsTypes) === null || _a === void 0 ? void 0 : _a.length)) {
271
+ return lookupGlobalSymbol(baseSymbol.extendsTypes[0] + name.substring(base.length));
272
+ }
273
+ }
249
274
  return sym;
250
275
  }
251
276
  function initApis(apisInfo, tsShadowFiles) {
@@ -328,7 +353,10 @@ var pxt;
328
353
  pref += ".";
329
354
  }
330
355
  let qualifiedName = pref + name;
331
- if (isLocalScope(scope)
356
+ if (scope.kind === "ClassDef") {
357
+ varSym = addSymbol(2 /* Property */, qualifiedName);
358
+ }
359
+ else if (isLocalScope(scope)
332
360
  && (modifier === py_1.VarModifier.Global
333
361
  || modifier === py_1.VarModifier.NonLocal)) {
334
362
  varSym = addSymbol(4 /* Variable */, name);
@@ -442,7 +470,7 @@ var pxt;
442
470
  };
443
471
  }
444
472
  }
445
- // next free error 9575
473
+ // next free error 9576
446
474
  function error(astNode, code, msg) {
447
475
  diagnostics.push(mkDiag(astNode, pxtc.DiagnosticCategory.Error, code, msg));
448
476
  //const pos = position(astNode ? astNode.startPos || 0 : 0, mod.source)
@@ -657,8 +685,19 @@ var pxt;
657
685
  let qn = cd.symInfo.qName;
658
686
  return pxt.U.values(internalApis).filter(e => e.namespace == qn && e.kind == 2 /* Property */);
659
687
  }
660
- function getClassField(ct, n, checkOnly = false, skipBases = false) {
661
- let qid = ct.pyQName + "." + n;
688
+ function getClassField(ct, n, isStatic, checkOnly = false, skipBases = false) {
689
+ let qid;
690
+ if (n === "__init__") {
691
+ qid = ct.pyQName + ".__constructor";
692
+ }
693
+ else {
694
+ if (n.startsWith(ct.pyQName + ".")) {
695
+ qid = n;
696
+ }
697
+ else {
698
+ qid = ct.pyQName + "." + n;
699
+ }
700
+ }
662
701
  let f = lookupGlobalSymbol(qid);
663
702
  if (f)
664
703
  return f;
@@ -668,7 +707,7 @@ var pxt;
668
707
  if (sym) {
669
708
  if (sym == ct)
670
709
  pxt.U.userError("field lookup loop on: " + sym.qName + " / " + n);
671
- let classF = getClassField(sym, n, true);
710
+ let classF = getClassField(sym, n, isStatic, true);
672
711
  if (classF)
673
712
  return classF;
674
713
  }
@@ -676,7 +715,7 @@ var pxt;
676
715
  }
677
716
  if (!checkOnly && ct.pyAST && ct.pyAST.kind == "ClassDef") {
678
717
  let sym = addSymbol(2 /* Property */, qid);
679
- sym.isInstance = true;
718
+ sym.isInstance = !isStatic;
680
719
  return sym;
681
720
  }
682
721
  return null;
@@ -693,16 +732,14 @@ var pxt;
693
732
  const recvType = typeOf(recv);
694
733
  const constructorTypes = getTypesForFieldLookup(recvType);
695
734
  for (let ct of constructorTypes) {
696
- let f = getClassField(ct, n, checkOnly);
735
+ let isModule = !!recvType.moduleType;
736
+ let f = getClassField(ct, n, isModule, checkOnly);
697
737
  if (f) {
698
- let isModule = !!recvType.moduleType;
699
738
  if (isModule) {
700
739
  if (f.isInstance)
701
740
  error(null, 9505, pxt.U.lf("the field '{0}' of '{1}' is not static", n, ct.pyQName));
702
741
  }
703
742
  else {
704
- if (!f.isInstance)
705
- error(null, 9504, pxt.U.lf("the field '{0}' of '{1}' is static", n, ct.pyQName));
706
743
  if (isSuper(recv))
707
744
  f.isProtected = true;
708
745
  else if (isThis(recv)) {
@@ -885,14 +922,17 @@ var pxt;
885
922
  return mkType({});
886
923
  }
887
924
  function doArgs(n, isMethod) {
925
+ var _a;
888
926
  const args = n.args;
889
927
  if (args.kwonlyargs.length)
890
928
  error(n, 9517, pxt.U.lf("keyword-only arguments not supported yet"));
891
929
  let nargs = args.args.slice();
892
930
  if (isMethod) {
893
- if (nargs[0].arg != "self")
894
- error(n, 9518, pxt.U.lf("first argument of method has to be called 'self'"));
895
- nargs.shift();
931
+ if (((_a = nargs[0]) === null || _a === void 0 ? void 0 : _a.arg) !== "self")
932
+ n.symInfo.isStatic = true;
933
+ else {
934
+ nargs.shift();
935
+ }
896
936
  }
897
937
  else {
898
938
  if (nargs.some(a => a.arg == "self"))
@@ -1054,6 +1094,7 @@ var pxt;
1054
1094
  }
1055
1095
  function emitFunctionDef(n, inline = false) {
1056
1096
  return guardedScope(n, () => {
1097
+ var _a, _b, _c, _d;
1057
1098
  const isMethod = !!ctx.currClass && !ctx.currFun;
1058
1099
  const topLev = isTopLevel();
1059
1100
  const nested = !!ctx.currFun;
@@ -1106,7 +1147,7 @@ var pxt;
1106
1147
  let scopeValueVar = n.vars["value"];
1107
1148
  let valueVar = scopeValueVar === null || scopeValueVar === void 0 ? void 0 : scopeValueVar.symbol;
1108
1149
  if (funname == "__set__" && valueVar) {
1109
- let cf = getClassField(ctx.currClass.symInfo, "__get__");
1150
+ let cf = getClassField(ctx.currClass.symInfo, "__get__", false);
1110
1151
  if (cf && cf.pyAST && cf.pyAST.kind == "FunctionDef")
1111
1152
  unify(n, valueVar.pyRetType, cf.pyRetType);
1112
1153
  }
@@ -1114,6 +1155,9 @@ var pxt;
1114
1155
  }
1115
1156
  if (!prefix) {
1116
1157
  prefix = funname[0] == "_" ? (sym.isProtected ? "protected" : "private") : "public";
1158
+ if (n.symInfo.isStatic) {
1159
+ prefix += " static";
1160
+ }
1117
1161
  }
1118
1162
  nodes.push(B.mkText(prefix + " "), quote(funname));
1119
1163
  }
@@ -1125,7 +1169,7 @@ var pxt;
1125
1169
  else
1126
1170
  nodes.push(B.mkText("export function "), quote(funname));
1127
1171
  }
1128
- let retType = n.returns ? compileType(n.returns) : sym.pyRetType;
1172
+ let retType = n.name == "__init__" ? undefined : (n.returns ? compileType(n.returns) : sym.pyRetType);
1129
1173
  nodes.push(doArgs(n, isMethod), retType && canonicalize(retType) != tpVoid ? typeAnnot(retType) : B.mkText(""));
1130
1174
  // make sure type is initialized
1131
1175
  getOrSetSymbolType(sym);
@@ -1133,6 +1177,13 @@ var pxt;
1133
1177
  if (n.name == "__init__") {
1134
1178
  if (!ctx.currClass)
1135
1179
  error(n, 9533, lf("__init__ method '{0}' is missing current class context", sym.pyQName));
1180
+ if ((_a = ctx.currClass) === null || _a === void 0 ? void 0 : _a.baseClass) {
1181
+ const firstStatement = n.body[0];
1182
+ const superConstructor = ctx.currClass.baseClass.pyQName + ".__constructor";
1183
+ if (((_d = (_c = (_b = firstStatement.value) === null || _b === void 0 ? void 0 : _b.func) === null || _c === void 0 ? void 0 : _c.symbolInfo) === null || _d === void 0 ? void 0 : _d.pyQName) !== superConstructor) {
1184
+ error(n, 9575, lf("Sub classes must call 'super().__init__' as the first statement inside an __init__ method"));
1185
+ }
1186
+ }
1136
1187
  for (let f of listClassFields(ctx.currClass)) {
1137
1188
  let p = f.pyAST;
1138
1189
  if (p && p.value) {
@@ -1176,22 +1227,61 @@ var pxt;
1176
1227
  nodes.push(B.mkCommaSep(n.bases.map(expr)));
1177
1228
  let b = getClassDef(n.bases[0]);
1178
1229
  if (b) {
1179
- n.baseClass = b;
1230
+ n.baseClass = b.symInfo;
1180
1231
  sym.extendsTypes = [b.symInfo.pyQName];
1181
1232
  }
1233
+ else {
1234
+ const nm = tryGetName(n.bases[0]);
1235
+ if (nm) {
1236
+ const localSym = lookupSymbol(nm);
1237
+ const globalSym = lookupGlobalSymbol(nm);
1238
+ n.baseClass = localSym || globalSym;
1239
+ if (n.baseClass)
1240
+ sym.extendsTypes = [n.baseClass.pyQName];
1241
+ }
1242
+ }
1182
1243
  }
1183
1244
  }
1184
- let body = stmts(n.body);
1245
+ const classDefs = n.body.filter(s => n.isNamespace || s.kind === "FunctionDef");
1246
+ const staticStmts = n.isNamespace ? [] : n.body.filter(s => classDefs.indexOf(s) === -1 && s.kind !== "Pass");
1247
+ let body = stmts(classDefs);
1185
1248
  nodes.push(body);
1186
- let fieldDefs = listClassFields(n)
1187
- .filter(f => f.kind == 2 /* Property */ && f.isInstance)
1188
- .map(f => {
1189
- if (!f.pyName || !f.pyRetType)
1190
- error(n, 9535, lf("field definition missing py name or ret type", f.qName));
1191
- return f;
1192
- })
1193
- .map((f) => B.mkStmt(accessAnnot(f), quote(f.pyName), typeAnnot(f.pyRetType)));
1194
- body.children = fieldDefs.concat(body.children);
1249
+ // Python classes allow arbitrary statements in their bodies, sort of like namespaces.
1250
+ // Take all of these statements and put them in a static method that we can call when
1251
+ // the class is defined.
1252
+ let generatedInitFunction = false;
1253
+ if (staticStmts.length) {
1254
+ generatedInitFunction = true;
1255
+ const staticBody = stmts(staticStmts);
1256
+ const initFun = B.mkStmt(B.mkGroup([
1257
+ B.mkText(`public static __init${n.name}() `),
1258
+ staticBody
1259
+ ]));
1260
+ body.children.unshift(initFun);
1261
+ }
1262
+ if (!n.isNamespace) {
1263
+ const fieldDefs = listClassFields(n)
1264
+ .map(f => {
1265
+ if (!f.pyName || !f.pyRetType)
1266
+ error(n, 9535, lf("field definition missing py name or return type", f.qName));
1267
+ return f;
1268
+ });
1269
+ const staticFieldSymbols = fieldDefs.filter(f => !f.isInstance);
1270
+ const instanceFields = fieldDefs.filter(f => f.isInstance)
1271
+ .map((f) => B.mkStmt(accessAnnot(f), quote(f.pyName), typeAnnot(f.pyRetType)));
1272
+ const staticFields = staticFieldSymbols
1273
+ .map((f) => B.mkGroup([
1274
+ B.mkStmt(accessAnnot(f), B.mkText("static "), quote(f.pyName), typeAnnot(f.pyRetType)),
1275
+ declareLocalStatic(quoteStr(n.name), quoteStr(f.pyName), t2s(f.pyRetType))
1276
+ ]));
1277
+ body.children = staticFields.concat(instanceFields).concat(body.children);
1278
+ }
1279
+ if (generatedInitFunction) {
1280
+ nodes = [
1281
+ B.mkStmt(B.mkGroup(nodes)),
1282
+ B.mkStmt(B.mkText(`${n.name}.__init${n.name}()`))
1283
+ ];
1284
+ }
1195
1285
  return B.mkStmt(B.mkGroup(nodes));
1196
1286
  }),
1197
1287
  Return: (n) => {
@@ -1498,7 +1588,7 @@ var pxt;
1498
1588
  // class fields can't be const
1499
1589
  // hack: value in @namespace should always be const
1500
1590
  isConstCall = !!(value && ctx.currClass.isNamespace);
1501
- let fd = getClassField(ctx.currClass.symInfo, nm);
1591
+ let fd = getClassField(ctx.currClass.symInfo, nm, true);
1502
1592
  if (!fd)
1503
1593
  error(n, 9544, lf("cannot get class field"));
1504
1594
  // TODO: use or remove this code
@@ -1540,7 +1630,9 @@ var pxt;
1540
1630
  error(n, 9539, lf("function '{0}' missing return type", fd.pyQName));
1541
1631
  unifyTypeOf(target, fd.pyRetType);
1542
1632
  fd.isInstance = false;
1543
- pref = ctx.currClass.isNamespace ? `export ${isConstCall ? "const" : "let"} ` : "static ";
1633
+ if (ctx.currClass.isNamespace) {
1634
+ pref = `export ${isConstCall ? "const" : "let"} `;
1635
+ }
1544
1636
  }
1545
1637
  if (value)
1546
1638
  unifyTypeOf(target, typeOf(value));
@@ -1606,6 +1698,7 @@ var pxt;
1606
1698
  }
1607
1699
  }
1608
1700
  function possibleDef(n, excludeLet = false) {
1701
+ var _a, _b;
1609
1702
  let id = n.id;
1610
1703
  let currScopeVar = lookupScopeSymbol(id);
1611
1704
  let curr = currScopeVar === null || currScopeVar === void 0 ? void 0 : currScopeVar.symbol;
@@ -1640,6 +1733,10 @@ var pxt;
1640
1733
  if (n.isdef && !excludeLet) {
1641
1734
  return B.mkGroup([B.mkText("let "), quote(id)]);
1642
1735
  }
1736
+ else if ((curr === null || curr === void 0 ? void 0 : curr.namespace) && (curr === null || curr === void 0 ? void 0 : curr.qName) && !(((_a = ctx.currClass) === null || _a === void 0 ? void 0 : _a.isNamespace) && ((_b = ctx.currClass) === null || _b === void 0 ? void 0 : _b.name) === (curr === null || curr === void 0 ? void 0 : curr.namespace))) {
1737
+ // If this is a static variable in a class, we want the full qname
1738
+ return quote(curr.qName);
1739
+ }
1643
1740
  else
1644
1741
  return quote(id);
1645
1742
  }
@@ -1653,20 +1750,27 @@ var pxt;
1653
1750
  //return id.replace(/([a-z0-9])_([a-zA-Z0-9])/g, (f: string, x: string, y: string) => x + y.toUpperCase())
1654
1751
  }
1655
1752
  function tryGetName(e) {
1753
+ var _a;
1656
1754
  if (e.kind == "Name") {
1657
1755
  let s = e.id;
1658
1756
  let scopeV = lookupVar(s);
1659
1757
  let v = scopeV === null || scopeV === void 0 ? void 0 : scopeV.symbol;
1660
- if (v && v.expandsTo)
1661
- return v.expandsTo;
1662
- else
1663
- return s;
1758
+ if (v) {
1759
+ if (v.expandsTo)
1760
+ return v.expandsTo;
1761
+ else if (ctx.currClass && !ctx.currFun && !(scopeV === null || scopeV === void 0 ? void 0 : scopeV.modifier) && v.qName)
1762
+ return v.qName;
1763
+ }
1764
+ return s;
1664
1765
  }
1665
1766
  if (e.kind == "Attribute") {
1666
1767
  let pref = tryGetName(e.value);
1667
1768
  if (pref)
1668
1769
  return pref + "." + e.attr;
1669
1770
  }
1771
+ if (isSuper(e) && ((_a = ctx.currClass) === null || _a === void 0 ? void 0 : _a.baseClass)) {
1772
+ return ctx.currClass.baseClass.qName;
1773
+ }
1670
1774
  return undefined;
1671
1775
  }
1672
1776
  function getName(e) {
@@ -1874,6 +1978,7 @@ var pxt;
1874
1978
  return r;
1875
1979
  },
1876
1980
  Call: (n) => {
1981
+ var _a, _b, _c, _d, _e;
1877
1982
  // TODO(dz): move body out; needs seperate PR that doesn't touch content
1878
1983
  n.func.inCalledPosition = true;
1879
1984
  let nm = tryGetName(n.func);
@@ -1885,6 +1990,9 @@ var pxt;
1885
1990
  let methName = "";
1886
1991
  if (isClass) {
1887
1992
  fun = lookupSymbol(namedSymbol.pyQName + ".__constructor");
1993
+ if (!fun) {
1994
+ fun = addSymbolFor(3 /* Function */, createDummyConstructorSymbol(namedSymbol === null || namedSymbol === void 0 ? void 0 : namedSymbol.pyAST));
1995
+ }
1888
1996
  }
1889
1997
  else {
1890
1998
  if (n.func.kind == "Attribute") {
@@ -1904,7 +2012,7 @@ var pxt;
1904
2012
  if (ctx.currClass && ctx.currClass.baseClass) {
1905
2013
  if (!n.tsType)
1906
2014
  error(n, 9543, lf("call expr missing ts type"));
1907
- unifyClass(n, n.tsType, ctx.currClass.baseClass.symInfo);
2015
+ unifyClass(n, n.tsType, ctx.currClass.baseClass);
1908
2016
  }
1909
2017
  return B.mkText("super");
1910
2018
  }
@@ -1964,6 +2072,17 @@ var pxt;
1964
2072
  unify(n, n.tsType, tpString);
1965
2073
  return B.mkInfix(B.mkText(`""`), "+", expr(n.args[0]));
1966
2074
  }
2075
+ const isSuperAttribute = n.func.kind === "Attribute" && isSuper(n.func.value);
2076
+ if (!fun && isSuperAttribute) {
2077
+ fun = lookupGlobalSymbol(nm);
2078
+ }
2079
+ const isSuperConstructor = ((_a = ctx.currFun) === null || _a === void 0 ? void 0 : _a.name) === "__init__" &&
2080
+ (fun === null || fun === void 0 ? void 0 : fun.name) === "__constructor" &&
2081
+ ((_c = (_b = ctx.currClass) === null || _b === void 0 ? void 0 : _b.baseClass) === null || _c === void 0 ? void 0 : _c.pyQName) === (fun === null || fun === void 0 ? void 0 : fun.namespace) &&
2082
+ isSuperAttribute;
2083
+ if (isSuperConstructor) {
2084
+ fun = lookupSymbol(((_e = (_d = ctx.currClass) === null || _d === void 0 ? void 0 : _d.baseClass) === null || _e === void 0 ? void 0 : _e.pyQName) + ".__constructor");
2085
+ }
1967
2086
  if (!fun) {
1968
2087
  error(n, 9508, pxt.U.lf("can't find called function '{0}'", nm));
1969
2088
  }
@@ -2071,7 +2190,13 @@ var pxt;
2071
2190
  ]);
2072
2191
  }
2073
2192
  }
2074
- let fn = methName ? B.mkInfix(expr(recv), ".", B.mkText(methName)) : expr(n.func);
2193
+ let fn;
2194
+ if (isSuperConstructor) {
2195
+ fn = B.mkText("super");
2196
+ }
2197
+ else {
2198
+ fn = methName ? B.mkInfix(expr(recv), ".", B.mkText(methName)) : expr(n.func);
2199
+ }
2075
2200
  let nodes = [
2076
2201
  fn,
2077
2202
  B.mkText("("),
@@ -2728,6 +2853,68 @@ var pxt;
2728
2853
  break;
2729
2854
  }
2730
2855
  }
2856
+ function createDummyConstructorSymbol(def, sym = def.symInfo) {
2857
+ var _a;
2858
+ const existing = lookupApi(sym.pyQName + ".__constructor");
2859
+ if (!existing && ((_a = sym.extendsTypes) === null || _a === void 0 ? void 0 : _a.length)) {
2860
+ const parentSymbol = lookupSymbol(sym.extendsTypes[0]) || lookupGlobalSymbol(sym.extendsTypes[0]);
2861
+ if (parentSymbol) {
2862
+ return createDummyConstructorSymbol(def, parentSymbol);
2863
+ }
2864
+ }
2865
+ const result = {
2866
+ kind: "FunctionDef",
2867
+ name: "__init__",
2868
+ startPos: def.startPos,
2869
+ endPos: def.endPos,
2870
+ parent: def,
2871
+ body: [],
2872
+ args: {
2873
+ kind: "Arguments",
2874
+ startPos: 0,
2875
+ endPos: 0,
2876
+ args: [{
2877
+ startPos: 0,
2878
+ endPos: 0,
2879
+ kind: "Arg",
2880
+ arg: "self"
2881
+ }],
2882
+ kw_defaults: [],
2883
+ kwonlyargs: [],
2884
+ defaults: []
2885
+ },
2886
+ decorator_list: [],
2887
+ vars: {},
2888
+ symInfo: mkSymbol(3 /* Function */, def.symInfo.qName + ".__constructor")
2889
+ };
2890
+ result.symInfo.parameters = [];
2891
+ result.symInfo.pyRetType = mkType({ classType: def.symInfo });
2892
+ if (existing) {
2893
+ result.args.args.push(...existing.parameters.map(p => ({
2894
+ startPos: 0,
2895
+ endPos: 0,
2896
+ kind: "Arg",
2897
+ arg: p.name,
2898
+ })));
2899
+ result.symInfo.parameters.push(...existing.parameters.map(p => {
2900
+ if (p.pyType)
2901
+ return p;
2902
+ const res = Object.assign(Object.assign({}, p), { pyType: mapTsType(p.type) });
2903
+ return res;
2904
+ }));
2905
+ }
2906
+ return result;
2907
+ }
2908
+ function declareLocalStatic(className, name, type) {
2909
+ const isSetVar = `___${name}_is_set`;
2910
+ const localVar = `___${name}`;
2911
+ return B.mkStmt(B.mkStmt(B.mkText(`private ${isSetVar}: boolean`)), B.mkStmt(B.mkText(`private ${localVar}: ${type}`)), B.mkStmt(B.mkText(`get ${name}(): ${type}`), B.mkBlock([
2912
+ B.mkText(`return this.${isSetVar} ? this.${localVar} : ${className}.${name}`)
2913
+ ])), B.mkStmt(B.mkText(`set ${name}(value: ${type})`), B.mkBlock([
2914
+ B.mkStmt(B.mkText(`this.${isSetVar} = true`)),
2915
+ B.mkStmt(B.mkText(`this.${localVar} = value`)),
2916
+ ])));
2917
+ }
2731
2918
  })(py = pxt.py || (pxt.py = {}));
2732
2919
  })(pxt || (pxt = {}));
2733
2920
  // Lexer spec: https://docs.python.org/3/reference/lexical_analysis.html