X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Floader%2FInterpreter.cpp;h=6bb022f1e4c6c46d354c1afc62fa6710be9da1e3;hb=1014598c02e9635d9d4a008010d43c3c0b845e06;hp=c2ce0d4145abf20ee1b90c291ad7965d2e5446aa;hpb=77915e0186f4fc0788054eb34651c726b80d981c;p=l2e.git diff --git a/src/loader/Interpreter.cpp b/src/loader/Interpreter.cpp index c2ce0d4..6bb022f 100644 --- a/src/loader/Interpreter.cpp +++ b/src/loader/Interpreter.cpp @@ -62,8 +62,16 @@ Interpreter::~Interpreter() { } -const Interpreter::ParsedDefinition &Interpreter::GetDefinition(const string &identifier) const { - return parsedDefinitions.at(identifier); +const Interpreter::ParsedDefinition &Interpreter::GetDefinition(const string &identifier) { + std::map::const_iterator i(parsedDefinitions.find(identifier)); + if (i != parsedDefinitions.end()) { + return i->second; + } else if (source.IsDefined(identifier)) { + ReadDefinition(source.GetDefinition(identifier)); + return parsedDefinitions.at(identifier); + } else { + throw Error("access to undefined object " + identifier); + } } @@ -114,13 +122,13 @@ void Interpreter::ReadLiteral(const Definition &dfn) { || dfn.GetLiteral()->GetType() == Literal::STRING) ? dfn.GetLiteral()->GetString().size() : td.Size()); char *object(alloc.Alloc(size)); + values[typeId].push_back(object); + parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, typeId, id))); if (dfn.GetLiteral()->GetType() == Literal::OBJECT) { ReadObject(typeId, id, object, *dfn.GetLiteral()->GetProperties()); } else { ReadLiteral(typeId, id, object, *dfn.GetLiteral()); } - values[typeId].push_back(object); - parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, typeId, id))); } void Interpreter::ReadLiteral(int typeId, int id, char *object, const Literal &literal) { @@ -221,8 +229,9 @@ void *Interpreter::GetObject(int typeId, const Value &v) { case Literal::SCRIPT: { typeId = TypeDescription::GetTypeId("Script"); + char *script(ReadScript(v.GetLiteral().GetScript())); id = values[typeId].size(); - values[typeId].push_back(ReadScript(v.GetLiteral().GetScript())); + values[typeId].push_back(script); } break; case Literal::STRING: @@ -271,8 +280,8 @@ void Interpreter::ReadObject(const Definition &dfn) { char *object(alloc.Alloc(td.Size())); td.Construct(object); values[typeId].push_back(object); - ReadObject(typeId, id, object, *dfn.GetProperties()); parsedDefinitions.insert(make_pair(dfn.Identifier(), ParsedDefinition(&dfn, typeId, id))); + ReadObject(typeId, id, object, *dfn.GetProperties()); } @@ -334,9 +343,16 @@ void Interpreter::ReadObject(int typeId, int id, char *object, const PropertyLis void Interpreter::ReadScript(const std::vector &s, Script *script) { + std::map labels; int size(0); for (vector::const_iterator i(s.begin()), end(s.end()); i != end; ++i) { - if ((*i)->GetType() != ScriptToken::COMMAND) { + if ((*i)->GetType() == ScriptToken::LABEL) { + if (labels.count((*i)->Label())) { + throw Error("duplicate label " + (*i)->Label()); + } else { + labels[(*i)->Label()] = size; + } + } else if ((*i)->GetType() != ScriptToken::COMMAND) { throw Error("unexpected script token"); } ++size; @@ -404,6 +420,58 @@ void Interpreter::ReadScript(const std::vector &s, Script *script if (i == end) { throw Error("unexpected script end after rand"); } + } else if (cmd == "cmp") { + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + } else if (cmd == "jmp") { + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + } else if (cmd == "jeq") { + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + } else if (cmd == "jne") { + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + } else if (cmd == "jl") { + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + } else if (cmd == "jle") { + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + } else if (cmd == "jg") { + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } + } else if (cmd == "jge") { + size += sizeof(int); + ++i; + if (i == end) { + throw Error("unexpected script end after cmp"); + } } else if (cmd == "sysc") { } else { @@ -414,6 +482,9 @@ void Interpreter::ReadScript(const std::vector &s, Script *script unsigned char *text(reinterpret_cast(alloc.Alloc(size))); int cursor(0); for (vector::const_iterator i(s.begin()), end(s.end()); i != end; ++i) { + if ((*i)->GetType() == ScriptToken::LABEL) { + continue; + } if ((*i)->GetType() != ScriptToken::COMMAND) { throw Error("unexpected script token"); } @@ -511,6 +582,91 @@ void Interpreter::ReadScript(const std::vector &s, Script *script } else { throw Error("unexpected register " + reg); } + } else if (cmd == "cmp") { + ++i; + const string ®((*i)->RegisterName()); + ++i; + if (reg == "i0") { + if ((*i)->GetType() == ScriptToken::REGISTER && (*i)->RegisterName() == "i1") { + text[cursor] = Script::CODE_CMP_I0_I1; + ++cursor; + } else { + text[cursor] = Script::CODE_CMP_I0; + ++cursor; + ReadScriptInteger(**i, text + cursor); + cursor += sizeof(int); + } + } else if (reg == "i1") { + text[cursor] = Script::CODE_CMP_I1; + ++cursor; + ReadScriptInteger(**i, text + cursor); + cursor += sizeof(int); + } else { + throw Error("cannot use " + reg + " as lhs for comparison"); + } + } else if (cmd == "jmp") { + text[cursor] = Script::CODE_JUMP; + ++cursor; + ++i; + if (!labels.count((*i)->Identifier())) { + throw Error("use of undefined label " + (*i)->Identifier()); + } + *reinterpret_cast(text + cursor) = labels[(*i)->Identifier()]; + cursor += sizeof(int); + } else if (cmd == "jeq") { + text[cursor] = Script::CODE_JUMP_EQUAL; + ++cursor; + ++i; + if (!labels.count((*i)->Identifier())) { + throw Error("use of undefined label " + (*i)->Identifier()); + } + *reinterpret_cast(text + cursor) = labels[(*i)->Identifier()]; + cursor += sizeof(int); + } else if (cmd == "jne") { + text[cursor] = Script::CODE_JUMP_NOT_EQUAL; + ++cursor; + ++i; + if (!labels.count((*i)->Identifier())) { + throw Error("use of undefined label " + (*i)->Identifier()); + } + *reinterpret_cast(text + cursor) = labels[(*i)->Identifier()]; + cursor += sizeof(int); + } else if (cmd == "jl") { + text[cursor] = Script::CODE_JUMP_LESS; + ++cursor; + ++i; + if (!labels.count((*i)->Identifier())) { + throw Error("use of undefined label " + (*i)->Identifier()); + } + *reinterpret_cast(text + cursor) = labels[(*i)->Identifier()]; + cursor += sizeof(int); + } else if (cmd == "jle") { + text[cursor] = Script::CODE_JUMP_LESS_EQUAL; + ++cursor; + ++i; + if (!labels.count((*i)->Identifier())) { + throw Error("use of undefined label " + (*i)->Identifier()); + } + *reinterpret_cast(text + cursor) = labels[(*i)->Identifier()]; + cursor += sizeof(int); + } else if (cmd == "jg") { + text[cursor] = Script::CODE_JUMP_GREATER; + ++cursor; + ++i; + if (!labels.count((*i)->Identifier())) { + throw Error("use of undefined label " + (*i)->Identifier()); + } + *reinterpret_cast(text + cursor) = labels[(*i)->Identifier()]; + cursor += sizeof(int); + } else if (cmd == "jge") { + text[cursor] = Script::CODE_JUMP_GREATER_EQUAL; + ++cursor; + ++i; + if (!labels.count((*i)->Identifier())) { + throw Error("use of undefined label " + (*i)->Identifier()); + } + *reinterpret_cast(text + cursor) = labels[(*i)->Identifier()]; + cursor += sizeof(int); } else if (cmd == "sysc") { text[cursor] = Script::CODE_SYSCALL; ++cursor; @@ -535,9 +691,9 @@ void Interpreter::ReadScriptAddress(const ScriptToken &t, unsigned char *dest) { if (t.GetType() != ScriptToken::IDENTIFIER) { throw Error("expected identifier for address"); } - if (source.IsDefined(t.GetIdentifier())) { - const ParsedDefinition &def(GetDefinition(t.GetIdentifier())); - void *addr(GetObject(def.type, t.GetIdentifier())); + if (source.IsDefined(t.Identifier())) { + const ParsedDefinition &def(GetDefinition(t.Identifier())); + void *addr(GetObject(def.type, t.Identifier())); *reinterpret_cast(dest) = addr; } else { throw Error("postponing values in scripts not implemented"); @@ -546,8 +702,8 @@ void Interpreter::ReadScriptAddress(const ScriptToken &t, unsigned char *dest) { void Interpreter::ReadScriptInteger(const ScriptToken &t, unsigned char *dest) { if (t.GetType() == ScriptToken::IDENTIFIER) { - if (source.IsDefined(t.GetIdentifier())) { - void *num(GetObject(TypeDescription::GetTypeId("Number"), t.GetIdentifier())); + if (source.IsDefined(t.Identifier())) { + void *num(GetObject(TypeDescription::GetTypeId("Number"), t.Identifier())); *reinterpret_cast(dest) = *reinterpret_cast(num); } else { throw Error("postponing values in scripts not implemented"); @@ -561,8 +717,8 @@ void Interpreter::ReadScriptInteger(const ScriptToken &t, unsigned char *dest) { void Interpreter::ReadScriptVector(const ScriptToken &t, unsigned char *dest) { if (t.GetType() == ScriptToken::IDENTIFIER) { - if (source.IsDefined(t.GetIdentifier())) { - void *vec(GetObject(TypeDescription::GetTypeId("Vector"), t.GetIdentifier())); + if (source.IsDefined(t.Identifier())) { + void *vec(GetObject(TypeDescription::GetTypeId("Vector"), t.Identifier())); *reinterpret_cast *>(dest) = *reinterpret_cast *>(vec); } else { throw Error("postponing values in scripts not implemented");