summaryrefslogtreecommitdiff
path: root/cpp/src/FreezeScript/TransformVisitor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/FreezeScript/TransformVisitor.cpp')
-rw-r--r--cpp/src/FreezeScript/TransformVisitor.cpp901
1 files changed, 901 insertions, 0 deletions
diff --git a/cpp/src/FreezeScript/TransformVisitor.cpp b/cpp/src/FreezeScript/TransformVisitor.cpp
new file mode 100644
index 00000000000..864b46dc66a
--- /dev/null
+++ b/cpp/src/FreezeScript/TransformVisitor.cpp
@@ -0,0 +1,901 @@
+// **********************************************************************
+//
+// Copyright (c) 2004
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <FreezeScript/TransformVisitor.h>
+#include <FreezeScript/Util.h>
+
+using namespace std;
+
+FreezeScript::TransformVisitor::TransformVisitor(const DataPtr& src, const DataFactoryPtr& factory,
+ const ErrorReporterPtr& errorReporter, TransformInfo* info,
+ const string& context) :
+ _src(src), _factory(factory), _errorReporter(errorReporter), _info(info), _context(context)
+{
+ assert(_info != 0);
+}
+
+void
+FreezeScript::TransformVisitor::visitBoolean(const BooleanDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ BooleanDataPtr b = BooleanDataPtr::dynamicCast(_src);
+ if(b)
+ {
+ dest->setValue(b->getValue());
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ string v = s->getValue();
+ if(v == "true")
+ {
+ dest->setValue(true);
+ }
+ else if(v == "false")
+ {
+ dest->setValue(false);
+ }
+ else
+ {
+ conversionError(type, _src->getType(), v);
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitInteger(const IntegerDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ IntegerDataPtr i = IntegerDataPtr::dynamicCast(_src);
+ if(i)
+ {
+ dest->setValue(i->getValue(), false);
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ string str = s->getValue();
+ string::size_type pos;
+ Ice::Long value;
+ if(IceUtil::stringToInt64(str, value, pos))
+ {
+ dest->setValue(value, false);
+ }
+ else
+ {
+ conversionError(type, _src->getType(), str);
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitDouble(const DoubleDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ DoubleDataPtr d = DoubleDataPtr::dynamicCast(_src);
+ if(d)
+ {
+ dest->setValue(d->doubleValue());
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ string str = s->stringValue();
+ const char* start = str.c_str();
+ char* end;
+ double v = strtod(start, &end);
+ if(errno == ERANGE)
+ {
+ rangeError(str, type);
+ }
+ else
+ {
+ while(*end)
+ {
+ if(!isspace(*end))
+ {
+ conversionError(type, _src->getType(), str);
+ return;
+ }
+ end++;
+ }
+ if(!*end)
+ {
+ dest->setValue(v);
+ }
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitString(const StringDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ BooleanDataPtr b = BooleanDataPtr::dynamicCast(_src);
+ IntegerDataPtr i = IntegerDataPtr::dynamicCast(_src);
+ DoubleDataPtr d = DoubleDataPtr::dynamicCast(_src);
+ EnumDataPtr e = EnumDataPtr::dynamicCast(_src);
+ ProxyDataPtr p = ProxyDataPtr::dynamicCast(_src);
+ if(s || b || i || d || e || p)
+ {
+ dest->setValue(_src->toString());
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitProxy(const ProxyDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ ProxyDataPtr p = ProxyDataPtr::dynamicCast(_src);
+ if(p)
+ {
+ dest->setValue(p->getValue());
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ dest->setValue(s->getValue(), false);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitStruct(const StructDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ StructDataPtr s = StructDataPtr::dynamicCast(_src);
+ if(s && isCompatible(type, _src->getType()))
+ {
+ //
+ // Transform members with the same name.
+ //
+ DataMemberMap srcMap = s->getMembers();
+ DataMemberMap destMap = dest->getMembers();
+ string typeName = typeToString(type);
+ for(DataMemberMap::iterator p = destMap.begin(); p != destMap.end(); ++p)
+ {
+ DataMemberMap::iterator q = srcMap.find(p->first);
+ if(q != srcMap.end())
+ {
+ string context = typeName + " member " + p->first + " value";
+ TransformVisitor v(q->second, _factory, _errorReporter, _info, context);
+ p->second->visit(v);
+ }
+ }
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitSequence(const SequenceDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ SequenceDataPtr s = SequenceDataPtr::dynamicCast(_src);
+ if(s && isCompatible(type, _src->getType()))
+ {
+ DataList& srcElements = s->getElements();
+ DataList destElements;
+ Slice::SequencePtr seqType = Slice::SequencePtr::dynamicCast(type);
+ assert(seqType);
+ Slice::TypePtr elemType = seqType->type();
+ string typeName = typeToString(type);
+ for(DataList::const_iterator p = srcElements.begin(); p != srcElements.end(); ++p)
+ {
+ DataPtr element = _factory->create(elemType, false);
+ Destroyer<DataPtr> elementDestroyer(element);
+ try
+ {
+ TransformVisitor v(*p, _factory, _errorReporter, _info, typeName + " element");
+ element->visit(v);
+ destElements.push_back(element);
+ elementDestroyer.release();
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the sequence element fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the sequence) or raise the exception again.
+ //
+ if(!_info->purgeObjects())
+ {
+ throw;
+ }
+ warning("purging element of sequence " + typeToString(type) +
+ " due to missing class type " + ex.id);
+ }
+ }
+ DataList& l = dest->getElements();
+ l.swap(destElements);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitEnum(const EnumDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ string name;
+ EnumDataPtr e = EnumDataPtr::dynamicCast(_src);
+ if(e && isCompatible(type, _src->getType()))
+ {
+ name = e->toString();
+ }
+ else
+ {
+ StringDataPtr s = StringDataPtr::dynamicCast(_src);
+ if(s)
+ {
+ name = s->getValue();
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ return;
+ }
+ }
+
+ if(!dest->setValueAsString(name))
+ {
+ conversionError(type, _src->getType(), name);
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitDictionary(const DictionaryDataPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ if(_info->doDefaultTransform(type))
+ {
+ DictionaryDataPtr d = DictionaryDataPtr::dynamicCast(_src);
+ if(d && isCompatible(type, _src->getType()))
+ {
+ DataMap& srcMap = d->getElements();
+ DataMap destMap;
+ Slice::DictionaryPtr dictType = Slice::DictionaryPtr::dynamicCast(type);
+ assert(dictType);
+ Slice::TypePtr keyType = dictType->keyType();
+ Slice::TypePtr valueType = dictType->valueType();
+ string typeName = typeToString(type);
+ for(DataMap::const_iterator p = srcMap.begin(); p != srcMap.end(); ++p)
+ {
+ DataPtr key = _factory->create(keyType, false);
+ Destroyer<DataPtr> keyDestroyer(key);
+ DataPtr value = _factory->create(valueType, false);
+ Destroyer<DataPtr> valueDestroyer(value);
+
+ TransformVisitor keyVisitor(p->first, _factory, _errorReporter, _info, typeName + " key");
+ key->visit(keyVisitor);
+
+ try
+ {
+ TransformVisitor valueVisitor(p->second, _factory, _errorReporter, _info, typeName + " value");
+ value->visit(valueVisitor);
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the dictionary value fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the dictionary) or raise the exception again.
+ //
+ if(!_info->purgeObjects())
+ {
+ throw;
+ }
+ warning("purging element of dictionary " + typeToString(dictType) + " due to missing class type " +
+ ex.id);
+ continue;
+ }
+
+ DataMap::const_iterator q = destMap.find(key);
+ if(q != destMap.end())
+ {
+ warning("duplicate dictionary key in " + typeToString(dictType));
+ }
+ else
+ {
+ destMap.insert(DataMap::value_type(key, value));
+ keyDestroyer.release();
+ valueDestroyer.release();
+ }
+ }
+ DataMap& m = dest->getElements();
+ m.swap(destMap);
+ }
+ else
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::visitObject(const ObjectRefPtr& dest)
+{
+ Slice::TypePtr type = dest->getType();
+ ObjectRefPtr src = ObjectRefPtr::dynamicCast(_src);
+ if(!src)
+ {
+ typeMismatchError(type, _src->getType());
+ }
+ else if(_info->doDefaultTransform(type))
+ {
+ ObjectDataPtr srcValue = src->getValue();
+ Slice::TypePtr srcType = src->getType();
+ if(!srcValue)
+ {
+ //
+ // Allow a nil value from type Object.
+ //
+ if(Slice::BuiltinPtr::dynamicCast(srcType) || isCompatible(type, srcType))
+ {
+ dest->setValue(0);
+ }
+ else
+ {
+ typeMismatchError(type, srcType);
+ }
+ }
+ else
+ {
+ Slice::TypePtr srcValueType = srcValue->getType();
+ if(isCompatible(type, srcValueType))
+ {
+ //
+ // If the types are in the same Slice unit, then we can simply
+ // copy the reference. Otherwise, we check the object map to
+ // see if an equivalent object has already been created, and
+ // if not, then we have to create one.
+ //
+ if(type->unit().get() == srcValueType->unit().get())
+ {
+ dest->setValue(srcValue);
+ }
+ else
+ {
+ ObjectDataMap& objectDataMap = _info->getObjectDataMap();
+ ObjectDataMap::iterator p = objectDataMap.find(srcValue.get());
+ if(p != objectDataMap.end() && p->second)
+ {
+ dest->setValue(p->second);
+ }
+ else
+ {
+ //
+ // If the type has been renamed, we need to get its equivalent
+ // in the new Slice definitions.
+ //
+ Slice::TypePtr newType = _info->getRenamedType(srcValueType);
+ if(!newType)
+ {
+ string name = typeToString(srcValueType);
+ Slice::TypeList l = type->unit()->lookupType(name, false);
+ if(l.empty())
+ {
+ throw ClassNotFoundException(name);
+ }
+ newType = l.front();
+ }
+
+ //
+ // Use createObject() so that an initializer is invoked if necessary.
+ //
+ DataPtr newObj = _factory->createObject(newType, false);
+ ObjectRefPtr newRef = ObjectRefPtr::dynamicCast(newObj);
+ assert(newRef);
+
+ ObjectDataPtr newValue = newRef->getValue();
+ try
+ {
+ transformObject(newValue, srcValue);
+ }
+ catch(...)
+ {
+ newObj->destroy();
+ throw;
+ }
+
+ dest->setValue(newValue);
+ newObj->destroy();
+ }
+ }
+ }
+ else
+ {
+ typeMismatchError(type, srcValueType);
+ }
+ }
+ }
+ _info->executeCustomTransform(dest, _src);
+}
+
+void
+FreezeScript::TransformVisitor::transformObject(const ObjectDataPtr& dest, const ObjectDataPtr& src)
+{
+ //
+ // The source object must be present in the object map (we currently don't support
+ // transforming two ObjectData instances from the same Slice unit - this transform
+ // would be handled by-reference at the ObjectRef level). We must update the object
+ // map before transforming members in order to handle cycles.
+ //
+ ObjectDataMap& objectDataMap = _info->getObjectDataMap();
+ ObjectDataMap::iterator p = objectDataMap.find(src.get());
+ assert(p != objectDataMap.end());
+ assert(p->second == 0);
+ objectDataMap.erase(p);
+ objectDataMap.insert(ObjectDataMap::value_type(src.get(), dest));
+
+ try
+ {
+ //
+ // Transform members with the same name.
+ //
+ DataMemberMap srcMap = src->getMembers();
+ DataMemberMap destMap = dest->getMembers();
+ string typeName = typeToString(dest->getType());
+ for(DataMemberMap::iterator p = destMap.begin(); p != destMap.end(); ++p)
+ {
+ DataMemberMap::iterator q = srcMap.find(p->first);
+ if(q != srcMap.end())
+ {
+ string context = typeName + " member " + p->first + " value";
+ TransformVisitor v(q->second, _factory, _errorReporter, _info, context);
+ p->second->visit(v);
+ }
+ }
+ }
+ catch(...)
+ {
+ objectDataMap.erase(p);
+ objectDataMap.insert(ObjectDataMap::value_type(src.get(), 0));
+ throw;
+ }
+}
+
+bool
+FreezeScript::TransformVisitor::checkRename(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ if(dest->unit().get() != src->unit().get())
+ {
+ Slice::TypePtr t = _info->getRenamedType(src);
+ return t.get() == dest.get();
+ }
+
+ return false;
+}
+
+bool
+FreezeScript::TransformVisitor::isCompatible(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ Slice::BuiltinPtr b1 = Slice::BuiltinPtr::dynamicCast(dest);
+ if(b1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ switch(b1->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindString:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindBool:
+ {
+ if(b2 && (b2->kind() == Slice::Builtin::KindBool || b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindObjectProxy:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindString:
+ {
+ if(b2)
+ {
+ switch(b2->kind())
+ {
+ case Slice::Builtin::KindByte:
+ case Slice::Builtin::KindBool:
+ case Slice::Builtin::KindShort:
+ case Slice::Builtin::KindInt:
+ case Slice::Builtin::KindLong:
+ case Slice::Builtin::KindFloat:
+ case Slice::Builtin::KindDouble:
+ case Slice::Builtin::KindString:
+ case Slice::Builtin::KindObjectProxy:
+ {
+ return true;
+ }
+ case Slice::Builtin::KindObject:
+ case Slice::Builtin::KindLocalObject:
+ {
+ return false;
+ }
+ }
+
+ return false;
+ }
+ else if(Slice::EnumPtr::dynamicCast(src))
+ {
+ return true;
+ }
+ else if(Slice::ProxyPtr::dynamicCast(src))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindObject:
+ {
+ //
+ // Allow transformation from Object to class. Validation has to
+ // be done during transformation, when the actual type of
+ // an instance can be compared for compatibility with the
+ // new type.
+ //
+ Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(src);
+ if(cl || (b2 && b2->kind() == Slice::Builtin::KindObject))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindObjectProxy:
+ {
+ Slice::ProxyPtr p = Slice::ProxyPtr::dynamicCast(src);
+ if(p || (b2 && b2->kind() == Slice::Builtin::KindObjectProxy) ||
+ (b2 && b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ case Slice::Builtin::KindLocalObject:
+ {
+ assert(false);
+ return false;
+ }
+ }
+
+ assert(false);
+ }
+
+ Slice::ClassDeclPtr cl1 = Slice::ClassDeclPtr::dynamicCast(dest);
+ if(cl1)
+ {
+ Slice::ClassDeclPtr cl2 = Slice::ClassDeclPtr::dynamicCast(src);
+ if(cl2 && checkClasses(cl1, cl2))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::StructPtr s1 = Slice::StructPtr::dynamicCast(dest);
+ if(s1)
+ {
+ if(checkRename(dest, src))
+ {
+ return true;
+ }
+
+ Slice::StructPtr s2 = Slice::StructPtr::dynamicCast(src);
+ if(s2 && s1->scoped() == s2->scoped())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::ProxyPtr p1 = Slice::ProxyPtr::dynamicCast(dest);
+ if(p1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ if(b2 && (b2->kind() == Slice::Builtin::KindObjectProxy || b2->kind() == Slice::Builtin::KindString))
+ {
+ return true;
+ }
+
+ Slice::ProxyPtr p2 = Slice::ProxyPtr::dynamicCast(src);
+ if(p2 && checkClasses(p1->_class(), p2->_class()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ Slice::DictionaryPtr d1 = Slice::DictionaryPtr::dynamicCast(dest);
+ if(d1)
+ {
+ Slice::DictionaryPtr d2 = Slice::DictionaryPtr::dynamicCast(src);
+ if(d2)
+ {
+ return isCompatible(d1->keyType(), d2->keyType()) &&
+ isCompatible(d1->valueType(), d2->valueType());
+ }
+
+ return false;
+ }
+
+ Slice::SequencePtr seq1 = Slice::SequencePtr::dynamicCast(dest);
+ if(seq1)
+ {
+ Slice::SequencePtr seq2 = Slice::SequencePtr::dynamicCast(src);
+ if(seq2)
+ {
+ return isCompatible(seq1->type(), seq2->type());
+ }
+
+ return false;
+ }
+
+ Slice::EnumPtr e1 = Slice::EnumPtr::dynamicCast(dest);
+ if(e1)
+ {
+ Slice::BuiltinPtr b2 = Slice::BuiltinPtr::dynamicCast(src);
+ if(b2 && b2->kind() == Slice::Builtin::KindString)
+ {
+ return true;
+ }
+
+ if(checkRename(dest, src))
+ {
+ return true;
+ }
+
+ Slice::EnumPtr e2 = Slice::EnumPtr::dynamicCast(src);
+ if(e2 && e1->scoped() == e2->scoped())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ assert(false);
+ return false;
+}
+
+bool
+FreezeScript::TransformVisitor::checkClasses(const Slice::ClassDeclPtr& dest, const Slice::ClassDeclPtr& src)
+{
+ //
+ // Here are the rules for verifying class compatibility:
+ //
+ // 1. If the type ids are the same, assume they are compatible.
+ // 2. If the source type has been renamed, then check its equivalent new definition for compatibility.
+ // 3. Otherwise, the types are only compatible if they are defined in the same Slice unit, and if the
+ // destination type is a base type of the source type.
+ //
+ string s1 = dest->scoped();
+ string s2 = src->scoped();
+ if(s1 == s2)
+ {
+ return true;
+ }
+ else
+ {
+ Slice::TypePtr t = _info->getRenamedType(src);
+ Slice::ClassDeclPtr s = Slice::ClassDeclPtr::dynamicCast(t);
+ if(s)
+ {
+ return checkClasses(dest, s);
+ }
+
+ if(dest->unit().get() != src->unit().get())
+ {
+ Slice::TypeList l = dest->unit()->lookupTypeNoBuiltin(s2, false);
+ if(l.empty())
+ {
+ _errorReporter->error("class " + s2 + " not found in new Slice definitions");
+ }
+ s = Slice::ClassDeclPtr::dynamicCast(l.front());
+ }
+ else
+ {
+ s = src;
+ }
+
+ if(s)
+ {
+ Slice::ClassDefPtr def = s->definition();
+ if(!def)
+ {
+ _errorReporter->error("class " + s2 + " declared but not defined");
+ }
+ return def->isA(s1);
+ }
+ }
+
+ return false;
+}
+
+void
+FreezeScript::TransformVisitor::typeMismatchError(const Slice::TypePtr& dest, const Slice::TypePtr& src)
+{
+ ostringstream ostr;
+ ostr << "unable to transform";
+ if(!_context.empty())
+ {
+ ostr << ' ' << _context;
+ }
+ ostr << " from " << typeToString(src) << " to " << typeToString(dest);
+ warning(ostr.str());
+}
+
+void
+FreezeScript::TransformVisitor::conversionError(const Slice::TypePtr& dest, const Slice::TypePtr& src,
+ const string& value)
+{
+ ostringstream ostr;
+ ostr << "unable to convert";
+ if(!_context.empty())
+ {
+ ostr << ' ' << _context;
+ }
+ ostr << " `" << value << "' from " << typeToString(src) << " to " << typeToString(dest);
+ warning(ostr.str());
+}
+
+void
+FreezeScript::TransformVisitor::rangeError(const string& value, const Slice::TypePtr& type)
+{
+ ostringstream ostr;
+ if(!_context.empty())
+ {
+ ostr << _context << ' ';
+ }
+ ostr << "`" << value << "' is out of range for type " << typeToString(type);
+ warning(ostr.str());
+}
+
+void
+FreezeScript::TransformVisitor::warning(const string& msg)
+{
+ _errorReporter->warning(msg);
+}