Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 59 additions & 17 deletions games/intrptr.arch
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ null main

verbmsg : UNDEFINED

sitrep : UNDEFINED

methods

'START' : {
Expand All @@ -150,6 +152,13 @@ methods

} # START

'ROLL CALL' : {
'ROLL CALL' -> system
'ANNOUNCE MEMBERS' -> player
'ANNOUNCE MEMBERS' -> player.location
'ANNOUNCE SELF' -> player.location
}

'UPDATE' : {
if not started then {
# The INITIAL and ASSEMBLE messages are broadcast separately because
Expand All @@ -158,14 +167,11 @@ methods
for each do 'ASSEMBLE' -> each
'ASSEMBLE VOCABULARY'
'ENTERED' -> player.location
'ROLL CALL'
started := TRUE
}

'UPDATE' -> player
'ROLL CALL' -> system
'ANNOUNCE MEMBERS' -> player
'ANNOUNCE MEMBERS' -> player.location
'ANNOUNCE SELF' -> player.location

# Prompt for input and parse
writes prompt; command := read; write normal
Expand All @@ -191,6 +197,18 @@ methods
'MENTION SELF' -> subj

'SEND EVENT' -> after
'ROLL CALL'
}

'SITREP' : {
sitrep := UNDEFINED
sitrep := [ "location" player.location ] @ sitrep
sitrep := [ "exits" ('INVENTORY OBJECTS' -> compass) ] @ sitrep
sitrep := [ "visible" ('INVENTORY OBJECTS' -> player.location) ] @ sitrep
sitrep := [ "inventory" ('INVENTORY OBJECTS' -> player) ] @ sitrep
if it then
sitrep := [ "it" it.referent ] @ sitrep
sitrep
}


Expand Down Expand Up @@ -355,7 +373,7 @@ end

class event_handler based on null

subscribers : { }
subscribers : [ ]
temp : UNDEFINED

event : 'EVENT'
Expand Down Expand Up @@ -453,7 +471,9 @@ methods
}
}

'INVENTORY' : message -> list_inventory
'INVENTORY' : message -> list_inventory
'INVENTORY NAMES' : message -> list_inventory
'INVENTORY OBJECTS' : message -> list_inventory

end

Expand All @@ -467,26 +487,48 @@ null list_inventory
number : 0
temp : UNDEFINED
last : UNDEFINED
names : UNDEFINED

methods

'INVENTORY OBJECTS' : {
names := UNDEFINED
temp := sender.members
while temp do {
if 'INVENTORY NAME' -> head temp then
names := (head temp) @ names
temp := tail temp
}
names
}

'INVENTORY NAMES' : {
names := UNDEFINED
temp := sender.members
while temp do {
if 'INVENTORY NAME' -> head temp then
names := ('INVENTORY NAME' -> head temp) @ names
temp := tail temp
}
names
}

'INVENTORY' : {

'INVENTORY NAMES' # bring 'names' up to date
number := 0
temp := sender.members
temp := names
last := UNDEFINED

while temp do {
if 'INVENTORY NAME' -> head temp then { # we may proceed
number +:= 1
if not last then
writes sender.intro
else {
if number > 2 then writes ","
writes " ", last
}
last := 'INVENTORY NAME' -> head temp
number +:= 1
if not last then
writes sender.intro
else {
if number > 2 then writes ","
writes " ", last
}
last := head temp
temp := tail temp
}
if number = 0 then
Expand All @@ -496,7 +538,7 @@ methods
if number > 1 then writes " and"
write " ", last, "."
}

names
} # INVENTORY

end
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ SystemParser.cc
SystemSorter.cc
TestExpression.cc
TestIdIndex.cc
TestInspectUniverse.cc
TestObject.cc
TestRegistry.cc
TestSerialization.cc
Expand Down
6 changes: 3 additions & 3 deletions src/Expression.cc
Original file line number Diff line number Diff line change
Expand Up @@ -814,9 +814,9 @@ namespace archetype {
}

Expression form_list_expr(TokenStream& t) {
// Called when the list has already begun, with an opening '{'.
// Called when the list has already begun, with an opening '['.
stack<Expression> elements;
while (t.fetch() and t.token() != Token(Token::PUNCTUATION, '}')) {
while (t.fetch() and t.token() != Token(Token::PUNCTUATION, ']')) {
if (t.token() != Token(Token::PUNCTUATION, ';')) {
t.didNotConsume();
}
Expand Down Expand Up @@ -848,7 +848,7 @@ namespace archetype {
} else {
return nullptr;
}
case '{':
case '[':
return form_list_expr(t);
default:
return nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/Object.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace archetype {
std::map<int, Expression> attributes_;
std::map<int, Statement> methods_;

friend void inspect_universe(Storage& in, std::ostream& out);
friend void inspect_universe(Storage& in, std::ostream& out, bool include_methods);

public:
static const int INVALID = -1;
Expand Down
7 changes: 1 addition & 6 deletions src/ReadEvalPrintLoop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,8 @@ namespace archetype {
}
Value result = stmt->execute();
ostringstream sout;
sout << "[";
sout << "=> ";
result->display(sout);
sout << "]";
Value result_str = result->stringConversion();
if (result_str->isDefined()) {
sout << " " << result_str->getString();
}
sout << endl;
out->put(sout.str());
}
Expand Down
3 changes: 2 additions & 1 deletion src/SystemObject.hh
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ namespace archetype {
bool figureState_(const Value& message);
void resetSystem_();

friend void inspect_universe(Storage& in, std::ostream& out);
friend void inspect_universe(Storage& in, std::ostream& out, bool include_methods);
friend std::string sitrep_parser_context();

};
}
Expand Down
3 changes: 2 additions & 1 deletion src/SystemParser.hh
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ namespace archetype {
void matchVerbs_(std::list<Value>& wordValues);
void matchNouns_(std::list<Value>& wordValues);

friend void inspect_universe(Storage& in, std::ostream& out);
friend void inspect_universe(Storage& in, std::ostream& out, bool include_methods);
friend std::string sitrep_parser_context();
};

Storage& operator<<(Storage& out, const SystemParser& p);
Expand Down
53 changes: 53 additions & 0 deletions src/TestExpression.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "Expression.hh"
#include "Serialization.hh"
#include "StringInput.hh"
#include "StringOutput.hh"
#include "ReadEvalPrintLoop.hh"
#include "Universe.hh"

using namespace std;
Expand Down Expand Up @@ -327,11 +329,62 @@ namespace archetype {
ARCHETYPE_TEST(expr7 != nullptr);
}

void TestExpression::testListLiterals_() {
// A list literal uses square brackets and evaluates to a PairValue
// chain whose display round-trips to the same bracket form.
Expression list_expr = make_expr_from_str("[1 2 3]");
ARCHETYPE_TEST(list_expr != nullptr);
Value list_val = list_expr->evaluate()->valueConversion();
ostringstream list_out;
list_val->display(list_out);
ARCHETYPE_TEST_EQUAL(list_out.str(), string{"[1 2 3]"});

// The empty list still parses.
Expression empty_expr = make_expr_from_str("[]");
ARCHETYPE_TEST(empty_expr != nullptr);

// Nested list literals.
Expression nested_expr = make_expr_from_str("[[1 2] [3 4]]");
ARCHETYPE_TEST(nested_expr != nullptr);
Value nested_val = nested_expr->evaluate()->valueConversion();
ostringstream nested_out;
nested_val->display(nested_out);
ARCHETYPE_TEST_EQUAL(nested_out.str(), string{"[[1 2] [3 4]]"});

// Curly braces in expression position no longer form a list literal.
Expression curly_expr = make_expr_from_str("{1 2 3}");
ARCHETYPE_TEST(curly_expr == nullptr);
}

void TestExpression::testReplDisplay_() {
// Drive the REPL with a few inputs and verify each result is echoed
// once with the `=> ` prefix — the display form only, matching the
// Python/Ruby/Lisp convention. No duplicated stringConversion tail.
UserInput prior_input = Universe::instance().input();
UserOutput prior_output = Universe::instance().output();
UserInput repl_input{new StringInput{"3 + 5\n[1 2 3]\n\"hi\"\nexit\n"}};
UserOutput repl_output{new StringOutput};
Universe::instance().setInput(repl_input);
Universe::instance().setOutput(repl_output);
int errors = repl();
ARCHETYPE_TEST_EQUAL(errors, 0);
string text = dynamic_cast<StringOutput*>(repl_output.get())->getOutput();
ARCHETYPE_TEST(text.find("=> 8\n") != string::npos);
ARCHETYPE_TEST(text.find("=> 8 8") == string::npos);
ARCHETYPE_TEST(text.find("=> [1 2 3]\n") != string::npos);
ARCHETYPE_TEST(text.find("=> \"hi\"\n") != string::npos);
ARCHETYPE_TEST(text.find("\"hi\" hi") == string::npos);
Universe::instance().setInput(prior_input);
Universe::instance().setOutput(prior_output);
}

void TestExpression::runTests_() {
testTranslation_();
testEvaluation_();
testSerialization_();
testInput_();
testVerification_();
testListLiterals_();
testReplDisplay_();
}
}
2 changes: 2 additions & 0 deletions src/TestExpression.hh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace archetype {
void testSerialization_();
void testInput_();
void testVerification_();
void testListLiterals_();
void testReplDisplay_();
protected:
virtual void runTests_() override;
public:
Expand Down
Loading
Loading