Represent enumerations as constant definitions

- Instead of representating enumeration values with a special node type,
  use the same ZCC_ConstantDef nodes that const_def produces. These are
  created at the same scope as the ZCC_Enum, rather than being contained
  entirely within it. To mark the end of enums for a single instance of
  ZCC_Enum, a ZCC_EnumTerminator node is now appended to the chain of
  ZCC_ConstantDefs.
This commit is contained in:
Randy Heit 2013-09-12 21:39:10 -05:00
parent d5fa550118
commit af8e0f2ba6
3 changed files with 93 additions and 44 deletions

View file

@ -301,16 +301,13 @@ static void PrintEnum(FLispString &out, ZCC_TreeNode *node)
out.Open("enum");
out.AddName(enode->EnumName);
PrintBuiltInType(out, enode->EnumType);
PrintNodes(out, enode->Elements, false, true);
out.Add(enode->Elements == NULL ? "nil" : "...", 3);
out.Close();
}
static void PrintEnumNode(FLispString &out, ZCC_TreeNode *node)
static void PrintEnumTerminator(FLispString &out, ZCC_TreeNode *node)
{
ZCC_EnumNode *enode = (ZCC_EnumNode *)node;
out.Open("enum-node");
out.AddName(enode->ElemName);
PrintNodes(out, enode->ElemValue, false);
out.Open("enum-term");
out.Close();
}
@ -802,7 +799,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
PrintClass,
PrintStruct,
PrintEnum,
PrintEnumNode,
PrintEnumTerminator,
PrintStates,
PrintStatePart,
PrintStateLabel,

View file

@ -33,6 +33,16 @@ static void SetNodeLine(ZCC_TreeNode *name, int line)
// If a is non-null, appends b to a. Otherwise, sets a to b.
#define SAFE_APPEND(a,b) \
if (a == NULL) a = b; else a->AppendSibling(b);
#define UNARY_EXPR(X,T) NEW_AST_NODE(ExprUnary, expr, X); expr->Operation = T; expr->Operand = X; expr->Type = NULL
#define BINARY_EXPR(X,Y,T) NEW_AST_NODE(ExprBinary, expr, X); expr->Operation = T; expr->Type = NULL; expr->Left = X; expr->Right = Y
#define NEW_INTCONST_NODE(name,type,val,tok) \
NEW_AST_NODE(ExprConstant, name, tok); \
name->Operation = PEX_ConstValue; \
name->Type = type; \
name->IntVal = val
}
%token_prefix ZCC_
@ -237,20 +247,81 @@ struct_body(X) ::= struct_member(A) struct_body(B). { X = A; A->AppendSibling(B
struct_member(X) ::= declarator_no_fun(A). { X = A; }
struct_member(X) ::= enum_def(A). { X = A; }
/*----- Constant Definition ------*/
/* Like UnrealScript, a constant's type is implied by its value's type. */
const_def(X) ::= CONST(T) IDENTIFIER(A) EQ expr(B) SEMICOLON.
{
NEW_AST_NODE(ConstantDef,def,T);
def->Name = A.Name();
def->Value = B;
def->Symbol = NULL;
X = def;
}
/*----- Enum Definition -----*/
/* Enumerators are lists of named integers. */
%type enum_list {ZCC_EnumNode *}
%type opt_enum_list {ZCC_EnumNode *}
%type enumerator {ZCC_EnumNode *}
%type enum_list {ZCC_ConstantDef *}
%type opt_enum_list {ZCC_ConstantDef *}
%type enumerator {ZCC_ConstantDef *}
enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRACE opt_semicolon.
enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRACE(U) opt_semicolon.
{
NEW_AST_NODE(Enum,def,T);
def->EnumName = A.Name();
def->EnumType = (EZCCBuiltinType)B.Int;
def->Elements = C;
// If the first element does not have an explicit value, make it 0.
if (C != NULL)
{
ZCC_ConstantDef *node = C, *prev = node;
ZCC_ExprConstant *one = NULL;
if (node->Value == NULL)
{
NEW_INTCONST_NODE(zero, TypeSInt32, 0, C);
node->Value = zero;
}
for (node = static_cast<ZCC_ConstantDef *>(node->SiblingNext);
node != C;
prev = node, node = static_cast<ZCC_ConstantDef *>(node->SiblingNext))
{
assert(node->NodeType == AST_ConstantDef);
// Leave explicit values alone.
if (node->Value != NULL)
{
continue;
}
// Compute implicit values by adding one to the preceding value.
assert(prev->Value != NULL);
// If the preceding node is a constant, then we can do this now.
if (prev->Value->Operation == PEX_ConstValue && prev->Value->Type->IsA(RUNTIME_CLASS(PInt)))
{
NEW_INTCONST_NODE(cval, prev->Value->Type, static_cast<ZCC_ExprConstant *>(prev->Value)->IntVal + 1, node);
node->Value = cval;
}
// Otherwise, create a new addition expression to add 1.
else
{
if (one == NULL)
{ // Use a single 1 node for the right-hand side of the addition.
NEW_INTCONST_NODE(cval, TypeSInt32, 1, T);
one = cval;
}
BINARY_EXPR(prev->Value, one, PEX_Add);
node->Value = expr;
}
}
// Add a new terminating node, to indicate that the ConstantDefs for this enum are done.
NEW_AST_NODE(EnumTerminator,term,U);
C->AppendSibling(term);
}
if (C != NULL)
{
def->AppendSibling(C);
}
X = def;
}
@ -266,16 +337,18 @@ opt_enum_list(X) ::= enum_list(A) opt_comma. { X = A; }
enumerator(X) ::= IDENTIFIER(A).
{
NEW_AST_NODE(EnumNode,node,A);
node->ElemName = A.Name();
node->ElemValue = NULL;
NEW_AST_NODE(ConstantDef,node,A);
node->Name = A.Name();
node->Value = NULL;
node->Symbol = NULL;
X = node;
}
enumerator(X) ::= IDENTIFIER(A) EQ expr(B). /* Expression must be constant. */
{
NEW_AST_NODE(EnumNode,node,A);
node->ElemName = A.Name();
node->ElemValue = B;
NEW_AST_NODE(ConstantDef,node,A);
node->Name = A.Name();
node->Value = B;
node->Symbol = NULL;
X = node;
}
@ -711,15 +784,6 @@ func_param_flags(X) ::= func_param_flags(A) IN(T). { X.Int = A.Int | ZCC_In; X
func_param_flags(X) ::= func_param_flags(A) OUT(T). { X.Int = A.Int | ZCC_Out; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_Optional; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
/* Like UnrealScript, a constant's type is implied by its value's type. */
const_def(X) ::= CONST(T) IDENTIFIER(A) EQ expr(B) SEMICOLON.
{
NEW_AST_NODE(ConstantDef,def,T);
def->Name = A.Name();
def->Value = B;
X = def;
}
/************ Expressions ************/
/* We use default to access a class's default instance. */
@ -731,11 +795,6 @@ const_def(X) ::= CONST(T) IDENTIFIER(A) EQ expr(B) SEMICOLON.
%type unary_expr{ZCC_Expression *}
%type constant{ZCC_ExprConstant *}
%include {
#define UNARY_EXPR(X,T) NEW_AST_NODE(ExprUnary, expr, X); expr->Operation = T; expr->Operand = X; expr->Type = NULL
#define BINARY_EXPR(X,Y,T) NEW_AST_NODE(ExprBinary, expr, X); expr->Operation = T; expr->Type = NULL; expr->Left = X; expr->Right = Y
}
/*----- Primary Expressions -----*/
primary(X) ::= IDENTIFIER(A).
@ -1119,18 +1178,12 @@ constant(X) ::= string_constant(A).
}
constant(X) ::= INTCONST(A).
{
NEW_AST_NODE(ExprConstant, intconst, A);
intconst->Operation = PEX_ConstValue;
intconst->Type = TypeSInt32;
intconst->IntVal = A.Int;
NEW_INTCONST_NODE(intconst, TypeSInt32, A.Int, A);
X = intconst;
}
constant(X) ::= UINTCONST(A).
{
NEW_AST_NODE(ExprConstant, intconst, A);
intconst->Operation = PEX_ConstValue;
intconst->Type = TypeUInt32;
intconst->IntVal = A.Int;
NEW_INTCONST_NODE(intconst, TypeUInt32, A.Int, A);
X = intconst;
}
constant(X) ::= FLOATCONST(A).

View file

@ -57,7 +57,7 @@ enum EZCCTreeNodeType
AST_Class,
AST_Struct,
AST_Enum,
AST_EnumNode,
AST_EnumTerminator,
AST_States,
AST_StatePart,
AST_StateLabel,
@ -251,13 +251,11 @@ struct ZCC_Enum : ZCC_TreeNode
{
ENamedName EnumName;
EZCCBuiltinType EnumType;
struct ZCC_EnumNode *Elements;
struct ZCC_ConstantDef *Elements;
};
struct ZCC_EnumNode : ZCC_TreeNode
struct ZCC_EnumTerminator : ZCC_TreeNode
{
ENamedName ElemName;
ZCC_TreeNode *ElemValue;
};
struct ZCC_States : ZCC_TreeNode
@ -478,6 +476,7 @@ struct ZCC_ConstantDef : ZCC_TreeNode
{
ENamedName Name;
ZCC_Expression *Value;
PSymbolConst *Symbol;
};
struct ZCC_Declarator : ZCC_TreeNode