pxt-calliope/libs/core/core.cpp

413 lines
8.1 KiB
C++
Raw Normal View History

2016-11-30 06:35:26 +01:00
#include "pxt.h"
2016-04-02 07:32:33 +02:00
#include <limits.h>
namespace String_ {
2016-04-02 07:32:33 +02:00
//%
StringData *charAt(StringData *s, int pos) {
return ManagedString((char)ManagedString(s).charAt(pos)).leakData();
}
//%
int charCodeAt(StringData *s, int index) {
return ManagedString(s).charAt(index);
2016-04-02 07:32:33 +02:00
}
//%
StringData *concat(StringData *s, StringData *other) {
ManagedString a(s), b(other);
return (a + b).leakData();
}
//%
int compare(StringData *s, StringData *that) {
return strcmp(s->data, that->data);
}
//%
int length(StringData *s) { return s->len; }
//%
StringData *fromCharCode(int code)
{
return ManagedString((char)code).leakData();
}
//%
int toNumber(StringData *s) {
return atoi(s->data);
}
//%
StringData *mkEmpty()
{
return ManagedString::EmptyString.leakData();
2016-04-13 04:08:26 +02:00
}
//%
StringData *substr(StringData *s, int start, int length)
{
if (length <= 0)
return mkEmpty();
if (start < 0)
start = max(s->len + start, 0);
length = min(length, s->len - start);
ManagedString x(s);
return x.substring(start, length).leakData();
2016-04-02 07:32:33 +02:00
}
}
namespace Boolean_ {
2016-04-02 07:32:33 +02:00
// Cache the string literals "true" and "false" when used.
// Note that the representation of booleans stays the usual C-one.
static const char sTrue[] __attribute__ ((aligned (4))) = "\xff\xff\x04\x00" "true\0";
static const char sFalse[] __attribute__ ((aligned (4))) = "\xff\xff\x05\x00" "false\0";
//%
StringData* toString(bool v)
{
if (v) {
return (StringData*)(void*)sTrue;
} else {
return (StringData*)(void*)sFalse;
}
}
2016-04-02 20:22:36 +02:00
//%
bool bang(int v) { return v == 0; }
2016-04-02 07:32:33 +02:00
}
namespace Number_ {
2016-04-02 07:32:33 +02:00
//%
StringData* toString(int n)
{
return ManagedString(n).leakData();
}
2016-04-02 20:22:36 +02:00
// +, - and friends are handled directly by assembly instructions
// The comparisons are here as they are more code-size efficient
//%
bool lt(int x, int y) { return x < y; }
//%
bool le(int x, int y) { return x <= y; }
//%
bool neq(int x, int y) { return x != y; }
//%
bool eq(int x, int y) { return x == y; }
//%
bool gt(int x, int y) { return x > y; }
//%
bool ge(int x, int y) { return x >= y; }
// These in fact call into C runtime on Cortex-M0
//%
int div(int x, int y) { return x / y; }
//%
int mod(int x, int y) { return x % y; }
}
2016-04-03 05:35:22 +02:00
namespace Math_ {
2016-04-02 07:32:33 +02:00
//%
int pow(int x, int y)
{
if (y < 0)
return 0;
int r = 1;
while (y) {
if (y & 1)
r *= x;
y >>= 1;
x *= x;
}
return r;
}
//%
int random(int max) {
if (max == INT_MIN)
return -microbit_random(INT_MAX);
2016-04-02 07:32:33 +02:00
else if (max < 0)
return -microbit_random(-max);
2016-04-02 07:32:33 +02:00
else if (max == 0)
return 0;
else
return microbit_random(max);
2016-04-02 07:32:33 +02:00
}
//%
int sqrt(int x)
{
return ::sqrt(x);
}
}
2016-04-02 07:46:06 +02:00
namespace Array_ {
2016-04-02 07:46:06 +02:00
//%
RefCollection *mk(uint32_t flags)
{
2016-04-02 22:44:29 +02:00
return new RefCollection(flags);
2016-04-02 07:46:06 +02:00
}
//%
2016-04-02 22:44:29 +02:00
int length(RefCollection *c) { return c->length(); }
2016-04-02 07:46:06 +02:00
//%
void setLength(RefCollection *c, int newLength) { c->setLength(newLength); }
//%
2016-04-02 22:44:29 +02:00
void push(RefCollection *c, uint32_t x) { c->push(x); }
2016-04-02 07:46:06 +02:00
//%
uint32_t pop(RefCollection *c) { return c->pop(); }
//%
2016-04-02 22:44:29 +02:00
uint32_t getAt(RefCollection *c, int x) { return c->getAt(x); }
2016-04-02 07:46:06 +02:00
//%
void setAt(RefCollection *c, int x, uint32_t y) { c->setAt(x, y); }
//%
uint32_t removeAt(RefCollection *c, int x) { return c->removeAt(x); }
2016-04-02 07:46:06 +02:00
//%
void insertAt(RefCollection *c, int x, uint32_t value) { c->insertAt(x, value); }
2016-04-02 07:46:06 +02:00
//%
2016-04-02 22:44:29 +02:00
int indexOf(RefCollection *c, uint32_t x, int start) { return c->indexOf(x, start); }
2016-04-02 07:46:06 +02:00
//%
2016-04-02 22:44:29 +02:00
int removeElement(RefCollection *c, uint32_t x) { return c->removeElement(x); }
2016-04-02 07:46:06 +02:00
}
2016-09-09 11:17:28 +02:00
2016-04-02 22:44:29 +02:00
// Import some stuff directly
2016-04-07 21:52:02 +02:00
namespace pxt {
2016-04-02 22:44:29 +02:00
//%
void registerWithDal(int id, int event, Action a);
//%
2016-08-17 17:08:46 +02:00
uint32_t runAction3(Action a, int arg0, int arg1, int arg2);
2016-04-02 22:44:29 +02:00
//%
2016-08-17 17:08:46 +02:00
uint32_t runAction2(Action a, int arg0, int arg1);
//%
uint32_t runAction1(Action a, int arg0);
//%
uint32_t runAction0(Action a);
2016-04-02 22:44:29 +02:00
//%
Action mkAction(int reflen, int totallen, int startptr);
//%
RefRecord* mkClassInstance(int offset);
//%
2016-09-09 11:17:28 +02:00
void RefRecord_destroy(RefRecord *r);
//%
void RefRecord_print(RefRecord *r);
//%
2016-04-02 22:44:29 +02:00
void debugMemLeaks();
//%
int incr(uint32_t e);
//%
void decr(uint32_t e);
//%
uint32_t *allocate(uint16_t sz);
//%
int templateHash();
//%
int programHash();
//%
void *ptrOfLiteral(int offset);
2016-08-30 12:48:58 +02:00
//%
int getNumGlobals();
//%
uint32_t programSize() {
return bytecode[17] * 2;
}
//%
uint32_t afterProgramPage() {
uint32_t ptr = (uint32_t)&bytecode[0];
ptr += programSize();
ptr = (ptr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
return ptr;
}
2016-04-02 20:22:36 +02:00
}
2016-04-07 21:52:02 +02:00
namespace pxtrt {
2016-04-02 20:22:36 +02:00
//%
uint32_t ldloc(RefLocal *r) {
return r->v;
}
//%
uint32_t ldlocRef(RefRefLocal *r) {
uint32_t tmp = r->v;
incr(tmp);
return tmp;
}
//%
void stloc(RefLocal *r, uint32_t v) {
r->v = v;
}
//%
void stlocRef(RefRefLocal *r, uint32_t v) {
decr(r->v);
r->v = v;
}
//%
RefLocal *mkloc() {
return new RefLocal();
}
//%
RefRefLocal *mklocRef() {
return new RefRefLocal();
}
// All of the functions below unref() self. This is for performance reasons -
// the code emitter will not emit the unrefs for them.
//%
uint32_t ldfld(RefRecord *r, int idx) {
auto tmp = r->ld(idx);
r->unref();
return tmp;
}
//%
uint32_t ldfldRef(RefRecord *r, int idx) {
auto tmp = r->ldref(idx);
r->unref();
return tmp;
}
//%
void stfld(RefRecord *r, int idx, uint32_t val) {
r->st(idx, val);
r->unref();
}
//%
void stfldRef(RefRecord *r, int idx, uint32_t 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, uint32_t v)
{
//DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v);
2016-04-04 01:52:57 +02:00
a->stCore(idx, v);
2016-04-02 20:22:36 +02:00
return a;
}
//%
2016-04-02 22:44:29 +02:00
void panic(int code)
{
microbit_panic(code);
2016-04-02 20:22:36 +02:00
}
2016-04-27 20:26:55 +02:00
2016-08-26 13:14:48 +02:00
//%
int stringToBool(StringData *s) {
if (s == NULL) return 0;
if (s->len == 0) {
s->decr();
return 0;
}
s->decr();
return 1;
}
//%
StringData* emptyToNull(StringData *s) {
if (!s || s->len == 0)
return NULL;
return s;
}
//%
int ptrToBool(uint32_t p) {
if (p) {
decr(p);
return 1;
} else {
return 0;
}
}
//%
RefMap *mkMap() {
return new RefMap();
}
//%
uint32_t mapGet(RefMap *map, uint32_t key) {
int i = map->findIdx(key);
if (i < 0) {
map->unref();
return 0;
}
uint32_t r = map->data[i].val;
map->unref();
return r;
}
//%
uint32_t mapGetRef(RefMap *map, uint32_t key) {
int i = map->findIdx(key);
if (i < 0) {
map->unref();
return 0;
}
uint32_t r = incr(map->data[i].val);
map->unref();
return r;
}
//%
void mapSet(RefMap *map, uint32_t key, uint32_t val) {
int i = map->findIdx(key);
if (i < 0) {
map->data.push_back({
key << 1,
val
});
} else {
if (map->data[i].key & 1) {
decr(map->data[i].val);
map->data[i].key = key << 1;
}
map->data[i].val = val;
}
map->unref();
}
//%
void mapSetRef(RefMap *map, uint32_t key, uint32_t val) {
int i = map->findIdx(key);
if (i < 0) {
map->data.push_back({
(key << 1) | 1,
val
});
} else {
if (map->data[i].key & 1) {
decr(map->data[i].val);
} else {
map->data[i].key = (key << 1) | 1;
}
map->data[i].val = val;
}
map->unref();
}
2016-04-27 20:26:55 +02:00
//
// Debugger
//
//%
void* getGlobalsPtr() {
return globals;
}
//%
void runtimeWarning(StringData *s) {
// noop for now
}
2016-04-02 22:44:29 +02:00
}