-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d99548c
commit 0139b8e
Showing
14 changed files
with
687 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
Author of the start.png texture: http://opengameart.org/users/awesomepenguin | ||
License: CC BY 3.0 | ||
The image file had been modified with the pngcrush tool. | ||
The image file had been cropped with Preview.app and modified with the pngcrush tool. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
turn r | ||
go r | ||
j 0 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
#include "executable.hpp" | ||
#include <unordered_map> | ||
#include <functional> | ||
#include "util.hpp" | ||
|
||
|
||
Executable::Executable(const std::string &path) { | ||
auto in = FileOpenIn(path); | ||
|
||
std::vector<Word> jmp; | ||
Word offs = 0; | ||
|
||
std::string line; | ||
int n = 1; | ||
while (std::getline(in, line)) { | ||
jmp.push_back(offs); | ||
|
||
std::vector<std::string> insn; | ||
|
||
std::size_t i = 0; | ||
std::size_t d; | ||
do { | ||
std::string s; | ||
d = line.find(' ', i); | ||
if (d == s.npos) | ||
s = std::string(line, i); | ||
else | ||
s = std::string(line, i, d - i); | ||
|
||
if (s.length()) | ||
insn.push_back(s); | ||
|
||
i = d + 1; | ||
} while (d != std::string::npos); | ||
|
||
auto parseOpN = [this, insn, path, n] { | ||
switch (insn.size()) { | ||
case 1: | ||
bytecode.push_back(1); | ||
break; | ||
case 2: | ||
try { | ||
bytecode.push_back((Word)std::stoul(insn[1])); | ||
} catch (const std::invalid_argument &) { | ||
throw ExecutableError(path, n); | ||
} | ||
break; | ||
default: | ||
throw ExecutableError(path, n); | ||
} | ||
}; | ||
|
||
auto parseOpR = [this, insn, path, n] { | ||
if (insn.size() != 2 || insn[1] != "r") | ||
throw ExecutableError(path, n); | ||
}; | ||
|
||
auto parseOpNR = [this, insn, path, n] { | ||
switch (insn.size()) { | ||
case 1: | ||
bytecode.push_back(1); | ||
break; | ||
case 2: | ||
if (insn[1] == "r") | ||
bytecode.push_back(0); | ||
else { | ||
try { | ||
bytecode.push_back(static_cast<Word>(std::stoul(insn[1]))); | ||
} catch (const std::invalid_argument &) { | ||
throw ExecutableError(path, n); | ||
} | ||
|
||
if (bytecode.back() < 2 || bytecode.back() > 99) | ||
throw ExecutableError(path, n); | ||
} | ||
|
||
break; | ||
default: | ||
throw ExecutableError(path, n); | ||
} | ||
}; | ||
|
||
auto parseOpNN = [this, insn, path, n] { | ||
try { | ||
bytecode.push_back(static_cast<Word>(std::stoul(insn.at(1)))); | ||
bytecode.push_back(static_cast<Word>(std::stoul(insn.at(2)))); | ||
} catch (const std::logic_error &) { | ||
throw ExecutableError(path, n); | ||
} | ||
}; | ||
|
||
auto parseOpNone = [this, insn, path, n] { | ||
if (insn.size() != 1) | ||
throw ExecutableError(path, n); | ||
}; | ||
|
||
auto leaveJumpAddr = [this, jmp, path, n](Word pc) { | ||
if (pc >= jmp.size()) | ||
throw ExecutableError(path, n); | ||
|
||
bytecode.push_back(jmp[pc]); | ||
}; | ||
|
||
auto parseOpNJ = [this, insn, path, n, leaveJumpAddr] { | ||
try { | ||
bytecode.push_back((Word)std::stoul(insn.at(1))); | ||
leaveJumpAddr((Word)std::stoul(insn[2])); | ||
} catch (const std::logic_error &) { | ||
throw ExecutableError(path, n); | ||
} | ||
}; | ||
|
||
auto parseOpJ = [this, insn, path, n, leaveJumpAddr] { | ||
try { | ||
leaveJumpAddr((Word)std::stoul(insn.at(1))); | ||
} catch (const std::logic_error &) { | ||
throw ExecutableError(path, n); | ||
} | ||
}; | ||
|
||
std::unordered_map<std::string, std::function<void()>> handle = { | ||
#define INSN(n, i, o) \ | ||
{#n, [this, parseOp ## o] {\ | ||
bytecode.push_back(Insn ## i);\ | ||
parseOp ## o();\ | ||
}} | ||
|
||
INSN(eat, Eat, NR), | ||
INSN(go, Go, NR), | ||
INSN(clon, Clon, None), | ||
INSN(str, Str, N), | ||
INSN(left, Left, N), | ||
INSN(right, Right, N), | ||
INSN(back, Back, None), | ||
INSN(turn, Turn, R), | ||
INSN(jg, JG, NJ), | ||
INSN(jl, JL, NJ), | ||
INSN(j, J, J), | ||
INSN(je, JE, J) | ||
|
||
#undef INSN | ||
}; | ||
|
||
try { | ||
handle.at(insn[0])(); | ||
} catch (const std::out_of_range &) { | ||
throw ExecutableError(path, n); | ||
} | ||
|
||
offs += bytecode[jmp.back()] == InsnTurn ? 1 : insn.size(); | ||
|
||
n++; | ||
} | ||
} | ||
|
||
ExecutableError::ExecutableError(const std::string &path, int line) { | ||
reason = path + ":" + std::to_string(line) + ": Syntax error."; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#ifndef EXECUTABLE_HPP | ||
#define EXECUTABLE_HPP | ||
|
||
|
||
#include <vector> | ||
#include <string> | ||
#include <fstream> | ||
#include <cstdint> | ||
#include <exception> | ||
|
||
|
||
/* | ||
* Executable. | ||
*/ | ||
|
||
class Executable { | ||
public: | ||
/* | ||
* All opcodes and operands are 32-bit. | ||
* Random values are specified by 0 if applicable. | ||
*/ | ||
typedef std::uint32_t Word; | ||
typedef std::vector<Word> Bytecode; | ||
|
||
enum { | ||
InsnEat, | ||
InsnGo, | ||
InsnClon, | ||
InsnStr, | ||
InsnLeft, | ||
InsnRight, | ||
InsnBack, | ||
InsnTurn, | ||
InsnJG, | ||
InsnJL, | ||
InsnJ, | ||
InsnJE, | ||
InsnMax = InsnJE | ||
}; | ||
|
||
Executable() {} | ||
Executable(const std::string &path); | ||
|
||
const Bytecode &getBytecode() const {return bytecode;} | ||
std::size_t size() const {return bytecode.size();} | ||
Word operator[](std::size_t i) const {return bytecode[i];} | ||
|
||
private: | ||
Bytecode bytecode; | ||
}; | ||
|
||
/* | ||
* ExecutableError. | ||
*/ | ||
|
||
class ExecutableError : public std::exception { | ||
private: | ||
std::string reason; | ||
|
||
public: | ||
ExecutableError(const std::string &path, int line); | ||
|
||
virtual const char *what() const noexcept {return reason.c_str();} | ||
}; | ||
|
||
|
||
#endif |
Oops, something went wrong.