#include "Interpreter.h"
#include "ParsedSource.h"
+#include "TypeDescription.h"
#include "../battle/Hero.h"
#include "../battle/Monster.h"
#include "../battle/PartyLayout.h"
}
}
+const Interpreter::ParsedDefinition &Interpreter::GetDefinition(const string &identifier) const {
+ std::map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(identifier));
+ if (i != parsedDefinitions.end()) {
+ return i->second;
+ } else {
+ throw Error("access to undefined object " + identifier);
+ }
+}
-void *Interpreter::GetObject(int typeId, const std::string &name) {
- std::map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+
+void *Interpreter::GetObject(
+ int typeId,
+ const std::string &name) {
+ std::map<string, ParsedDefinition>::const_iterator
+ i(parsedDefinitions.find(name));
if (i != parsedDefinitions.end()) {
- const TypeDescription &requested(TypeDescription::Get(typeId));
- const TypeDescription &actual(TypeDescription::Get(i->second.type));
+ const TypeDescription &requested =
+ TypeDescription::Get(typeId);
+ const TypeDescription &actual =
+ TypeDescription::Get(i->second.type);
if (requested.TypeId() == actual.TypeId()) {
return values[actual.TypeId()][i->second.id];
} else if (actual.IsSubtypeOf(requested)) {
- char *sub(reinterpret_cast<char *>(values[actual.TypeId()][i->second.id]));
- std::ptrdiff_t offset(actual.SupertypeOffset(requested));
+ char *sub = reinterpret_cast<char *>(
+ values[actual.TypeId()][i->second.id]);
+ std::ptrdiff_t offset =
+ actual.SupertypeOffset(requested);
return sub - offset;
} else {
- throw Error("cannot cast " + actual.TypeName() + " to " + requested.TypeName());
+ throw Error("cannot cast " + actual.TypeName()
+ + " to " + requested.TypeName());
+ }
+ } else {
+ throw Error("access to undefined object " + name);
+ }
+}
+
+const void *Interpreter::GetObject(
+ int typeId,
+ const std::string &name) const {
+ std::map<string, ParsedDefinition>::const_iterator
+ i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ const TypeDescription &requested =
+ TypeDescription::Get(typeId);
+ const TypeDescription &actual =
+ TypeDescription::Get(i->second.type);
+ if (requested.TypeId() == actual.TypeId()) {
+ return values.at(actual.TypeId()).at(i->second.id);
+ } else if (actual.IsSubtypeOf(requested)) {
+ char *sub = reinterpret_cast<char *>(
+ values.at(actual.TypeId()).at(i->second.id));
+ std::ptrdiff_t offset =
+ actual.SupertypeOffset(requested);
+ return sub - offset;
+ } else {
+ throw Error("cannot cast " + actual.TypeName()
+ + " to " + requested.TypeName());
}
} else {
throw Error("access to undefined object " + name);
char *dest(object + fd.Offset());
if (fd.IsAggregate()) {
int arraySize(i->second->GetLiteral().ArraySize());
- char *aggregate;
+ size_t memberSize = fd.IsReferenced() ? sizeof(char *) : fieldType.Size();
+ Array array;
+ array.size = arraySize * memberSize;
+ array.data = alloc.Alloc(array.size);
+ array.ref = fd.IsReferenced();
+ arrays.push_back(array);
+ char *iter = reinterpret_cast<char *>(array.data);
if (i->second->GetLiteral().GetType() == Literal::ARRAY_PROPS) {
- aggregate = alloc.Alloc(fieldType.Size() * arraySize);
- char *iter = aggregate;
const vector<PropertyList *> &list(i->second->GetLiteral().GetPropertyLists());
- for (vector<PropertyList *>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) {
- fieldType.Construct(iter);
- ReadObject(fieldType.TypeId(), -1, iter, **j);
+ for (vector<PropertyList *>::const_iterator
+ j(list.begin()), end(list.end());
+ j != end; ++j, iter += memberSize) {
+ char *member;
+ if (fd.IsReferenced()) {
+ member = alloc.Alloc(fieldType.Size());
+ *reinterpret_cast<char **>(iter) = member;
+ } else {
+ member = iter;
+ }
+ fieldType.Construct(member);
+ ReadObject(fieldType.TypeId(), -1, member, **j);
}
} else if (i->second->GetLiteral().GetType() == Literal::ARRAY_VALUES) {
- aggregate = alloc.Alloc(fieldType.Size() * arraySize);
- char *iter = aggregate;
const vector<Value *> &list(i->second->GetLiteral().GetValues());
- for (vector<Value *>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) {
- fieldType.Construct(iter);
- ReadLiteral(fieldType.TypeId(), -1, iter, (*j)->GetLiteral());
+ for (vector<Value *>::const_iterator j(list.begin()), end(list.end());
+ j != end; ++j, iter += memberSize) {
+ char *member;
+ if (fd.IsReferenced()) {
+ member = alloc.Alloc(fieldType.Size());
+ *reinterpret_cast<char **>(iter) = member;
+ } else {
+ member = iter;
+ }
+ fieldType.Construct(member);
+ ReadLiteral(fieldType.TypeId(), -1, member, (*j)->GetLiteral());
}
} else {
- aggregate = alloc.Alloc(sizeof(char *) * arraySize);
- char *iter = aggregate;
+ if (!fd.IsReferenced()) {
+ // TODO: implement inline identifier arrays
+ throw std::runtime_error("inline identifier arrays not implemented (yet)");
+ }
const vector<string> &list(i->second->GetLiteral().GetIdentifiers());
- for (vector<string>::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += sizeof(void *)) {
+ for (vector<string>::const_iterator j(list.begin()), end(list.end());
+ j != end; ++j, iter += memberSize) {
if (source.IsDefined(*j)) {
*reinterpret_cast<void **>(iter)
= GetObject(fd.TypeId(), *j);
} else {
- Postpone(typeId, id, fd.Offset() + (iter - aggregate), *j, fd.TypeId(), false);
+ Postpone(reinterpret_cast<char *>(array.data),
+ iter, *j, fd.TypeId(), false);
}
}
}
- if (fd.IsReferenced()) {
- std::memcpy(dest, &aggregate, sizeof(char *));
- dest += sizeof(char *);
- std::memcpy(dest, &arraySize, sizeof(int));
- } else {
- throw Error("aggregate type fields must be referenced");
- }
+ std::memcpy(dest, &array.data, sizeof(char *));
+ dest += sizeof(char *);
+ std::memcpy(dest, &arraySize, sizeof(int));
} else if (i->second->IsLiteral() && !fd.IsReferenced()) {
// inline literals
if (i->second->GetLiteral().IsObject()) {
}
}
} else {
- Postpone(typeId, id, fd.Offset(), i->second->GetIdentifier(), fd.TypeId(), !fd.IsReferenced());
+ Postpone(object, object + fd.Offset(), i->second->GetIdentifier(), fd.TypeId(), !fd.IsReferenced(), fd.IsAggregate());
}
}
td.Load(object);
return v.IsLiteral() || source.IsDefined(v.GetIdentifier());
}
-void Interpreter::Postpone(int type, int id, std::ptrdiff_t offset, const std::string &identifier, int linkedType, bool inlined) {
- char *str(alloc.Alloc(identifier.size() + 1));
- std::memcpy(str, identifier.c_str(), identifier.size());
- str[identifier.size()] = '\0';
- postponedDefinitions.push_back(PostponedDefinition(type, id, offset, str, linkedType, inlined));
+void Interpreter::Postpone(
+ char *object,
+ char *dest,
+ const std::string &identifier,
+ int type,
+ bool inlined,
+ bool aggregate) {
+ postponedDefinitions.push_back(
+ PostponedDefinition(object, dest, identifier, type, inlined, aggregate));
}