Skip to content

Commit

Permalink
Script|libdeng2: Creating records with expressions
Browse files Browse the repository at this point in the history
Previously it was only possible to create a new record using the
“record” statement or the Record() function. This commit makes it
possible to put “record” in front of any expression that refers to
an identifier, and that identifier will be created as a (sub)record.

For instance:

<pre># Old way:
record a
a.b = 1
record a.sub
# Alternatively: a.sub = Record()
a.sub.c = 2

# New way:
(record a).b = 1
a.(record sub).c = 2</pre>
  • Loading branch information
skyjake committed Jan 6, 2014
1 parent c161f21 commit 3ced433
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
2 changes: 1 addition & 1 deletion doomsday/libdeng2/src/scriptsys/nameexpression.cpp
Expand Up @@ -46,7 +46,7 @@ Value *NameExpression::evaluate(Evaluator &evaluator) const
{
//LOG_AS("NameExpression::evaluate");
//std::cout << "NameExpression::evaluator: " << _flags.to_string() << "\n";
//LOG_DEBUG("path = %s, scope = %x") << _path << evaluator.names();
LOGDEV_SCR_XVERBOSE_DEBUGONLY("evaluating name:\"%s\" flags:%x", _identifier << flags());

// Collect the namespaces to search.
Evaluator::Namespaces spaces;
Expand Down
30 changes: 27 additions & 3 deletions doomsday/libdeng2/src/scriptsys/parser.cpp
Expand Up @@ -619,7 +619,7 @@ Expression *Parser::parseExpression(TokenRange const &fullRange, Expression::Fla
TokenRange range = fullRange;

LOG_AS("parseExpression");
LOGDEV_SCR_XVERBOSE_DEBUGONLY("", range.asText());
LOGDEV_SCR_XVERBOSE_DEBUGONLY("%s (flags:%x)", range.asText() << flags);

if(!range.size())
{
Expand All @@ -633,6 +633,21 @@ Expression *Parser::parseExpression(TokenRange const &fullRange, Expression::Fla
range = range.shrink(1);
}

// Do we have a record declaration in the expression?
if(range.firstToken().type() == Token::KEYWORD &&
range.firstToken().equals(ScriptLex::RECORD))
{
LOGDEV_SCR_XVERBOSE_DEBUGONLY("declaration expression: RECORD %s", range.startingFrom(1).asText());

if(range.size() == 1)
{
throw MissingTokenError("Parser::parseDeclarationExpression",
"Expected identifier to follow " + range.firstToken().asText());
}
return parseExpression(range.startingFrom(1),
flags | Expression::LocalOnly | Expression::NewSubrecord);
}

TokenRange leftSide = range.between(0, 0);
TokenRange rightSide = leftSide;

Expand Down Expand Up @@ -673,7 +688,7 @@ ArrayExpression *Parser::parseArrayExpression(TokenRange const &range)
"Expected brackets for the array expression beginning at " +
range.firstToken().asText());
}
return parseList(range.between(1, range.size() - 1));
return parseList(range.shrink(1));
}

DictionaryExpression *Parser::parseDictionaryExpression(TokenRange const &range)
Expand Down Expand Up @@ -791,7 +806,16 @@ OperatorExpression *Parser::parseOperatorExpression(Operator op, TokenRange cons
Expression::ByReference : Expression::ByValue);

Expression::Flags rightOpFlags = rightFlags;
if(op != MEMBER) rightOpFlags &= ~Expression::ByReference;
if(op == MEMBER)
{
// Don't create new variables for the left side of the member. The only place
// where a new variable is created is on the right.
leftOpFlags &= ~Expression::NewVariable;
}
else
{
rightOpFlags &= ~Expression::ByReference;
}

// Binary operation.
QScopedPointer<Expression> leftOperand(parseExpression(leftSide, leftOpFlags));
Expand Down
9 changes: 8 additions & 1 deletion doomsday/tests/test_script/kitchen_sink.de
Expand Up @@ -449,14 +449,21 @@ end
# ---------------------------------------------------------------------------
sections.begin('RECORDS')

sections.subsection('Creating a record.')
sections.subsection('Creating a record with a statement.')
record myrec
print len(myrec)
print "Alternative way using Record()."
del myrec
myrec = Record()
print len(myrec)

sections.subsection('Creating a record using an expression.')
del myrec
(record myrec).expressionCreated = True
myrec.(record subexp).alsoExpCreated = True
print myrec
del myrec.subexp

sections.subsection('Creating variables into a record.')
myrec.newMember = 100
print len(myrec)
Expand Down

0 comments on commit 3ced433

Please sign in to comment.