pxt-core 7.5.45 → 7.5.48

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.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
  }
@@ -247,7 +264,7 @@ var pxt;
247
264
  let sym = lookupApi(name);
248
265
  if (sym)
249
266
  getOrSetSymbolType(sym);
250
- else if (name.indexOf(".")) {
267
+ else if (name.indexOf(".") && !name.endsWith(".__constructor")) {
251
268
  const base = name.substring(0, name.lastIndexOf("."));
252
269
  const baseSymbol = lookupGlobalSymbol(base);
253
270
  if ((baseSymbol === null || baseSymbol === void 0 ? void 0 : baseSymbol.kind) === 8 /* Class */ && ((_a = baseSymbol.extendsTypes) === null || _a === void 0 ? void 0 : _a.length)) {
@@ -336,7 +353,10 @@ var pxt;
336
353
  pref += ".";
337
354
  }
338
355
  let qualifiedName = pref + name;
339
- if (isLocalScope(scope)
356
+ if (scope.kind === "ClassDef") {
357
+ varSym = addSymbol(2 /* Property */, qualifiedName);
358
+ }
359
+ else if (isLocalScope(scope)
340
360
  && (modifier === py_1.VarModifier.Global
341
361
  || modifier === py_1.VarModifier.NonLocal)) {
342
362
  varSym = addSymbol(4 /* Variable */, name);
@@ -661,17 +681,22 @@ var pxt;
661
681
  return n.symInfo;
662
682
  }
663
683
  // TODO optimize ?
664
- function listClassFields(cd, excludeVariables = true) {
684
+ function listClassFields(cd) {
665
685
  let qn = cd.symInfo.qName;
666
- return pxt.U.values(internalApis).filter(e => e.namespace == qn && ((e.kind == 4 /* Variable */ && !excludeVariables) || e.kind == 2 /* Property */));
686
+ return pxt.U.values(internalApis).filter(e => e.namespace == qn && e.kind == 2 /* Property */);
667
687
  }
668
- function getClassField(ct, n, checkOnly = false, skipBases = false) {
688
+ function getClassField(ct, n, isStatic, checkOnly = false, skipBases = false) {
669
689
  let qid;
670
690
  if (n === "__init__") {
671
691
  qid = ct.pyQName + ".__constructor";
672
692
  }
673
693
  else {
674
- qid = ct.pyQName + "." + n;
694
+ if (n.startsWith(ct.pyQName + ".")) {
695
+ qid = n;
696
+ }
697
+ else {
698
+ qid = ct.pyQName + "." + n;
699
+ }
675
700
  }
676
701
  let f = lookupGlobalSymbol(qid);
677
702
  if (f)
@@ -682,7 +707,7 @@ var pxt;
682
707
  if (sym) {
683
708
  if (sym == ct)
684
709
  pxt.U.userError("field lookup loop on: " + sym.qName + " / " + n);
685
- let classF = getClassField(sym, n, true);
710
+ let classF = getClassField(sym, n, isStatic, true);
686
711
  if (classF)
687
712
  return classF;
688
713
  }
@@ -690,7 +715,7 @@ var pxt;
690
715
  }
691
716
  if (!checkOnly && ct.pyAST && ct.pyAST.kind == "ClassDef") {
692
717
  let sym = addSymbol(2 /* Property */, qid);
693
- sym.isInstance = true;
718
+ sym.isInstance = !isStatic;
694
719
  return sym;
695
720
  }
696
721
  return null;
@@ -707,16 +732,14 @@ var pxt;
707
732
  const recvType = typeOf(recv);
708
733
  const constructorTypes = getTypesForFieldLookup(recvType);
709
734
  for (let ct of constructorTypes) {
710
- let f = getClassField(ct, n, checkOnly);
735
+ let isModule = !!recvType.moduleType;
736
+ let f = getClassField(ct, n, isModule, checkOnly);
711
737
  if (f) {
712
- let isModule = !!recvType.moduleType;
713
738
  if (isModule) {
714
739
  if (f.isInstance)
715
740
  error(null, 9505, pxt.U.lf("the field '{0}' of '{1}' is not static", n, ct.pyQName));
716
741
  }
717
742
  else {
718
- if (!f.isInstance)
719
- error(null, 9504, pxt.U.lf("the field '{0}' of '{1}' is static", n, ct.pyQName));
720
743
  if (isSuper(recv))
721
744
  f.isProtected = true;
722
745
  else if (isThis(recv)) {
@@ -1124,7 +1147,7 @@ var pxt;
1124
1147
  let scopeValueVar = n.vars["value"];
1125
1148
  let valueVar = scopeValueVar === null || scopeValueVar === void 0 ? void 0 : scopeValueVar.symbol;
1126
1149
  if (funname == "__set__" && valueVar) {
1127
- let cf = getClassField(ctx.currClass.symInfo, "__get__");
1150
+ let cf = getClassField(ctx.currClass.symInfo, "__get__", false);
1128
1151
  if (cf && cf.pyAST && cf.pyAST.kind == "FunctionDef")
1129
1152
  unify(n, valueVar.pyRetType, cf.pyRetType);
1130
1153
  }
@@ -1220,7 +1243,7 @@ var pxt;
1220
1243
  }
1221
1244
  }
1222
1245
  const classDefs = n.body.filter(s => n.isNamespace || s.kind === "FunctionDef");
1223
- const staticStmts = n.isNamespace ? [] : n.body.filter(s => classDefs.indexOf(s) === -1);
1246
+ const staticStmts = n.isNamespace ? [] : n.body.filter(s => classDefs.indexOf(s) === -1 && s.kind !== "Pass");
1224
1247
  let body = stmts(classDefs);
1225
1248
  nodes.push(body);
1226
1249
  // Python classes allow arbitrary statements in their bodies, sort of like namespaces.
@@ -1237,18 +1260,20 @@ var pxt;
1237
1260
  body.children.unshift(initFun);
1238
1261
  }
1239
1262
  if (!n.isNamespace) {
1240
- let isStatic = (f) => f.kind === 2 /* Property */ && !f.isInstance || f.kind === 4 /* Variable */;
1241
- const fieldDefs = listClassFields(n, false)
1242
- .filter(f => f.kind == 2 /* Property */ || isStatic(f))
1263
+ const fieldDefs = listClassFields(n)
1243
1264
  .map(f => {
1244
1265
  if (!f.pyName || !f.pyRetType)
1245
1266
  error(n, 9535, lf("field definition missing py name or return type", f.qName));
1246
1267
  return f;
1247
1268
  });
1248
- const instanceFields = fieldDefs.filter(f => !isStatic(f))
1269
+ const staticFieldSymbols = fieldDefs.filter(f => !f.isInstance);
1270
+ const instanceFields = fieldDefs.filter(f => f.isInstance)
1249
1271
  .map((f) => B.mkStmt(accessAnnot(f), quote(f.pyName), typeAnnot(f.pyRetType)));
1250
- const staticFields = fieldDefs.filter(f => isStatic(f))
1251
- .map((f) => B.mkStmt(accessAnnot(f), B.mkText("static "), 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
+ ]));
1252
1277
  body.children = staticFields.concat(instanceFields).concat(body.children);
1253
1278
  }
1254
1279
  if (generatedInitFunction) {
@@ -1563,7 +1588,7 @@ var pxt;
1563
1588
  // class fields can't be const
1564
1589
  // hack: value in @namespace should always be const
1565
1590
  isConstCall = !!(value && ctx.currClass.isNamespace);
1566
- let fd = getClassField(ctx.currClass.symInfo, nm);
1591
+ let fd = getClassField(ctx.currClass.symInfo, nm, true);
1567
1592
  if (!fd)
1568
1593
  error(n, 9544, lf("cannot get class field"));
1569
1594
  // TODO: use or remove this code
@@ -1965,6 +1990,9 @@ var pxt;
1965
1990
  let methName = "";
1966
1991
  if (isClass) {
1967
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
+ }
1968
1996
  }
1969
1997
  else {
1970
1998
  if (n.func.kind == "Attribute") {
@@ -2162,7 +2190,6 @@ var pxt;
2162
2190
  ]);
2163
2191
  }
2164
2192
  }
2165
- // TODO (riknoll): Make sure __init__ isn't being added as a symbol by the super call in the subclass. Should be converted to .__constructor
2166
2193
  let fn;
2167
2194
  if (isSuperConstructor) {
2168
2195
  fn = B.mkText("super");
@@ -2826,6 +2853,68 @@ var pxt;
2826
2853
  break;
2827
2854
  }
2828
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
+ }
2829
2918
  })(py = pxt.py || (pxt.py = {}));
2830
2919
  })(pxt || (pxt = {}));
2831
2920
  // Lexer spec: https://docs.python.org/3/reference/lexical_analysis.html