From 20500fb9aea2d46c475402ab685b0e79bacb264f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Moskal?= Date: Mon, 10 Sep 2018 10:11:41 -0700 Subject: [PATCH 1/4] Pull common files from pxt-common-packages (#1165) --- libs/core/buffer.cpp | 356 ------------- libs/core/core.cpp | 1137 ------------------------------------------ libs/core/platform.h | 13 + libs/core/pxt.cpp | 567 --------------------- libs/core/pxt.json | 4 +- libs/core/pxtbase.h | 713 -------------------------- package.json | 1 + 7 files changed, 16 insertions(+), 2775 deletions(-) delete mode 100644 libs/core/buffer.cpp delete mode 100644 libs/core/core.cpp create mode 100644 libs/core/platform.h delete mode 100644 libs/core/pxt.cpp delete mode 100644 libs/core/pxtbase.h diff --git a/libs/core/buffer.cpp b/libs/core/buffer.cpp deleted file mode 100644 index e315065d..00000000 --- a/libs/core/buffer.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "pxtbase.h" -#include - -using namespace std; - -//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte -namespace BufferMethods { -//% -uint8_t *getBytes(Buffer buf) { - return buf->data; -} - -//% -int getByte(Buffer buf, int off) { - if (buf && 0 <= off && off < buf->length) - return buf->data[off]; - return 0; -} - -//% -void setByte(Buffer buf, int off, int v) { - if (buf && 0 <= off && off < buf->length) - buf->data[off] = v; -} - -int writeBuffer(Buffer buf, int dstOffset, Buffer src, int srcOffset = 0, int length = -1) { - if (length < 0) - length = src->length; - - if (srcOffset < 0 || dstOffset < 0 || dstOffset > buf->length) - return -1; - - length = min(src->length - srcOffset, buf->length - dstOffset); - - if (length < 0) - return -1; - - if (buf == src) { - memmove(buf->data + dstOffset, src->data + srcOffset, length); - } else { - memcpy(buf->data + dstOffset, src->data + srcOffset, length); - } - - return 0; -} - -/** - * Write a number in specified format in the buffer. - */ -//% -void setNumber(Buffer buf, NumberFormat format, int offset, TNumber value) { - if (offset < 0) - return; - setNumberCore(buf->data + offset, buf->length - offset, format, value); -} - -/** - * Read a number in specified format from the buffer. - */ -//% -TNumber getNumber(Buffer buf, NumberFormat format, int offset) { - if (offset < 0) - return fromInt(0); - return getNumberCore(buf->data + offset, buf->length - offset, format); -} - -/** Returns the length of a Buffer object. */ -//% property -int length(Buffer s) { - return s->length; -} - -/** - * Fill (a fragment) of the buffer with given value. - */ -//% -void fill(Buffer buf, int value, int offset = 0, int length = -1) { - if (offset < 0 || offset > buf->length) - return; // DEVICE_INVALID_PARAMETER; - if (length < 0) - length = buf->length; - length = min(length, buf->length - offset); - memset(buf->data + offset, value, length); -} - -/** - * Return a copy of a fragment of a buffer. - */ -//% -Buffer slice(Buffer buf, int offset = 0, int length = -1) { - offset = min((int)buf->length, offset); - if (length < 0) - length = buf->length; - length = min(length, buf->length - offset); - return mkBuffer(buf->data + offset, length); -} - -/** - * Shift buffer left in place, with zero padding. - * @param offset number of bytes to shift; use negative value to shift right - * @param start start offset in buffer. Default is 0. - * @param length number of elements in buffer. If negative, length is set as the buffer length minus - * start. eg: -1 - */ -//% -void shift(Buffer buf, int offset, int start = 0, int length = -1) { - if (length < 0) - length = buf->length - start; - if (start < 0 || start + length > buf->length || start + length < start || length == 0 || - offset == 0 || offset == INT_MIN) - return; - if (offset <= -length || offset >= length) { - fill(buf, 0); - return; - } - - uint8_t *data = buf->data + start; - if (offset < 0) { - offset = -offset; - memmove(data + offset, data, length - offset); - memset(data, 0, offset); - } else { - length = length - offset; - memmove(data, data + offset, length); - memset(data + length, 0, offset); - } -} - -/** - * Convert a buffer to its hexadecimal representation. - */ -//% -String toHex(Buffer buf) { - const char *hex = "0123456789abcdef"; - auto res = mkString(NULL, buf->length * 2); - for (int i = 0; i < buf->length; ++i) { - res->data[i << 1] = hex[buf->data[i] >> 4]; - res->data[(i << 1) + 1] = hex[buf->data[i] & 0xf]; - } - return res; -} - -/** - * Rotate buffer left in place. - * @param offset number of bytes to shift; use negative value to shift right - * @param start start offset in buffer. Default is 0. - * @param length number of elements in buffer. If negative, length is set as the buffer length minus - * start. eg: -1 - */ -//% -void rotate(Buffer buf, int offset, int start = 0, int length = -1) { - if (length < 0) - length = buf->length - start; - if (start < 0 || start + length > buf->length || start + length < start || length == 0 || - offset == 0 || offset == INT_MIN) - return; - - if (offset < 0) - offset += length << 8; // try to make it positive - offset %= length; - if (offset < 0) - offset += length; - - uint8_t *data = buf->data + start; - - uint8_t *n_first = data + offset; - uint8_t *first = data; - uint8_t *next = n_first; - uint8_t *last = data + length; - - while (first != next) { - uint8_t tmp = *first; - *first++ = *next; - *next++ = tmp; - if (next == last) { - next = n_first; - } else if (first == n_first) { - n_first = next; - } - } -} - -/** - * Write contents of `src` at `dstOffset` in current buffer. - */ -//% -void write(Buffer buf, int dstOffset, Buffer src) { - // srcOff and length not supported, we only do up to 4 args :/ - writeBuffer(buf, dstOffset, src, 0, -1); -} -} - -namespace control { -/** - * Create a new zero-initialized buffer. - * @param size number of bytes in the buffer - */ -//% -Buffer createBuffer(int size) { - return mkBuffer(NULL, size); -} -} - -namespace pxt { -static int writeBytes(uint8_t *dst, uint8_t *src, int length, bool swapBytes, int szLeft) { - if (szLeft < length) { - return -1; - } - - if (swapBytes) { - uint8_t *p = dst + length; - for (int i = 0; i < length; ++i) - *--p = src[i]; - } else { - if (length == 4 && ((uint32_t)dst & 3) == 0) - *(uint32_t *)dst = *(uint32_t *)src; - else if (length == 2 && ((uint32_t)dst & 1) == 0) - *(uint16_t *)dst = *(uint16_t *)src; - else - memcpy(dst, src, length); - } - - return 0; -} - -static int readBytes(uint8_t *src, uint8_t *dst, int length, bool swapBytes, int szLeft) { - if (szLeft < length) { - memset(dst, 0, length); - return -1; - } - - if (swapBytes) { - uint8_t *p = src + length; - for (int i = 0; i < length; ++i) - dst[i] = *--p; - } else { - if (length == 4 && ((uint32_t)src & 3) == 0) - *(uint32_t *)dst = *(uint32_t *)src; - else if (length == 2 && ((uint32_t)src & 1) == 0) - *(uint16_t *)dst = *(uint16_t *)src; - else - memcpy(dst, src, length); - } - - return 0; -} - -void setNumberCore(uint8_t *buf, int szLeft, NumberFormat format, TNumber value) { - int8_t i8; - uint8_t u8; - int16_t i16; - uint16_t u16; - int32_t i32; - uint32_t u32; - float f32; - double f64; - -// Assume little endian -#define WRITEBYTES(isz, swap, toInt) \ - isz = toInt(value); \ - writeBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \ - break - - switch (format) { - case NumberFormat::Int8LE: - WRITEBYTES(i8, false, toInt); - case NumberFormat::UInt8LE: - WRITEBYTES(u8, false, toInt); - case NumberFormat::Int16LE: - WRITEBYTES(i16, false, toInt); - case NumberFormat::UInt16LE: - WRITEBYTES(u16, false, toInt); - case NumberFormat::Int32LE: - WRITEBYTES(i32, false, toInt); - case NumberFormat::UInt32LE: - WRITEBYTES(u32, false, toUInt); - - case NumberFormat::Int8BE: - WRITEBYTES(i8, true, toInt); - case NumberFormat::UInt8BE: - WRITEBYTES(u8, true, toInt); - case NumberFormat::Int16BE: - WRITEBYTES(i16, true, toInt); - case NumberFormat::UInt16BE: - WRITEBYTES(u16, true, toInt); - case NumberFormat::Int32BE: - WRITEBYTES(i32, true, toInt); - case NumberFormat::UInt32BE: - WRITEBYTES(u32, true, toUInt); - - case NumberFormat::Float32LE: - WRITEBYTES(f32, false, toFloat); - case NumberFormat::Float32BE: - WRITEBYTES(f32, true, toFloat); - case NumberFormat::Float64LE: - WRITEBYTES(f64, false, toDouble); - case NumberFormat::Float64BE: - WRITEBYTES(f64, true, toDouble); - } -} - -TNumber getNumberCore(uint8_t *buf, int szLeft, NumberFormat format) { - int8_t i8; - uint8_t u8; - int16_t i16; - uint16_t u16; - int32_t i32; - uint32_t u32; - float f32; - double f64; - -// Assume little endian -#define READBYTES(isz, swap, conv) \ - readBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \ - return conv(isz) - - switch (format) { - case NumberFormat::Int8LE: - READBYTES(i8, false, fromInt); - case NumberFormat::UInt8LE: - READBYTES(u8, false, fromInt); - case NumberFormat::Int16LE: - READBYTES(i16, false, fromInt); - case NumberFormat::UInt16LE: - READBYTES(u16, false, fromInt); - case NumberFormat::Int32LE: - READBYTES(i32, false, fromInt); - case NumberFormat::UInt32LE: - READBYTES(u32, false, fromUInt); - - case NumberFormat::Int8BE: - READBYTES(i8, true, fromInt); - case NumberFormat::UInt8BE: - READBYTES(u8, true, fromInt); - case NumberFormat::Int16BE: - READBYTES(i16, true, fromInt); - case NumberFormat::UInt16BE: - READBYTES(u16, true, fromInt); - case NumberFormat::Int32BE: - READBYTES(i32, true, fromInt); - case NumberFormat::UInt32BE: - READBYTES(u32, true, fromUInt); - - case NumberFormat::Float32LE: - READBYTES(f32, false, fromFloat); - case NumberFormat::Float32BE: - READBYTES(f32, true, fromFloat); - case NumberFormat::Float64LE: - READBYTES(f64, false, fromDouble); - case NumberFormat::Float64BE: - READBYTES(f64, true, fromDouble); - } - - return 0; -} -} \ No newline at end of file diff --git a/libs/core/core.cpp b/libs/core/core.cpp deleted file mode 100644 index 4b0b9ada..00000000 --- a/libs/core/core.cpp +++ /dev/null @@ -1,1137 +0,0 @@ -#include "pxtbase.h" -#include -#include - -using namespace std; - -#define p10(v) __builtin_powi(10, v) - -namespace pxt { - -static HandlerBinding *handlerBindings; - -HandlerBinding *findBinding(int source, int value) { - for (auto p = handlerBindings; p; p = p->next) { - if (p->source == source && p->value == value) { - return p; - } - } - return 0; -} - -void setBinding(int source, int value, Action act) { - auto curr = findBinding(source, value); - incr(act); - if (curr) { - decr(curr->action); - curr->action = act; - return; - } - curr = new HandlerBinding(); - curr->next = handlerBindings; - curr->source = source; - curr->value = value; - curr->action = act; - handlerBindings = curr; -} - -static const uint16_t emptyString[] - __attribute__((aligned(4))) = {0xffff, PXT_REF_TAG_STRING, 0, 0}; - -static const uint16_t emptyBuffer[] - __attribute__((aligned(4))) = {0xffff, PXT_REF_TAG_BUFFER, 0, 0}; - -String mkString(const char *data, int len) { - if (len < 0) - len = strlen(data); - if (len == 0) - return (String)emptyString; - String r = new (::operator new(sizeof(BoxedString) + len + 1)) BoxedString(); - r->length = len; - if (data) - memcpy(r->data, data, len); - r->data[len] = 0; - MEMDBG("mkString: len=%d => %p", len, r); - return r; -} - -Buffer mkBuffer(const uint8_t *data, int len) { - if (len <= 0) - return (Buffer)emptyBuffer; - Buffer r = new (::operator new(sizeof(BoxedBuffer) + len)) BoxedBuffer(); - r->length = len; - if (data) - memcpy(r->data, data, len); - else - memset(r->data, 0, len); - MEMDBG("mkBuffer: len=%d => %p", len, r); - return r; -} - -#ifndef X86_64 -TNumber mkNaN() { - // TODO optimize - return fromDouble(NAN); -} -#endif - -static unsigned random_value = 0xC0DA1; - -void seedRandom(unsigned seed) { - random_value = seed; -} - -unsigned getRandom(unsigned max) { - unsigned m, result; - - do { - m = (unsigned)max; - result = 0; - - do { - // Cycle the LFSR (Linear Feedback Shift Register). - // We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneier here - // (a true legend in the field!), - // For those interested, it's documented in his paper: - // "Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent - // generator for 32-bit Microprocessors" - // https://www.schneier.com/paper-pseudorandom-sequence.html - unsigned r = random_value; - - r = ((((r >> 31) ^ (r >> 6) ^ (r >> 4) ^ (r >> 2) ^ (r >> 1) ^ r) & 1) << 31) | - (r >> 1); - - random_value = r; - - result = ((result << 1) | (r & 0x00000001)); - } while (m >>= 1); - } while (result > (unsigned)max); - - return result; -} - -PXT_DEF_STRING(sTrue, "\x04\x00true") -PXT_DEF_STRING(sFalse, "\x05\x00false") -PXT_DEF_STRING(sUndefined, "\x09\x00undefined") -PXT_DEF_STRING(sNull, "\x04\x00null") -PXT_DEF_STRING(sObject, "\x08\x00[Object]") -PXT_DEF_STRING(sFunction, "\x0A\x00[Function]") -PXT_DEF_STRING(sNaN, "\x03\x00NaN") -PXT_DEF_STRING(sInf, "\x08\x00Infinity") -PXT_DEF_STRING(sMInf, "\x09\x00-Infinity") -} // namespace pxt - -#ifndef X86_64 - -namespace String_ { - -//% -String mkEmpty() { - return mkString("", 0); -} - -//% -String fromCharCode(int code) { - char buf[] = {(char)code, 0}; - return mkString(buf, 1); -} - -//% -String charAt(String s, int pos) { - if (s && 0 <= pos && pos < s->length) { - return fromCharCode(s->data[pos]); - } else { - return mkEmpty(); - } -} - -//% -TNumber charCodeAt(String s, int pos) { - if (s && 0 <= pos && pos < s->length) { - return fromInt(s->data[pos]); - } else { - return mkNaN(); - } -} - -//% -String concat(String s, String other) { - if (!s) - s = (String)sNull; - if (!other) - other = (String)sNull; - if (s->length == 0) - return (String)incrRC(other); - if (other->length == 0) - return (String)incrRC(s); - String r = mkString(NULL, s->length + other->length); - memcpy(r->data, s->data, s->length); - memcpy(r->data + s->length, other->data, other->length); - return r; -} - -//% -int compare(String s, String that) { - if (s == that) - return 0; - // TODO this isn't quite right, in JS both `null < "foo"` and `null > "foo"` are false - if (!s) - return -1; - if (!that) - return 1; - int compareResult = strcmp(s->data, that->data); - if (compareResult < 0) - return -1; - else if (compareResult > 0) - return 1; - return 0; -} - -//% -int length(String s) { - return s->length; -} - -#define isspace(c) ((c) == ' ') - -double mystrtod(const char *p, char **endp) { - while (isspace(*p)) - p++; - double m = 1; - double v = 0; - int dot = 0; - if (*p == '+') - p++; - if (*p == '-') { - m = -1; - p++; - } - if (*p == '0' && (p[1] | 0x20) == 'x') { - return m * strtol(p, endp, 16); - } - while (*p) { - int c = *p - '0'; - if (0 <= c && c <= 9) { - v *= 10; - v += c; - if (dot) - m /= 10; - } else if (!dot && *p == '.') { - dot = 1; - } else if (*p == 'e' || *p == 'E') { - break; - } else { - while (isspace(*p)) - p++; - if (*p) - return NAN; - break; - } - p++; - } - - v *= m; - - if (*p) { - p++; - int pw = strtol(p, endp, 10); - v *= p10(pw); - } - else { - *endp = (char *) p; - } - - return v; -} - -//% -TNumber toNumber(String s) { - // JSCHECK - char *endptr; - double v = mystrtod(s->data, &endptr); - if (endptr != s->data + s->length) - v = NAN; - else if (v == 0.0 || v == -0.0) - v = v; - else if (!isnormal(v)) - v = NAN; - return fromDouble(v); -} - -//% -String substr(String s, int start, int length) { - if (length <= 0) - return mkEmpty(); - if (start < 0) - start = max(s->length + start, 0); - length = min(length, s->length - start); - return mkString(s->data + start, length); -} -} // namespace String_ - -namespace Boolean_ { -//% -bool bang(int v) { - return v == 0; -} -} // namespace Boolean_ - -namespace pxt { - -// ES5 9.5, 9.6 -unsigned toUInt(TNumber v) { - if (isNumber(v)) - return numValue(v); - if (isSpecial(v)) { - if ((intptr_t)v >> 6) - return 1; - else - return 0; - } - if (!v) - return 0; - - double num = toDouble(v); - if (!isnormal(num)) - return 0; - double rem = fmod(trunc(num), 4294967296.0); - if (rem < 0.0) - rem += 4294967296.0; - return (unsigned)rem; -} -int toInt(TNumber v) { - return (int)toUInt(v); -} - -// only support double in tagged mode -double toDouble(TNumber v) { - if (isTagged(v)) - return toInt(v); - - // JSCHECK - ValType t = valType(v); - if (t == ValType::Number) { - BoxedNumber *p = (BoxedNumber *)v; - return p->num; - } else if (t == ValType::String) { - return toDouble(String_::toNumber((String)v)); - } else { - return NAN; - } -} - -float toFloat(TNumber v) { - // TODO optimize? - return (float)toDouble(v); -} - -TNumber fromDouble(double r) { -#ifndef PXT_BOX_DEBUG - int ri = ((int)r) << 1; - if ((ri >> 1) == r) - return (TNumber)(ri | 1); -#endif - BoxedNumber *p = new BoxedNumber(); - p->num = r; - MEMDBG("mkNum: %p", p); - return (TNumber)p; -} - -TNumber fromFloat(float r) { - // TODO optimize - return fromDouble(r); -} - -TNumber fromInt(int v) { - if (canBeTagged(v)) - return TAG_NUMBER(v); - return fromDouble(v); -} - -TNumber fromUInt(unsigned v) { -#ifndef PXT_BOX_DEBUG - if (v <= 0x3fffffff) - return TAG_NUMBER(v); -#endif - return fromDouble(v); -} - -TValue fromBool(bool v) { - if (v) - return TAG_TRUE; - else - return TAG_FALSE; -} - -TNumber eqFixup(TNumber v) { - if (v == TAG_NULL) - return TAG_UNDEFINED; - if (v == TAG_TRUE) - return TAG_NUMBER(1); - if (v == TAG_FALSE) - return TAG_NUMBER(0); - return v; -} - -bool eqq_bool(TValue a, TValue b) { - // TODO improve this - - if (a == b) - return true; - - ValType ta = valType(a); - ValType tb = valType(b); - - if (ta != tb) - return false; - - if (ta == ValType::String) - return String_::compare((String)a, (String)b) == 0; - - int aa = (int)a; - int bb = (int)b; - - // if at least one of the values is tagged, they are not equal - if ((aa | bb) & 3) - return false; - - if (ta == ValType::Number) - return toDouble(a) == toDouble(b); - else - return a == b; -} - -bool eq_bool(TValue a, TValue b) { - return eqq_bool(eqFixup(a), eqFixup(b)); -} - -//% -bool switch_eq(TValue a, TValue b) { - if (eqq_bool(eqFixup(a), eqFixup(b))) { - decr(b); - return true; - } - return false; -} - -} // namespace pxt - -namespace langsupp { -//% -TValue ptreq(TValue a, TValue b) { - return eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TValue ptreqq(TValue a, TValue b) { - return eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TValue ptrneq(TValue a, TValue b) { - return !eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TValue ptrneqq(TValue a, TValue b) { - return !eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} -} // namespace langsupp - -#define NUMOP(op) return fromDouble(toDouble(a) op toDouble(b)); -#define BITOP(op) return fromInt(toInt(a) op toInt(b)); -namespace numops { - -//% -int toBool(TValue v) { - if (isTagged(v)) { - if (v == TAG_UNDEFINED || v == TAG_NULL || v == TAG_FALSE || v == TAG_NUMBER(0)) - return 0; - else - return 1; - } - - ValType t = valType(v); - if (t == ValType::String) { - String s = (String)v; - if (s->length == 0) - return 0; - } else if (t == ValType::Number) { - double x = toDouble(v); - if (isnan(x) || x == 0.0 || x == -0.0) - return 0; - else - return 1; - } - - return 1; -} - -//% -int toBoolDecr(TValue v) { - if (v == TAG_TRUE) - return 1; - if (v == TAG_FALSE) - return 0; - int r = toBool(v); - decr(v); - return r; -} - -// TODO -// The integer, non-overflow case for add/sub/bit opts is handled in assembly - -//% -TNumber adds(TNumber a, TNumber b){NUMOP(+)} - -//% -TNumber subs(TNumber a, TNumber b){NUMOP(-)} - -//% -TNumber muls(TNumber a, TNumber b) { - if (bothNumbers(a, b)) { - int aa = (int)a; - int bb = (int)b; - // if both operands fit 15 bits, the result will not overflow int - if ((aa >> 15 == 0 || aa >> 15 == -1) && (bb >> 15 == 0 || bb >> 15 == -1)) { - // it may overflow 31 bit int though - use fromInt to convert properly - return fromInt((aa >> 1) * (bb >> 1)); - } - } - NUMOP(*) -} - -//% -TNumber div(TNumber a, TNumber b){NUMOP(/)} - -//% -TNumber mod(TNumber a, TNumber b) { - if (isNumber(a) && isNumber(b) && numValue(b)) - BITOP(%) - return fromDouble(fmod(toDouble(a), toDouble(b))); -} - -//% -TNumber lsls(TNumber a, TNumber b){BITOP(<<)} - -//% -TNumber lsrs(TNumber a, TNumber b) { - return fromUInt(toUInt(a) >> toUInt(b)); -} - -//% -TNumber asrs(TNumber a, TNumber b){BITOP(>>)} - -//% -TNumber eors(TNumber a, TNumber b){BITOP (^)} - -//% -TNumber orrs(TNumber a, TNumber b){BITOP(|)} - -//% -TNumber bnot(TNumber a) { - return fromInt(~toInt(a)); -} - -//% -TNumber ands(TNumber a, TNumber b) { - BITOP(&) -} - -#define CMPOP_RAW(op) \ - if (bothNumbers(a, b)) \ - return (int)a op((int)b); \ - return toDouble(a) op toDouble(b); - -#define CMPOP(op) \ - if (bothNumbers(a, b)) \ - return ((int)a op((int)b)) ? TAG_TRUE : TAG_FALSE; \ - return toDouble(a) op toDouble(b) ? TAG_TRUE : TAG_FALSE; - -//% -bool lt_bool(TNumber a, TNumber b){CMPOP_RAW(<)} - -//% -TNumber le(TNumber a, TNumber b){CMPOP(<=)} - -//% -TNumber lt(TNumber a, TNumber b){CMPOP(<)} - -//% -TNumber ge(TNumber a, TNumber b){CMPOP(>=)} - -//% -TNumber gt(TNumber a, TNumber b){CMPOP(>)} - -//% -TNumber eq(TNumber a, TNumber b) { - return pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TNumber neq(TNumber a, TNumber b) { - return !pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TNumber eqq(TNumber a, TNumber b) { - return pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TNumber neqq(TNumber a, TNumber b) { - return !pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -void mycvt(double d, char *buf) { - if (d < 0) { - *buf++ = '-'; - d = -d; - } - - if (!d) { - *buf++ = '0'; - *buf++ = 0; - return; - } - - int pw = (int)log10(d); - int e = 1; - int beforeDot = 1; - - if (0.000001 <= d && d < 1e21) { - if (pw > 0) { - d /= p10(pw); - beforeDot = 1 + pw; - } - } else { - d /= p10(pw); - e = pw; - } - - int sig = 0; - while (sig < 17 || beforeDot > 0) { - // printf("%f sig=%d bd=%d\n", d, sig, beforeDot); - int c = (int)d; - *buf++ = '0' + c; - d = (d - c) * 10; - if (--beforeDot == 0) - *buf++ = '.'; - if (sig || c) - sig++; - } - - buf--; - while (*buf == '0') - buf--; - if (*buf == '.') - buf--; - buf++; - - if (e != 1) { - *buf++ = 'e'; - itoa(e, buf); - } else { - *buf = 0; - } -} - -//% -String toString(TValue v) { - - if (v == TAG_UNDEFINED) - return (String)(void *)sUndefined; - else if (v == TAG_FALSE) - return (String)(void *)sFalse; - else if (v == TAG_TRUE) - return (String)(void *)sTrue; - else if (v == TAG_NULL) - return (String)(void *)sNull; - ValType t = valType(v); - - if (t == ValType::String) { - return (String)(void *)incr(v); - } else if (t == ValType::Number) { - char buf[64]; - - if (isNumber(v)) { - itoa(numValue(v), buf); - return mkString(buf); - } - - double x = toDouble(v); - - if (isnan(x)) - return (String)(void *)sNaN; - if (isinf(x)) { - if (x < 0) - return (String)(void *)sMInf; - else - return (String)(void *)sInf; - } - mycvt(x, buf); - - return mkString(buf); - } else if (t == ValType::Function) { - return (String)(void *)sFunction; - } else { - return (String)(void *)sObject; - } -} -} // namespace numops - -namespace Math_ { -//% -TNumber pow(TNumber x, TNumber y) { - // regular pow() from math.h is 4k of code - return fromDouble(__builtin_powi(toDouble(x), toInt(y))); -} - -//% -TNumber atan2(TNumber y, TNumber x) { - return fromDouble(::atan2(toDouble(y), toDouble(x))); -} - -double randomDouble() { - return getRandom(UINT_MAX) / ((double)UINT_MAX + 1) + - getRandom(0xffffff) / ((double)UINT_MAX * 0xffffff); -} - -//% -TNumber random() { - return fromDouble(randomDouble()); -} - -//% -TNumber randomRange(TNumber min, TNumber max) { - if (isNumber(min) && isNumber(max)) { - int mini = numValue(min); - int maxi = numValue(max); - if (mini > maxi) { - int temp = mini; - mini = maxi; - maxi = temp; - } - if (maxi == mini) - return fromInt(mini); - else - return fromInt(mini + getRandom(maxi - mini)); - } else { - double mind = toDouble(min); - double maxd = toDouble(max); - if (mind > maxd) { - double temp = mind; - mind = maxd; - maxd = temp; - } - if (maxd == mind) - return fromDouble(mind); - else { - return fromDouble(mind + randomDouble() * (maxd - mind)); - } - } -} - -#define SINGLE(op) return fromDouble(::op(toDouble(x))); - -//% -TNumber log(TNumber x){SINGLE(log)} - -//% -TNumber log10(TNumber x){SINGLE(log10)} - -//% -TNumber tan(TNumber x){SINGLE(tan)} - -//% -TNumber sin(TNumber x){SINGLE(sin)} - -//% -TNumber cos(TNumber x){SINGLE(cos)} - -//% -TNumber atan(TNumber x){SINGLE(atan)} - -//% -TNumber asin(TNumber x){SINGLE(asin)} - -//% -TNumber acos(TNumber x){SINGLE(acos)} - -//% -TNumber sqrt(TNumber x){SINGLE(sqrt)} - -//% -TNumber floor(TNumber x){SINGLE(floor)} - -//% -TNumber ceil(TNumber x){SINGLE(ceil)} - -//% -TNumber trunc(TNumber x){SINGLE(trunc)} - -//% -TNumber round(TNumber x) { - // In C++, round(-1.5) == -2, while in JS, round(-1.5) == -1. Align to the JS convention for consistency between - // simulator and device. The following does rounding with ties (x.5) going towards positive infinity. - return fromDouble(::floor(toDouble(x) + 0.5)); -} - -//% -int imul(int x, int y) { - return x * y; -} - -//% -int idiv(int x, int y) { - return x / y; -} -} // namespace Math_ - -namespace Array_ { -//% -RefCollection *mk(unsigned flags) { - auto r = new RefCollection(); - MEMDBG("mkColl: %p", r); - return r; -} -//% -int length(RefCollection *c) { - return c->length(); -} -//% -void setLength(RefCollection *c, int newLength) { - c->setLength(newLength); -} -//% -void push(RefCollection *c, TValue x) { - c->push(x); -} -//% -TValue pop(RefCollection *c) { - return c->pop(); -} -//% -TValue getAt(RefCollection *c, int x) { - return c->getAt(x); -} -//% -void setAt(RefCollection *c, int x, TValue y) { - c->setAt(x, y); -} -//% -TValue removeAt(RefCollection *c, int x) { - return c->removeAt(x); -} -//% -void insertAt(RefCollection *c, int x, TValue value) { - c->insertAt(x, value); -} -//% -int indexOf(RefCollection *c, TValue x, int start) { - return c->indexOf(x, start); -} -//% -bool removeElement(RefCollection *c, TValue x) { - return c->removeElement(x); -} -} // namespace Array_ - -namespace pxt { -//% -void *ptrOfLiteral(int offset); - -//% -unsigned programSize() { - return bytecode[17] * 2; -} - -//% -int getConfig(int key, int defl) { - int *cfgData = *(int **)&bytecode[18]; - for (int i = 0;; i += 2) { - if (cfgData[i] == key) - return cfgData[i + 1]; - if (cfgData[i] == 0) - return defl; - } -} - -} // namespace pxt - -namespace pxtrt { -//% -TValue ldloc(RefLocal *r) { - return r->v; -} - -//% -TValue ldlocRef(RefRefLocal *r) { - TValue tmp = r->v; - incr(tmp); - return tmp; -} - -//% -void stloc(RefLocal *r, TValue v) { - r->v = v; -} - -//% -void stlocRef(RefRefLocal *r, TValue v) { - decr(r->v); - r->v = v; -} - -//% -RefLocal *mkloc() { - auto r = new RefLocal(); - MEMDBG("mkloc: %p", r); - return r; -} - -//% -RefRefLocal *mklocRef() { - auto r = new RefRefLocal(); - MEMDBG("mklocRef: %p", r); - return r; -} - -// All of the functions below unref() self. This is for performance reasons - -// the code emitter will not emit the unrefs for them. - -//% -TValue ldfld(RefRecord *r, int idx) { - TValue tmp = r->ld(idx); - r->unref(); - return tmp; -} - -//% -TValue ldfldRef(RefRecord *r, int idx) { - TValue tmp = r->ldref(idx); - r->unref(); - return tmp; -} - -//% -void stfld(RefRecord *r, int idx, TValue val) { - r->st(idx, val); - r->unref(); -} - -//% -void stfldRef(RefRecord *r, int idx, TValue val) { - r->stref(idx, val); - r->unref(); -} - -// Store a captured local in a closure. It returns the action, so it can be chained. -//% -RefAction *stclo(RefAction *a, int idx, TValue v) { - // DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v); - a->stCore(idx, v); - return a; -} - -//% -void panic(int code) { - target_panic(code); -} - -//% -String emptyToNull(String s) { - if (!s || s->length == 0) - return NULL; - return s; -} - -//% -int ptrToBool(TValue p) { - if (p) { - decr(p); - return 1; - } else { - return 0; - } -} - -//% -RefMap *mkMap() { - auto r = new RefMap(); - MEMDBG("mkMap: %p", r); - return r; -} - -//% -TValue mapGet(RefMap *map, unsigned key) { - int i = map->findIdx(key); - if (i < 0) { - map->unref(); - return 0; - } - TValue r = incr(map->values.get(i)); - map->unref(); - return r; -} - -//% -TValue mapGetRef(RefMap *map, unsigned key) { - return mapGet(map, key); -} - -//% -void mapSet(RefMap *map, unsigned key, TValue val) { - int i = map->findIdx(key); - if (i < 0) { - map->keys.push((TValue)key); - map->values.push(val); - } else { - map->values.setRef(i, val); - } - map->unref(); -} - -//% -void mapSetRef(RefMap *map, unsigned key, TValue val) { - mapSet(map, key, val); -} - -// -// Debugger -// - -// This is only to be called once at the beginning of lambda function -//% -void *getGlobalsPtr() { -#ifdef DEVICE_GROUP_ID_USER - fiber_set_group(DEVICE_GROUP_ID_USER); -#endif - - return globals; -} - -//% -void runtimeWarning(String s) { - // noop for now -} -} // namespace pxtrt -#endif - -namespace pxt { - -//% -ValType valType(TValue v) { - if (isTagged(v)) { - if (!v) - return ValType::Undefined; - - if (isNumber(v)) - return ValType::Number; - if (v == TAG_TRUE || v == TAG_FALSE) - return ValType::Boolean; - else if (v == TAG_NULL) - return ValType::Object; - else { - oops(); - return ValType::Object; - } - } else { - int tag = ((RefObject *)v)->vtable; - - if (tag == PXT_REF_TAG_STRING) - return ValType::String; - else if (tag == PXT_REF_TAG_NUMBER) - return ValType::Number; - else if (tag == PXT_REF_TAG_ACTION || getVTable((RefObject *)v) == &RefAction_vtable) - return ValType::Function; - - return ValType::Object; - } -} - -PXT_DEF_STRING(sObjectTp, "\x06\x00object") -PXT_DEF_STRING(sBooleanTp, "\x07\x00boolean") -PXT_DEF_STRING(sStringTp, "\x06\x00string") -PXT_DEF_STRING(sNumberTp, "\x06\x00number") -PXT_DEF_STRING(sFunctionTp, "\x08\x00function") -PXT_DEF_STRING(sUndefinedTp, "\x09\x00undefined") - -//% -String typeOf(TValue v) { - switch (valType(v)) { - case ValType::Undefined: - return (String)sUndefinedTp; - case ValType::Boolean: - return (String)sBooleanTp; - case ValType::Number: - return (String)sNumberTp; - case ValType::String: - return (String)sStringTp; - case ValType::Object: - return (String)sObjectTp; - case ValType::Function: - return (String)sFunctionTp; - default: - oops(); - return 0; - } -} - -// Maybe in future we will want separate print methods; for now ignore -void anyPrint(TValue v) { - if (valType(v) == ValType::Object) { - if (isRefCounted(v)) { - auto o = (RefObject *)v; - auto meth = ((RefObjectMethod)getVTable(o)->methods[1]); - if ((void *)meth == (void *)&anyPrint) - DMESG("[RefObject refs=%d vt=%p]", o->refcnt, o->vtable); - else - meth(o); - } else { - DMESG("[Native %p]", v); - } - } else { -#ifndef X86_64 - String s = numops::toString(v); - DMESG("[%s %p = %s]", pxt::typeOf(v)->data, v, s->data); - decr((TValue)s); -#endif - } -} - -void dtorDoNothing() {} - -#define PRIM_VTABLE(name, sz) \ - const VTable name = {sz, \ - 0, \ - 0, \ - { \ - (void *)&dtorDoNothing, \ - (void *)&anyPrint, \ - }}; -PRIM_VTABLE(string_vt, 0) -PRIM_VTABLE(image_vt, 0) -PRIM_VTABLE(buffer_vt, 0) -PRIM_VTABLE(number_vt, 12) -PRIM_VTABLE(action_vt, 0) - -static const VTable *primVtables[] = {0, // 0 - &string_vt, // 1 - &buffer_vt, // 2 - &image_vt, // 3 - // filler: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - &number_vt, // 32 - &action_vt, // 33 - 0}; - -VTable *getVTable(RefObject *r) { - if (r->vtable >= 34) - return (VTable *)((uintptr_t)r->vtable << vtableShift); - if (r->vtable == 0) - target_panic(100); - return (VTable *)primVtables[r->vtable]; -} -} // namespace pxt diff --git a/libs/core/platform.h b/libs/core/platform.h new file mode 100644 index 00000000..9752a0b0 --- /dev/null +++ b/libs/core/platform.h @@ -0,0 +1,13 @@ +// helpful define to handle C++ differences in package +#define PXT_MICROBIT_TAGGED_INT 1 + +// cross version compatible way of access data field +#ifndef PXT_BUFFER_DATA +#define PXT_BUFFER_DATA(buffer) buffer->data +#endif + +#ifndef PXT_CREATE_BUFFER +#define PXT_CREATE_BUFFER(data, len) pxt::mkBuffer(data, len) +#endif + +#define PXT_POWI 1 diff --git a/libs/core/pxt.cpp b/libs/core/pxt.cpp deleted file mode 100644 index 22720878..00000000 --- a/libs/core/pxt.cpp +++ /dev/null @@ -1,567 +0,0 @@ -#include "pxtbase.h" - -using namespace std; - -namespace pxt { - -TValue incr(TValue e) { - if (isRefCounted(e)) { - getVTable((RefObject *)e); -#if MEMDBG_ENABLED - if (((RefObject *)e)->refcnt != 0xffff) - MEMDBG("INCR: %p refs=%d", e, ((RefObject *)e)->refcnt); -#endif - ((RefObject *)e)->ref(); - } - return e; -} - -void decr(TValue e) { - if (isRefCounted(e)) { -#if MEMDBG_ENABLED - if (((RefObject *)e)->refcnt != 0xffff) - MEMDBG("DECR: %p refs=%d", e, ((RefObject *)e)->refcnt); -#endif - ((RefObject *)e)->unref(); - } -} - -// TODO -Action mkAction(int reflen, int totallen, int startptr) { - check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1); - check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2); - check(bytecode[startptr] == 0xffff, ERR_INVALID_BINARY_HEADER, 3); - check(bytecode[startptr + 1] == PXT_REF_TAG_ACTION, ERR_INVALID_BINARY_HEADER, 4); - - uintptr_t tmp = (uintptr_t)&bytecode[startptr]; - - if (totallen == 0) { - return (TValue)tmp; // no closure needed - } - - void *ptr = ::operator new(sizeof(RefAction) + totallen * sizeof(unsigned)); - RefAction *r = new (ptr) RefAction(); - r->len = totallen; - r->reflen = reflen; - r->func = (ActionCB)((tmp + 4) | 1); - memset(r->fields, 0, r->len * sizeof(unsigned)); - - MEMDBG("mkAction: start=%p => %p", startptr, r); - - return (Action)r; -} - -// TODO -TValue runAction3(Action a, TValue arg0, TValue arg1, TValue arg2) { - auto aa = (RefAction *)a; - if (aa->vtable == PXT_REF_TAG_ACTION) { - check(aa->refcnt == 0xffff, ERR_INVALID_BINARY_HEADER, 4); - return ((ActionCB)(((uintptr_t)a + 4) | 1))(NULL, arg0, arg1, arg2); - } else { - check(aa->refcnt != 0xffff, ERR_INVALID_BINARY_HEADER, 4); - return aa->runCore(arg0, arg1, arg2); - } -} - -TValue runAction2(Action a, TValue arg0, TValue arg1) { - return runAction3(a, arg0, arg1, 0); -} - -TValue runAction1(Action a, TValue arg0) { - return runAction3(a, arg0, 0, 0); -} - -TValue runAction0(Action a) { - return runAction3(a, 0, 0, 0); -} - -RefRecord *mkClassInstance(int vtableOffset) { - VTable *vtable = (VTable *)&bytecode[vtableOffset]; - - intcheck(vtable->methods[0] == &RefRecord_destroy, ERR_SIZE, 3); - intcheck(vtable->methods[1] == &RefRecord_print, ERR_SIZE, 4); - - void *ptr = ::operator new(vtable->numbytes); - RefRecord *r = new (ptr) RefRecord(PXT_VTABLE_TO_INT(vtable)); - memset(r->fields, 0, vtable->numbytes - sizeof(RefRecord)); - MEMDBG("mkClass: vt=%p => %p", vtable, r); - return r; -} - -TValue RefRecord::ld(int idx) { - // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, ERR_OUT_OF_BOUNDS, 1); - return fields[idx]; -} - -TValue RefRecord::ldref(int idx) { - // DMESG("LD %p len=%d reflen=%d idx=%d", this, len, reflen, idx); - // intcheck(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 2); - TValue tmp = fields[idx]; - incr(tmp); - return tmp; -} - -void RefRecord::st(int idx, TValue v) { - // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, ERR_OUT_OF_BOUNDS, 3); - fields[idx] = v; -} - -void RefRecord::stref(int idx, TValue v) { - // DMESG("ST %p len=%d reflen=%d idx=%d", this, len, reflen, idx); - // intcheck(0 <= idx && idx < reflen, ERR_OUT_OF_BOUNDS, 4); - decr(fields[idx]); - fields[idx] = v; -} - -void RefObject::destroyVT() { - ((RefObjectMethod)getVTable(this)->methods[0])(this); - ::operator delete(this); -} - -void RefObject::printVT() { - ((RefObjectMethod)getVTable(this)->methods[1])(this); -} - -void RefRecord_destroy(RefRecord *r) { - VTable *tbl = getVTable(r); - uint8_t *refmask = (uint8_t *)&tbl->methods[tbl->userdata & 0xff]; - int len = (tbl->numbytes >> 2) - 1; - for (int i = 0; i < len; ++i) { - if (refmask[i]) - decr(r->fields[i]); - r->fields[i] = 0; - } -} - -void RefRecord_print(RefRecord *r) { - DMESG("RefRecord %p r=%d size=%d bytes", r, r->refcnt, getVTable(r)->numbytes); -} - -TValue Segment::get(unsigned i) { -#ifdef DEBUG_BUILD - DMESG("In Segment::get index:%d", i); - this->print(); -#endif - - if (i < length) { - return data[i]; - } - return Segment::DefaultValue; -} - -void Segment::setRef(unsigned i, TValue value) { - decr(get(i)); - set(i, value); -} - -void Segment::set(unsigned i, TValue value) { - if (i < size) { - data[i] = value; - } else if (i < Segment::MaxSize) { - growByMin(i + 1); - data[i] = value; - } else { - return; - } - if (length <= i) { - length = i + 1; - } - -#ifdef DEBUG_BUILD - DMESG("In Segment::set"); - this->print(); -#endif - - return; -} - -ramint_t Segment::growthFactor(ramint_t size) { - if (size == 0) { - return 4; - } - if (size < 64) { - return size * 2; // Double - } - if (size < 512) { - return size * 5 / 3; // Grow by 1.66 rate - } - // Grow by constant rate - if ((unsigned)size + 256 < MaxSize) - return size + 256; - else - return MaxSize; -} - -void Segment::growByMin(ramint_t minSize) { - growBy(max(minSize, growthFactor(size))); -} - -void Segment::growBy(ramint_t newSize) { -#ifdef DEBUG_BUILD - DMESG("growBy: %d", newSize); - this->print(); -#endif - if (size < newSize) { - // this will throw if unable to allocate - TValue *tmp = (TValue *)(::operator new(newSize * sizeof(TValue))); - - // Copy existing data - if (size) { - memcpy(tmp, data, size * sizeof(TValue)); - } - // fill the rest with default value - memset(tmp + size, 0, (newSize - size) * sizeof(TValue)); - - // free older segment; - ::operator delete(data); - - data = tmp; - size = newSize; - -#ifdef DEBUG_BUILD - DMESG("growBy - after reallocation"); - this->print(); -#endif - } - // else { no shrinking yet; } - return; -} - -void Segment::ensure(ramint_t newSize) { - if (newSize < size) { - return; - } - growByMin(newSize); -} - -void Segment::setLength(unsigned newLength) { - if (newLength > size) { - ensure(length); - } - length = newLength; - return; -} - -void Segment::push(TValue value) { - this->set(length, value); -} - -TValue Segment::pop() { -#ifdef DEBUG_BUILD - DMESG("In Segment::pop"); - this->print(); -#endif - - if (length > 0) { - --length; - TValue value = data[length]; - data[length] = Segment::DefaultValue; - return value; - } - return Segment::DefaultValue; -} - -// this function removes an element at index i and shifts the rest of the elements to -// left to fill the gap -TValue Segment::remove(unsigned i) { -#ifdef DEBUG_BUILD - DMESG("In Segment::remove index:%d", i); - this->print(); -#endif - if (i < length) { - // value to return - TValue ret = data[i]; - if (i + 1 < length) { - // Move the rest of the elements to fill in the gap. - memmove(data + i, data + i + 1, (length - i - 1) * sizeof(unsigned)); - } - length--; - data[length] = Segment::DefaultValue; -#ifdef DEBUG_BUILD - DMESG("After Segment::remove index:%d", i); - this->print(); -#endif - return ret; - } - return Segment::DefaultValue; -} - -// this function inserts element value at index i by shifting the rest of the elements right. -void Segment::insert(unsigned i, TValue value) { -#ifdef DEBUG_BUILD - DMESG("In Segment::insert index:%d value:%d", i, value); - this->print(); -#endif - - if (i < length) { - ensure(length + 1); - - // Move the rest of the elements to fill in the gap. - memmove(data + i + 1, data + i, (length - i) * sizeof(unsigned)); - - data[i] = value; - length++; - } else { - // This is insert beyond the length, just call set which will adjust the length - set(i, value); - } -#ifdef DEBUG_BUILD - DMESG("After Segment::insert index:%d", i); - this->print(); -#endif -} - -void Segment::print() { - DMESG("Segment: %p, length: %d, size: %d", data, (unsigned)length, (unsigned)size); - for (unsigned i = 0; i < size; i++) { - DMESG("-> %d", (unsigned)(uintptr_t)data[i]); - } -} - -bool Segment::isValidIndex(unsigned i) { - if (i > length) { - return false; - } - return true; -} - -void Segment::destroy() { -#ifdef DEBUG_BUILD - DMESG("In Segment::destroy"); - this->print(); -#endif - length = size = 0; - ::operator delete(data); - data = nullptr; -} - -void RefCollection::push(TValue x) { - incr(x); - head.push(x); -} - -TValue RefCollection::pop() { - TValue ret = head.pop(); - incr(ret); - return ret; -} - -TValue RefCollection::getAt(int i) { - TValue tmp = head.get(i); - incr(tmp); - return tmp; -} - -TValue RefCollection::removeAt(int i) { - return head.remove(i); -} - -void RefCollection::insertAt(int i, TValue value) { - head.insert(i, value); - incr(value); -} - -void RefCollection::setAt(int i, TValue value) { - incr(value); - head.setRef(i, value); -} - -int RefCollection::indexOf(TValue x, int start) { -#ifndef X86_64 - unsigned i = start; - while (head.isValidIndex(i)) { - if (pxt::eq_bool(head.get(i), x)) { - return (int)i; - } - i++; - } -#endif - return -1; -} - -bool RefCollection::removeElement(TValue x) { - int idx = indexOf(x, 0); - if (idx >= 0) { - decr(removeAt(idx)); - return 1; - } - return 0; -} - -namespace Coll0 { -PXT_VTABLE_BEGIN(RefCollection, 0, 0) -PXT_VTABLE_END -} // namespace Coll0 - -RefCollection::RefCollection() : RefObject(0) { - vtable = PXT_VTABLE_TO_INT(&Coll0::RefCollection_vtable); -} - -void RefCollection::destroy(RefCollection *t) { - for (unsigned i = 0; i < t->head.getLength(); i++) { - decr(t->head.get(i)); - } - t->head.destroy(); -} - -void RefCollection::print(RefCollection *t) { - DMESG("RefCollection %p r=%d size=%d", t, t->refcnt, t->head.getLength()); - t->head.print(); -} - -PXT_VTABLE_CTOR(RefAction) {} - -// fields[] contain captured locals -void RefAction::destroy(RefAction *t) { - for (int i = 0; i < t->reflen; ++i) { - decr(t->fields[i]); - t->fields[i] = 0; - } -} - -void RefAction::print(RefAction *t) { - DMESG("RefAction %p r=%d pc=%X size=%d (%d refs)", t, t->refcnt, - (const uint8_t *)t->func - (const uint8_t *)bytecode, t->len, t->reflen); -} - -void RefLocal::print(RefLocal *t) { - DMESG("RefLocal %p r=%d v=%d", t, t->refcnt, t->v); -} - -void RefLocal::destroy(RefLocal *) {} - -PXT_VTABLE_CTOR(RefLocal) { - v = 0; -} - -PXT_VTABLE_CTOR(RefRefLocal) { - v = 0; -} - -void RefRefLocal::print(RefRefLocal *t) { - DMESG("RefRefLocal %p r=%d v=%p", t, t->refcnt, (void *)t->v); -} - -void RefRefLocal::destroy(RefRefLocal *t) { - decr(t->v); -} - -PXT_VTABLE_BEGIN(RefMap, 0, RefMapMarker) -PXT_VTABLE_END -RefMap::RefMap() : PXT_VTABLE_INIT(RefMap) {} - -void RefMap::destroy(RefMap *t) { - for (unsigned i = 0; i < t->values.getLength(); ++i) { - decr(t->values.get(i)); - t->values.set(i, 0); - } - t->keys.destroy(); - t->values.destroy(); -} - -int RefMap::findIdx(unsigned key) { - for (unsigned i = 0; i < keys.getLength(); ++i) { - if ((uintptr_t)keys.get(i) == key) - return i; - } - return -1; -} - -void RefMap::print(RefMap *t) { - DMESG("RefMap %p r=%d size=%d", t, t->refcnt, t->keys.getLength()); -} - -#ifdef PXT_MEMLEAK_DEBUG -std::set allptrs; -void debugMemLeaks() { - DMESG("LIVE POINTERS:"); - for (std::set::iterator itr = allptrs.begin(); itr != allptrs.end(); itr++) { - anyPrint(*itr); - } - DMESG("LIVE POINTERS END."); - dumpDmesg(); -} -#else -void debugMemLeaks() {} -#endif - -void error(PXT_ERROR code, int subcode) { - DMESG("Error: %d [%d]", code, subcode); - target_panic(42); -} - -uint16_t *bytecode; -TValue *globals; - -unsigned *allocate(ramint_t sz) { - unsigned *arr = new unsigned[sz]; - memset(arr, 0, sz * sizeof(unsigned)); - return arr; -} - -void checkStr(bool cond, const char *msg) { - if (!cond) { - while (true) { - // uBit.display.scroll(msg, 100); - // uBit.sleep(100); - } - } -} - -int templateHash() { - return ((int *)bytecode)[4]; -} - -int programHash() { - return ((int *)bytecode)[6]; -} - -int getNumGlobals() { - return bytecode[16]; -} - -#ifndef X86_64 -void exec_binary(unsigned *pc) { - // XXX re-enable once the calibration code is fixed and [editor/embedded.ts] - // properly prepends a call to [internal_main]. - // ::touch_develop::internal_main(); - - // unique group for radio based on source hash - // ::touch_develop::micro_bit::radioDefaultGroup = programHash(); - - unsigned ver = *pc++; - checkStr(ver == 0x4209, ":( Bad runtime version"); - - bytecode = *((uint16_t **)pc++); // the actual bytecode is here - globals = (TValue *)allocate(getNumGlobals()); - - // can be any valid address, best in RAM for speed - globals[0] = (TValue)&globals; - - // just compare the first word - // TODO - checkStr(((uint32_t *)bytecode)[0] == 0x923B8E70 && (unsigned)templateHash() == *pc, - ":( Failed partial flash"); - - uintptr_t startptr = (uintptr_t)bytecode; - - startptr += 48; // header - startptr |= 1; // Thumb state - - initRuntime(); - - ((unsigned (*)())startptr)(); - -#ifdef PXT_MEMLEAK_DEBUG - pxt::debugMemLeaks(); -#endif - - pxt::releaseFiber(); -} - -void start() { - exec_binary((unsigned *)functionsAndBytecode); -} -#endif - -} // namespace pxt diff --git a/libs/core/pxt.json b/libs/core/pxt.json index a72b5afe..4c001b7e 100644 --- a/libs/core/pxt.json +++ b/libs/core/pxt.json @@ -1,7 +1,7 @@ { "name": "core", "description": "The microbit core library", - "installedVersion": "tsmdvf", + "additionalFilePath": "../../node_modules/pxt-common-packages/libs/base", "files": [ "README.md", "pxt.cpp", @@ -105,4 +105,4 @@ } ] } -} \ No newline at end of file +} diff --git a/libs/core/pxtbase.h b/libs/core/pxtbase.h deleted file mode 100644 index bcf228d0..00000000 --- a/libs/core/pxtbase.h +++ /dev/null @@ -1,713 +0,0 @@ -#ifndef __PXTBASE_H -#define __PXTBASE_H - -//#define PXT_MEMLEAK_DEBUG 1 - -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wformat" -#pragma GCC diagnostic ignored "-Warray-bounds" - -// helpful define to handle C++ differences in package -#define PXT_MICROBIT_TAGGED_INT 1 - -// cross version compatible way of access data field -#ifndef PXT_BUFFER_DATA -#define PXT_BUFFER_DATA(buffer) buffer->data -#endif - -#ifndef PXT_CREATE_BUFFER -#define PXT_CREATE_BUFFER(data, len) pxt::mkBuffer(data, len) -#endif - -// needed for gcc6; not sure why -#undef min -#undef max - -#define NOLOG(...) \ - do { \ - } while (0) - -#define MEMDBG_ENABLED 0 -#define MEMDBG NOLOG - -#include "pxtconfig.h" - -#define intcheck(...) check(__VA_ARGS__) -//#define intcheck(...) do {} while (0) - -#include -#include -#include - -#include - -#ifdef PXT_MEMLEAK_DEBUG -#include -#endif - -#include "pxtcore.h" - -#ifndef PXT_VTABLE_SHIFT -#define PXT_VTABLE_SHIFT 2 -#endif - -#define CONCAT_1(a, b) a##b -#define CONCAT_0(a, b) CONCAT_1(a, b) -#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }; - -#ifndef ramint_t -// this type limits size of arrays -#ifdef __linux__ -#define ramint_t uint32_t -#else -#define ramint_t uint16_t -#endif -#endif - -#if 0 -inline void *operator new(size_t, void *p) { - return p; -} -inline void *operator new[](size_t, void *p) { - return p; -} -#endif - -namespace pxt { - -template inline const T &max(const T &a, const T &b) { - if (a < b) - return b; - return a; -} - -template inline const T &min(const T &a, const T &b) { - if (a < b) - return a; - return b; -} - -template inline void swap(T &a, T &b) { - T tmp = a; - a = b; - b = tmp; -} - -// -// Tagged values (assume 4 bytes for now, Cortex-M0) -// -struct TValueStruct {}; -typedef TValueStruct *TValue; - -typedef TValue TNumber; -typedef TValue Action; -typedef TValue ImageLiteral; - -// To be implemented by the target -extern "C" void target_panic(int error_code); -extern "C" void target_reset(); -void sleep_ms(unsigned ms); -void sleep_us(uint64_t us); -void releaseFiber(); -int current_time_ms(); -void initRuntime(); -void sendSerial(const char *data, int len); -int getSerialNumber(); -void registerWithDal(int id, int event, Action a, int flags = 16); // EVENT_LISTENER_DEFAULT_FLAGS -void runInParallel(Action a); -void runForever(Action a); -void waitForEvent(int id, int event); -//% -unsigned afterProgramPage(); -//% -void dumpDmesg(); - -// also defined DMESG macro -// end - -#define TAGGED_SPECIAL(n) (TValue)(void *)((n << 2) | 2) -#define TAG_FALSE TAGGED_SPECIAL(2) -#define TAG_TRUE TAGGED_SPECIAL(16) -#define TAG_UNDEFINED (TValue)0 -#define TAG_NULL TAGGED_SPECIAL(1) -#define TAG_NUMBER(n) (TNumber)(void *)((n << 1) | 1) - -inline bool isTagged(TValue v) { - return ((intptr_t)v & 3) || !v; -} - -inline bool isNumber(TValue v) { - return (intptr_t)v & 1; -} - -inline bool isSpecial(TValue v) { - return (intptr_t)v & 2; -} - -inline bool bothNumbers(TValue a, TValue b) { - return (intptr_t)a & (intptr_t)b & 1; -} - -inline int numValue(TValue n) { - return (intptr_t)n >> 1; -} - -#ifdef PXT_BOX_DEBUG -inline bool canBeTagged(int) { - return false; -} -#else -inline bool canBeTagged(int v) { - return (v << 1) >> 1 == v; -} -#endif - -typedef enum { - ERR_INVALID_BINARY_HEADER = 5, - ERR_OUT_OF_BOUNDS = 8, - ERR_REF_DELETED = 7, - ERR_SIZE = 9, -} PXT_ERROR; - -extern const unsigned functionsAndBytecode[]; -extern TValue *globals; -extern uint16_t *bytecode; -class RefRecord; - -// Utility functions - -//% -TValue runAction3(Action a, TValue arg0, TValue arg1, TValue arg2); -//% -TValue runAction2(Action a, TValue arg0, TValue arg1); -//% -TValue runAction1(Action a, TValue arg0); -//% -TValue runAction0(Action a); -//% -Action mkAction(int reflen, int totallen, int startptr); -// allocate [sz] words and clear them -//% -unsigned *allocate(ramint_t sz); -//% -int templateHash(); -//% -int programHash(); -//% -unsigned programSize(); -//% -int getNumGlobals(); -//% -RefRecord *mkClassInstance(int vtableOffset); -//% -void debugMemLeaks(); -//% -void anyPrint(TValue v); - -int getConfig(int key, int defl = -1); - -//% -int toInt(TNumber v); -//% -unsigned toUInt(TNumber v); -//% -double toDouble(TNumber v); -//% -float toFloat(TNumber v); -//% -TNumber fromDouble(double r); -//% -TNumber fromFloat(float r); - -//% -TNumber fromInt(int v); -//% -TNumber fromUInt(unsigned v); -//% -TValue fromBool(bool v); -//% -bool eq_bool(TValue a, TValue b); -//% -bool eqq_bool(TValue a, TValue b); - -void error(PXT_ERROR code, int subcode = 0); -void exec_binary(unsigned *pc); -void start(); - -struct HandlerBinding { - HandlerBinding *next; - int source; - int value; - Action action; -}; -HandlerBinding *findBinding(int source, int value); -void setBinding(int source, int value, Action act); - -// The standard calling convention is: -// - when a pointer is loaded from a local/global/field etc, and incr()ed -// (in other words, its presence on stack counts as a reference) -// - after a function call, all pointers are popped off the stack and decr()ed -// This does not apply to the RefRecord and st/ld(ref) methods - they unref() -// the RefRecord* this. -//% -TValue incr(TValue e); -//% -void decr(TValue e); - -class RefObject; - -static inline RefObject *incrRC(RefObject *r) { - return (RefObject *)incr((TValue)r); -} -static inline void decrRC(RefObject *r) { - decr((TValue)r); -} - -inline void *ptrOfLiteral(int offset) { - return &bytecode[offset]; -} - -// Checks if object is ref-counted, and has a custom PXT vtable in front -// TODO -inline bool isRefCounted(TValue e) { - return !isTagged(e) && (*((unsigned *)e) & 1) == 1; -} - -inline void check(int cond, PXT_ERROR code, int subcode = 0) { - if (!cond) - error(code, subcode); -} - -inline void oops() { - target_panic(47); -} - -class RefObject; -#ifdef PXT_MEMLEAK_DEBUG -extern std::set allptrs; -#endif - -typedef void (*RefObjectMethod)(RefObject *self); -typedef void *PVoid; -typedef void **PPVoid; - -typedef void *Object_; - -const PPVoid RefMapMarker = (PPVoid)(void *)43; - -struct VTable { - uint16_t numbytes; // in the entire object, including the vtable pointer - uint16_t userdata; - PVoid *ifaceTable; - PVoid methods[2]; // we only use up to two methods here; pxt will generate more - // refmask sits at &methods[nummethods] -}; - -const int vtableShift = PXT_VTABLE_SHIFT; - -// A base abstract class for ref-counted objects. -class RefObject { - public: - uint16_t refcnt; - uint16_t vtable; - - RefObject(uint16_t vt) { - refcnt = 3; - vtable = vt; -#ifdef PXT_MEMLEAK_DEBUG - allptrs.insert((TValue)this); -#endif - } - - void destroyVT(); - void printVT(); - - // Call to disable pointer tracking on the current instance (in destructor or some other hack) - inline void untrack() { -#ifdef PXT_MEMLEAK_DEBUG - allptrs.erase((TValue)this); -#endif - } - - inline bool isReadOnly() { return refcnt == 0xffff; } - - // Increment/decrement the ref-count. Decrementing to zero deletes the current object. - inline void ref() { - if (isReadOnly()) - return; - check(refcnt > 1, ERR_REF_DELETED); - // DMESG("INCR "); this->print(); - refcnt += 2; - } - - inline void unref() { - if (isReadOnly()) - return; - check(refcnt > 1, ERR_REF_DELETED); - check((refcnt & 1), ERR_REF_DELETED); - // DMESG("DECR "); this->print(); - refcnt -= 2; - if (refcnt == 1) { - untrack(); - destroyVT(); - } - } -}; - -class Segment { - private: - TValue *data; - ramint_t length; - ramint_t size; - - // this just gives max value of ramint_t - static constexpr ramint_t MaxSize = (((1U << (8 * sizeof(ramint_t) - 1)) - 1) << 1) + 1; - static constexpr TValue DefaultValue = TAG_UNDEFINED; - - static ramint_t growthFactor(ramint_t size); - void growByMin(ramint_t minSize); - void growBy(ramint_t newSize); - void ensure(ramint_t newSize); - - public: - Segment() : data(nullptr), length(0), size(0){}; - - TValue get(unsigned i); - void set(unsigned i, TValue value); - void setRef(unsigned i, TValue value); - - unsigned getLength() { return length; }; - void setLength(unsigned newLength); - void resize(unsigned newLength) { setLength(newLength); } - - void push(TValue value); - TValue pop(); - - TValue remove(unsigned i); - void insert(unsigned i, TValue value); - - bool isValidIndex(unsigned i); - - void destroy(); - - void print(); -}; - -// A ref-counted collection of either primitive or ref-counted objects (String, Image, -// user-defined record, another collection) -class RefCollection : public RefObject { - private: - Segment head; - - public: - RefCollection(); - - static void destroy(RefCollection *coll); - static void print(RefCollection *coll); - - unsigned length() { return head.getLength(); } - void setLength(unsigned newLength) { head.setLength(newLength); } - - void push(TValue x); - TValue pop(); - TValue getAt(int i); - void setAt(int i, TValue x); - // removes the element at index i and shifts the other elements left - TValue removeAt(int i); - // inserts the element at index i and moves the other elements right. - void insertAt(int i, TValue x); - - int indexOf(TValue x, int start); - bool removeElement(TValue x); -}; - -class RefMap : public RefObject { - public: - Segment keys; - Segment values; - - RefMap(); - static void destroy(RefMap *map); - static void print(RefMap *map); - int findIdx(unsigned key); -}; - -// A ref-counted, user-defined JS object. -class RefRecord : public RefObject { - public: - // The object is allocated, so that there is space at the end for the fields. - TValue fields[]; - - RefRecord(uint16_t v) : RefObject(v) {} - - TValue ld(int idx); - TValue ldref(int idx); - void st(int idx, TValue v); - void stref(int idx, TValue v); -}; - -//% -VTable *getVTable(RefObject *r); - -// these are needed when constructing vtables for user-defined classes -//% -void RefRecord_destroy(RefRecord *r); -//% -void RefRecord_print(RefRecord *r); - -class RefAction; -typedef TValue (*ActionCB)(TValue *captured, TValue arg0, TValue arg1, TValue arg2); - -// Ref-counted function pointer. -class RefAction : public RefObject { - public: - // This is the same as for RefRecord. - uint8_t len; - uint8_t reflen; - ActionCB func; // The function pointer - // fields[] contain captured locals - TValue fields[]; - - static void destroy(RefAction *act); - static void print(RefAction *act); - - RefAction(); - - inline void stCore(int idx, TValue v) { - // DMESG("ST [%d] = %d ", idx, v); this->print(); - intcheck(0 <= idx && idx < len, ERR_OUT_OF_BOUNDS, 10); - intcheck(fields[idx] == 0, ERR_OUT_OF_BOUNDS, 11); // only one assignment permitted - fields[idx] = v; - } - - inline TValue runCore(TValue arg0, TValue arg1, - TValue arg2) // internal; use runAction*() functions - { - this->ref(); - TValue r = this->func(&this->fields[0], arg0, arg1, arg2); - this->unref(); - return r; - } -}; - -// These two are used to represent locals written from inside inline functions -class RefLocal : public RefObject { - public: - TValue v; - static void destroy(RefLocal *l); - static void print(RefLocal *l); - RefLocal(); -}; - -class RefRefLocal : public RefObject { - public: - TValue v; - static void destroy(RefRefLocal *l); - static void print(RefRefLocal *l); - RefRefLocal(); -}; - -typedef int color; - -// note: this is hardcoded in PXT (hexfile.ts) - -#define PXT_REF_TAG_STRING 1 -#define PXT_REF_TAG_BUFFER 2 -#define PXT_REF_TAG_IMAGE 3 -#define PXT_REF_TAG_NUMBER 32 -#define PXT_REF_TAG_ACTION 33 - -class BoxedNumber : public RefObject { - public: - double num; - BoxedNumber() : RefObject(PXT_REF_TAG_NUMBER) {} -} __attribute__((packed)); - -class BoxedString : public RefObject { - public: - uint16_t length; - char data[0]; - BoxedString() : RefObject(PXT_REF_TAG_STRING) {} -}; - -class BoxedBuffer : public RefObject { - public: - // data needs to be word-aligned, so we use 32 bits for length - int length; - uint8_t data[0]; - BoxedBuffer() : RefObject(PXT_REF_TAG_BUFFER) {} -}; - - -// the first byte of data indicates the format - currently 0xE1 or 0xE4 to 1 or 4 bit bitmaps -// second byte indicates width in pixels -// third byte indicates the height (which should also match the size of the buffer) -// just like ordinary buffers, these can be layed out in flash -class RefImage : public RefObject { - uintptr_t _buffer; - uint8_t _data[0]; - - public: - RefImage(BoxedBuffer *buf); - RefImage(uint32_t sz); - - bool hasBuffer() { return !(_buffer & 1); } - BoxedBuffer *buffer() { return hasBuffer() ? (BoxedBuffer *)_buffer : NULL; } - void setBuffer(BoxedBuffer *b); - bool isDirty() { return (_buffer & 3) == 3; } - void clearDirty() { if (isDirty()) _buffer &= ~2; } - - uint8_t *data() { return hasBuffer() ? buffer()->data : _data; } - int length() { return hasBuffer() ? buffer()->length : (_buffer >> 2); } - int pixLength() { return length() - 4; } - - int height(); - int width(); - int byteHeight(); - int wordHeight(); - int bpp(); - - bool hasPadding() { return (height() & 0x1f) != 0; } - - uint8_t *pix() { return data() + 4; } - uint8_t *pix(int x, int y); - uint8_t fillMask(color c); - bool inRange(int x, int y); - void clamp(int *x, int *y); - void makeWritable(); - - static void destroy(RefImage *t); - static void print(RefImage *t); -}; - -RefImage *mkImage(int w, int h, int bpp); - - -typedef BoxedBuffer *Buffer; -typedef BoxedString *String; -typedef RefImage *Image_; - -// keep in sync with github/pxt/pxtsim/libgeneric.ts -enum class NumberFormat { - Int8LE = 1, - UInt8LE, - Int16LE, - UInt16LE, - Int32LE, - Int8BE, - UInt8BE, - Int16BE, - UInt16BE, - Int32BE, - - UInt32LE, - UInt32BE, - Float32LE, - Float64LE, - Float32BE, - Float64BE, -}; - -// data can be NULL in both cases -String mkString(const char *data, int len = -1); -Buffer mkBuffer(const uint8_t *data, int len); - -TNumber getNumberCore(uint8_t *buf, int size, NumberFormat format); -void setNumberCore(uint8_t *buf, int size, NumberFormat format, TNumber value); - -TNumber mkNaN(); - -void seedRandom(unsigned seed); -// max is inclusive -unsigned getRandom(unsigned max); - -extern const VTable string_vt; -extern const VTable image_vt; -extern const VTable buffer_vt; -extern const VTable number_vt; -extern const VTable RefAction_vtable; - -enum class ValType { - Undefined, - Boolean, - Number, - String, - Object, - Function, -}; - -ValType valType(TValue v); -} // namespace pxt - -#define PXT_DEF_STRING(name, val) \ - static const char name[] __attribute__((aligned(4))) = "\xff\xff\x01\x00" val; - -using namespace pxt; - -namespace pins { -Buffer createBuffer(int size); -} - -namespace String_ { -int compare(String s, String that); -} - -// The ARM Thumb generator in the JavaScript code is parsing -// the hex file and looks for the magic numbers as present here. -// -// Then it fetches function pointer addresses from there. -// -// The vtable pointers are there, so that the ::emptyData for various types -// can be patched with the right vtable. -// -#define PXT_SHIMS_BEGIN \ - namespace pxt { \ - const unsigned functionsAndBytecode[] \ - __attribute__((aligned(0x20))) = {0x08010801, 0x42424242, 0x08010801, 0x8de9d83e, - -#define PXT_SHIMS_END \ - } \ - ; \ - } - -#ifndef X86_64 -#pragma GCC diagnostic ignored "-Wpmf-conversions" -#endif - -#define PXT_VTABLE_TO_INT(vt) ((uintptr_t)(vt) >> vtableShift) -#define PXT_VTABLE_BEGIN(classname, flags, iface) \ - const VTable classname##_vtable __attribute__((aligned(1 << vtableShift))) = { \ - sizeof(classname), flags, iface, {(void *)&classname::destroy, (void *)&classname::print, - -#define PXT_VTABLE_END \ - } \ - } \ - ; - -#define PXT_VTABLE_INIT(classname) RefObject(PXT_VTABLE_TO_INT(&classname##_vtable)) - -#define PXT_VTABLE_CTOR(classname) \ - PXT_VTABLE_BEGIN(classname, 0, 0) \ - PXT_VTABLE_END classname::classname() : PXT_VTABLE_INIT(classname) - -#define PXT_MAIN \ - int main() { \ - pxt::start(); \ - return 0; \ - } - -#define PXT_FNPTR(x) (unsigned)(void *)(x) - -#define PXT_ABI(...) - -#define JOIN(a, b) a##b -/// Defines getClassName() function to fetch the singleton -#define SINGLETON(ClassName) \ - static ClassName *JOIN(inst, ClassName); \ - ClassName *JOIN(get, ClassName)() { \ - if (!JOIN(inst, ClassName)) \ - JOIN(inst, ClassName) = new ClassName(); \ - return JOIN(inst, ClassName); \ - } - -#endif diff --git a/package.json b/package.json index 0b485c0d..f3b4ff67 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@types/node": "8.0.53" }, "dependencies": { + "pxt-common-packages": "0.23.53", "pxt-core": "3.22.17" } } From c499b7b54d02d94b618207eed8995df39de9395b Mon Sep 17 00:00:00 2001 From: Guillaume Jenkins Date: Mon, 10 Sep 2018 15:35:06 -0400 Subject: [PATCH 2/4] Set DAL tag to dal-integration-5 (v1) (#1200) * Set DAL tag to dal-integration-5 (v1) * Add partial flashing config * Move partial bluetooth flashing config to optional --- libs/core/pxt.json | 5 +++-- pxtarget.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/core/pxt.json b/libs/core/pxt.json index 4c001b7e..3a948a55 100644 --- a/libs/core/pxt.json +++ b/libs/core/pxt.json @@ -43,7 +43,7 @@ ], "public": true, "dependencies": {}, - "yotta": { + "yotta": { "optionalConfig": { "microbit-dal": { "bluetooth": { @@ -59,7 +59,8 @@ "pairing_mode": 1, "whitelist": 1, "security_level": "SECURITY_MODE_ENCRYPTION_NO_MITM", - "gatt_table_size": "0x700" + "gatt_table_size": "0x700", + "partial_flashing": 1 } } }, diff --git a/pxtarget.json b/pxtarget.json index ea5cb6c8..1344a131 100644 --- a/pxtarget.json +++ b/pxtarget.json @@ -215,7 +215,7 @@ "yottaTarget": "bbc-microbit-classic-gcc", "yottaCorePackage": "microbit", "githubCorePackage": "lancaster-university/microbit", - "gittag": "dal-integration-3", + "gittag": "dal-integration-5", "serviceId": "microbit", "dockerImage": "pext/yotta:latest" }, From 84e4689db7e9ea78d5cb022eae21f9eae39f4d89 Mon Sep 17 00:00:00 2001 From: Guillaume Jenkins Date: Mon, 10 Sep 2018 15:57:48 -0400 Subject: [PATCH 3/4] bump pxt-core to 3.22.18, --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3b4ff67..df6e17a8 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,6 @@ }, "dependencies": { "pxt-common-packages": "0.23.53", - "pxt-core": "3.22.17" + "pxt-core": "3.22.18" } } From 7be71bf9b77bc07b7f4e3664c21681b1f9c4ba85 Mon Sep 17 00:00:00 2001 From: Guillaume Jenkins Date: Mon, 10 Sep 2018 15:57:54 -0400 Subject: [PATCH 4/4] 1.1.49 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b6082c36..558e1629 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pxt-microbit", - "version": "1.1.48", + "version": "1.1.49", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index df6e17a8..8bbd2f7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pxt-microbit", - "version": "1.1.48", + "version": "1.1.49", "description": "micro:bit target for Microsoft MakeCode (PXT)", "keywords": [ "JavaScript",