diff --git a/doomsday/libcore/include/de/data/recordvalue.h b/doomsday/libcore/include/de/data/recordvalue.h index f0e9b93be5..b43263c016 100644 --- a/doomsday/libcore/include/de/data/recordvalue.h +++ b/doomsday/libcore/include/de/data/recordvalue.h @@ -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; diff --git a/doomsday/libcore/src/data/recordvalue.cpp b/doomsday/libcore/src/data/recordvalue.cpp index d4e621c4b8..16c25216b0 100644 --- a/doomsday/libcore/src/data/recordvalue.cpp +++ b/doomsday/libcore/src/data/recordvalue.cpp @@ -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" @@ -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 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("__init__"); + process.call(func.function(), arguments.as(), + 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; diff --git a/doomsday/libcore/src/scriptsys/nameexpression.cpp b/doomsday/libcore/src/scriptsys/nameexpression.cpp index 8b407cc401..2706b61bbe 100644 --- a/doomsday/libcore/src/scriptsys/nameexpression.cpp +++ b/doomsday/libcore/src/scriptsys/nameexpression.cpp @@ -46,11 +46,11 @@ DENG2_PIMPL_NOREF(NameExpression) foundIn = const_cast(&where); return const_cast(&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().dereference(), diff --git a/doomsday/libcore/src/scriptsys/parser.cpp b/doomsday/libcore/src/scriptsys/parser.cpp index 45cb62d331..340ca1983c 100644 --- a/doomsday/libcore/src/scriptsys/parser.cpp +++ b/doomsday/libcore/src/scriptsys/parser.cpp @@ -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 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));