#include #include #include // #include namespace Fig { std::map TypeInfo::typeMap = {}; TypeInfo::TypeInfo() : // only allow use in evaluate time !! <---- dynamic type system requirement id(1), name(FString(u8"Any")) { } TypeInfo::TypeInfo(const FString &_name, bool reg) { static size_t id_count = 0; name = _name; // std::cerr << "TypeInfo constructor called for type name: " << name.toBasicString() << "\n"; if (reg) { typeMap[name] = ++id_count; id = id_count; } else { if (!typeMap.contains(_name)) { throw RuntimeError(FString(std::format( "No type named '{}'", _name.toBasicString()))); // *this = ValueType::String; } id = typeMap.at(name); // may throw } } size_t ValueKeyHash::operator()(const ValueKey &key) const { { ObjectPtr value = key.value; const TypeInfo &type = value->getTypeInfo(); if (type == ValueType::Int) { return std::hash{}(value->as()); } if (type == ValueType::Double) { return std::hash{}(value->as()); } if (type == ValueType::String) { return std::hash{}(value->as()); } if (type == ValueType::Bool) { return std::hash{}(value->as()); } if (type == ValueType::StructType) { auto HashFields = [](std::vector fields) { size_t r = 0; for (auto &f : fields) { r += std::hash{}(f); } return r; }; const StructType &st = value->as(); return std::hash{}(st.type) + HashFields(st.fields); } if (type == ValueType::StructInstance) { const StructInstance &si = value->as(); return std::hash{}(si.parentType) + std::hash{}(reinterpret_cast(std::addressof(*si.localContext))); } assert(false); throw ""; // ignore warning } } FString prettyType(std::shared_ptr obj) { auto t = obj->getTypeInfo(); if (t == ValueType::StructInstance) return obj->as().parentType.toString(); return t.toString(); } const TypeInfo ValueType::Any(FString(u8"Any"), true); // id: 1 const TypeInfo ValueType::Null(FString(u8"Null"), true); // id: 2 const TypeInfo ValueType::Int(FString(u8"Int"), true); // id: 3 const TypeInfo ValueType::String(FString(u8"String"), true); // id: 4 const TypeInfo ValueType::Bool(FString(u8"Bool"), true); // id: 5 const TypeInfo ValueType::Double(FString(u8"Double"), true); // id: 6 const TypeInfo ValueType::Function(FString(u8"Function"), true); // id: 7 const TypeInfo ValueType::StructType(FString(u8"StructType"), true); // id: 8 const TypeInfo ValueType::StructInstance(FString(u8"StructInstance"), true); // id: 9 const TypeInfo ValueType::List(FString(u8"List"), true); // id: 10 const TypeInfo ValueType::Map(FString(u8"Map"), true); // id: 11 const TypeInfo ValueType::Module(FString(u8"Module"), true); // id: 12 const TypeInfo ValueType::InterfaceType(FString(u8"InterfaceType"), true); // id: 13 bool implements(const TypeInfo &structType, const TypeInfo &interfaceType, ContextPtr ctx) { return ctx->hasImplRegisted(structType, interfaceType); } bool isTypeMatch(const TypeInfo &expected, ObjectPtr obj, ContextPtr ctx) { if (expected == ValueType::Any) return true; TypeInfo actual = obj->getTypeInfo(); if (obj->is()) { const StructInstance &si = obj->as(); if (si.parentType == expected) { return true; } if (implements(si.parentType, expected, ctx)) { return true; } return false; } else { return expected == actual; } } } // namespace Fig