Skip to content

Commit

Permalink
Scripting|libcore: Instantiating a class record
Browse files Browse the repository at this point in the history
Any record can be instantiated using the call operator. This
automatically calls the __init__ method if one exists in the class
record.
  • Loading branch information
skyjake committed Jun 11, 2014
1 parent 8bb9b7d commit 07f3bf1
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
1 change: 1 addition & 0 deletions doomsday/libcore/include/de/data/recordvalue.h
Expand Up @@ -113,6 +113,7 @@ class DENG2_PUBLIC RecordValue : public Value, DENG2_OBSERVES(Record, Deletion)
bool contains(Value const &value) const;
bool isTrue() const;
dint compare(Value const &value) const;
void call(Process &process, Value const &arguments, Value *instanceScope = 0) const;

// Implements ISerializable.
void operator >> (Writer &to) const;
Expand Down
30 changes: 30 additions & 0 deletions doomsday/libcore/src/data/recordvalue.cpp
Expand Up @@ -21,6 +21,10 @@
#include "de/TextValue"
#include "de/RefValue"
#include "de/NoneValue"
#include "de/FunctionValue"
#include "de/Process"
#include "de/Context"
#include "de/Evaluator"
#include "de/Variable"
#include "de/Writer"
#include "de/Reader"
Expand Down Expand Up @@ -233,6 +237,32 @@ dint RecordValue::compare(Value const &value) const
return cmp(recValue->d->record, d->record);
}

void RecordValue::call(Process &process, Value const &arguments, Value *) const
{
verify();

// Calling a record causes it to be treated as a class and a new record is
// initialized as a member of the class.
QScopedPointer<RecordValue> instance(new RecordValue(new Record, RecordValue::OwnsRecord));

ArrayValue *super = new ArrayValue;
*super << new RecordValue(d->record);
instance->record()->add(new Variable("__super__", super));

// If there is an initializer method, call it now.
if(dereference().hasMember("__init__"))
{
FunctionValue const &func = dereference().getAs<FunctionValue>("__init__");
process.call(func.function(), arguments.as<ArrayValue>(),
instance->duplicateAsReference());

// Discard the return value from the init function.
delete process.context().evaluator().popResult();
}

process.context().evaluator().pushResult(instance.take());
}

// Flags for serialization:
static duint8 const OWNS_RECORD = 0x1;

Expand Down
4 changes: 2 additions & 2 deletions doomsday/libcore/src/scriptsys/nameexpression.cpp
Expand Up @@ -46,11 +46,11 @@ DENG2_PIMPL_NOREF(NameExpression)
foundIn = const_cast<Record *>(&where);
return const_cast<Variable *>(&where[identifier]);
}
if(lookInClass && where.hasMember("__isa__"))
if(lookInClass && where.hasMember("__super__"))
{
// The namespace is derived from another record. Let's look into each
// super-record in turn.
ArrayValue const &supers = where.geta("__isa__");
ArrayValue const &supers = where.geta("__super__");
for(dsize i = 0; i < supers.size(); ++i)
{
if(Variable *found = findIdentifier(supers.at(i).as<RecordValue>().dereference(),
Expand Down
7 changes: 5 additions & 2 deletions doomsday/libcore/src/scriptsys/parser.cpp
Expand Up @@ -340,17 +340,20 @@ DeleteStatement *Parser::parseDeleteStatement()

FunctionStatement *Parser::parseFunctionStatement()
{
// "def" name-expr "(" [ name-expr ["," name-expr]* ] ")" cond-compound

dint pos = _statementRange.find(Token::PARENTHESIS_OPEN);
if(pos < 0)
{
throw MissingTokenError("Parser::parseMethodStatement",
throw MissingTokenError("Parser::parseFunctionStatement",
"Expected arguments for " + _statementRange.firstToken().asText());
}

// The function must have a name that is not already in use in the scope.
auto_ptr<FunctionStatement> statement(new FunctionStatement(
parseExpression(_statementRange.between(1, pos),
Expression::LocalOnly | Expression::ByReference | Expression::NewVariable | Expression::NotInScope)));
Expression::LocalOnly | Expression::ByReference |
Expression::NewVariable | Expression::NotInScope)));

// Collect the argument names.
TokenRange argRange = _statementRange.between(pos + 1, _statementRange.closingBracket(pos));
Expand Down

0 comments on commit 07f3bf1

Please sign in to comment.