pxt-core 13.2.14 → 13.2.15
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/backendutils.d.ts +120 -0
- package/built/backendutils.js +2171 -5
- package/built/cli.js +5 -2
- package/built/pxt.js +5785 -5553
- package/built/pxtcompiler.js +2 -2
- package/built/pxtlib.d.ts +178 -127
- package/built/pxtlib.js +21858 -21629
- package/built/target.js +1 -1
- package/built/targetlight.js +1 -1
- package/built/web/main.js +1 -1
- package/built/web/pxtapp.js +2 -2
- package/built/web/pxtcompiler.js +1 -1
- package/built/web/pxtembed.js +1 -1
- package/built/web/pxtlib.js +1 -1
- package/built/web/pxtworker.js +1 -1
- package/built/web/rtlsemantic.css +1 -1
- package/built/web/semantic.css +1 -1
- package/package.json +1 -1
- package/theme/project-backpack.less +1 -1
- package/theme/project-tools.less +4 -4
package/built/backendutils.js
CHANGED
|
@@ -119,6 +119,14 @@ var pxtc = ts.pxtc;
|
|
|
119
119
|
(function (pxtc) {
|
|
120
120
|
var Util;
|
|
121
121
|
(function (Util) {
|
|
122
|
+
function contains(str, contains) {
|
|
123
|
+
if (str.length < contains.length)
|
|
124
|
+
return false;
|
|
125
|
+
if (contains.length == 0)
|
|
126
|
+
return true;
|
|
127
|
+
return str.indexOf(contains) > -1;
|
|
128
|
+
}
|
|
129
|
+
Util.contains = contains;
|
|
122
130
|
function assert(cond, msg = "Assertion failed") {
|
|
123
131
|
if (!cond) {
|
|
124
132
|
debugger;
|
|
@@ -469,10 +477,180 @@ var pxtc = ts.pxtc;
|
|
|
469
477
|
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
470
478
|
})(ts || (ts = {}));
|
|
471
479
|
const lf = ts.pxtc.Util.lf;
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
480
|
+
(function (ts) {
|
|
481
|
+
var pxtc;
|
|
482
|
+
(function (pxtc) {
|
|
483
|
+
/**
|
|
484
|
+
* atob replacement
|
|
485
|
+
* @param s
|
|
486
|
+
*/
|
|
487
|
+
pxtc.decodeBase64 = function (s) { return atob(s); };
|
|
488
|
+
/**
|
|
489
|
+
* bota replacement
|
|
490
|
+
* @param s
|
|
491
|
+
*/
|
|
492
|
+
pxtc.encodeBase64 = function (s) { return btoa(s); };
|
|
493
|
+
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
494
|
+
})(ts || (ts = {}));
|
|
495
|
+
(function (ts) {
|
|
496
|
+
var pxtc;
|
|
497
|
+
(function (pxtc) {
|
|
498
|
+
var Util;
|
|
499
|
+
(function (Util) {
|
|
500
|
+
function iterMap(m, f) {
|
|
501
|
+
Object.keys(m).forEach(k => f(k, m[k]));
|
|
502
|
+
}
|
|
503
|
+
Util.iterMap = iterMap;
|
|
504
|
+
function values(m) {
|
|
505
|
+
return Object.keys(m || {}).map(k => m[k]);
|
|
506
|
+
}
|
|
507
|
+
Util.values = values;
|
|
508
|
+
function pushRange(trg, src) {
|
|
509
|
+
if (src)
|
|
510
|
+
for (let i = 0; i < src.length; ++i)
|
|
511
|
+
trg.push(src[i]);
|
|
512
|
+
}
|
|
513
|
+
Util.pushRange = pushRange;
|
|
514
|
+
// TS gets lost in type inference when this is passed an array
|
|
515
|
+
function concatArrayLike(arrays) {
|
|
516
|
+
return concat(arrays);
|
|
517
|
+
}
|
|
518
|
+
Util.concatArrayLike = concatArrayLike;
|
|
519
|
+
function concat(arrays) {
|
|
520
|
+
let r = [];
|
|
521
|
+
for (let i = 0; i < arrays.length; ++i) {
|
|
522
|
+
pushRange(r, arrays[i]);
|
|
523
|
+
}
|
|
524
|
+
return r;
|
|
525
|
+
}
|
|
526
|
+
Util.concat = concat;
|
|
527
|
+
function isKV(v) {
|
|
528
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
529
|
+
}
|
|
530
|
+
function jsonMergeFrom(trg, src) {
|
|
531
|
+
if (!src)
|
|
532
|
+
return;
|
|
533
|
+
Object.keys(src).forEach(k => {
|
|
534
|
+
if (isKV(trg[k]) && isKV(src[k]))
|
|
535
|
+
jsonMergeFrom(trg[k], src[k]);
|
|
536
|
+
else
|
|
537
|
+
trg[k] = Util.clone(src[k]);
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
Util.jsonMergeFrom = jsonMergeFrom;
|
|
541
|
+
function jsonCopyFrom(trg, src) {
|
|
542
|
+
let v = Util.clone(src);
|
|
543
|
+
for (let k of Object.keys(src)) {
|
|
544
|
+
trg[k] = v[k];
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
Util.jsonCopyFrom = jsonCopyFrom;
|
|
548
|
+
// { a: { b: 1 }, c: 2} => { "a.b": 1, c: 2 }
|
|
549
|
+
function jsonFlatten(v) {
|
|
550
|
+
let res = {};
|
|
551
|
+
let loop = (pref, v) => {
|
|
552
|
+
if (v !== null && typeof v == "object") {
|
|
553
|
+
Util.assert(!Array.isArray(v));
|
|
554
|
+
if (pref)
|
|
555
|
+
pref += ".";
|
|
556
|
+
for (let k of Object.keys(v)) {
|
|
557
|
+
loop(pref + k, v[k]);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
res[pref] = v;
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
loop("", v);
|
|
565
|
+
return res;
|
|
566
|
+
}
|
|
567
|
+
Util.jsonFlatten = jsonFlatten;
|
|
568
|
+
function jsonUnFlatten(v) {
|
|
569
|
+
let res = {};
|
|
570
|
+
for (let k of Object.keys(v)) {
|
|
571
|
+
let ptr = res;
|
|
572
|
+
let parts = k.split(".");
|
|
573
|
+
for (let i = 0; i < parts.length; ++i) {
|
|
574
|
+
let part = parts[i];
|
|
575
|
+
if (i == parts.length - 1)
|
|
576
|
+
ptr[part] = v[k];
|
|
577
|
+
else {
|
|
578
|
+
if (typeof ptr[part] != "object")
|
|
579
|
+
ptr[part] = {};
|
|
580
|
+
ptr = ptr[part];
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return res;
|
|
585
|
+
}
|
|
586
|
+
Util.jsonUnFlatten = jsonUnFlatten;
|
|
587
|
+
function strcmp(a, b) {
|
|
588
|
+
if (a == b)
|
|
589
|
+
return 0;
|
|
590
|
+
if (a < b)
|
|
591
|
+
return -1;
|
|
592
|
+
else
|
|
593
|
+
return 1;
|
|
594
|
+
}
|
|
595
|
+
Util.strcmp = strcmp;
|
|
596
|
+
function endsWith(str, suffix) {
|
|
597
|
+
if (str.length < suffix.length)
|
|
598
|
+
return false;
|
|
599
|
+
if (suffix.length == 0)
|
|
600
|
+
return true;
|
|
601
|
+
return str.slice(-suffix.length) == suffix;
|
|
602
|
+
}
|
|
603
|
+
Util.endsWith = endsWith;
|
|
604
|
+
function startsWith(str, prefix) {
|
|
605
|
+
if (str.length < prefix.length)
|
|
606
|
+
return false;
|
|
607
|
+
if (prefix.length == 0)
|
|
608
|
+
return true;
|
|
609
|
+
return str.slice(0, prefix.length) == prefix;
|
|
610
|
+
}
|
|
611
|
+
Util.startsWith = startsWith;
|
|
612
|
+
function toUTF8(str, cesu8) {
|
|
613
|
+
let res = "";
|
|
614
|
+
if (!str)
|
|
615
|
+
return res;
|
|
616
|
+
for (let i = 0; i < str.length; ++i) {
|
|
617
|
+
let code = str.charCodeAt(i);
|
|
618
|
+
if (code <= 0x7f)
|
|
619
|
+
res += str.charAt(i);
|
|
620
|
+
else if (code <= 0x7ff) {
|
|
621
|
+
res += String.fromCharCode(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
if (!cesu8 && 0xd800 <= code && code <= 0xdbff) {
|
|
625
|
+
let next = str.charCodeAt(++i);
|
|
626
|
+
if (!isNaN(next))
|
|
627
|
+
code = 0x10000 + ((code - 0xd800) << 10) + (next - 0xdc00);
|
|
628
|
+
}
|
|
629
|
+
if (code <= 0xffff)
|
|
630
|
+
res += String.fromCharCode(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
|
|
631
|
+
else
|
|
632
|
+
res += String.fromCharCode(0xf0 | (code >> 18), 0x80 | ((code >> 12) & 0x3f), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return res;
|
|
636
|
+
}
|
|
637
|
+
Util.toUTF8 = toUTF8;
|
|
638
|
+
function toUTF8Array(s) {
|
|
639
|
+
return (new TextEncoder()).encode(s);
|
|
640
|
+
}
|
|
641
|
+
Util.toUTF8Array = toUTF8Array;
|
|
642
|
+
})(Util = pxtc.Util || (pxtc.Util = {}));
|
|
643
|
+
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
644
|
+
})(ts || (ts = {}));
|
|
645
|
+
var pxt;
|
|
646
|
+
(function (pxt) {
|
|
647
|
+
pxt.U = pxtc.Util;
|
|
648
|
+
pxt.Util = pxtc.Util;
|
|
649
|
+
})(pxt || (pxt = {}));
|
|
650
|
+
/// <reference path='../../localtypings/pxtarget.d.ts' />
|
|
651
|
+
/// <reference path='../../localtypings/dompurify.d.ts' />
|
|
652
|
+
/// <reference path="../commonutil.ts"/>
|
|
653
|
+
/// <reference path="../logger.ts" />
|
|
476
654
|
var pxt;
|
|
477
655
|
(function (pxt) {
|
|
478
656
|
var docs;
|
|
@@ -1617,5 +1795,1993 @@ My links
|
|
|
1617
1795
|
docs.hydrateYouTubeEmbeds = hydrateYouTubeEmbeds;
|
|
1618
1796
|
})(docs = pxt.docs || (pxt.docs = {}));
|
|
1619
1797
|
})(pxt || (pxt = {}));
|
|
1620
|
-
/// <reference path="../
|
|
1798
|
+
/// <reference path="../commonutil.ts"/>
|
|
1799
|
+
var ts;
|
|
1800
|
+
(function (ts) {
|
|
1801
|
+
var pxtc;
|
|
1802
|
+
(function (pxtc) {
|
|
1803
|
+
var BrowserImpl;
|
|
1804
|
+
(function (BrowserImpl) {
|
|
1805
|
+
function rotr(v, b) {
|
|
1806
|
+
return (v >>> b) | (v << (32 - b));
|
|
1807
|
+
}
|
|
1808
|
+
const sha256_k = new Uint32Array([
|
|
1809
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
1810
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
1811
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
1812
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
1813
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
1814
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
1815
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
1816
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
1817
|
+
]);
|
|
1818
|
+
function sha256round(hs, w) {
|
|
1819
|
+
pxtc.Util.assert(hs.length == 8);
|
|
1820
|
+
pxtc.Util.assert(w.length == 64);
|
|
1821
|
+
for (let i = 16; i < 64; ++i) {
|
|
1822
|
+
let s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >>> 3);
|
|
1823
|
+
let s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >>> 10);
|
|
1824
|
+
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) | 0;
|
|
1825
|
+
}
|
|
1826
|
+
let a = hs[0];
|
|
1827
|
+
let b = hs[1];
|
|
1828
|
+
let c = hs[2];
|
|
1829
|
+
let d = hs[3];
|
|
1830
|
+
let e = hs[4];
|
|
1831
|
+
let f = hs[5];
|
|
1832
|
+
let g = hs[6];
|
|
1833
|
+
let h = hs[7];
|
|
1834
|
+
for (let i = 0; i < 64; ++i) {
|
|
1835
|
+
let s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
1836
|
+
let ch = (e & f) ^ (~e & g);
|
|
1837
|
+
let temp1 = (h + s1 + ch + sha256_k[i] + w[i]) | 0;
|
|
1838
|
+
let s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
1839
|
+
let maj = (a & b) ^ (a & c) ^ (b & c);
|
|
1840
|
+
let temp2 = (s0 + maj) | 0;
|
|
1841
|
+
h = g;
|
|
1842
|
+
g = f;
|
|
1843
|
+
f = e;
|
|
1844
|
+
e = (d + temp1) | 0;
|
|
1845
|
+
d = c;
|
|
1846
|
+
c = b;
|
|
1847
|
+
b = a;
|
|
1848
|
+
a = (temp1 + temp2) | 0;
|
|
1849
|
+
}
|
|
1850
|
+
hs[0] += a;
|
|
1851
|
+
hs[1] += b;
|
|
1852
|
+
hs[2] += c;
|
|
1853
|
+
hs[3] += d;
|
|
1854
|
+
hs[4] += e;
|
|
1855
|
+
hs[5] += f;
|
|
1856
|
+
hs[6] += g;
|
|
1857
|
+
hs[7] += h;
|
|
1858
|
+
}
|
|
1859
|
+
function sha256buffer(buf) {
|
|
1860
|
+
let h = new Uint32Array(8);
|
|
1861
|
+
h[0] = 0x6a09e667;
|
|
1862
|
+
h[1] = 0xbb67ae85;
|
|
1863
|
+
h[2] = 0x3c6ef372;
|
|
1864
|
+
h[3] = 0xa54ff53a;
|
|
1865
|
+
h[4] = 0x510e527f;
|
|
1866
|
+
h[5] = 0x9b05688c;
|
|
1867
|
+
h[6] = 0x1f83d9ab;
|
|
1868
|
+
h[7] = 0x5be0cd19;
|
|
1869
|
+
let work = new Uint32Array(64);
|
|
1870
|
+
let chunkLen = 16 * 4;
|
|
1871
|
+
function addBuf(buf) {
|
|
1872
|
+
let end = buf.length - (chunkLen - 1);
|
|
1873
|
+
for (let i = 0; i < end; i += chunkLen) {
|
|
1874
|
+
for (let j = 0; j < 16; j++) {
|
|
1875
|
+
let off = (j << 2) + i;
|
|
1876
|
+
work[j] = (buf[off] << 24) | (buf[off + 1] << 16) | (buf[off + 2] << 8) | buf[off + 3];
|
|
1877
|
+
}
|
|
1878
|
+
sha256round(h, work);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
addBuf(buf);
|
|
1882
|
+
let padSize = 64 - (buf.length + 9) % 64;
|
|
1883
|
+
if (padSize == 64)
|
|
1884
|
+
padSize = 0;
|
|
1885
|
+
let endPos = buf.length - (buf.length % chunkLen);
|
|
1886
|
+
let padBuf = new Uint8Array((buf.length - endPos) + 1 + padSize + 8);
|
|
1887
|
+
let dst = 0;
|
|
1888
|
+
while (endPos < buf.length)
|
|
1889
|
+
padBuf[dst++] = buf[endPos++];
|
|
1890
|
+
padBuf[dst++] = 0x80;
|
|
1891
|
+
while (padSize-- > 0)
|
|
1892
|
+
padBuf[dst++] = 0x00;
|
|
1893
|
+
let len = buf.length * 8;
|
|
1894
|
+
dst = padBuf.length;
|
|
1895
|
+
while (len > 0) {
|
|
1896
|
+
padBuf[--dst] = len & 0xff;
|
|
1897
|
+
len >>= 8;
|
|
1898
|
+
}
|
|
1899
|
+
addBuf(padBuf);
|
|
1900
|
+
let res = "";
|
|
1901
|
+
for (let i = 0; i < h.length; ++i)
|
|
1902
|
+
res += ("000000000" + h[i].toString(16)).slice(-8);
|
|
1903
|
+
return res.toLowerCase();
|
|
1904
|
+
}
|
|
1905
|
+
BrowserImpl.sha256buffer = sha256buffer;
|
|
1906
|
+
})(BrowserImpl = pxtc.BrowserImpl || (pxtc.BrowserImpl = {}));
|
|
1907
|
+
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
1908
|
+
})(ts || (ts = {}));
|
|
1909
|
+
var Measurements;
|
|
1910
|
+
(function (Measurements) {
|
|
1911
|
+
Measurements.TutorialInfoDbSetAsync = "tutorial info db setAsync";
|
|
1912
|
+
Measurements.ReloadAppTargetVariant = "reloadAppTargetVariant";
|
|
1913
|
+
Measurements.Sha256Buffer = "sha256buffer";
|
|
1914
|
+
Measurements.WebworkerRecvHandler = "webworker recvHandler";
|
|
1915
|
+
Measurements.NetworkRequest = "network.request";
|
|
1916
|
+
})(Measurements || (Measurements = {}));
|
|
1917
|
+
/// <reference path="../../localtypings/pxtpackage.d.ts"/>
|
|
1918
|
+
/// <reference path="../commonutil.ts"/>
|
|
1919
|
+
var pxt;
|
|
1920
|
+
(function (pxt) {
|
|
1921
|
+
var packageUtils;
|
|
1922
|
+
(function (packageUtils) {
|
|
1923
|
+
var U = pxtc.Util;
|
|
1924
|
+
function getVersionProtocol(version) {
|
|
1925
|
+
const separator = version.indexOf(":");
|
|
1926
|
+
return separator < 0 ? "" : version.slice(0, separator);
|
|
1927
|
+
}
|
|
1928
|
+
packageUtils.getVersionProtocol = getVersionProtocol;
|
|
1929
|
+
function isVariantDisabled(config, variant) {
|
|
1930
|
+
return !!config && !!config.disablesVariants && config.disablesVariants.indexOf(variant) >= 0;
|
|
1931
|
+
}
|
|
1932
|
+
packageUtils.isVariantDisabled = isVariantDisabled;
|
|
1933
|
+
function getConfigDependencies(config, includeTests, includeCpp, isTestDependencyAvailable) {
|
|
1934
|
+
if (!config)
|
|
1935
|
+
return {};
|
|
1936
|
+
const dependencies = Object.assign({}, config.dependencies);
|
|
1937
|
+
if (includeTests) {
|
|
1938
|
+
for (const id of Object.keys(config.testDependencies || {})) {
|
|
1939
|
+
const version = config.testDependencies[id];
|
|
1940
|
+
if (isTestDependencyAvailable(id, version))
|
|
1941
|
+
dependencies[id] = version;
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
if (includeCpp)
|
|
1945
|
+
U.jsonMergeFrom(dependencies, config.cppDependencies);
|
|
1946
|
+
return dependencies;
|
|
1947
|
+
}
|
|
1948
|
+
packageUtils.getConfigDependencies = getConfigDependencies;
|
|
1949
|
+
/** Evaluates fileDependencies with && taking precedence over ||, without reading target or package globals. */
|
|
1950
|
+
function evaluateDependencyCondition(condition, target, hasDependency, onInvalidCondition) {
|
|
1951
|
+
if (!condition || !condition.trim())
|
|
1952
|
+
return true;
|
|
1953
|
+
const evaluate = (term) => {
|
|
1954
|
+
term = term.trim();
|
|
1955
|
+
if (term[0] == "!")
|
|
1956
|
+
return !evaluate(term.slice(1));
|
|
1957
|
+
if (/^[\w-]+$/.test(term))
|
|
1958
|
+
return hasDependency(term);
|
|
1959
|
+
const match = /^target:(\w+)$/.exec(term);
|
|
1960
|
+
if (match)
|
|
1961
|
+
return match[1] == target.id || match[1] == target.platformid;
|
|
1962
|
+
onInvalidCondition(term);
|
|
1963
|
+
return false;
|
|
1964
|
+
};
|
|
1965
|
+
return condition.split("||").some(c => c.split("&&").every(evaluate));
|
|
1966
|
+
}
|
|
1967
|
+
packageUtils.evaluateDependencyCondition = evaluateDependencyCondition;
|
|
1968
|
+
function getConfigFiles(config, includeTests, target, hasDependency, onInvalidCondition) {
|
|
1969
|
+
const files = config.files.concat(includeTests ? config.testFiles || [] : []);
|
|
1970
|
+
if (!config.fileDependencies)
|
|
1971
|
+
return files;
|
|
1972
|
+
return files.filter(filename => evaluateDependencyCondition(U.lookup(config.fileDependencies, filename), target, hasDependency, condition => onInvalidCondition(condition, filename)));
|
|
1973
|
+
}
|
|
1974
|
+
packageUtils.getConfigFiles = getConfigFiles;
|
|
1975
|
+
})(packageUtils = pxt.packageUtils || (pxt.packageUtils = {}));
|
|
1976
|
+
})(pxt || (pxt = {}));
|
|
1977
|
+
/// <reference path="../../localtypings/pxtarget.d.ts"/>
|
|
1978
|
+
/// <reference path="../commonutil.ts"/>
|
|
1979
|
+
var pxt;
|
|
1980
|
+
(function (pxt) {
|
|
1981
|
+
/** Resolves compile defaults and a variant without modifying the supplied target. */
|
|
1982
|
+
function getAppTargetVariant(target, variant) {
|
|
1983
|
+
const result = pxt.U.cloneTargetBundle(target);
|
|
1984
|
+
if (variant) {
|
|
1985
|
+
const overrides = result.variants && result.variants[variant];
|
|
1986
|
+
if (!overrides)
|
|
1987
|
+
pxt.U.userError(pxt.U.lf("Variant '{0}' not defined in pxtarget.json", variant));
|
|
1988
|
+
pxt.U.jsonMergeFrom(result, overrides);
|
|
1989
|
+
}
|
|
1990
|
+
patchCompileTarget(result);
|
|
1991
|
+
return result;
|
|
1992
|
+
}
|
|
1993
|
+
pxt.getAppTargetVariant = getAppTargetVariant;
|
|
1994
|
+
function patchCompileTarget(target) {
|
|
1995
|
+
let comp = target.compile;
|
|
1996
|
+
if (!comp)
|
|
1997
|
+
comp = target.compile = { isNative: false, hasHex: false, switches: {} };
|
|
1998
|
+
if (comp.hasHex) {
|
|
1999
|
+
if (!comp.nativeType)
|
|
2000
|
+
comp.nativeType = pxtc.NATIVE_TYPE_THUMB;
|
|
2001
|
+
}
|
|
2002
|
+
if (!comp.switches)
|
|
2003
|
+
comp.switches = {};
|
|
2004
|
+
if (comp.nativeType == pxtc.NATIVE_TYPE_VM)
|
|
2005
|
+
comp.sourceMap = true;
|
|
2006
|
+
// JS ref counting currently not supported
|
|
2007
|
+
comp.jsRefCounting = false;
|
|
2008
|
+
if (!comp.useUF2 && !comp.useELF && comp.noSourceInFlash == undefined)
|
|
2009
|
+
comp.noSourceInFlash = true; // no point putting sources in hex to be flashed
|
|
2010
|
+
if (comp.utf8 === undefined)
|
|
2011
|
+
comp.utf8 = true;
|
|
2012
|
+
let cs = target.compileService;
|
|
2013
|
+
if (cs) {
|
|
2014
|
+
if (cs.yottaTarget && !cs.yottaBinary)
|
|
2015
|
+
cs.yottaBinary = "pxt-microbit-app-combined.hex";
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
pxt.patchCompileTarget = patchCompileTarget;
|
|
2019
|
+
})(pxt || (pxt = {}));
|
|
2020
|
+
var ts;
|
|
2021
|
+
(function (ts) {
|
|
2022
|
+
var pxtc;
|
|
2023
|
+
(function (pxtc) {
|
|
2024
|
+
var Util;
|
|
2025
|
+
(function (Util) {
|
|
2026
|
+
function cloneTargetBundle(target) {
|
|
2027
|
+
target = Object.assign({}, target);
|
|
2028
|
+
const apiInfo = target.apiInfo;
|
|
2029
|
+
delete target.apiInfo;
|
|
2030
|
+
const bundleddirs = target.bundleddirs;
|
|
2031
|
+
delete target.bundleddirs;
|
|
2032
|
+
const bundledpkgs = target.bundledpkgs;
|
|
2033
|
+
delete target.bundledpkgs;
|
|
2034
|
+
const tutorialInfo = target.tutorialInfo;
|
|
2035
|
+
delete target.tutorialInfo;
|
|
2036
|
+
const res = Util.clone(target);
|
|
2037
|
+
if (apiInfo) {
|
|
2038
|
+
res.apiInfo = {};
|
|
2039
|
+
for (const key of Object.keys(apiInfo)) {
|
|
2040
|
+
const apis = apiInfo[key].apis;
|
|
2041
|
+
res.apiInfo[key] = {
|
|
2042
|
+
sha: apiInfo[key].sha,
|
|
2043
|
+
apis: {
|
|
2044
|
+
jres: Object.assign({}, apis.jres),
|
|
2045
|
+
byQName: cloneApis(apis.byQName)
|
|
2046
|
+
}
|
|
2047
|
+
};
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
if (bundleddirs) {
|
|
2051
|
+
res.bundleddirs = [...bundleddirs];
|
|
2052
|
+
}
|
|
2053
|
+
if (bundledpkgs) {
|
|
2054
|
+
res.bundledpkgs = {};
|
|
2055
|
+
for (const key of Object.keys(bundledpkgs)) {
|
|
2056
|
+
res.bundledpkgs[key] = Object.assign({}, bundledpkgs[key]);
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
if (tutorialInfo) {
|
|
2060
|
+
res.tutorialInfo = {};
|
|
2061
|
+
for (const key of Object.keys(tutorialInfo)) {
|
|
2062
|
+
const built = tutorialInfo[key];
|
|
2063
|
+
res.tutorialInfo[key] = {
|
|
2064
|
+
hash: built.hash,
|
|
2065
|
+
usedBlocks: Object.assign({}, built.usedBlocks),
|
|
2066
|
+
snippetBlocks: Object.assign({}, built.snippetBlocks),
|
|
2067
|
+
highlightBlocks: Object.assign({}, built.highlightBlocks),
|
|
2068
|
+
validateBlocks: Object.assign({}, built.validateBlocks),
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
return res;
|
|
2073
|
+
}
|
|
2074
|
+
Util.cloneTargetBundle = cloneTargetBundle;
|
|
2075
|
+
function cloneApis(byQName) {
|
|
2076
|
+
const res = {};
|
|
2077
|
+
for (const key of Object.keys(byQName)) {
|
|
2078
|
+
res[key] = cloneSymbolInfo(byQName[key]);
|
|
2079
|
+
}
|
|
2080
|
+
return res;
|
|
2081
|
+
}
|
|
2082
|
+
Util.cloneApis = cloneApis;
|
|
2083
|
+
function cloneSymbolInfo(sym) {
|
|
2084
|
+
var _a;
|
|
2085
|
+
return {
|
|
2086
|
+
// FIXME: This is a little dangerous, because we do edit the symbol attributes in some places
|
|
2087
|
+
// for localization. However, most of those edits are to top-level properties and only edits
|
|
2088
|
+
// to child objects matter so it *should* be fine
|
|
2089
|
+
attributes: Object.assign({}, sym.attributes),
|
|
2090
|
+
parameters: (_a = sym.parameters) === null || _a === void 0 ? void 0 : _a.map(cloneParameterDesc),
|
|
2091
|
+
extendsTypes: sym.extendsTypes ? [...sym.extendsTypes] : undefined,
|
|
2092
|
+
pkgs: sym.pkgs ? [...sym.pkgs] : undefined,
|
|
2093
|
+
combinedProperties: sym.combinedProperties ? [...sym.combinedProperties] : undefined,
|
|
2094
|
+
name: sym.name,
|
|
2095
|
+
namespace: sym.namespace,
|
|
2096
|
+
fileName: sym.fileName,
|
|
2097
|
+
kind: sym.kind,
|
|
2098
|
+
retType: sym.retType,
|
|
2099
|
+
isInstance: sym.isInstance,
|
|
2100
|
+
isContextual: sym.isContextual,
|
|
2101
|
+
qName: sym.qName,
|
|
2102
|
+
pkg: sym.pkg,
|
|
2103
|
+
snippet: sym.snippet,
|
|
2104
|
+
snippetName: sym.snippetName,
|
|
2105
|
+
snippetWithMarkers: sym.snippetWithMarkers,
|
|
2106
|
+
pySnippet: sym.pySnippet,
|
|
2107
|
+
pySnippetName: sym.pySnippetName,
|
|
2108
|
+
pySnippetWithMarkers: sym.pySnippetWithMarkers,
|
|
2109
|
+
blockFields: sym.blockFields,
|
|
2110
|
+
isReadOnly: sym.isReadOnly,
|
|
2111
|
+
pyName: sym.pyName,
|
|
2112
|
+
pyQName: sym.pyQName,
|
|
2113
|
+
snippetAddsDefinitions: sym.snippetAddsDefinitions,
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
Util.cloneSymbolInfo = cloneSymbolInfo;
|
|
2117
|
+
function cloneParameterDesc(param) {
|
|
2118
|
+
var _a, _b;
|
|
2119
|
+
return {
|
|
2120
|
+
name: param.name,
|
|
2121
|
+
description: param.description,
|
|
2122
|
+
type: param.type,
|
|
2123
|
+
pyTypeString: param.pyTypeString,
|
|
2124
|
+
initializer: param.initializer,
|
|
2125
|
+
default: param.default,
|
|
2126
|
+
properties: (_a = param.properties) === null || _a === void 0 ? void 0 : _a.map(clonePropertyDesc),
|
|
2127
|
+
handlerParameters: (_b = param.handlerParameters) === null || _b === void 0 ? void 0 : _b.map(clonePropertyDesc),
|
|
2128
|
+
options: param.options ? Util.clone(param.options) : undefined,
|
|
2129
|
+
isEnum: param.isEnum
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
function clonePropertyDesc(prop) {
|
|
2133
|
+
return {
|
|
2134
|
+
name: prop.name,
|
|
2135
|
+
type: prop.type
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
})(Util = pxtc.Util || (pxtc.Util = {}));
|
|
2139
|
+
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
2140
|
+
})(ts || (ts = {}));
|
|
2141
|
+
/// <reference path="../commonutil.ts"/>
|
|
2142
|
+
var ts;
|
|
2143
|
+
(function (ts) {
|
|
2144
|
+
var pxtc;
|
|
2145
|
+
(function (pxtc) {
|
|
2146
|
+
var U = pxtc.Util;
|
|
2147
|
+
const numberAttributes = [
|
|
2148
|
+
"weight",
|
|
2149
|
+
"imageLiteral",
|
|
2150
|
+
"gridLiteral",
|
|
2151
|
+
"colorGridLiteral",
|
|
2152
|
+
"topblockWeight",
|
|
2153
|
+
"inlineInputModeLimit",
|
|
2154
|
+
"gridLiteralVerticalSpacing",
|
|
2155
|
+
"gridLiteralHorizontalSpacing",
|
|
2156
|
+
"gridLiteralBorderRadius",
|
|
2157
|
+
];
|
|
2158
|
+
const booleanAttributes = [
|
|
2159
|
+
"advanced",
|
|
2160
|
+
"handlerStatement",
|
|
2161
|
+
"forceStatement",
|
|
2162
|
+
"afterOnStart",
|
|
2163
|
+
"optionalVariableArgs",
|
|
2164
|
+
"blockHidden",
|
|
2165
|
+
"constantShim",
|
|
2166
|
+
"blockCombine",
|
|
2167
|
+
"enumIsBitMask",
|
|
2168
|
+
"enumIsHash",
|
|
2169
|
+
"decompileIndirectFixedInstances",
|
|
2170
|
+
"topblock",
|
|
2171
|
+
"callInDebugger",
|
|
2172
|
+
"duplicateShadowOnDrag",
|
|
2173
|
+
"argsNullable",
|
|
2174
|
+
"compileHiddenArguments",
|
|
2175
|
+
"expandArgumentsInToolbox",
|
|
2176
|
+
"gridLiteralUseProjectPalette"
|
|
2177
|
+
];
|
|
2178
|
+
function parseCommentString(cmt) {
|
|
2179
|
+
let res = {
|
|
2180
|
+
paramDefl: {},
|
|
2181
|
+
callingConvention: 0 /* ir.CallingConvention.Plain */,
|
|
2182
|
+
_source: cmt
|
|
2183
|
+
};
|
|
2184
|
+
let didSomething = true;
|
|
2185
|
+
while (didSomething) {
|
|
2186
|
+
didSomething = false;
|
|
2187
|
+
cmt = cmt.replace(/\/\/%[ \t]*([\w\.-]+)(=(("[^"\n]*")|'([^'\n]*)'|([^\s]*)))?/, (f, n, d0, d1, v0, v1, v2) => {
|
|
2188
|
+
let v = v0 ? JSON.parse(v0) : (d0 ? (v0 || v1 || v2) : "true");
|
|
2189
|
+
if (!v)
|
|
2190
|
+
v = "";
|
|
2191
|
+
if (U.startsWith(n, "block.loc.")) {
|
|
2192
|
+
if (!res.locs)
|
|
2193
|
+
res.locs = {};
|
|
2194
|
+
res.locs[n.slice("block.loc.".length).toLowerCase() + "|block"] = v;
|
|
2195
|
+
}
|
|
2196
|
+
else if (U.startsWith(n, "jsdoc.loc.")) {
|
|
2197
|
+
if (!res.locs)
|
|
2198
|
+
res.locs = {};
|
|
2199
|
+
res.locs[n.slice("jsdoc.loc.".length).toLowerCase() + "|jsdoc"] = v;
|
|
2200
|
+
}
|
|
2201
|
+
else if (U.startsWith(n, "ariaLabel.loc.")) {
|
|
2202
|
+
if (!res.locs)
|
|
2203
|
+
res.locs = {};
|
|
2204
|
+
res.locs[n.slice("ariaLabel.loc.".length).toLowerCase() + "|ariaLabel"] = v;
|
|
2205
|
+
}
|
|
2206
|
+
else if (U.contains(n, ".loc.")) {
|
|
2207
|
+
if (!res.locs)
|
|
2208
|
+
res.locs = {};
|
|
2209
|
+
const p = n.slice(0, n.indexOf('.loc.'));
|
|
2210
|
+
const l = n.slice(n.indexOf('.loc.') + '.loc.'.length);
|
|
2211
|
+
res.locs[l + "|param|" + p] = v;
|
|
2212
|
+
}
|
|
2213
|
+
else if (U.endsWith(n, ".defl")) {
|
|
2214
|
+
if (v.indexOf(" ") > -1) {
|
|
2215
|
+
res.paramDefl[n.slice(0, n.length - 5)] = `"${v}"`;
|
|
2216
|
+
}
|
|
2217
|
+
else {
|
|
2218
|
+
res.paramDefl[n.slice(0, n.length - 5)] = v;
|
|
2219
|
+
}
|
|
2220
|
+
if (!res.explicitDefaults)
|
|
2221
|
+
res.explicitDefaults = [];
|
|
2222
|
+
res.explicitDefaults.push(n.slice(0, n.length - 5));
|
|
2223
|
+
}
|
|
2224
|
+
else if (U.endsWith(n, ".shadow")) {
|
|
2225
|
+
if (!res._shadowOverrides)
|
|
2226
|
+
res._shadowOverrides = {};
|
|
2227
|
+
res._shadowOverrides[n.slice(0, n.length - 7)] = v;
|
|
2228
|
+
}
|
|
2229
|
+
else if (U.endsWith(n, ".snippet")) {
|
|
2230
|
+
if (!res.paramSnippets)
|
|
2231
|
+
res.paramSnippets = {};
|
|
2232
|
+
const paramName = n.slice(0, n.length - 8);
|
|
2233
|
+
if (!res.paramSnippets[paramName])
|
|
2234
|
+
res.paramSnippets[paramName] = {};
|
|
2235
|
+
res.paramSnippets[paramName].ts = v;
|
|
2236
|
+
}
|
|
2237
|
+
else if (U.endsWith(n, ".pySnippet")) {
|
|
2238
|
+
if (!res.paramSnippets)
|
|
2239
|
+
res.paramSnippets = {};
|
|
2240
|
+
const paramName = n.slice(0, n.length - 10);
|
|
2241
|
+
if (!res.paramSnippets[paramName])
|
|
2242
|
+
res.paramSnippets[paramName] = {};
|
|
2243
|
+
res.paramSnippets[paramName].python = v;
|
|
2244
|
+
}
|
|
2245
|
+
else if (U.endsWith(n, ".fieldEditor")) {
|
|
2246
|
+
if (!res.paramFieldEditor)
|
|
2247
|
+
res.paramFieldEditor = {};
|
|
2248
|
+
res.paramFieldEditor[n.slice(0, n.length - 12)] = v;
|
|
2249
|
+
}
|
|
2250
|
+
else if (U.contains(n, ".fieldOptions.")) {
|
|
2251
|
+
if (!res.paramFieldEditorOptions)
|
|
2252
|
+
res.paramFieldEditorOptions = {};
|
|
2253
|
+
const field = n.slice(0, n.indexOf('.fieldOptions.'));
|
|
2254
|
+
const key = n.slice(n.indexOf('.fieldOptions.') + 14, n.length);
|
|
2255
|
+
if (!res.paramFieldEditorOptions[field])
|
|
2256
|
+
res.paramFieldEditorOptions[field] = {};
|
|
2257
|
+
res.paramFieldEditorOptions[field][key] = v;
|
|
2258
|
+
}
|
|
2259
|
+
else if (U.contains(n, ".shadowOptions.")) {
|
|
2260
|
+
if (!res.paramShadowOptions)
|
|
2261
|
+
res.paramShadowOptions = {};
|
|
2262
|
+
const field = n.slice(0, n.indexOf('.shadowOptions.'));
|
|
2263
|
+
const key = n.slice(n.indexOf('.shadowOptions.') + 15, n.length);
|
|
2264
|
+
if (!res.paramShadowOptions[field])
|
|
2265
|
+
res.paramShadowOptions[field] = {};
|
|
2266
|
+
res.paramShadowOptions[field][key] = v;
|
|
2267
|
+
}
|
|
2268
|
+
else if (U.endsWith(n, ".label")) {
|
|
2269
|
+
if (!res.paramLabels)
|
|
2270
|
+
res.paramLabels = {};
|
|
2271
|
+
res.paramLabels[n.slice(0, n.length - 6)] = v;
|
|
2272
|
+
}
|
|
2273
|
+
else if (U.endsWith(n, ".min")) {
|
|
2274
|
+
if (!res.paramMin)
|
|
2275
|
+
res.paramMin = {};
|
|
2276
|
+
res.paramMin[n.slice(0, n.length - 4)] = v;
|
|
2277
|
+
}
|
|
2278
|
+
else if (U.endsWith(n, ".max")) {
|
|
2279
|
+
if (!res.paramMax)
|
|
2280
|
+
res.paramMax = {};
|
|
2281
|
+
res.paramMax[n.slice(0, n.length - 4)] = v;
|
|
2282
|
+
}
|
|
2283
|
+
else {
|
|
2284
|
+
res[n] = v;
|
|
2285
|
+
}
|
|
2286
|
+
didSomething = true;
|
|
2287
|
+
return "//% ";
|
|
2288
|
+
});
|
|
2289
|
+
}
|
|
2290
|
+
for (let n of numberAttributes) {
|
|
2291
|
+
if (typeof res[n] == "string")
|
|
2292
|
+
res[n] = parseInt(res[n]);
|
|
2293
|
+
}
|
|
2294
|
+
for (let n of booleanAttributes) {
|
|
2295
|
+
if (typeof res[n] == "string")
|
|
2296
|
+
res[n] = res[n] == 'true' || res[n] == '1' ? true : false;
|
|
2297
|
+
}
|
|
2298
|
+
if (res.trackArgs) {
|
|
2299
|
+
res.trackArgs = res.trackArgs.split(/[ ,]+/).map(s => parseInt(s) || 0);
|
|
2300
|
+
}
|
|
2301
|
+
if (res.enumInitialMembers) {
|
|
2302
|
+
res.enumInitialMembers = res.enumInitialMembers.split(/[ ,]+/);
|
|
2303
|
+
}
|
|
2304
|
+
if (res.blockExternalInputs && !res.inlineInputMode) {
|
|
2305
|
+
res.inlineInputMode = "external";
|
|
2306
|
+
}
|
|
2307
|
+
res.paramHelp = {};
|
|
2308
|
+
res.jsDoc = "";
|
|
2309
|
+
cmt = cmt.replace(/\/\*\*([^]*?)\*\//g, (full, doccmt) => {
|
|
2310
|
+
doccmt = doccmt.replace(/\n\s*(\*\s*)?/g, "\n");
|
|
2311
|
+
doccmt = doccmt.replace(/^\s*@param\s+(\w+)\s+(.*)$/mg, (full, name, desc) => {
|
|
2312
|
+
res.paramHelp[name] = desc;
|
|
2313
|
+
if (!res.paramDefl[name]) {
|
|
2314
|
+
// these don't add to res.explicitDefaults
|
|
2315
|
+
let m = /\beg\.?:\s*(.+)/.exec(desc);
|
|
2316
|
+
if (m && m[1]) {
|
|
2317
|
+
let defaultValue = /(?:"([^"]*)")|(?:'([^']*)')|(?:([^\s,]+))/g.exec(m[1]);
|
|
2318
|
+
if (defaultValue) {
|
|
2319
|
+
let val = defaultValue[1] || defaultValue[2] || defaultValue[3];
|
|
2320
|
+
if (!val)
|
|
2321
|
+
val = "";
|
|
2322
|
+
// If there are spaces in the value, it means the value was surrounded with quotes, so add them back
|
|
2323
|
+
if (val.indexOf(" ") > -1) {
|
|
2324
|
+
res.paramDefl[name] = `"${val}"`;
|
|
2325
|
+
}
|
|
2326
|
+
else {
|
|
2327
|
+
res.paramDefl[name] = val;
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
return "";
|
|
2333
|
+
});
|
|
2334
|
+
res.jsDoc += doccmt;
|
|
2335
|
+
return "";
|
|
2336
|
+
});
|
|
2337
|
+
res.jsDoc = res.jsDoc.trim();
|
|
2338
|
+
if (res.async)
|
|
2339
|
+
res.callingConvention = 1 /* ir.CallingConvention.Async */;
|
|
2340
|
+
if (res.promise)
|
|
2341
|
+
res.callingConvention = 2 /* ir.CallingConvention.Promise */;
|
|
2342
|
+
if (res.jres)
|
|
2343
|
+
res.whenUsed = true;
|
|
2344
|
+
if (res.subcategories) {
|
|
2345
|
+
try {
|
|
2346
|
+
res.subcategories = JSON.parse(res.subcategories);
|
|
2347
|
+
}
|
|
2348
|
+
catch (e) {
|
|
2349
|
+
res.subcategories = undefined;
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
if (res.groups) {
|
|
2353
|
+
try {
|
|
2354
|
+
res.groups = JSON.parse(res.groups);
|
|
2355
|
+
}
|
|
2356
|
+
catch (e) {
|
|
2357
|
+
res.groups = undefined;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
if (res.groupIcons) {
|
|
2361
|
+
try {
|
|
2362
|
+
res.groupIcons = JSON.parse(res.groupIcons);
|
|
2363
|
+
}
|
|
2364
|
+
catch (e) {
|
|
2365
|
+
res.groupIcons = undefined;
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
if (res.groupHelp) {
|
|
2369
|
+
try {
|
|
2370
|
+
res.groupHelp = JSON.parse(res.groupHelp);
|
|
2371
|
+
}
|
|
2372
|
+
catch (e) {
|
|
2373
|
+
res.groupHelp = undefined;
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
updateBlockDef(res);
|
|
2377
|
+
return res;
|
|
2378
|
+
}
|
|
2379
|
+
pxtc.parseCommentString = parseCommentString;
|
|
2380
|
+
function updateBlockDef(attrs) {
|
|
2381
|
+
if (attrs.block) {
|
|
2382
|
+
const parts = attrs.block.split("||");
|
|
2383
|
+
attrs._def = applyOverrides(parseBlockDefinition(parts[0]));
|
|
2384
|
+
if (!attrs._def)
|
|
2385
|
+
pxt.debug("Unable to parse block def for id: " + attrs.blockId);
|
|
2386
|
+
if (parts[1])
|
|
2387
|
+
attrs._expandedDef = applyOverrides(parseBlockDefinition(parts[1]));
|
|
2388
|
+
if (parts[1] && !attrs._expandedDef)
|
|
2389
|
+
pxt.debug("Unable to parse expanded block def for id: " + attrs.blockId);
|
|
2390
|
+
}
|
|
2391
|
+
function applyOverrides(def) {
|
|
2392
|
+
if (attrs._shadowOverrides) {
|
|
2393
|
+
def.parameters.forEach(p => {
|
|
2394
|
+
const shadow = attrs._shadowOverrides[p.name];
|
|
2395
|
+
if (shadow === "unset")
|
|
2396
|
+
delete p.shadowBlockId;
|
|
2397
|
+
else if (shadow != null)
|
|
2398
|
+
p.shadowBlockId = shadow;
|
|
2399
|
+
});
|
|
2400
|
+
}
|
|
2401
|
+
return def;
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
pxtc.updateBlockDef = updateBlockDef;
|
|
2405
|
+
function parseBlockDefinition(def) {
|
|
2406
|
+
const tokens = [];
|
|
2407
|
+
let currentWord;
|
|
2408
|
+
let strIndex = 0;
|
|
2409
|
+
for (; strIndex < def.length; strIndex++) {
|
|
2410
|
+
const char = def[strIndex];
|
|
2411
|
+
const restoreIndex = strIndex;
|
|
2412
|
+
let newToken;
|
|
2413
|
+
switch (char) {
|
|
2414
|
+
case "*":
|
|
2415
|
+
case "_":
|
|
2416
|
+
const tk = eatToken(c => c == char);
|
|
2417
|
+
const offset = char === "_" ? 2 : 0;
|
|
2418
|
+
if (tk.length === 1)
|
|
2419
|
+
newToken = { kind: 1 /* TokenKind.SingleAsterisk */ << offset, content: tk };
|
|
2420
|
+
else if (tk.length === 2)
|
|
2421
|
+
newToken = { kind: 2 /* TokenKind.DoubleAsterisk */ << offset, content: tk };
|
|
2422
|
+
else if (tk.length === 3)
|
|
2423
|
+
newToken = { kind: 3 /* TokenKind.TripleAsterisk */ << offset, content: tk };
|
|
2424
|
+
else
|
|
2425
|
+
strIndex = restoreIndex; // error: no more than three style marks
|
|
2426
|
+
break;
|
|
2427
|
+
case "`":
|
|
2428
|
+
const image = eatEnclosure("`");
|
|
2429
|
+
if (image === undefined) {
|
|
2430
|
+
strIndex = restoreIndex; // error: not terminated
|
|
2431
|
+
break;
|
|
2432
|
+
}
|
|
2433
|
+
newToken = { kind: 256 /* TokenKind.Image */, content: image };
|
|
2434
|
+
break;
|
|
2435
|
+
case "|":
|
|
2436
|
+
newToken = { kind: 32 /* TokenKind.Pipe */ };
|
|
2437
|
+
break;
|
|
2438
|
+
case "\\":
|
|
2439
|
+
if (strIndex < (def.length - 1))
|
|
2440
|
+
newToken = { kind: 16 /* TokenKind.Escape */, content: def[1 + (strIndex++)] };
|
|
2441
|
+
break;
|
|
2442
|
+
case "[":
|
|
2443
|
+
const contentText = eatEnclosure("]");
|
|
2444
|
+
if (contentText !== undefined && def[strIndex++ + 1] === "(") {
|
|
2445
|
+
const contentClass = eatEnclosure(")");
|
|
2446
|
+
if (contentClass !== undefined) {
|
|
2447
|
+
newToken = { kind: 512 /* TokenKind.TaggedText */, content: contentText, type: contentClass };
|
|
2448
|
+
break;
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
strIndex = restoreIndex; // error: format should be [text](class)
|
|
2452
|
+
break;
|
|
2453
|
+
case "$":
|
|
2454
|
+
case "%":
|
|
2455
|
+
const param = eatToken(c => /[a-zA-Z0-9_=]/.test(c), true).split("=");
|
|
2456
|
+
if (param.length > 2) {
|
|
2457
|
+
strIndex = restoreIndex; // error: too many equals signs
|
|
2458
|
+
break;
|
|
2459
|
+
}
|
|
2460
|
+
let varName;
|
|
2461
|
+
if (def[strIndex + 1] === "(") {
|
|
2462
|
+
const oldIndex = strIndex;
|
|
2463
|
+
++strIndex;
|
|
2464
|
+
varName = eatEnclosure(")");
|
|
2465
|
+
if (!varName)
|
|
2466
|
+
strIndex = oldIndex;
|
|
2467
|
+
}
|
|
2468
|
+
newToken = { kind: (char === "$") ? 1024 /* TokenKind.ParamRef */ : 64 /* TokenKind.Parameter */, content: param[0], type: param[1], name: varName };
|
|
2469
|
+
break;
|
|
2470
|
+
}
|
|
2471
|
+
if (newToken) {
|
|
2472
|
+
if (currentWord)
|
|
2473
|
+
tokens.push({ kind: 128 /* TokenKind.Word */, content: currentWord });
|
|
2474
|
+
currentWord = undefined;
|
|
2475
|
+
tokens.push(newToken);
|
|
2476
|
+
}
|
|
2477
|
+
else if (!currentWord) {
|
|
2478
|
+
currentWord = char;
|
|
2479
|
+
}
|
|
2480
|
+
else {
|
|
2481
|
+
currentWord += char;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
if (currentWord)
|
|
2485
|
+
tokens.push({ kind: 128 /* TokenKind.Word */, content: currentWord });
|
|
2486
|
+
const parts = [];
|
|
2487
|
+
const parameters = [];
|
|
2488
|
+
let stack = [];
|
|
2489
|
+
let open = 0;
|
|
2490
|
+
let currentLabel = "";
|
|
2491
|
+
let labelStack = [];
|
|
2492
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
2493
|
+
const token = tokens[i].kind;
|
|
2494
|
+
const top = stack[stack.length - 1];
|
|
2495
|
+
if (token & 15 /* TokenKind.StyleMarks */) {
|
|
2496
|
+
pushCurrentLabel(tokens[i].content);
|
|
2497
|
+
if (token & open) {
|
|
2498
|
+
if (top & token) {
|
|
2499
|
+
stack.pop();
|
|
2500
|
+
open ^= token;
|
|
2501
|
+
// Handle triple tokens
|
|
2502
|
+
const remainder = (top & open) | (token & open);
|
|
2503
|
+
if (remainder) {
|
|
2504
|
+
stack.push(remainder);
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
else {
|
|
2508
|
+
// We encountered a mismatched mark, so clear previous styles
|
|
2509
|
+
collapseLabels();
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
else {
|
|
2513
|
+
open |= token;
|
|
2514
|
+
stack.push(token);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
else if (token & 144 /* TokenKind.Text */) {
|
|
2518
|
+
currentLabel += tokens[i].content;
|
|
2519
|
+
}
|
|
2520
|
+
else if (token & 1120 /* TokenKind.Unstylable */) {
|
|
2521
|
+
pushLabels();
|
|
2522
|
+
}
|
|
2523
|
+
if (token == 64 /* TokenKind.Parameter */) {
|
|
2524
|
+
const param = { kind: "param", name: tokens[i].content, shadowBlockId: tokens[i].type, ref: false };
|
|
2525
|
+
if (tokens[i].name)
|
|
2526
|
+
param.varName = tokens[i].name;
|
|
2527
|
+
parts.push(param);
|
|
2528
|
+
parameters.push(param);
|
|
2529
|
+
}
|
|
2530
|
+
else if (token == 1024 /* TokenKind.ParamRef */) {
|
|
2531
|
+
const param = { kind: "param", name: tokens[i].content, shadowBlockId: tokens[i].type, ref: true };
|
|
2532
|
+
if (tokens[i].name)
|
|
2533
|
+
param.varName = tokens[i].name;
|
|
2534
|
+
parts.push(param);
|
|
2535
|
+
parameters.push(param);
|
|
2536
|
+
}
|
|
2537
|
+
else if (token == 256 /* TokenKind.Image */) {
|
|
2538
|
+
pushCurrentLabel();
|
|
2539
|
+
labelStack.push({ kind: "image", uri: tokens[i].content });
|
|
2540
|
+
}
|
|
2541
|
+
else if (token == 512 /* TokenKind.TaggedText */) {
|
|
2542
|
+
pushCurrentLabel();
|
|
2543
|
+
labelStack.push({ kind: "label", text: tokens[i].content, cssClass: tokens[i].type });
|
|
2544
|
+
}
|
|
2545
|
+
else if (token == 32 /* TokenKind.Pipe */) {
|
|
2546
|
+
parts.push({ kind: "break" });
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
pushLabels();
|
|
2550
|
+
return { parts, parameters };
|
|
2551
|
+
function eatToken(pred, skipCurrent = false) {
|
|
2552
|
+
let current = "";
|
|
2553
|
+
if (skipCurrent)
|
|
2554
|
+
strIndex++;
|
|
2555
|
+
while (strIndex < def.length && pred(def[strIndex])) {
|
|
2556
|
+
current += def[strIndex];
|
|
2557
|
+
++strIndex;
|
|
2558
|
+
}
|
|
2559
|
+
if (current)
|
|
2560
|
+
strIndex--;
|
|
2561
|
+
return current;
|
|
2562
|
+
}
|
|
2563
|
+
function eatEnclosure(endMark) {
|
|
2564
|
+
const content = eatToken(c => c !== endMark, true);
|
|
2565
|
+
if (def[strIndex + 1] !== endMark)
|
|
2566
|
+
return undefined;
|
|
2567
|
+
++strIndex;
|
|
2568
|
+
return content;
|
|
2569
|
+
}
|
|
2570
|
+
function collapseLabels() {
|
|
2571
|
+
let combined = "";
|
|
2572
|
+
let newStack = [];
|
|
2573
|
+
for (const item of labelStack) {
|
|
2574
|
+
if (isBlockPart(item)) {
|
|
2575
|
+
newStack.push({
|
|
2576
|
+
content: combined,
|
|
2577
|
+
styles: 0
|
|
2578
|
+
});
|
|
2579
|
+
newStack.push(item);
|
|
2580
|
+
combined = "";
|
|
2581
|
+
}
|
|
2582
|
+
else {
|
|
2583
|
+
combined += item.content;
|
|
2584
|
+
if (item.endingToken) {
|
|
2585
|
+
combined += item.endingToken;
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
labelStack = newStack;
|
|
2590
|
+
if (combined) {
|
|
2591
|
+
labelStack.push({
|
|
2592
|
+
content: combined,
|
|
2593
|
+
styles: 0
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
// Clear the style state as well
|
|
2597
|
+
stack = [];
|
|
2598
|
+
open = 0;
|
|
2599
|
+
}
|
|
2600
|
+
function pushLabels() {
|
|
2601
|
+
pushCurrentLabel();
|
|
2602
|
+
if (open) {
|
|
2603
|
+
collapseLabels();
|
|
2604
|
+
}
|
|
2605
|
+
while (labelStack.length) {
|
|
2606
|
+
const label = labelStack.shift();
|
|
2607
|
+
if (isBlockPart(label)) {
|
|
2608
|
+
parts.push(label);
|
|
2609
|
+
}
|
|
2610
|
+
else {
|
|
2611
|
+
if (!label.content)
|
|
2612
|
+
continue;
|
|
2613
|
+
const styles = [];
|
|
2614
|
+
if (label.styles & 10 /* TokenKind.Bold */)
|
|
2615
|
+
styles.push("bold");
|
|
2616
|
+
if (label.styles & 5 /* TokenKind.Italics */)
|
|
2617
|
+
styles.push("italics");
|
|
2618
|
+
parts.push({ kind: "label", text: label.content, style: styles });
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
function pushCurrentLabel(endingToken) {
|
|
2623
|
+
labelStack.push({
|
|
2624
|
+
content: currentLabel,
|
|
2625
|
+
styles: open,
|
|
2626
|
+
endingToken
|
|
2627
|
+
});
|
|
2628
|
+
currentLabel = "";
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
pxtc.parseBlockDefinition = parseBlockDefinition;
|
|
2632
|
+
function isBlockPart(p) {
|
|
2633
|
+
return !!(p.kind);
|
|
2634
|
+
}
|
|
2635
|
+
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
2636
|
+
})(ts || (ts = {}));
|
|
2637
|
+
var pxt;
|
|
2638
|
+
(function (pxt) {
|
|
2639
|
+
var github;
|
|
2640
|
+
(function (github) {
|
|
2641
|
+
// parse https://github.com/[company]/[project](/filepath)(#tag)
|
|
2642
|
+
function parseRepoId(repo) {
|
|
2643
|
+
if (!repo)
|
|
2644
|
+
return undefined;
|
|
2645
|
+
// clean out whitespaces
|
|
2646
|
+
repo = repo.trim();
|
|
2647
|
+
// trim trailing /
|
|
2648
|
+
repo = repo.replace(/\/$/, '');
|
|
2649
|
+
// convert github pages into github repo
|
|
2650
|
+
const mgh = /^https:\/\/([^./#]+)\.github\.io\/([^/#]+)\/?$/i.exec(repo);
|
|
2651
|
+
if (mgh)
|
|
2652
|
+
repo = `github:${mgh[1]}/${mgh[2]}`;
|
|
2653
|
+
repo = repo.replace(/^github:/i, "");
|
|
2654
|
+
repo = repo.replace(/^https:\/\/github\.com\//i, "");
|
|
2655
|
+
repo = repo.replace(/\.git\b/i, "");
|
|
2656
|
+
const m = /^([^#\/:]+)\/([^#\/:]+)(\/([^#]+))?(#([^\/:]*))?$/.exec(repo);
|
|
2657
|
+
if (!m)
|
|
2658
|
+
return undefined;
|
|
2659
|
+
const owner = m[1];
|
|
2660
|
+
const project = m[2];
|
|
2661
|
+
let fileName = m[4];
|
|
2662
|
+
const tag = m[6];
|
|
2663
|
+
const treeM = fileName && /^tree\/([^\/]+\/)/.exec(fileName);
|
|
2664
|
+
if (treeM) {
|
|
2665
|
+
// https://github.com/pelikhan/mono-demo/tree/master/demo2
|
|
2666
|
+
fileName = fileName.slice(treeM[0].length);
|
|
2667
|
+
// branch info?
|
|
2668
|
+
}
|
|
2669
|
+
return {
|
|
2670
|
+
owner,
|
|
2671
|
+
project,
|
|
2672
|
+
slug: join(owner, project),
|
|
2673
|
+
fullName: join(owner, project, fileName),
|
|
2674
|
+
tag,
|
|
2675
|
+
fileName
|
|
2676
|
+
};
|
|
2677
|
+
}
|
|
2678
|
+
github.parseRepoId = parseRepoId;
|
|
2679
|
+
function stringifyRepo(p, ignoreCase = false) {
|
|
2680
|
+
return p ? "github:" + (ignoreCase ? p.fullName : p.fullName.toLowerCase()) + (p.tag ? `#${p.tag}` : '') : undefined;
|
|
2681
|
+
}
|
|
2682
|
+
github.stringifyRepo = stringifyRepo;
|
|
2683
|
+
function join(...parts) {
|
|
2684
|
+
return parts.filter(p => !!p).join('/');
|
|
2685
|
+
}
|
|
2686
|
+
github.join = join;
|
|
2687
|
+
})(github = pxt.github || (pxt.github = {}));
|
|
2688
|
+
})(pxt || (pxt = {}));
|
|
2689
|
+
/// <reference path="../../localtypings/pxtarget.d.ts"/>
|
|
2690
|
+
/// <reference path="../commonutil.ts"/>
|
|
2691
|
+
/// <reference path="sha256.ts"/>
|
|
2692
|
+
/// <reference path="../constants.ts"/>
|
|
2693
|
+
/// <reference path="packageutils.ts"/>
|
|
2694
|
+
/// <reference path="targetutils.ts"/>
|
|
2695
|
+
/// <reference path="commentattrs.ts"/>
|
|
2696
|
+
/// <reference path="githubid.ts"/>
|
|
2697
|
+
var ts;
|
|
2698
|
+
(function (ts) {
|
|
2699
|
+
var pxtc;
|
|
2700
|
+
(function (pxtc) {
|
|
2701
|
+
pxtc.NATIVE_TYPE_THUMB = "thumb";
|
|
2702
|
+
pxtc.NATIVE_TYPE_VM = "vm";
|
|
2703
|
+
function emptyExtInfo(compileService) {
|
|
2704
|
+
let cs = compileService;
|
|
2705
|
+
if (!cs)
|
|
2706
|
+
cs = {};
|
|
2707
|
+
const pio = !!cs.platformioIni;
|
|
2708
|
+
const docker = cs.buildEngine == "dockermake" || cs.buildEngine == "dockercross" || cs.buildEngine == "dockerespidf";
|
|
2709
|
+
const r = {
|
|
2710
|
+
functions: [],
|
|
2711
|
+
generatedFiles: {},
|
|
2712
|
+
extensionFiles: {},
|
|
2713
|
+
sha: "",
|
|
2714
|
+
compileData: "",
|
|
2715
|
+
shimsDTS: "",
|
|
2716
|
+
enumsDTS: "",
|
|
2717
|
+
onlyPublic: true
|
|
2718
|
+
};
|
|
2719
|
+
if (pio)
|
|
2720
|
+
r.platformio = { dependencies: {} };
|
|
2721
|
+
else if (docker)
|
|
2722
|
+
r.npmDependencies = {};
|
|
2723
|
+
else
|
|
2724
|
+
r.yotta = { config: {}, dependencies: {} };
|
|
2725
|
+
return r;
|
|
2726
|
+
}
|
|
2727
|
+
pxtc.emptyExtInfo = emptyExtInfo;
|
|
2728
|
+
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
2729
|
+
})(ts || (ts = {}));
|
|
2730
|
+
var pxt;
|
|
2731
|
+
(function (pxt) {
|
|
2732
|
+
var cpp;
|
|
2733
|
+
(function (cpp) {
|
|
2734
|
+
var U = pxtc.Util;
|
|
2735
|
+
const lf = U.lf;
|
|
2736
|
+
const vmKeepFunctions = {
|
|
2737
|
+
"pxt::mkAction": 1,
|
|
2738
|
+
"pxt::dumpPerfCounters": 1,
|
|
2739
|
+
"pxt::deepSleep": 1,
|
|
2740
|
+
"pxt::getConfig": 1,
|
|
2741
|
+
"pxtrt::mkMap": 1,
|
|
2742
|
+
"pxtrt::mapSet": 1,
|
|
2743
|
+
"pxtrt::stclo": 1,
|
|
2744
|
+
"pxtrt::mklocRef": 1,
|
|
2745
|
+
"pxtrt::stlocRef": 1,
|
|
2746
|
+
"pxtrt::ldlocRef": 1,
|
|
2747
|
+
"pxtrt::panic": 1,
|
|
2748
|
+
};
|
|
2749
|
+
function nsWriter(nskw = "namespace") {
|
|
2750
|
+
let text = "";
|
|
2751
|
+
let currNs = "";
|
|
2752
|
+
let setNs = (ns, over = "") => {
|
|
2753
|
+
if (currNs == ns)
|
|
2754
|
+
return;
|
|
2755
|
+
if (currNs)
|
|
2756
|
+
text += "}\n";
|
|
2757
|
+
if (ns)
|
|
2758
|
+
text += over || (nskw + " " + ns + " {\n");
|
|
2759
|
+
currNs = ns;
|
|
2760
|
+
};
|
|
2761
|
+
let indent = " ";
|
|
2762
|
+
return {
|
|
2763
|
+
setNs,
|
|
2764
|
+
clear: () => {
|
|
2765
|
+
text = "";
|
|
2766
|
+
currNs = "";
|
|
2767
|
+
},
|
|
2768
|
+
write: (s) => {
|
|
2769
|
+
if (!s.trim())
|
|
2770
|
+
text += "\n";
|
|
2771
|
+
else {
|
|
2772
|
+
s = s.trim()
|
|
2773
|
+
.replace(/^\s*/mg, indent)
|
|
2774
|
+
.replace(/^(\s*)\*/mg, (f, s) => s + " *");
|
|
2775
|
+
text += s + "\n";
|
|
2776
|
+
}
|
|
2777
|
+
},
|
|
2778
|
+
incrIndent: () => {
|
|
2779
|
+
indent += " ";
|
|
2780
|
+
},
|
|
2781
|
+
decrIndent: () => {
|
|
2782
|
+
indent = indent.slice(4);
|
|
2783
|
+
},
|
|
2784
|
+
finish: () => {
|
|
2785
|
+
setNs("");
|
|
2786
|
+
return text;
|
|
2787
|
+
}
|
|
2788
|
+
};
|
|
2789
|
+
}
|
|
2790
|
+
cpp.nsWriter = nsWriter;
|
|
2791
|
+
function parseCppInt(v) {
|
|
2792
|
+
if (!v)
|
|
2793
|
+
return null;
|
|
2794
|
+
v = v.trim();
|
|
2795
|
+
let mm = /^\((.*)\)/.exec(v);
|
|
2796
|
+
if (mm)
|
|
2797
|
+
v = mm[1];
|
|
2798
|
+
if (/^-?(\d+|0[xX][0-9a-fA-F]+)$/.test(v))
|
|
2799
|
+
return parseInt(v);
|
|
2800
|
+
return null;
|
|
2801
|
+
}
|
|
2802
|
+
cpp.parseCppInt = parseCppInt;
|
|
2803
|
+
class PkgConflictError extends Error {
|
|
2804
|
+
constructor(msg) {
|
|
2805
|
+
super(msg);
|
|
2806
|
+
this.isUserError = true;
|
|
2807
|
+
this.message = msg;
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
cpp.PkgConflictError = PkgConflictError;
|
|
2811
|
+
/**
|
|
2812
|
+
* Generates native extension files from pxt.json and project files, with dependencies
|
|
2813
|
+
* under pxt_modules/<directory>/. Dependencies resolve by directory, pxt.json name,
|
|
2814
|
+
* or their prefix before "---".
|
|
2815
|
+
* The target must not have variant overrides applied.
|
|
2816
|
+
* @example getExtensionInfo({ "pxt.json": config, "main.cpp": source }, target, "v2", host)
|
|
2817
|
+
*/
|
|
2818
|
+
function getExtensionInfo(files, target, variant, host) {
|
|
2819
|
+
const appTarget = pxt.getAppTargetVariant(target, variant);
|
|
2820
|
+
const constsName = "dal.d.ts";
|
|
2821
|
+
let sourcePath = "/source/";
|
|
2822
|
+
let disabledDeps = "";
|
|
2823
|
+
const packages = {};
|
|
2824
|
+
const runtimePackages = {};
|
|
2825
|
+
const packagePaths = Object.create(null);
|
|
2826
|
+
for (const path of Object.keys(files)) {
|
|
2827
|
+
const match = /^pxt_modules\/([^/]+)\/pxt\.json$/.exec(path);
|
|
2828
|
+
if (!match)
|
|
2829
|
+
continue;
|
|
2830
|
+
const config = JSON.parse(files[path]);
|
|
2831
|
+
const directory = path.slice(0, -"pxt.json".length);
|
|
2832
|
+
for (const id of [match[1], config.name]) {
|
|
2833
|
+
if (!id)
|
|
2834
|
+
continue;
|
|
2835
|
+
for (const alias of [id, id.replace(/---.*/, "")]) {
|
|
2836
|
+
const paths = packagePaths[alias] || (packagePaths[alias] = []);
|
|
2837
|
+
if (paths.indexOf(directory) < 0)
|
|
2838
|
+
paths.push(directory);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
const resolvePath = (id) => {
|
|
2843
|
+
if (id == "this")
|
|
2844
|
+
return "";
|
|
2845
|
+
const path = "pxt_modules/" + id + "/";
|
|
2846
|
+
if (files[path + "pxt.json"] != null)
|
|
2847
|
+
return path;
|
|
2848
|
+
const paths = packagePaths[id];
|
|
2849
|
+
if (paths && paths.length > 1)
|
|
2850
|
+
U.userError(`extension ${id} matches multiple directories: ${paths.join(", ")}`);
|
|
2851
|
+
return paths && paths[0];
|
|
2852
|
+
};
|
|
2853
|
+
const readFile = (pkg, name) => files[pkg.path + name];
|
|
2854
|
+
const dependencies = (pkg) => pxt.packageUtils.getConfigDependencies(pkg.config, pkg.id == "this", false, id => resolvePath(id) != null);
|
|
2855
|
+
const visit = (id, version, runtime) => {
|
|
2856
|
+
const path = resolvePath(id);
|
|
2857
|
+
if (path == null)
|
|
2858
|
+
U.userError(`extension ${id} is missing pxt.json`);
|
|
2859
|
+
if (runtimePackages[path] || (!runtime && packages[path]))
|
|
2860
|
+
return;
|
|
2861
|
+
if (runtime)
|
|
2862
|
+
runtimePackages[path] = true;
|
|
2863
|
+
let pkg = packages[path];
|
|
2864
|
+
if (!pkg) {
|
|
2865
|
+
const configText = files[path + "pxt.json"];
|
|
2866
|
+
if (!configText)
|
|
2867
|
+
U.userError(`extension ${id} is missing pxt.json`);
|
|
2868
|
+
const config = JSON.parse(configText);
|
|
2869
|
+
if (!config.dependencies || !Array.isArray(config.files))
|
|
2870
|
+
U.userError(`Invalid pxt.json in extension ${id}`);
|
|
2871
|
+
const packageId = path ? path.slice("pxt_modules/".length, -1) : "this";
|
|
2872
|
+
pkg = packages[path] = { id: packageId, path, config, files: [], version };
|
|
2873
|
+
}
|
|
2874
|
+
const deps = dependencies(pkg);
|
|
2875
|
+
for (const dep of Object.keys(deps))
|
|
2876
|
+
visit(dep, deps[dep], runtime);
|
|
2877
|
+
for (const dep of Object.keys(pkg.config.cppDependencies || {}))
|
|
2878
|
+
visit(dep, pkg.config.cppDependencies[dep], false);
|
|
2879
|
+
};
|
|
2880
|
+
visit("this", "file:.", true);
|
|
2881
|
+
const mainPkg = packages[""];
|
|
2882
|
+
const mainPkgDeps = U.values(packages).sort((a, b) => a.id == b.id ? 0 : a.id == "this" ? 1 : b.id == "this" ? -1 : U.strcmp(a.id, b.id));
|
|
2883
|
+
for (const pkg of mainPkgDeps) {
|
|
2884
|
+
pkg.files = pxt.packageUtils.getConfigFiles(pkg.config, pkg == mainPkg, appTarget, id => !!runtimePackages[resolvePath(id)], condition => host.logger.log(`invalid dependency expression: ${condition} in ${pkg.id}`));
|
|
2885
|
+
}
|
|
2886
|
+
const mainDeps = [];
|
|
2887
|
+
const disablesVariant = (pkg) => pxt.packageUtils.isVariantDisabled(pkg.config, variant);
|
|
2888
|
+
for (let pkg of mainPkgDeps) {
|
|
2889
|
+
if (disablesVariant(pkg) ||
|
|
2890
|
+
Object.keys(dependencies(pkg)).some(id => disablesVariant(packages[resolvePath(id)]))) {
|
|
2891
|
+
if (disabledDeps)
|
|
2892
|
+
disabledDeps += ", ";
|
|
2893
|
+
disabledDeps += pkg.id;
|
|
2894
|
+
host.logger.debug(`disable variant ${variant} due to ${pkg.id}`);
|
|
2895
|
+
continue;
|
|
2896
|
+
}
|
|
2897
|
+
mainDeps.push(pkg);
|
|
2898
|
+
}
|
|
2899
|
+
let compileService = appTarget.compileService;
|
|
2900
|
+
if (!compileService)
|
|
2901
|
+
compileService = {
|
|
2902
|
+
gittag: "none",
|
|
2903
|
+
serviceId: "nocompile"
|
|
2904
|
+
};
|
|
2905
|
+
compileService = U.clone(compileService);
|
|
2906
|
+
const compile = appTarget.compile;
|
|
2907
|
+
if (mainPkgDeps.some(pkg => pkg.config.utf8))
|
|
2908
|
+
compile.utf8 = true;
|
|
2909
|
+
const key = JSON.stringify({
|
|
2910
|
+
variant: variant || "",
|
|
2911
|
+
targetId: appTarget.id,
|
|
2912
|
+
compile,
|
|
2913
|
+
compileService,
|
|
2914
|
+
mainConfig: mainPkg.config,
|
|
2915
|
+
packages: mainDeps.map(pkg => ({
|
|
2916
|
+
id: pkg.id,
|
|
2917
|
+
config: pkg.config,
|
|
2918
|
+
version: pkg.version,
|
|
2919
|
+
files: pkg.files.filter(fn => fn == constsName ||
|
|
2920
|
+
/\.(h|cpp|c|S|s|mk)$/.test(fn) ||
|
|
2921
|
+
["Makefile", "sdkconfig.defaults", "CMakeLists.txt"].indexOf(fn) >= 0)
|
|
2922
|
+
.map(fn => [fn, readFile(pkg, fn)])
|
|
2923
|
+
}))
|
|
2924
|
+
});
|
|
2925
|
+
const prevInfo = host.cache[key];
|
|
2926
|
+
if (prevInfo) {
|
|
2927
|
+
host.logger.debug("Using cached extinfo");
|
|
2928
|
+
const result = U.clone(prevInfo);
|
|
2929
|
+
result.disabledDeps = disabledDeps;
|
|
2930
|
+
return result;
|
|
2931
|
+
}
|
|
2932
|
+
host.logger.debug("Generating new extinfo");
|
|
2933
|
+
const res = pxtc.emptyExtInfo(compileService);
|
|
2934
|
+
res.disabledDeps = disabledDeps;
|
|
2935
|
+
const isPlatformio = !!compileService.platformioIni;
|
|
2936
|
+
const isCodal = compileService.buildEngine == "codal" || compileService.buildEngine == "dockercodal";
|
|
2937
|
+
const isDockerMake = compileService.buildEngine == "dockermake" || compileService.buildEngine == "dockercross";
|
|
2938
|
+
const isEspIdf = compileService.buildEngine == "dockerespidf";
|
|
2939
|
+
const isYotta = !isPlatformio && !isCodal && !isDockerMake && !isEspIdf;
|
|
2940
|
+
const isVM = compile.nativeType == pxtc.NATIVE_TYPE_VM;
|
|
2941
|
+
if (isPlatformio)
|
|
2942
|
+
sourcePath = "/src/";
|
|
2943
|
+
else if (isCodal || isDockerMake)
|
|
2944
|
+
sourcePath = "/pxtapp/";
|
|
2945
|
+
else if (isEspIdf)
|
|
2946
|
+
sourcePath = "/main/";
|
|
2947
|
+
let pxtConfig = "// Configuration defines\n";
|
|
2948
|
+
let pointersInc = "\nPXT_SHIMS_BEGIN\n";
|
|
2949
|
+
let pointerIncPre = "";
|
|
2950
|
+
let abiInc = "";
|
|
2951
|
+
let includesInc = `#include "pxt.h"\n`;
|
|
2952
|
+
let thisErrors = "";
|
|
2953
|
+
let dTsNamespace = "";
|
|
2954
|
+
let err = (s) => thisErrors += ` ${fileName}(${lineNo}): ${s}\n`;
|
|
2955
|
+
let lineNo = 0;
|
|
2956
|
+
let fileName = "";
|
|
2957
|
+
let protos = nsWriter("namespace");
|
|
2958
|
+
let shimsDTS = nsWriter("declare namespace");
|
|
2959
|
+
let enumsDTS = nsWriter("declare namespace");
|
|
2960
|
+
let allErrors = "";
|
|
2961
|
+
let knownEnums = {};
|
|
2962
|
+
let vmVisitedFunctions = {};
|
|
2963
|
+
const enumVals = {
|
|
2964
|
+
"true": "1",
|
|
2965
|
+
"false": "0",
|
|
2966
|
+
"null": "0",
|
|
2967
|
+
"NULL": "0",
|
|
2968
|
+
};
|
|
2969
|
+
// we sometimes append _ to C++ names to avoid name clashes
|
|
2970
|
+
function toJs(name) {
|
|
2971
|
+
return name.trim().replace(/[\_\*]$/, "");
|
|
2972
|
+
}
|
|
2973
|
+
for (const pkg of mainDeps) {
|
|
2974
|
+
if (pkg.files.indexOf(constsName) >= 0) {
|
|
2975
|
+
const src = readFile(pkg, constsName);
|
|
2976
|
+
pxt.Util.assert(!!src, `${constsName} not found in ${pkg.id}`);
|
|
2977
|
+
src.split(/\r?\n/).forEach(ln => {
|
|
2978
|
+
let m = /^\s*(\w+) = (.*),/.exec(ln);
|
|
2979
|
+
if (m) {
|
|
2980
|
+
enumVals[m[1]] = m[2];
|
|
2981
|
+
}
|
|
2982
|
+
});
|
|
2983
|
+
}
|
|
2984
|
+
for (const fn of pkg.files) {
|
|
2985
|
+
if (["Makefile", "sdkconfig.defaults", "CMakeLists.txt"].indexOf(fn) >= 0 || U.endsWith(fn, ".mk")) {
|
|
2986
|
+
res.generatedFiles["/" + fn] = readFile(pkg, fn);
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
let hash_if_options = ["0", "false", "PXT_UTF8"];
|
|
2991
|
+
let cpp_options = {};
|
|
2992
|
+
if (compile.switches.boxDebug)
|
|
2993
|
+
cpp_options["PXT_BOX_DEBUG"] = 1;
|
|
2994
|
+
if (compile.utf8)
|
|
2995
|
+
cpp_options["PXT_UTF8"] = 1;
|
|
2996
|
+
if (compile.switches.profile)
|
|
2997
|
+
cpp_options["PXT_PROFILE"] = 1;
|
|
2998
|
+
if (compile.switches.gcDebug)
|
|
2999
|
+
cpp_options["PXT_GC_DEBUG"] = 1;
|
|
3000
|
+
if (compile.switches.numFloat)
|
|
3001
|
+
cpp_options["PXT_USE_FLOAT"] = 1;
|
|
3002
|
+
if (compile.nativeType == pxtc.NATIVE_TYPE_VM)
|
|
3003
|
+
cpp_options["PXT_VM"] = 1;
|
|
3004
|
+
function stripComments(ln) {
|
|
3005
|
+
return ln.replace(/\/\/.*/, "").replace(/\/\*/, "");
|
|
3006
|
+
}
|
|
3007
|
+
let enumVal = 0;
|
|
3008
|
+
let inEnum = false;
|
|
3009
|
+
let currNs = "";
|
|
3010
|
+
let currDocComment = "";
|
|
3011
|
+
let currAttrs = "";
|
|
3012
|
+
let inDocComment = false;
|
|
3013
|
+
function handleComments(ln) {
|
|
3014
|
+
if (inEnum)
|
|
3015
|
+
return true;
|
|
3016
|
+
if (/^\s*\/\*\*/.test(ln)) {
|
|
3017
|
+
inDocComment = true;
|
|
3018
|
+
currDocComment = ln + "\n";
|
|
3019
|
+
if (/\*\//.test(ln))
|
|
3020
|
+
inDocComment = false;
|
|
3021
|
+
return true;
|
|
3022
|
+
}
|
|
3023
|
+
if (inDocComment) {
|
|
3024
|
+
currDocComment += ln + "\n";
|
|
3025
|
+
if (/\*\//.test(ln)) {
|
|
3026
|
+
inDocComment = false;
|
|
3027
|
+
}
|
|
3028
|
+
return true;
|
|
3029
|
+
}
|
|
3030
|
+
if (/^\s*\/\/%/.test(ln)) {
|
|
3031
|
+
currAttrs += ln + "\n";
|
|
3032
|
+
return true;
|
|
3033
|
+
}
|
|
3034
|
+
return false;
|
|
3035
|
+
}
|
|
3036
|
+
function enterEnum(cpname, brace) {
|
|
3037
|
+
inEnum = true;
|
|
3038
|
+
enumVal = -1;
|
|
3039
|
+
enumsDTS.write("");
|
|
3040
|
+
enumsDTS.write("");
|
|
3041
|
+
if (currAttrs || currDocComment) {
|
|
3042
|
+
enumsDTS.write(currDocComment);
|
|
3043
|
+
enumsDTS.write(currAttrs);
|
|
3044
|
+
currAttrs = "";
|
|
3045
|
+
currDocComment = "";
|
|
3046
|
+
}
|
|
3047
|
+
enumsDTS.write(`declare const enum ${toJs(cpname)} ${brace}`);
|
|
3048
|
+
knownEnums[cpname] = true;
|
|
3049
|
+
}
|
|
3050
|
+
function processEnumLine(ln) {
|
|
3051
|
+
let lnNC = stripComments(ln);
|
|
3052
|
+
if (inEnum && lnNC.indexOf("}") >= 0) {
|
|
3053
|
+
inEnum = false;
|
|
3054
|
+
enumsDTS.write("}");
|
|
3055
|
+
}
|
|
3056
|
+
if (!inEnum)
|
|
3057
|
+
return;
|
|
3058
|
+
// parse the enum case, with lots of optional stuff (?)
|
|
3059
|
+
let mm = /^\s*(\w+)\s*(=\s*(.*?))?,?\s*$/.exec(lnNC);
|
|
3060
|
+
if (mm) {
|
|
3061
|
+
let nm = mm[1];
|
|
3062
|
+
let v = mm[3];
|
|
3063
|
+
let opt = "";
|
|
3064
|
+
if (v) {
|
|
3065
|
+
// user-supplied value
|
|
3066
|
+
v = v.trim();
|
|
3067
|
+
let curr = U.lookup(enumVals, v);
|
|
3068
|
+
if (curr != null) {
|
|
3069
|
+
opt = " // " + v;
|
|
3070
|
+
v = curr;
|
|
3071
|
+
}
|
|
3072
|
+
enumVal = parseCppInt(v);
|
|
3073
|
+
if (enumVal == null)
|
|
3074
|
+
err("cannot determine value of " + lnNC);
|
|
3075
|
+
}
|
|
3076
|
+
else {
|
|
3077
|
+
// no user-supplied value
|
|
3078
|
+
enumVal++;
|
|
3079
|
+
v = enumVal + "";
|
|
3080
|
+
}
|
|
3081
|
+
enumsDTS.write(` ${toJs(nm)} = ${v},${opt}`);
|
|
3082
|
+
}
|
|
3083
|
+
else {
|
|
3084
|
+
enumsDTS.write(ln);
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
function finishNamespace() {
|
|
3088
|
+
shimsDTS.setNs("");
|
|
3089
|
+
shimsDTS.write("");
|
|
3090
|
+
shimsDTS.write("");
|
|
3091
|
+
if (currAttrs || currDocComment) {
|
|
3092
|
+
shimsDTS.write(currDocComment);
|
|
3093
|
+
shimsDTS.write(currAttrs);
|
|
3094
|
+
currAttrs = "";
|
|
3095
|
+
currDocComment = "";
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
function parseArg(parsedAttrs, s) {
|
|
3099
|
+
s = s.trim();
|
|
3100
|
+
let m = /(.*)=\s*(-?\w+)$/.exec(s);
|
|
3101
|
+
let defl = "";
|
|
3102
|
+
let qm = "";
|
|
3103
|
+
if (m) {
|
|
3104
|
+
defl = m[2];
|
|
3105
|
+
qm = "?";
|
|
3106
|
+
s = m[1].trim();
|
|
3107
|
+
}
|
|
3108
|
+
m = /^(.*?)(\w+)$/.exec(s);
|
|
3109
|
+
if (!m) {
|
|
3110
|
+
err("invalid argument: " + s);
|
|
3111
|
+
return {
|
|
3112
|
+
name: "???",
|
|
3113
|
+
type: "int"
|
|
3114
|
+
};
|
|
3115
|
+
}
|
|
3116
|
+
let argName = m[2];
|
|
3117
|
+
if (parsedAttrs.paramDefl[argName]) {
|
|
3118
|
+
defl = parsedAttrs.paramDefl[argName];
|
|
3119
|
+
qm = "?";
|
|
3120
|
+
}
|
|
3121
|
+
let numVal = defl ? U.lookup(enumVals, defl) : null;
|
|
3122
|
+
if (numVal != null)
|
|
3123
|
+
defl = numVal;
|
|
3124
|
+
if (defl) {
|
|
3125
|
+
if (parseCppInt(defl) == null)
|
|
3126
|
+
err("Invalid default value (non-integer): " + defl);
|
|
3127
|
+
currAttrs += ` ${argName}.defl=${defl}`;
|
|
3128
|
+
}
|
|
3129
|
+
return {
|
|
3130
|
+
name: argName + qm,
|
|
3131
|
+
type: m[1]
|
|
3132
|
+
};
|
|
3133
|
+
}
|
|
3134
|
+
function parseCpp(src, isHeader) {
|
|
3135
|
+
currNs = "";
|
|
3136
|
+
currDocComment = "";
|
|
3137
|
+
currAttrs = "";
|
|
3138
|
+
inDocComment = false;
|
|
3139
|
+
let indexedInstanceAttrs;
|
|
3140
|
+
let indexedInstanceIdx = -1;
|
|
3141
|
+
// replace #if 0 .... #endif with newlines
|
|
3142
|
+
src = src.replace(/^(\s*#\s*if\s+(\w+)\s*$)([^]*?)(^\s*#\s*(elif|else|endif)\s*$)/mg, (f, _if, arg, middle, _endif) => hash_if_options.indexOf(arg) >= 0 && !cpp_options[arg] ?
|
|
3143
|
+
_if + middle.replace(/[^\n]/g, "") + _endif : f);
|
|
3144
|
+
// special handling of C++ namespace that ends with Methods (e.g. FooMethods)
|
|
3145
|
+
// such a namespace will be converted into a TypeScript interface
|
|
3146
|
+
// this enables simple objects with methods to be defined. See, for example:
|
|
3147
|
+
// https://github.com/microsoft/pxt-microbit/blob/master/libs/core/buffer.cpp
|
|
3148
|
+
// within that namespace, the first parameter of each function should have
|
|
3149
|
+
// the type Foo
|
|
3150
|
+
function interfaceName() {
|
|
3151
|
+
let n = currNs.replace(/Methods$/, "");
|
|
3152
|
+
if (n == currNs)
|
|
3153
|
+
return null;
|
|
3154
|
+
return n;
|
|
3155
|
+
}
|
|
3156
|
+
lineNo = 0;
|
|
3157
|
+
// the C++ types we can map to TypeScript
|
|
3158
|
+
function mapType(tp) {
|
|
3159
|
+
switch (tp.replace(/\s+/g, "")) {
|
|
3160
|
+
case "void": return "void";
|
|
3161
|
+
// TODO: need int16_t
|
|
3162
|
+
case "int32_t":
|
|
3163
|
+
case "int":
|
|
3164
|
+
return "int32";
|
|
3165
|
+
case "uint32_t":
|
|
3166
|
+
case "unsigned":
|
|
3167
|
+
return "uint32";
|
|
3168
|
+
case "TNumber":
|
|
3169
|
+
case "float":
|
|
3170
|
+
case "double":
|
|
3171
|
+
return "number";
|
|
3172
|
+
case "uint16_t": return "uint16";
|
|
3173
|
+
case "int16_t":
|
|
3174
|
+
case "short": return "int16";
|
|
3175
|
+
case "uint8_t":
|
|
3176
|
+
case "byte": return "uint8";
|
|
3177
|
+
case "int8_t":
|
|
3178
|
+
case "sbyte": return "int8";
|
|
3179
|
+
case "bool":
|
|
3180
|
+
if (compile.shortPointers)
|
|
3181
|
+
err("use 'boolean' not 'bool' on 8 bit targets");
|
|
3182
|
+
return "boolean";
|
|
3183
|
+
case "StringData*": return "string";
|
|
3184
|
+
case "String": return "string";
|
|
3185
|
+
case "ImageLiteral_": return "string";
|
|
3186
|
+
case "ImageLiteral": return "string";
|
|
3187
|
+
case "Action": return "() => void";
|
|
3188
|
+
case "TValue": return "any";
|
|
3189
|
+
default:
|
|
3190
|
+
return toJs(tp);
|
|
3191
|
+
//err("Don't know how to map type: " + tp)
|
|
3192
|
+
//return "any"
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
function mapRunTimeType(tp) {
|
|
3196
|
+
tp = tp.replace(/\s+/g, "");
|
|
3197
|
+
switch (tp) {
|
|
3198
|
+
case "int32_t":
|
|
3199
|
+
case "uint32_t":
|
|
3200
|
+
case "unsigned":
|
|
3201
|
+
case "uint16_t":
|
|
3202
|
+
case "int16_t":
|
|
3203
|
+
case "short":
|
|
3204
|
+
case "uint8_t":
|
|
3205
|
+
case "byte":
|
|
3206
|
+
case "int8_t":
|
|
3207
|
+
case "sbyte":
|
|
3208
|
+
case "int":
|
|
3209
|
+
case "ramint_t":
|
|
3210
|
+
return "I";
|
|
3211
|
+
case "void": return "V";
|
|
3212
|
+
case "float": return "F";
|
|
3213
|
+
case "TNumber": return "N";
|
|
3214
|
+
case "TValue": return "T";
|
|
3215
|
+
case "bool": return "B";
|
|
3216
|
+
case "double": return "D";
|
|
3217
|
+
case "ImageLiteral_":
|
|
3218
|
+
return "T";
|
|
3219
|
+
case "String":
|
|
3220
|
+
return "S";
|
|
3221
|
+
default:
|
|
3222
|
+
if (U.lookup(knownEnums, tp))
|
|
3223
|
+
return "I";
|
|
3224
|
+
return "_" + tp.replace(/[\*_]+$/, "");
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
function generateVMWrapper(fi, argTypes) {
|
|
3228
|
+
if (argTypes[0] == "FiberContext*")
|
|
3229
|
+
return "::" + fi.name; // no wrapper
|
|
3230
|
+
let wrap = "_wrp_" + fi.name.replace(/:/g, "_");
|
|
3231
|
+
if (vmVisitedFunctions[fi.name])
|
|
3232
|
+
return wrap;
|
|
3233
|
+
vmVisitedFunctions[fi.name] = true;
|
|
3234
|
+
/*
|
|
3235
|
+
void call_getConfig(FiberContext *ctx) {
|
|
3236
|
+
int a0 = toInt(ctx->sp[0]);
|
|
3237
|
+
int a1 = toInt(ctx->r0); // last argument in r0
|
|
3238
|
+
int r = getConfig(a0, a1);
|
|
3239
|
+
ctx->r0 = fromInt(r);
|
|
3240
|
+
ctx->sp += 1;
|
|
3241
|
+
}
|
|
3242
|
+
*/
|
|
3243
|
+
pointerIncPre += `\nvoid ${wrap}(FiberContext *ctx) {\n`;
|
|
3244
|
+
const numArgs = argTypes.length;
|
|
3245
|
+
let refs = [];
|
|
3246
|
+
let needsStackSave = false;
|
|
3247
|
+
let allConvs = "";
|
|
3248
|
+
for (let i = 0; i < numArgs; ++i) {
|
|
3249
|
+
const ind = fi.argsFmt[i + 1];
|
|
3250
|
+
const tp = argTypes[i];
|
|
3251
|
+
let conv = ind == "I" ? "toInt" :
|
|
3252
|
+
ind == "B" ? "numops::toBool" :
|
|
3253
|
+
"";
|
|
3254
|
+
const inp = i == numArgs - 1 ? "ctx->r0" : `ctx->sp[${numArgs - i - 2}]`;
|
|
3255
|
+
let argPref = "";
|
|
3256
|
+
switch (tp) {
|
|
3257
|
+
case "TValue":
|
|
3258
|
+
case "TNumber":
|
|
3259
|
+
break;
|
|
3260
|
+
case "Action":
|
|
3261
|
+
conv = "asRefAction";
|
|
3262
|
+
break;
|
|
3263
|
+
case "String":
|
|
3264
|
+
conv = "convertToString";
|
|
3265
|
+
argPref = "ctx, ";
|
|
3266
|
+
needsStackSave = true;
|
|
3267
|
+
break;
|
|
3268
|
+
default:
|
|
3269
|
+
if (!conv)
|
|
3270
|
+
conv = "as" + tp.replace(/\*/g, "");
|
|
3271
|
+
break;
|
|
3272
|
+
}
|
|
3273
|
+
allConvs += ` ${tp} a${i} = (${tp}) ${conv}(${argPref}${inp});\n`;
|
|
3274
|
+
refs.push("a" + i);
|
|
3275
|
+
}
|
|
3276
|
+
if (needsStackSave)
|
|
3277
|
+
pointerIncPre += " auto prevSP = ctx->sp;\n";
|
|
3278
|
+
pointerIncPre += allConvs;
|
|
3279
|
+
if (needsStackSave)
|
|
3280
|
+
pointerIncPre += " if (panicCode) { ctx->sp = prevSP; return; }\n";
|
|
3281
|
+
const call = `::${fi.name}(${refs.join(", ")})`;
|
|
3282
|
+
if (fi.argsFmt[0] == "V") {
|
|
3283
|
+
pointerIncPre += ` ${call};\n`;
|
|
3284
|
+
pointerIncPre += ` ctx->r0 = NULL;\n`;
|
|
3285
|
+
}
|
|
3286
|
+
else if (fi.argsFmt[0] == "I") {
|
|
3287
|
+
pointerIncPre += ` ctx->r0 = fromInt(${call});\n`;
|
|
3288
|
+
}
|
|
3289
|
+
else if (fi.argsFmt[0] == "B") {
|
|
3290
|
+
pointerIncPre += ` ctx->r0 = fromBool(${call});\n`;
|
|
3291
|
+
}
|
|
3292
|
+
else {
|
|
3293
|
+
pointerIncPre += ` ctx->r0 = (TValue)${call};\n`;
|
|
3294
|
+
}
|
|
3295
|
+
if (needsStackSave)
|
|
3296
|
+
pointerIncPre += " ctx->sp = prevSP;\n";
|
|
3297
|
+
if (numArgs > 1)
|
|
3298
|
+
pointerIncPre += ` ctx->sp += ${numArgs - 1};\n`;
|
|
3299
|
+
pointerIncPre += `}\n`;
|
|
3300
|
+
return wrap;
|
|
3301
|
+
}
|
|
3302
|
+
inEnum = false;
|
|
3303
|
+
enumVal = 0;
|
|
3304
|
+
enumsDTS.setNs("");
|
|
3305
|
+
shimsDTS.setNs("");
|
|
3306
|
+
src.split(/\r?\n/).forEach(ln => {
|
|
3307
|
+
++lineNo;
|
|
3308
|
+
// remove comments (NC = no comments)
|
|
3309
|
+
let lnNC = stripComments(ln);
|
|
3310
|
+
processEnumLine(ln);
|
|
3311
|
+
// "enum class" and "enum struct" is C++ syntax to force scoping of
|
|
3312
|
+
// enum members
|
|
3313
|
+
let enM = /^\s*enum\s+(|class\s+|struct\s+)(\w+)\s*({|$)/.exec(lnNC);
|
|
3314
|
+
if (enM) {
|
|
3315
|
+
enterEnum(enM[2], enM[3]);
|
|
3316
|
+
if (!isHeader) {
|
|
3317
|
+
protos.setNs(currNs);
|
|
3318
|
+
protos.write(`enum ${enM[2]} : int;`);
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3321
|
+
if (handleComments(ln))
|
|
3322
|
+
return;
|
|
3323
|
+
if (/^typedef.*;\s*$/.test(ln)) {
|
|
3324
|
+
protos.setNs(currNs);
|
|
3325
|
+
protos.write(ln);
|
|
3326
|
+
}
|
|
3327
|
+
let m = /^\s*namespace\s+(\w+)/.exec(ln);
|
|
3328
|
+
if (m) {
|
|
3329
|
+
//if (currNs) err("more than one namespace declaration not supported")
|
|
3330
|
+
currNs = m[1];
|
|
3331
|
+
if (interfaceName()) {
|
|
3332
|
+
finishNamespace();
|
|
3333
|
+
let tpName = interfaceName();
|
|
3334
|
+
shimsDTS.setNs(currNs, `declare interface ${tpName} {`);
|
|
3335
|
+
}
|
|
3336
|
+
else if (currAttrs || currDocComment) {
|
|
3337
|
+
finishNamespace();
|
|
3338
|
+
shimsDTS.setNs(toJs(currNs));
|
|
3339
|
+
enumsDTS.setNs(toJs(currNs));
|
|
3340
|
+
}
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
m = /^PXT_ABI\((\w+)\)/.exec(ln);
|
|
3344
|
+
if (m && !isVM) {
|
|
3345
|
+
pointersInc += `PXT_FNPTR(::${m[1]}),\n`;
|
|
3346
|
+
abiInc += `extern "C" void ${m[1]}();\n`;
|
|
3347
|
+
res.functions.push({
|
|
3348
|
+
name: m[1],
|
|
3349
|
+
argsFmt: [],
|
|
3350
|
+
value: 0
|
|
3351
|
+
});
|
|
3352
|
+
}
|
|
3353
|
+
m = /^\s*PXT_EXPORT\(([:\&\w]+)\)/.exec(ln);
|
|
3354
|
+
if (m) {
|
|
3355
|
+
if (!res.vmPointers)
|
|
3356
|
+
res.vmPointers = [];
|
|
3357
|
+
res.vmPointers.push(m[1]);
|
|
3358
|
+
}
|
|
3359
|
+
m = /^#define\s+PXT_COMM_BASE\s+([0-9a-fx]+)/.exec(ln);
|
|
3360
|
+
if (m)
|
|
3361
|
+
res.commBase = parseInt(m[1]);
|
|
3362
|
+
// function definition
|
|
3363
|
+
m = /^\s*(\w+)([\*\&]*\s+[\*\&]*)(\w+)\s*\(([^\(\)]*)\)\s*(;\s*$|\{|$)/.exec(ln);
|
|
3364
|
+
if (currAttrs && m) {
|
|
3365
|
+
indexedInstanceAttrs = null;
|
|
3366
|
+
let parsedAttrs = pxtc.parseCommentString(currAttrs);
|
|
3367
|
+
// top-level functions (outside of a namespace) are not permitted
|
|
3368
|
+
if (!currNs)
|
|
3369
|
+
err("missing namespace declaration");
|
|
3370
|
+
let retTp = (m[1] + m[2]).replace(/\s+/g, "");
|
|
3371
|
+
let funName = m[3];
|
|
3372
|
+
let origArgs = m[4];
|
|
3373
|
+
currAttrs = currAttrs.trim().replace(/ \w+\.defl=\w+/g, "");
|
|
3374
|
+
let argsFmt = [mapRunTimeType(retTp)];
|
|
3375
|
+
let argTypes = [];
|
|
3376
|
+
let args = origArgs.split(/,/).filter(s => !!s).map(s => {
|
|
3377
|
+
let r = parseArg(parsedAttrs, s);
|
|
3378
|
+
argsFmt.push(mapRunTimeType(r.type));
|
|
3379
|
+
argTypes.push(r.type.replace(/ /g, ""));
|
|
3380
|
+
return `${r.name}: ${mapType(r.type)}`;
|
|
3381
|
+
});
|
|
3382
|
+
let fi = {
|
|
3383
|
+
name: currNs + "::" + funName,
|
|
3384
|
+
argsFmt,
|
|
3385
|
+
value: null
|
|
3386
|
+
};
|
|
3387
|
+
//pxt.log(`${ln.trim()} : ${argsFmt}`)
|
|
3388
|
+
if (currDocComment) {
|
|
3389
|
+
shimsDTS.setNs(toJs(currNs));
|
|
3390
|
+
shimsDTS.write("");
|
|
3391
|
+
shimsDTS.write(currDocComment);
|
|
3392
|
+
if (/ImageLiteral/.test(m[4]) && !/imageLiteral=/.test(currAttrs))
|
|
3393
|
+
currAttrs += ` imageLiteral=1`;
|
|
3394
|
+
currAttrs += ` shim=${fi.name}`;
|
|
3395
|
+
shimsDTS.write(currAttrs);
|
|
3396
|
+
funName = toJs(funName);
|
|
3397
|
+
if (interfaceName()) {
|
|
3398
|
+
let tp0 = (args[0] || "").replace(/^.*:\s*/, "").trim();
|
|
3399
|
+
if (tp0.toLowerCase() != interfaceName().toLowerCase()) {
|
|
3400
|
+
err(lf("Invalid first argument; should be of type '{0}', but is '{1}'", interfaceName(), tp0));
|
|
3401
|
+
}
|
|
3402
|
+
args.shift();
|
|
3403
|
+
if (args.length == 0 && /\bproperty\b/.test(currAttrs))
|
|
3404
|
+
shimsDTS.write(`${funName}: ${mapType(retTp)};`);
|
|
3405
|
+
else
|
|
3406
|
+
shimsDTS.write(`${funName}(${args.join(", ")}): ${mapType(retTp)};`);
|
|
3407
|
+
}
|
|
3408
|
+
else {
|
|
3409
|
+
shimsDTS.write(`function ${funName}(${args.join(", ")}): ${mapType(retTp)};`);
|
|
3410
|
+
}
|
|
3411
|
+
}
|
|
3412
|
+
currDocComment = "";
|
|
3413
|
+
currAttrs = "";
|
|
3414
|
+
if (!isHeader) {
|
|
3415
|
+
protos.setNs(currNs);
|
|
3416
|
+
protos.write(`${retTp} ${funName}(${origArgs});`);
|
|
3417
|
+
}
|
|
3418
|
+
res.functions.push(fi);
|
|
3419
|
+
if (isYotta)
|
|
3420
|
+
pointersInc += "(uint32_t)(void*)::" + fi.name + ",\n";
|
|
3421
|
+
else if (isVM) {
|
|
3422
|
+
if (U.startsWith(fi.name, "pxt::op_") ||
|
|
3423
|
+
vmKeepFunctions[fi.name] ||
|
|
3424
|
+
parsedAttrs.expose ||
|
|
3425
|
+
(!U.startsWith(fi.name, "pxt::") && !U.startsWith(fi.name, "pxtrt::"))) {
|
|
3426
|
+
const wrap = generateVMWrapper(fi, argTypes);
|
|
3427
|
+
const nargs = fi.argsFmt.length - 1;
|
|
3428
|
+
pointersInc += `{ "${fi.name}", (OpFun)(void*)${wrap}, ${nargs} },\n`;
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
else
|
|
3432
|
+
pointersInc += "PXT_FNPTR(::" + fi.name + "),\n";
|
|
3433
|
+
return;
|
|
3434
|
+
}
|
|
3435
|
+
m = /^\s*extern const (\w+) (\w+);/.exec(ln);
|
|
3436
|
+
if (currAttrs && m) {
|
|
3437
|
+
let fi = {
|
|
3438
|
+
name: currNs + "::" + m[2],
|
|
3439
|
+
argsFmt: [],
|
|
3440
|
+
value: null
|
|
3441
|
+
};
|
|
3442
|
+
res.functions.push(fi);
|
|
3443
|
+
if (!isVM)
|
|
3444
|
+
pointersInc += "PXT_FNPTR(&::" + fi.name + "),\n";
|
|
3445
|
+
currAttrs = "";
|
|
3446
|
+
return;
|
|
3447
|
+
}
|
|
3448
|
+
m = /^\s*(\w+)\s+(\w+)\s*;/.exec(ln);
|
|
3449
|
+
if (currAttrs && m) {
|
|
3450
|
+
let parsedAttrs = pxtc.parseCommentString(currAttrs);
|
|
3451
|
+
if (parsedAttrs.indexedInstanceNS) {
|
|
3452
|
+
indexedInstanceAttrs = parsedAttrs;
|
|
3453
|
+
shimsDTS.setNs(parsedAttrs.indexedInstanceNS);
|
|
3454
|
+
indexedInstanceIdx = 0;
|
|
3455
|
+
}
|
|
3456
|
+
let tp = m[1];
|
|
3457
|
+
let nm = m[2];
|
|
3458
|
+
if (indexedInstanceAttrs) {
|
|
3459
|
+
currAttrs = currAttrs.trim();
|
|
3460
|
+
currAttrs += ` fixedInstance shim=${indexedInstanceAttrs.indexedInstanceShim}(${indexedInstanceIdx++})`;
|
|
3461
|
+
shimsDTS.write("");
|
|
3462
|
+
shimsDTS.write(currDocComment);
|
|
3463
|
+
shimsDTS.write(currAttrs);
|
|
3464
|
+
shimsDTS.write(`const ${nm}: ${mapType(tp)};`);
|
|
3465
|
+
currDocComment = "";
|
|
3466
|
+
currAttrs = "";
|
|
3467
|
+
return;
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
if (currAttrs && ln.trim()) {
|
|
3471
|
+
err("declaration not understood: " + ln);
|
|
3472
|
+
currAttrs = "";
|
|
3473
|
+
currDocComment = "";
|
|
3474
|
+
return;
|
|
3475
|
+
}
|
|
3476
|
+
});
|
|
3477
|
+
}
|
|
3478
|
+
const currSettings = U.clone(compileService.yottaConfig || {});
|
|
3479
|
+
const optSettings = {};
|
|
3480
|
+
const settingSrc = {};
|
|
3481
|
+
const codalLibraries = {};
|
|
3482
|
+
function parseJson(pkg) {
|
|
3483
|
+
const j0 = pkg.config.platformio;
|
|
3484
|
+
if (j0 && j0.dependencies) {
|
|
3485
|
+
U.jsonCopyFrom(res.platformio.dependencies, j0.dependencies);
|
|
3486
|
+
}
|
|
3487
|
+
if (res.npmDependencies && pkg.config.npmDependencies)
|
|
3488
|
+
U.jsonCopyFrom(res.npmDependencies, pkg.config.npmDependencies);
|
|
3489
|
+
const codal = pkg.config.codal;
|
|
3490
|
+
if (isCodal && codal) {
|
|
3491
|
+
for (const lib of codal.libraries || []) {
|
|
3492
|
+
const repo = pxt.github.parseRepoId(lib);
|
|
3493
|
+
if (!repo)
|
|
3494
|
+
U.userError(lf("codal library {0} doesn't look like github repo", lib));
|
|
3495
|
+
const canonical = pxt.github.stringifyRepo(repo);
|
|
3496
|
+
const existing = U.lookup(codalLibraries, repo.project);
|
|
3497
|
+
if (existing) {
|
|
3498
|
+
if (pxt.github.stringifyRepo(existing) != canonical)
|
|
3499
|
+
U.userError(lf("conflict between codal libraries: {0} and {1}", pxt.github.stringifyRepo(existing), canonical));
|
|
3500
|
+
}
|
|
3501
|
+
else {
|
|
3502
|
+
codalLibraries[repo.project] = repo;
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
const json = pkg.config.yotta;
|
|
3507
|
+
if (!json)
|
|
3508
|
+
return;
|
|
3509
|
+
// TODO check for conflicts
|
|
3510
|
+
if (json.dependencies) {
|
|
3511
|
+
U.jsonCopyFrom(res.yotta.dependencies, json.dependencies);
|
|
3512
|
+
}
|
|
3513
|
+
if (json.config) {
|
|
3514
|
+
const cfg = U.jsonFlatten(json.config);
|
|
3515
|
+
for (const settingName of Object.keys(cfg)) {
|
|
3516
|
+
const prev = U.lookup(settingSrc, settingName);
|
|
3517
|
+
const settingValue = cfg[settingName];
|
|
3518
|
+
if (!prev || prev.config.yotta.configIsJustDefaults) {
|
|
3519
|
+
settingSrc[settingName] = pkg;
|
|
3520
|
+
currSettings[settingName] = settingValue;
|
|
3521
|
+
}
|
|
3522
|
+
else if (currSettings[settingName] === settingValue) {
|
|
3523
|
+
// OK
|
|
3524
|
+
}
|
|
3525
|
+
else if (!mainPkg.config.yotta || !mainPkg.config.yotta.ignoreConflicts) {
|
|
3526
|
+
let err = new PkgConflictError(lf("conflict on yotta setting {0} between extensions {1} and {2}", settingName, pkg.id, prev.id));
|
|
3527
|
+
err.pkg0Id = prev.id;
|
|
3528
|
+
err.pkg1Id = pkg.id;
|
|
3529
|
+
err.settingName = settingName;
|
|
3530
|
+
throw err;
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
if (json.optionalConfig) {
|
|
3535
|
+
const cfg = U.jsonFlatten(json.optionalConfig);
|
|
3536
|
+
for (const settingName of Object.keys(cfg)) {
|
|
3537
|
+
const settingValue = cfg[settingName];
|
|
3538
|
+
// last one wins
|
|
3539
|
+
optSettings[settingName] = settingValue;
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
// This is overridden on the build server, but we need it for command line build
|
|
3544
|
+
if (isYotta && compile.hasHex) {
|
|
3545
|
+
let cs = compileService;
|
|
3546
|
+
U.assert(!!cs.yottaCorePackage);
|
|
3547
|
+
U.assert(!!cs.githubCorePackage);
|
|
3548
|
+
U.assert(!!cs.gittag);
|
|
3549
|
+
let tagged = cs.githubCorePackage + "#" + compileService.gittag;
|
|
3550
|
+
res.yotta.dependencies[cs.yottaCorePackage] = tagged;
|
|
3551
|
+
}
|
|
3552
|
+
if (mainPkg) {
|
|
3553
|
+
let seenMain = false;
|
|
3554
|
+
for (let pkg of mainDeps) {
|
|
3555
|
+
thisErrors = "";
|
|
3556
|
+
parseJson(pkg);
|
|
3557
|
+
if (pkg == mainPkg) {
|
|
3558
|
+
seenMain = true;
|
|
3559
|
+
// we only want the main package in generated .d.ts
|
|
3560
|
+
shimsDTS.clear();
|
|
3561
|
+
enumsDTS.clear();
|
|
3562
|
+
}
|
|
3563
|
+
else {
|
|
3564
|
+
U.assert(!seenMain);
|
|
3565
|
+
}
|
|
3566
|
+
// Generally, headers need to be processed before sources, as they contain definitions
|
|
3567
|
+
// (in particular of enums, which are needed to decide if we're doing conversions for
|
|
3568
|
+
// function arguments). This can still fail if one header uses another and they are
|
|
3569
|
+
// listed in invalid order...
|
|
3570
|
+
const isHeaderFn = (fn) => U.endsWith(fn, ".h");
|
|
3571
|
+
const ext = ".cpp";
|
|
3572
|
+
const files = pkg.files.filter(isHeaderFn)
|
|
3573
|
+
.concat(pkg.files.filter(s => !isHeaderFn(s)));
|
|
3574
|
+
for (let fn of files) {
|
|
3575
|
+
const isHeader = isHeaderFn(fn);
|
|
3576
|
+
if (isHeader || U.endsWith(fn, ext)) {
|
|
3577
|
+
let fullName = pkg.config.name + "/" + fn;
|
|
3578
|
+
if ((pkg.config.name == "base" || /^core($|---)/.test(pkg.config.name)) && isHeader)
|
|
3579
|
+
fullName = fn;
|
|
3580
|
+
if (isHeader)
|
|
3581
|
+
includesInc += `#include "${isYotta ? sourcePath.slice(1) : ""}${fullName}"\n`;
|
|
3582
|
+
let src = readFile(pkg, fn);
|
|
3583
|
+
if (src == null)
|
|
3584
|
+
U.userError(lf("C++ file {0} is missing in extension {1}.", fn, pkg.config.name));
|
|
3585
|
+
fileName = fullName;
|
|
3586
|
+
parseCpp(src, isHeader);
|
|
3587
|
+
// src = src.replace(/^[ \t]*/mg, "") // HACK: shrink the files
|
|
3588
|
+
res.extensionFiles[sourcePath + fullName] = src;
|
|
3589
|
+
if (pkg == mainPkg)
|
|
3590
|
+
res.onlyPublic = false;
|
|
3591
|
+
const protocol = pxt.packageUtils.getVersionProtocol(pkg.version);
|
|
3592
|
+
if (protocol && protocol != "pub" && protocol != "embed")
|
|
3593
|
+
res.onlyPublic = false;
|
|
3594
|
+
}
|
|
3595
|
+
if (U.endsWith(fn, ".c") || U.endsWith(fn, ".S") || U.endsWith(fn, ".s")) {
|
|
3596
|
+
let src = readFile(pkg, fn);
|
|
3597
|
+
res.extensionFiles[sourcePath + pkg.config.name + "/" + fn.replace(/\.S$/, ".s")] = src;
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
if (thisErrors) {
|
|
3601
|
+
allErrors += lf("Extension {0}:\n", pkg.id) + thisErrors;
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
if (!seenMain) {
|
|
3605
|
+
// this can happen if the main package is disabled in current variant
|
|
3606
|
+
shimsDTS.clear();
|
|
3607
|
+
enumsDTS.clear();
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
if (allErrors)
|
|
3611
|
+
U.userError(allErrors);
|
|
3612
|
+
// merge optional settings
|
|
3613
|
+
U.jsonCopyFrom(optSettings, currSettings);
|
|
3614
|
+
U.iterMap(optSettings, (k, v) => {
|
|
3615
|
+
if (v === null) {
|
|
3616
|
+
delete optSettings[k];
|
|
3617
|
+
}
|
|
3618
|
+
});
|
|
3619
|
+
// fix keys - ==> _
|
|
3620
|
+
Object.keys(optSettings)
|
|
3621
|
+
.filter(k => /-/.test(k)).forEach(k => {
|
|
3622
|
+
const v = optSettings[k];
|
|
3623
|
+
delete optSettings[k];
|
|
3624
|
+
optSettings[k.replace(/-/g, '_')] = v;
|
|
3625
|
+
});
|
|
3626
|
+
if (!isYotta && compileService.yottaConfigCompatibility) { // yotta automatically adds YOTTA_CFG_
|
|
3627
|
+
Object.keys(optSettings)
|
|
3628
|
+
.forEach(k => optSettings["YOTTA_CFG_" + k] = optSettings[k]);
|
|
3629
|
+
}
|
|
3630
|
+
optSettings["PXT_TARGET"] = JSON.stringify(appTarget.id);
|
|
3631
|
+
function allFilesWithExt(ext) {
|
|
3632
|
+
let allfiles = Object.keys(res.extensionFiles).concat(Object.keys(res.generatedFiles));
|
|
3633
|
+
return allfiles.filter(f => U.endsWith(f, ext)).map(s => s.slice(1));
|
|
3634
|
+
}
|
|
3635
|
+
const configJson = U.jsonUnFlatten(optSettings);
|
|
3636
|
+
if (isDockerMake) {
|
|
3637
|
+
let packageJson = {
|
|
3638
|
+
name: "pxt-app",
|
|
3639
|
+
private: true,
|
|
3640
|
+
dependencies: res.npmDependencies,
|
|
3641
|
+
};
|
|
3642
|
+
res.generatedFiles["/package.json"] = JSON.stringify(packageJson, null, 4) + "\n";
|
|
3643
|
+
}
|
|
3644
|
+
else if (isEspIdf) {
|
|
3645
|
+
const files = U.concatArrayLike([
|
|
3646
|
+
allFilesWithExt(".c"),
|
|
3647
|
+
allFilesWithExt(".cpp"),
|
|
3648
|
+
allFilesWithExt(".s")
|
|
3649
|
+
]).map(s => s.slice(sourcePath.length - 1)).concat(["main.cpp"]);
|
|
3650
|
+
files.push("pointers.cpp");
|
|
3651
|
+
res.generatedFiles[sourcePath + "CMakeLists.txt"] =
|
|
3652
|
+
`idf_component_register(\n SRCS\n` +
|
|
3653
|
+
files.map(f => ` "${f}"\n`).join("") +
|
|
3654
|
+
` INCLUDE_DIRS\n "."\n)\n`;
|
|
3655
|
+
}
|
|
3656
|
+
else if (isCodal) {
|
|
3657
|
+
let cs = compileService;
|
|
3658
|
+
let cfg = U.clone(cs.codalDefinitions) || {};
|
|
3659
|
+
let trg = cs.codalTarget;
|
|
3660
|
+
if (typeof trg == "string")
|
|
3661
|
+
trg = trg + ".json";
|
|
3662
|
+
let codalJson = {
|
|
3663
|
+
"target": trg,
|
|
3664
|
+
"definitions": cfg,
|
|
3665
|
+
"config": cfg,
|
|
3666
|
+
"application": "pxtapp",
|
|
3667
|
+
"output_folder": "build",
|
|
3668
|
+
// include these, because we use hash of this file to see if anything changed
|
|
3669
|
+
"pxt_gitrepo": cs.githubCorePackage,
|
|
3670
|
+
"pxt_gittag": cs.gittag,
|
|
3671
|
+
"libraries": U.values(codalLibraries).map(r => ({
|
|
3672
|
+
"name": r.project,
|
|
3673
|
+
"url": "https://github.com/" + r.fullName,
|
|
3674
|
+
"branch": r.tag || "master",
|
|
3675
|
+
"type": "git"
|
|
3676
|
+
}))
|
|
3677
|
+
};
|
|
3678
|
+
if (codalJson.libraries.length == 0)
|
|
3679
|
+
delete codalJson.libraries;
|
|
3680
|
+
U.iterMap(U.jsonFlatten(configJson), (k, v) => {
|
|
3681
|
+
k = k.replace(/^codal\./, "device.").toUpperCase().replace(/\./g, "_");
|
|
3682
|
+
cfg[k] = v;
|
|
3683
|
+
});
|
|
3684
|
+
res.generatedFiles["/codal.json"] = JSON.stringify(codalJson, null, 4) + "\n";
|
|
3685
|
+
host.logger.debug(`codal.json: ${res.generatedFiles["/codal.json"]}`);
|
|
3686
|
+
res.codal = codalJson;
|
|
3687
|
+
}
|
|
3688
|
+
else if (isPlatformio) {
|
|
3689
|
+
const iniLines = compileService.platformioIni.slice();
|
|
3690
|
+
// TODO merge configjson
|
|
3691
|
+
iniLines.push("lib_deps =");
|
|
3692
|
+
U.iterMap(res.platformio.dependencies, (pkg, ver) => {
|
|
3693
|
+
let pkgSpec = /[@#\/]/.test(ver) ? ver : pkg + "@" + ver;
|
|
3694
|
+
iniLines.push(" " + pkgSpec);
|
|
3695
|
+
});
|
|
3696
|
+
res.generatedFiles["/platformio.ini"] = iniLines.join("\n") + "\n";
|
|
3697
|
+
}
|
|
3698
|
+
else {
|
|
3699
|
+
res.yotta.config = configJson;
|
|
3700
|
+
let name = "pxt-app";
|
|
3701
|
+
if (compileService.yottaBinary)
|
|
3702
|
+
name = compileService.yottaBinary.replace(/-combined/, "").replace(/\.hex$/, "");
|
|
3703
|
+
let moduleJson = {
|
|
3704
|
+
"name": name,
|
|
3705
|
+
"version": "0.0.0",
|
|
3706
|
+
"description": "Auto-generated. Do not edit.",
|
|
3707
|
+
"license": "n/a",
|
|
3708
|
+
"dependencies": res.yotta.dependencies,
|
|
3709
|
+
"targetDependencies": {},
|
|
3710
|
+
"bin": "./source"
|
|
3711
|
+
};
|
|
3712
|
+
res.generatedFiles["/module.json"] = JSON.stringify(moduleJson, null, 4) + "\n";
|
|
3713
|
+
host.logger.debug(`module.json: ${res.generatedFiles["/module.json"]}`);
|
|
3714
|
+
}
|
|
3715
|
+
for (let k of Object.keys(cpp_options)) {
|
|
3716
|
+
pxtConfig += `#define ${k} ${cpp_options[k]}\n`;
|
|
3717
|
+
}
|
|
3718
|
+
if (compile.uf2Family)
|
|
3719
|
+
pxtConfig += `#define PXT_UF2_FAMILY ${compile.uf2Family}\n`;
|
|
3720
|
+
res.generatedFiles[sourcePath + "pointers.cpp"] = includesInc + protos.finish() + abiInc +
|
|
3721
|
+
pointerIncPre + pointersInc + "\nPXT_SHIMS_END\n";
|
|
3722
|
+
res.generatedFiles[sourcePath + "pxtconfig.h"] = pxtConfig;
|
|
3723
|
+
host.logger.debug(`pxtconfig.h: ${res.generatedFiles[sourcePath + "pxtconfig.h"]}`);
|
|
3724
|
+
if (isYotta) {
|
|
3725
|
+
res.generatedFiles["/config.json"] = JSON.stringify(configJson, null, 4) + "\n";
|
|
3726
|
+
host.logger.debug(`yotta config.json: ${res.generatedFiles["/config.json"]}`);
|
|
3727
|
+
}
|
|
3728
|
+
res.generatedFiles[sourcePath + "main.cpp"] = `
|
|
3729
|
+
#include "pxt.h"
|
|
3730
|
+
#ifdef PXT_MAIN
|
|
3731
|
+
PXT_MAIN
|
|
3732
|
+
#else
|
|
3733
|
+
int main() {
|
|
3734
|
+
uBit.init();
|
|
3735
|
+
pxt::start();
|
|
3736
|
+
release_fiber();
|
|
3737
|
+
return 0; // your program will never reach this line.
|
|
3738
|
+
}
|
|
3739
|
+
#endif
|
|
3740
|
+
`;
|
|
3741
|
+
if (res.generatedFiles["/Makefile"]) {
|
|
3742
|
+
let inc = "";
|
|
3743
|
+
let add = (name, ext) => {
|
|
3744
|
+
inc += `${name} = ${allFilesWithExt(ext).join(" ")}\n`;
|
|
3745
|
+
};
|
|
3746
|
+
add("PXT_C", ".c");
|
|
3747
|
+
add("PXT_CPP", ".cpp");
|
|
3748
|
+
add("PXT_S", ".s");
|
|
3749
|
+
add("PXT_HEADERS", ".h");
|
|
3750
|
+
inc += "PXT_SOURCES := $(PXT_C) $(PXT_S) $(PXT_CPP)\n";
|
|
3751
|
+
inc += "PXT_OBJS := $(addprefix bld/, $(PXT_C:.c=.o) $(PXT_S:.s=.o) $(PXT_CPP:.cpp=.o))\n";
|
|
3752
|
+
res.generatedFiles["/Makefile.inc"] = inc;
|
|
3753
|
+
}
|
|
3754
|
+
res.generatedFiles["/functions.json"] = JSON.stringify(res.functions, null, 1);
|
|
3755
|
+
let tmp = res.extensionFiles;
|
|
3756
|
+
U.jsonCopyFrom(tmp, res.generatedFiles);
|
|
3757
|
+
let creq = {
|
|
3758
|
+
config: compileService.serviceId,
|
|
3759
|
+
tag: compileService.gittag,
|
|
3760
|
+
replaceFiles: tmp,
|
|
3761
|
+
dependencies: (isYotta ? res.yotta.dependencies : null)
|
|
3762
|
+
};
|
|
3763
|
+
let data = JSON.stringify(creq);
|
|
3764
|
+
host.perf.measureStart(Measurements.Sha256Buffer);
|
|
3765
|
+
try {
|
|
3766
|
+
res.sha = pxtc.BrowserImpl.sha256buffer(U.toUTF8Array(data));
|
|
3767
|
+
}
|
|
3768
|
+
finally {
|
|
3769
|
+
host.perf.measureEnd(Measurements.Sha256Buffer);
|
|
3770
|
+
}
|
|
3771
|
+
res.skipCloudBuild = !!compileService.skipCloudBuild;
|
|
3772
|
+
res.compileData = ts.pxtc.encodeBase64(U.toUTF8(data));
|
|
3773
|
+
res.shimsDTS = shimsDTS.finish();
|
|
3774
|
+
res.enumsDTS = enumsDTS.finish();
|
|
3775
|
+
if (Object.keys(host.cache).length > 10) {
|
|
3776
|
+
for (const key of Object.keys(host.cache))
|
|
3777
|
+
delete host.cache[key];
|
|
3778
|
+
}
|
|
3779
|
+
host.cache[key] = U.clone(res);
|
|
3780
|
+
return res;
|
|
3781
|
+
}
|
|
3782
|
+
cpp.getExtensionInfo = getExtensionInfo;
|
|
3783
|
+
})(cpp = pxt.cpp || (pxt.cpp = {}));
|
|
3784
|
+
})(pxt || (pxt = {}));
|
|
3785
|
+
/// <reference path="../pxtlib/shared/docsrender.ts"/>
|
|
3786
|
+
/// <reference path="../pxtlib/shared/extensioninfo.ts"/>
|
|
1621
3787
|
global.pxt = pxt;
|