#include "daScript/misc/platform.h"
#include "daScript/simulate/data_walker.h"
#include "daScript/ast/ast.h"
#include "daScript/simulate/hash.h"
namespace das {
void DataWalker::error ( const char * message ) {
if ( context ) {
context->throw_error(message);
}
_cancel = true;
}
void DataWalker::walk ( vec4f x, TypeInfo * info ) {
if ( info->flags & TypeInfo::flag_refType ) {
walk(cast::to(x), info );
} else {
walk((char *)&x, info );
}
}
void DataWalker::walk_struct ( char * ps, StructInfo * si ) {
if ( ps && (si->flags & StructInfo::flag_class) ) {
auto ti = *(TypeInfo **) ps;
if ( ti!=nullptr ) si = ti->structType;
else invalidData(); // we are walking uninitialized class here
}
if ( canVisitStructure_(ps, si) ) {
beforeStructure_(ps, si);
if ( cancel() ) {
afterStructureCancel_(ps, si);
return;
}
for ( uint32_t i=0, is=si->count; i!=is; ++i ) {
bool last = i==(si->count-1);
VarInfo * vi = si->fields[i];
char * pf = ps + vi->offset;
beforeStructureField(ps, si, pf, vi, last);
if ( cancel() ) {
afterStructureCancel_(ps, si);
return;
}
walk(pf, vi);
if ( cancel() ) {
afterStructureCancel_(ps, si);
return;
}
afterStructureField(ps, si, pf, vi, last);
if ( cancel() ) {
afterStructureCancel_(ps, si);
return;
}
}
afterStructure_(ps, si);
}
}
void DataWalker::walk_tuple ( char * ps, TypeInfo * ti ) {
if ( canVisitTuple(ps,ti) ) {
beforeTuple(ps, ti);
if ( cancel() ) return;
int fieldOffset = 0;
for ( uint32_t i=0, is=ti->argCount; i!=is; ++i ) {
bool last = i==(ti->argCount-1);
TypeInfo * vi = ti->argTypes[i];
auto fa = getTypeAlign(vi) - 1;
fieldOffset = (fieldOffset + fa) & ~fa;
char * pf = ps + fieldOffset;
beforeTupleEntry(ps, ti, pf, i, last);
if ( cancel() ) return;
walk(pf, vi);
if ( cancel() ) return;
afterTupleEntry(ps, ti, pf, i, last);
if ( cancel() ) return;
fieldOffset += vi->size;
}
afterTuple(ps, ti);
}
}
void DataWalker::walk_variant ( char * ps, TypeInfo * ti ) {
if ( canVisitVariant(ps,ti) ) {
beforeVariant(ps, ti);
if ( cancel() ) return;
if (ti->argCount != 0) {
int32_t fidx = *((int32_t *)ps);
DAS_ASSERTF(uint32_t(fidx)argCount,"invalid variant index");
int fieldOffset = getTypeBaseSize(Type::tInt);
TypeInfo * vi = ti->argTypes[fidx];
auto fa = getTypeAlign(ti) - 1;
fieldOffset = (fieldOffset + fa) & ~fa;
char * pf = ps + fieldOffset;
if ( cancel() ) return;
walk(pf, vi);
if ( cancel() ) return;
}
afterVariant(ps, ti);
}
}
void DataWalker::walk_array ( char * pa, uint32_t stride, uint32_t count, TypeInfo * ti ) {
if ( !canVisitArrayData(ti,count) ) return;
char * pe = pa;
beforeArrayData(pa, stride, count, ti);
if ( cancel() ) return;
for ( uint32_t i=0; i!=count; ++i ) {
bool last = i==count-1;
beforeArrayElement(pa, ti, pe, i, last);
if ( cancel() ) return;
walk(pe, ti);
if ( cancel() ) return;
afterArrayElement(pa, ti, pe, i, last);
if ( cancel() ) return;
pe += stride;
}
afterArrayData(pa, stride, count, ti);
}
void DataWalker::walk_dim ( char * pa, TypeInfo * ti ) {
TypeInfo copyInfo = *ti;
DAS_ASSERT(copyInfo.dimSize);
copyInfo.size = ti->dim[0] ? copyInfo.size / ti->dim[0] : copyInfo.size;
copyInfo.dimSize --;
vector udim;
if ( copyInfo.dimSize ) {
for ( uint32_t i=0, is=copyInfo.dimSize; i!=is; ++i) {
udim.push_back(ti->dim[i+1]);
}
copyInfo.dim = udim.data();
} else {
copyInfo.dim = nullptr;
}
uint32_t stride = copyInfo.size;
uint32_t count = ti->dim[0];
walk_array(pa, stride, count, ©Info);
}
void DataWalker::walk_table ( Table * tab, TypeInfo * info ) {
if ( !canVisitTableData(info) ) return;
int keySize = info->firstType->size;
int valueSize = info->secondType->size;
uint32_t count = 0;
for ( uint32_t i=0, is=tab->capacity; i!=is; ++i ) {
if ( tab->hashes[i] > HASH_KILLED64 ) {
bool last = (count == (tab->size-1));
// key
char * key = tab->keys + i*keySize;
beforeTableKey(tab, info, key, info->firstType, count, last);
if ( cancel() ) return;
walk ( key, info->firstType );
if ( cancel() ) return;
afterTableKey(tab, info, key, info->firstType, count, last);
if ( cancel() ) return;
// value
char * value = tab->data + i*valueSize;
beforeTableValue(tab, info, value, info->secondType, count, last);
if ( cancel() ) return;
walk ( value, info->secondType );
if ( cancel() ) return;
afterTableValue(tab, info, value, info->secondType, count, last);
if ( cancel() ) return;
// next
count ++;
}
}
}
void DataWalker::walk ( char * pa, TypeInfo * info ) {
if ( pa == nullptr ) {
Null(info);
} else if ( info->flags & TypeInfo::flag_ref ) {
beforeRef(pa,info);
if ( cancel() ) return;
TypeInfo ti = *info;
ti.flags &= ~TypeInfo::flag_ref;
walk(*(char **)pa, &ti);
ti.flags |= TypeInfo::flag_ref;
if ( cancel() ) return;
afterRef(pa,info);
} else if ( info->dimSize ) {
if ( canVisitDim(pa,info) ) {
beforeDim(pa, info);
if ( cancel() ) return;
walk_dim(pa, info);
if ( cancel() ) return;
afterDim(pa, info);
}
} else if ( info->type==Type::tArray ) {
auto arr = (Array *) pa;
if ( canVisitArray(arr,info) ) {
beforeArray(arr, info);
if ( cancel() ) return;
walk_array(arr->data, info->firstType->size, arr->size, info->firstType);
if ( cancel() ) return;
afterArray(arr, info);
}
} else if ( info->type==Type::tTable ) {
auto tab = (Table *) pa;
if ( canVisitTable(pa,info) ) {
beforeTable(tab, info);
if ( cancel() ) return;
walk_table(tab, info);
if ( cancel() ) return;
afterTable(tab, info);
}
} else {
switch ( info->type ) {
case Type::tBool: Bool(*((bool *)pa)); break;
case Type::tInt8: Int8(*((int8_t *)pa)); break;
case Type::tUInt8: UInt8(*((uint8_t *)pa)); break;
case Type::tInt16: Int16(*((int16_t *)pa)); break;
case Type::tUInt16: UInt16(*((uint16_t *)pa)); break;
case Type::tInt64: Int64(*((int64_t *)pa)); break;
case Type::tUInt64: UInt64(*((uint64_t *)pa)); break;
case Type::tString: String(*((char **)pa)); break;
case Type::tInt: Int(*((int32_t *)pa)); break;
case Type::tInt2: Int2(*((int2 *)pa)); break;
case Type::tInt3: Int3(*((int3 *)pa)); break;
case Type::tInt4: Int4(*((int4 *)pa)); break;
case Type::tUInt: UInt(*((uint32_t *)pa)); break;
case Type::tBitfield: Bitfield(*((uint32_t *)pa),info); break;
case Type::tBitfield8: Bitfield8(*((uint8_t *)pa),info); break;
case Type::tBitfield16: Bitfield16(*((uint16_t *)pa),info); break;
case Type::tBitfield64: Bitfield64(*((uint64_t *)pa),info); break;
case Type::tUInt2: UInt2(*((uint2 *)pa)); break;
case Type::tUInt3: UInt3(*((uint3 *)pa)); break;
case Type::tUInt4: UInt4(*((uint4 *)pa)); break;
case Type::tFloat: Float(*((float *)pa)); break;
case Type::tFloat2: Float2(*((float2 *)pa)); break;
case Type::tFloat3: Float3(*((float3 *)pa)); break;
case Type::tFloat4: Float4(*((float4 *)pa)); break;
case Type::tDouble: Double(*((double *)pa)); break;
case Type::tRange: Range(*((range *)pa)); break;
case Type::tURange: URange(*((urange *)pa)); break;
case Type::tRange64: Range64(*((range64 *)pa)); break;
case Type::tURange64: URange64(*((urange64 *)pa)); break;
case Type::tEnumeration: WalkEnumeration(*((int32_t *)pa), info->enumType); break;
case Type::tEnumeration8: WalkEnumeration8(*((int8_t *)pa), info->enumType); break;
case Type::tEnumeration16: WalkEnumeration16(*((int16_t *)pa), info->enumType); break;
case Type::tEnumeration64: WalkEnumeration64(*((int64_t *)pa), info->enumType); break;
case Type::fakeContext: FakeContext(*(Context**)pa); break;
case Type::fakeLineInfo: FakeLineInfo(*(LineInfo**)pa); break;
case Type::tPointer:
if ( canVisitPointer(info) ) {
beforePtr(pa, info);
if ( cancel() ) return;
if ( info->firstType && info->firstType->type!=Type::tVoid ) {
walk(*(char**)pa, info->firstType);
if ( cancel() ) return;
} else {
VoidPtr(*(void**)pa);
if ( cancel() ) return;
}
afterPtr(pa, info);
}
break;
case Type::tStructure: walk_struct(pa, info->structType); break;
case Type::tTuple: walk_tuple(pa, info); break;
case Type::tVariant: walk_variant(pa, info); break;
case Type::tBlock: WalkBlock((Block *)pa); break;
case Type::tFunction: WalkFunction((Func *)pa); break;
case Type::tLambda: {
if ( canVisitLambda(info) ) {
auto ll = (Lambda *) pa;
beforeLambda(ll, info);
if ( cancel() ) return;
walk ( ll->capture, ll->getTypeInfo() );
if ( cancel() ) return;
afterLambda(ll, info);
}
}
break;
case Type::tIterator: {
if ( canVisitIterator(info) ) {
auto ll = (Sequence *) pa;
beforeIterator(ll, info);
if ( cancel() ) return;
if ( ll->iter ) {
ll->iter->walk(*this);
} else {
Null(info);
}
if ( cancel() ) return;
afterIterator(ll, info);
}
}
break;
case Type::tHandle:
if ( canVisitHandle_(pa, info) ) {
beforeHandle_(pa, info);
if ( cancel() ) {
afterHandleCancel_(pa, info);
return;
}
info->getAnnotation()->walk(*this, pa);
if ( cancel() ) {
afterHandleCancel_(pa, info);
return;
}
afterHandle_(pa, info);
}
break;
case Type::tVoid: break; // skip void
case Type::anyArgument: break; // skip any argument
default: DAS_ASSERTF(0, "unsupported print type"); break;
}
}
}
}