- changed assignment operators to be expressions, like they are in C and DECORATE.

This also means that for now Lua-style multi-assignments are disabled, those should be easy to enable by making some changes to the assignment_statement grammar so that it doesn't recognize single assignments, but for now this is low priority because it adds a significant amount of complexity to do this right with functions that have multiple return values.
This commit is contained in:
Christoph Oelckers 2016-10-21 12:22:42 +02:00
parent 1450c3dffb
commit 3e995d7aac
5 changed files with 102 additions and 60 deletions

View file

@ -747,21 +747,6 @@ static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node)
{
ZCC_AssignStmt *snode = (ZCC_AssignStmt *)node;
out.Open("assign-stmt");
switch (snode->AssignOp)
{
case ZCC_EQ: out.AddChar('='); break;
case ZCC_MULEQ: out.Add("*=", 2); break;
case ZCC_DIVEQ: out.Add("/=", 2); break;
case ZCC_MODEQ: out.Add("%=", 2); break;
case ZCC_ADDEQ: out.Add("+=", 2); break;
case ZCC_SUBEQ: out.Add("-=", 2); break;
case ZCC_LSHEQ: out.Add("<<=", 2); break;
case ZCC_RSHEQ: out.Add(">>=", 2); break;
case ZCC_ANDEQ: out.Add("&=", 2); break;
case ZCC_OREQ: out.Add("|=", 2); break;
case ZCC_XOREQ: out.Add("^=", 2); break;
default: BadAssignOp(out, snode->AssignOp); break;
}
PrintNodes(out, snode->Dests);
PrintNodes(out, snode->Sources);
out.Close();

View file

@ -104,7 +104,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line)
%parse_accept { DPrintf(DMSG_SPAMMY, "Input accepted\n"); }
%parse_failure { /**failed = true;*/ }
%nonassoc EQ MULEQ DIVEQ MODEQ ADDEQ SUBEQ LSHEQ RSHEQ ANDEQ OREQ XOREQ.
%right EQ MULEQ DIVEQ MODEQ ADDEQ SUBEQ LSHEQ RSHEQ ANDEQ OREQ XOREQ URSHEQ.
%right QUESTION COLON.
%left OROR.
%left ANDAND.
@ -1247,6 +1247,67 @@ expr(X) ::= expr(A) OROR expr(B). /* a || b */
BINARY_EXPR(A,B,PEX_BoolOr);
X = expr2;
}
expr(X) ::= expr(A) EQ expr(B). /* a = b */
{
BINARY_EXPR(A,B,PEX_Assign);
X = expr2;
}
expr(X) ::= expr(A) ADDEQ expr(B). /* a += b */
{
BINARY_EXPR(A,B,PEX_AddAssign);
X = expr2;
}
expr(X) ::= expr(A) SUBEQ expr(B). /* a -= b */
{
BINARY_EXPR(A,B,PEX_SubAssign);
X = expr2;
}
expr(X) ::= expr(A) MULEQ expr(B). /* a *= b */
{
BINARY_EXPR(A,B,PEX_MulAssign);
X = expr2;
}
expr(X) ::= expr(A) DIVEQ expr(B). /* a /= b */
{
BINARY_EXPR(A,B,PEX_DivAssign);
X = expr2;
}
expr(X) ::= expr(A) MODEQ expr(B). /* a %= b */
{
BINARY_EXPR(A,B,PEX_ModAssign);
X = expr2;
}
expr(X) ::= expr(A) LSHEQ expr(B). /* a <<= b */
{
BINARY_EXPR(A,B,PEX_LshAssign);
X = expr2;
}
expr(X) ::= expr(A) RSHEQ expr(B). /* a >>= b */
{
BINARY_EXPR(A,B,PEX_RshAssign);
X = expr2;
}
expr(X) ::= expr(A) URSHEQ expr(B). /* a >>>= b */
{
BINARY_EXPR(A,B,PEX_URshAssign);
X = expr2;
}
expr(X) ::= expr(A) ANDEQ expr(B). /* a &= b */
{
BINARY_EXPR(A,B,PEX_AndAssign);
X = expr2;
}
expr(X) ::= expr(A) OREQ expr(B). /* a |= b */
{
BINARY_EXPR(A,B,PEX_OrAssign);
X = expr2;
}
expr(X) ::= expr(A) XOREQ expr(B). /* a ^= b */
{
BINARY_EXPR(A,B,PEX_XorAssign);
X = expr2;
}
expr(X) ::= expr(A) SCOPE expr(B).
{
@ -1402,7 +1463,7 @@ statement(X) ::= expression_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/
statement(X) ::= selection_statement(X).
statement(X) ::= iteration_statement(X).
statement(X) ::= jump_statement(X).
statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ }
//statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ }
statement(X) ::= local_var(A) SEMICOLON. { X = A; /*X-overwrites-A*/ }
statement(X) ::= error SEMICOLON. { X = NULL; }
@ -1553,7 +1614,6 @@ for_init(X) ::= for_bump(A). { X = A /*X-overwrites-A*/; }
%type for_bump{ZCC_Statement *}
for_bump(X) ::= . { X = NULL; }
for_bump(X) ::= expression_statement(A). { X = A; /*X-overwrites-A*/ }
for_bump(X) ::= assign_statement(A). { X = A; /*X-overwrites-A*/ }
/*----- If Statements -----*/
@ -1614,28 +1674,19 @@ labeled_statement(X) ::= DEFAULT(T) COLON.
/*----- Assignment Statements -----*/
/* This is no longer being used, in favor of handling assignments as expressions, just like C and C++ do.
Keep this here in case some other parts require assignment syntax or Lua-style multi-assignments become a thing.
%type assign_statement{ZCC_AssignStmt *}
assign_statement(X) ::= expr_list(A) assign_op(OP) expr_list(B). [EQ]
assign_statement(X) ::= expr_list(A) EQ expr_list(B). [EQ]
{
NEW_AST_NODE(AssignStmt,stmt,OP);
stmt->AssignOp = OP.Int;
NEW_AST_NODE(AssignStmt,stmt,A);
stmt->AssignOp = ZCC_EQ;
stmt->Dests = A;
stmt->Sources = B;
X = stmt;
}
assign_op(X) ::= EQ(T). { X.Int = ZCC_EQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= MULEQ(T). { X.Int = ZCC_MULEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= DIVEQ(T). { X.Int = ZCC_DIVEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= MODEQ(T). { X.Int = ZCC_MODEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= ADDEQ(T). { X.Int = ZCC_ADDEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= SUBEQ(T). { X.Int = ZCC_SUBEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= LSHEQ(T). { X.Int = ZCC_LSHEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= RSHEQ(T). { X.Int = ZCC_RSHEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= ANDEQ(T). { X.Int = ZCC_ANDEQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= OREQ(T). { X.Int = ZCC_OREQ; X.SourceLoc = T.SourceLoc; }
assign_op(X) ::= XOREQ(T). { X.Int = ZCC_XOREQ; X.SourceLoc = T.SourceLoc; }
*/
/*----- Local Variable Definition "Statements" -----*/

View file

@ -2373,33 +2373,6 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
break;
}
case AST_AssignStmt:
{
auto assign = static_cast<ZCC_AssignStmt *>(ast);
switch (assign->AssignOp)
{
case ZCC_EQ:
// this ignores multi-assign statements (these should probably be disabled in the grammar.)
return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources));
case ZCC_MULEQ:
case ZCC_DIVEQ:
case ZCC_MODEQ:
case ZCC_ADDEQ:
case ZCC_SUBEQ:
case ZCC_LSHEQ:
case ZCC_RSHEQ:
case ZCC_ANDEQ:
case ZCC_OREQ:
case ZCC_XOREQ:
//break;
default:
Error(ast, "Invalid assign statement");
}
break;
}
case AST_FuncParm:
{
auto fparm = static_cast<ZCC_FuncParm *>(ast);
@ -2526,6 +2499,23 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
case PEX_NEQ:
return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right);
case PEX_Assign:
return new FxAssign(left, right);
/*
case ZCC_MULEQ:
case ZCC_DIVEQ:
case ZCC_MODEQ:
case ZCC_ADDEQ:
case ZCC_SUBEQ:
case ZCC_LSHEQ:
case ZCC_RSHEQ:
case ZCC_ANDEQ:
case ZCC_OREQ:
case ZCC_XOREQ:
//break;
default:
Error(ast, "Invalid assign statement");
*/
// todo: These do not have representations in DECORATE and no implementation exists yet.
case PEX_LTGTEQ:
@ -2537,6 +2527,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
// vector operations will be done later.
case PEX_CrossProduct:
case PEX_DotProduct:
default:
I_Error("Binary operator %d not implemented yet", op);
}

View file

@ -53,6 +53,19 @@ xx(BitXor, )
xx(BoolAnd, )
xx(BoolOr, )
xx(Assign, )
xx(AddAssign, )
xx(SubAssign, )
xx(MulAssign, )
xx(DivAssign, )
xx(ModAssign, )
xx(LshAssign, )
xx(RshAssign, )
xx(URshAssign, )
xx(AndAssign, )
xx(OrAssign, )
xx(XorAssign, )
xx(Scope, )
xx(Trinary, )

View file

@ -73,6 +73,7 @@ static void InitTokenMap()
TOKENDEF (TK_SubEq, ZCC_SUBEQ);
TOKENDEF (TK_LShiftEq, ZCC_LSHEQ);
TOKENDEF (TK_RShiftEq, ZCC_RSHEQ);
TOKENDEF (TK_URShiftEq, ZCC_URSHEQ);
TOKENDEF (TK_AndEq, ZCC_ANDEQ);
TOKENDEF (TK_OrEq, ZCC_OREQ);
TOKENDEF (TK_XorEq, ZCC_XOREQ);