Nasal now supports calls to "subcontexts" and errors can be thrown across them, leading to complete stack traces when call() is used, instead of the truncated ones we now see. Vectors can now be concatenated using the ~ operator that used to work only for strings. Better runtime error messages in general due to a fancier naRuntimeError() implementation A big data size shrink on 64 bit systems; the size of a naRef dropped by a factor of two. "Braceless code blocks" have been added to the parser, so you can write expressions like "if(a) b();" just like in C. Note that there's still a parser bug in there that fails when you nest a braced block within a braceless one. Character constants that appear in Nasal source code can now be literal multibyte UTF8 characters (this was always supported for string literals, but character constants were forced to be a single byte). New modules: "bits", "thread", "utf8" and (gulp...) "io". The bits library might be useful to FlightGear, the utf8 one probably not as Plib does not support wide character text rendering. The thread library will work fine for spawning threads to do Nasal stuff, but obviously contact with the rest of FlightGear must be hand-synchronized as FlightGear isn't threadsafe. The io library is no doubt the most useful, as it exposes all the basic stdio.h facilities; it's also frighteningly dangerous when combined with networked code...
98 lines
2.2 KiB
C
98 lines
2.2 KiB
C
#include "nasal.h"
|
|
#include "data.h"
|
|
|
|
static struct VecRec* newvecrec(struct VecRec* old)
|
|
{
|
|
int i, oldsz = old ? old->size : 0, newsz = 1 + ((oldsz*3)>>1);
|
|
struct VecRec* vr = naAlloc(sizeof(struct VecRec) + sizeof(naRef) * newsz);
|
|
if(oldsz > newsz) oldsz = newsz; // race protection
|
|
vr->alloced = newsz;
|
|
vr->size = oldsz;
|
|
for(i=0; i<oldsz; i++)
|
|
vr->array[i] = old->array[i];
|
|
return vr;
|
|
}
|
|
|
|
static void resize(struct naVec* v)
|
|
{
|
|
struct VecRec* vr = newvecrec(v->rec);
|
|
naGC_swapfree((void**)&(v->rec), vr);
|
|
}
|
|
|
|
void naVec_gcclean(struct naVec* v)
|
|
{
|
|
naFree(v->rec);
|
|
v->rec = 0;
|
|
}
|
|
|
|
naRef naVec_get(naRef v, int i)
|
|
{
|
|
if(IS_VEC(v)) {
|
|
struct VecRec* r = PTR(v).vec->rec;
|
|
if(r) {
|
|
if(i < 0) i += r->size;
|
|
if(i >= 0 && i < r->size) return r->array[i];
|
|
}
|
|
}
|
|
return naNil();
|
|
}
|
|
|
|
void naVec_set(naRef vec, int i, naRef o)
|
|
{
|
|
if(IS_VEC(vec)) {
|
|
struct VecRec* r = PTR(vec).vec->rec;
|
|
if(r && i >= r->size) return;
|
|
r->array[i] = o;
|
|
}
|
|
}
|
|
|
|
int naVec_size(naRef v)
|
|
{
|
|
if(IS_VEC(v)) {
|
|
struct VecRec* r = PTR(v).vec->rec;
|
|
return r ? r->size : 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int naVec_append(naRef vec, naRef o)
|
|
{
|
|
if(IS_VEC(vec)) {
|
|
struct VecRec* r = PTR(vec).vec->rec;
|
|
while(!r || r->size >= r->alloced) {
|
|
resize(PTR(vec).vec);
|
|
r = PTR(vec).vec->rec;
|
|
}
|
|
r->array[r->size] = o;
|
|
return r->size++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void naVec_setsize(naRef vec, int sz)
|
|
{
|
|
int i;
|
|
struct VecRec* v = PTR(vec).vec->rec;
|
|
struct VecRec* nv = naAlloc(sizeof(struct VecRec) + sizeof(naRef) * sz);
|
|
nv->size = sz;
|
|
nv->alloced = sz;
|
|
for(i=0; i<sz; i++)
|
|
nv->array[i] = (v && i < v->size) ? v->array[i] : naNil();
|
|
naGC_swapfree((void**)&(PTR(vec).vec->rec), nv);
|
|
}
|
|
|
|
naRef naVec_removelast(naRef vec)
|
|
{
|
|
naRef o;
|
|
if(IS_VEC(vec)) {
|
|
struct VecRec* v = PTR(vec).vec->rec;
|
|
if(!v || v->size == 0) return naNil();
|
|
o = v->array[v->size - 1];
|
|
v->size--;
|
|
if(v->size < (v->alloced >> 1))
|
|
resize(PTR(vec).vec);
|
|
return o;
|
|
}
|
|
return naNil();
|
|
}
|