Skip to content

Commit 256b213

Browse files
authored
prg instruction (#329)
1 parent a3a45c2 commit 256b213

File tree

14 files changed

+133
-16
lines changed

14 files changed

+133
-16
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ To install or update LODA, please follow the [installation instructions](https:/
22

33
## [Unreleased]
44

5+
## v24.9.2
6+
57
## Featues
68

7-
* Support for program directives
9+
* Support for directives and `prg` instruction
810

911
### Enhancements
1012

src/cmd/test.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,11 @@ void Test::knownPrograms() {
686686
8192, 16384, 32768, 65536}));
687687
testSeq(1489, Sequence({0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12,
688688
-13, -14, -15, -16, -17}));
689+
testSeq(1497, Sequence({1, 1, 1, 3, 3, 1, 15, 15, 6,
690+
1, 105, 105, 45, 10, 1, 945, 945, 420,
691+
105, 15, 1, 10395, 10395, 4725, 1260, 210}));
692+
testSeq(2260, Sequence({1, 1, 2, 1, 2, 3, 1, 2, 3, 4,
693+
1, 2, 3, 4, 5, 1, 2, 3, 4, 5}));
689694
testSeq(248765,
690695
Sequence({1, 1, 1, 1, 1, 2, 2,
691696
2, 6, 12, 12, 12, 12, 12,

src/lang/interpreter.cpp

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ Number Interpreter::calc(const Operation::Type type, const Number& target,
115115
case Operation::Type::CLR:
116116
case Operation::Type::SRT:
117117
case Operation::Type::SEQ:
118+
case Operation::Type::PRG:
118119
case Operation::Type::__COUNT:
119120
Log::get().error(
120121
"non-arithmetic operation: " + Operation::Metadata::get(type).name,
@@ -230,11 +231,18 @@ size_t Interpreter::run(const Program& p, Memory& mem) {
230231
case Operation::Type::SEQ: {
231232
target = get(op.target, mem);
232233
source = get(op.source, mem);
233-
auto result = call(source.asInt(), target);
234+
auto result = callSeq(source.asInt(), target);
234235
set(op.target, result.first, mem, op);
235236
cycles += result.second;
236237
break;
237238
}
239+
case Operation::Type::PRG: {
240+
target = get(op.target, mem, true);
241+
source = get(op.source, mem);
242+
cycles += callPrg(source.asInt(), target.asInt(), mem);
243+
break;
244+
}
245+
238246
case Operation::Type::CLR: {
239247
length = get(op.source, mem).asInt();
240248
start = get(op.target, mem, true).asInt();
@@ -375,7 +383,15 @@ void Interpreter::set(const Operand& a, const Number& v, Memory& mem,
375383
mem.set(index, v);
376384
}
377385

378-
std::pair<Number, size_t> Interpreter::call(int64_t id, const Number& arg) {
386+
std::string getProgramPath(int64_t id) {
387+
if (id < 0) {
388+
return OeisSequence(-id).getProgramPath("prg", "P");
389+
} else {
390+
return OeisSequence(id).getProgramPath();
391+
}
392+
}
393+
394+
std::pair<Number, size_t> Interpreter::callSeq(int64_t id, const Number& arg) {
379395
if (arg < 0) {
380396
throw std::runtime_error("seq using negative argument: " +
381397
std::to_string(id));
@@ -421,15 +437,52 @@ std::pair<Number, size_t> Interpreter::call(int64_t id, const Number& arg) {
421437
return result;
422438
}
423439

440+
size_t Interpreter::callPrg(int64_t id, int64_t start, Memory& mem) {
441+
// load program
442+
id = -id; // internally use negative IDs for prg calls
443+
auto& call_program = getProgram(id);
444+
445+
// check for recursive calls
446+
if (running_programs.find(id) != running_programs.end()) {
447+
throw std::runtime_error("Recursion detected: " + getProgramPath(id));
448+
}
449+
450+
// get number of inputs and outputs
451+
auto inputs = call_program.getDirective("inputs");
452+
auto outputs = call_program.getDirective("outputs");
453+
454+
// set inputs for program
455+
Memory tmp;
456+
for (int64_t i = 0; i < inputs; i++) {
457+
tmp.set(i, mem.get(start + i));
458+
}
459+
460+
// evaluate program
461+
size_t steps = 0;
462+
running_programs.insert(id);
463+
try {
464+
steps = run(call_program, tmp);
465+
running_programs.erase(id);
466+
} catch (...) {
467+
running_programs.erase(id);
468+
std::rethrow_exception(std::current_exception());
469+
}
470+
471+
// set outputs for program
472+
for (int64_t i = 0; i < outputs; i++) {
473+
mem.set(start + i, tmp.get(i));
474+
}
475+
return steps;
476+
}
477+
424478
const Program& Interpreter::getProgram(int64_t id) {
425479
if (missing_programs.find(id) != missing_programs.end()) {
426-
throw std::runtime_error("Program not found: " + OeisSequence(id).id_str());
480+
throw std::runtime_error("Program not found: " + getProgramPath(id));
427481
}
428482
if (program_cache.find(id) == program_cache.end()) {
429-
Parser parser;
430-
auto path = OeisSequence(id).getProgramPath();
431483
try {
432-
program_cache[id] = parser.parse(path);
484+
Parser parser;
485+
program_cache[id] = parser.parse(getProgramPath(id));
433486
} catch (...) {
434487
missing_programs.insert(id);
435488
std::rethrow_exception(std::current_exception());

src/lang/interpreter.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ class Interpreter {
3535
void set(const Operand &a, const Number &v, Memory &mem,
3636
const Operation &last_op) const;
3737

38-
std::pair<Number, size_t> call(int64_t id, const Number &arg);
38+
std::pair<Number, size_t> callSeq(int64_t id, const Number &arg);
39+
40+
size_t callPrg(int64_t id, int64_t start, Memory &mem);
3941

4042
const Program &getProgram(int64_t id);
4143

src/lang/parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Program Parser::parse(const std::string &file) {
2121
}
2222

2323
Program Parser::parse(std::istream &in_) {
24-
const static std::set<std::string> valid_directives = {};
24+
const static std::set<std::string> valid_directives = {"inputs", "outputs"};
2525
in = &in_;
2626
Program p;
2727
Operation o;

src/lang/program.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#include "lang/number.hpp"
66

7-
const std::array<Operation::Type, 31> Operation::Types = {
7+
const std::array<Operation::Type, 32> Operation::Types = {
88
Operation::Type::NOP, Operation::Type::MOV, Operation::Type::ADD,
99
Operation::Type::SUB, Operation::Type::TRN, Operation::Type::MUL,
1010
Operation::Type::DIV, Operation::Type::DIF, Operation::Type::MOD,
@@ -15,7 +15,7 @@ const std::array<Operation::Type, 31> Operation::Types = {
1515
Operation::Type::MAX, Operation::Type::BAN, Operation::Type::BOR,
1616
Operation::Type::BXO, Operation::Type::LPB, Operation::Type::LPE,
1717
Operation::Type::CLR, Operation::Type::SRT, Operation::Type::SEQ,
18-
Operation::Type::DBG,
18+
Operation::Type::PRG, Operation::Type::DBG,
1919
};
2020

2121
const Operation::Metadata& Operation::Metadata::get(Type t) {
@@ -79,6 +79,8 @@ const Operation::Metadata& Operation::Metadata::get(Type t) {
7979
Operation::Type::SRT, "srt", 2, true, true, true};
8080
static Operation::Metadata seq{
8181
Operation::Type::SEQ, "seq", 2, true, true, true};
82+
static Operation::Metadata prg{
83+
Operation::Type::PRG, "prg", 2, true, true, true};
8284
static Operation::Metadata dbg{
8385
Operation::Type::DBG, "dbg", 0, false, false, false};
8486
switch (t) {
@@ -142,6 +144,8 @@ const Operation::Metadata& Operation::Metadata::get(Type t) {
142144
return srt;
143145
case Operation::Type::SEQ:
144146
return seq;
147+
case Operation::Type::PRG:
148+
return prg;
145149
case Operation::Type::DBG:
146150
return dbg;
147151
case Operation::Type::__COUNT:
@@ -173,6 +177,14 @@ void Program::push_back(Operation::Type t, Operand::Type tt, const Number& tv,
173177
ops.insert(ops.end(), Operation(t, Operand(tt, tv), Operand(st, sv)));
174178
}
175179

180+
int64_t Program::getDirective(const std::string& name) const {
181+
auto d = directives.find(name);
182+
if (d == directives.end()) {
183+
throw std::runtime_error("directive not found: " + name);
184+
}
185+
return d->second;
186+
}
187+
176188
bool Program::operator==(const Program& p) const { return (ops == p.ops); }
177189

178190
bool Program::operator!=(const Program& p) const { return !(*this == p); }

src/lang/program.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,12 @@ class Operation {
6464
CLR, // clear
6565
SRT, // sort
6666
SEQ, // sequence
67+
PRG, // program
6768
DBG, // debug
6869
__COUNT // number of operation types
6970
};
7071

71-
static const std::array<Type, 31> Types;
72+
static const std::array<Type, 32> Types;
7273

7374
class Metadata {
7475
public:
@@ -123,6 +124,8 @@ class Program {
123124
void push_back(Operation::Type t, Operand::Type tt, const Number &tv,
124125
Operand::Type st, const Number &sv);
125126

127+
int64_t getDirective(const std::string &name) const;
128+
126129
bool operator==(const Program &p) const;
127130

128131
bool operator!=(const Program &p) const;

src/lang/program_util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ bool ProgramUtil::isArithmetic(Operation::Type t) {
9797
return (t != Operation::Type::NOP && t != Operation::Type::DBG &&
9898
t != Operation::Type::LPB && t != Operation::Type::LPE &&
9999
t != Operation::Type::CLR && t != Operation::Type::SRT &&
100-
t != Operation::Type::SEQ);
100+
t != Operation::Type::SEQ && t != Operation::Type::PRG);
101101
}
102102

103103
bool ProgramUtil::isCommutative(Operation::Type t) {

src/mine/iterator.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ bool Iterator::inc(Operation& op) {
130130
case Operation::Type::CLR: // skipped
131131
case Operation::Type::SRT: // skipped
132132
case Operation::Type::SEQ: // skipped
133+
case Operation::Type::PRG: // skipped
133134
case Operation::Type::__COUNT: // skipped
134135

135136
case Operation::Type::LPB:
@@ -149,7 +150,8 @@ bool Iterator::supportsOperationType(Operation::Type t) {
149150
t != Operation::Type::BAN && t != Operation::Type::BOR &&
150151
t != Operation::Type::BXO && t != Operation::Type::NOP &&
151152
t != Operation::Type::DBG && t != Operation::Type::CLR &&
152-
t != Operation::Type::SRT && t != Operation::Type::SEQ;
153+
t != Operation::Type::SRT && t != Operation::Type::SEQ &&
154+
t != Operation::Type::PRG;
153155
}
154156

155157
bool Iterator::incWithSkip(Operation& op) {

src/oeis/oeis_sequence.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,16 @@ std::string OeisSequence::getProgramPath(bool local) const {
8484
if (local) {
8585
return Setup::getProgramsHome() + "local" + FILE_SEP + id_str() + ".asm";
8686
} else {
87-
return Setup::getProgramsHome() + "oeis" + FILE_SEP + dir_str() + FILE_SEP +
88-
id_str() + ".asm";
87+
return getProgramPath("oeis", "A");
8988
}
9089
}
9190

91+
std::string OeisSequence::getProgramPath(const std::string& dir,
92+
const std::string& prefix) const {
93+
return Setup::getProgramsHome() + dir + FILE_SEP + dir_str() + FILE_SEP +
94+
id_str(prefix) + ".asm";
95+
}
96+
9297
std::string OeisSequence::getBFilePath() const {
9398
return Setup::getOeisHome() + "b" + FILE_SEP + dir_str() + FILE_SEP +
9499
id_str("b") + ".txt";

0 commit comments

Comments
 (0)