#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 ( canVisitStructure(ps, si) ) { beforeStructure(ps, si); if ( cancel ) { afterStructureCancel(ps, si); return; } for ( uint32_t i=0; i!=si->count; ++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 ) { beforeTuple(ps, ti); if ( cancel ) return; int fieldOffset = 0; for ( uint32_t i=0; i!=ti->argCount; ++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, vi, last); if ( cancel ) return; walk(pf, vi); if ( cancel ) return; afterTupleEntry(ps, ti, pf, vi, last); if ( cancel ) return; fieldOffset += getTypeSize(vi); } afterTuple(ps, ti); } void DataWalker::walk_variant ( char * ps, TypeInfo * ti ) { beforeVariant(ps, ti); if ( cancel ) return; 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 ) { 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 ) { beforeDim(pa, ti); if ( cancel ) return; TypeInfo copyInfo = *ti; DAS_ASSERT(copyInfo.dimSize); copyInfo.dimSize --; vector udim; if ( copyInfo.dimSize ) { for ( uint32_t i=0; i!=copyInfo.dimSize; ++i) { udim.push_back(ti->dim[i+1]); } copyInfo.dim = udim.data(); } else { copyInfo.dim = nullptr; } uint32_t stride = getTypeSize(©Info); uint32_t count = ti->dim[0]; walk_array(pa, stride, count, ©Info); if ( cancel ) return; afterDim(pa, ti); } void DataWalker::walk_table ( Table * tab, TypeInfo * info ) { int keySize = getTypeSize(info->firstType); int valueSize = getTypeSize(info->secondType); uint32_t count = 0; for ( uint32_t i=0; i!=tab->capacity; ++i ) { if ( tab->hashes[i] > HASH_KILLED32 ) { 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); if ( cancel ) return; afterRef(pa,info); } else if ( info->dimSize ) { walk_dim(pa, info); } else if ( info->type==Type::tArray ) { auto arr = (Array *) pa; beforeArray(arr, info); if ( cancel ) return; walk_array(arr->data, getTypeSize(info->firstType), arr->size, info->firstType); if ( cancel ) return; afterArray(arr, info); } else if ( info->type==Type::tTable ) { auto tab = (Table *) pa; 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; // TODO: verify!!! 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::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::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::fakeContext: FakeContext(*(Context**)pa); break; case Type::tPointer: beforePtr(pa, info); if ( cancel ) return; if ( info->firstType ) { walk(*(char**)pa, info->firstType); 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: { auto ll = (Lambda *) pa; beforeLambda(ll, info); walk ( ll->capture, ll->getTypeInfo() ); afterLambda(ll, info); } break; case Type::tIterator: { auto ll = (Sequence *) pa; beforeIterator(ll, info); if ( ll->iter ) { ll->iter->walk(*this); } else { Null(info); } afterIterator(ll, info); } break; case Type::tHandle: if ( canVisitHandle(pa, info) ) { beforeHandle(pa, info); if ( cancel ) return; info->getAnnotation()->walk(*this, pa); if ( cancel ) 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; } } } }