diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 3f5b734c4..603cb85d7 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -628,6 +628,8 @@ void PType::StaticInit() TypeVector3->AddField(NAME_X, TypeFloat64); TypeVector3->AddField(NAME_Y, TypeFloat64); TypeVector3->AddField(NAME_Z, TypeFloat64); + // allow accessing xy as a vector2. This is marked native because it's not supposed to be serialized. + TypeVector3->Symbols.AddSymbol(new PField(NAME_XY, TypeVector2, VARF_Native, 0)); TypeTable.AddType(TypeVector3); diff --git a/src/namedef.h b/src/namedef.h index 3587643e8..ea4a7b890 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -313,6 +313,7 @@ xx(WaterLevel) xx(X) xx(Y) xx(Z) +xx(XY) xx(MomX) xx(MomY) xx(MomZ) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 8fbb28ef5..bc0a4b2e2 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -124,7 +124,8 @@ std2: 'sound' { RET(TK_Sound); } 'state' { RET(TK_State); } 'color' { RET(TK_Color); } - 'vector' { RET(TK_Vector); } + 'vector2' { RET(TK_Vector2); } + 'vector3' { RET(TK_Vector3); } 'map' { RET(TK_Map); } 'array' { RET(TK_Array); } 'in' { RET(TK_In); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 7d9f81e9b..2b93c9ac2 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -113,7 +113,8 @@ xx(TK_Include, "'include'") xx(TK_Is, "'is'") xx(TK_Replaces, "'replaces'") -xx(TK_Vector, "'vector'") +xx(TK_Vector2, "'vector2'") +xx(TK_Vector3, "'vector3'") xx(TK_Map, "'map'") xx(TK_Array, "'array'") xx(TK_In, "'in'") diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 0cf061bef..3f70799ec 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -656,7 +656,8 @@ type_name1(X) ::= int_type(X). type_name1(X) ::= FLOAT(T). { X.Int = ZCC_FloatAuto; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= DOUBLE(T). { X.Int = ZCC_Float64; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= STRING(T). { X.Int = ZCC_String; X.SourceLoc = T.SourceLoc; } -type_name1(X) ::= VECTOR(T) vector_size(A). { X.Int = A.Int; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= VECTOR2(T). { X.Int = ZCC_Vector2; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= VECTOR3(T). { X.Int = ZCC_Vector3; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= NAME(T). { X.Int = ZCC_Name; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= SOUND(T). { X.Int = ZCC_Sound; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= STATE(T). { X.Int = ZCC_State; X.SourceLoc = T.SourceLoc; } @@ -686,30 +687,10 @@ type_name(X) ::= DOT dottable_id(A). X = type; } -/* Vectors can be 2, 3, or 4 entries long. Default is a 3D vector. - * (Well, actually, I'm not sure if 4D ones are going to happen - * straight away.) - */ -%token_class intconst INTCONST|UINTCONST. -vector_size(X) ::= . { X.Int = ZCC_Vector3; X.SourceLoc = stat->sc->GetMessageLine(); } -vector_size(X) ::= LT intconst(A) GT. -{ - if (A.Int >= 2 && A.Int <= 4) - { - X.Int = ZCC_Vector2 + A.Int - 2; - } - else - { - X.Int = ZCC_Vector3; - stat->sc->ScriptMessage("Invalid vector size %d\n", A.Int); - } - X.SourceLoc = A.SourceLoc; -} - /* Type names can also be used as identifiers in contexts where type names * are not normally allowed. */ %fallback IDENTIFIER - SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR NAME MAP ARRAY VOID. + SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 NAME MAP ARRAY VOID. /* Aggregate types */ %type aggregate_type {ZCC_Type *} @@ -986,6 +967,29 @@ primary(X) ::= SUPER(T). } primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ } +primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. +{ + NEW_AST_NODE(VectorInitializer, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector3; + expr->X = A; + expr->Y = B; + expr->Z = C; + XX = expr; +} + + +primary(X) ::= LPAREN expr(A) COMMA expr(B) RPAREN. +{ + NEW_AST_NODE(VectorInitializer, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector2; + expr->X = A; + expr->Y = B; + expr->Z = nullptr; + X = expr; +} + primary(X) ::= LPAREN expr(A) RPAREN. { X = A; /*X-overwrites-A*/ diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index bbf99189c..b565c00fb 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -9,6 +9,7 @@ xx(FuncCall, '(') xx(ArrayAccess, TK_Array) xx(MemberAccess, '.') xx(TypeRef, TK_Class) +xx(Vector, TK_Vector2) xx(PostInc, TK_Incr) xx(PostDec, TK_Decr) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 8ebc86167..ef4a2ac41 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -141,7 +141,8 @@ static void InitTokenMap() TOKENDEF2(TK_Float, ZCC_FLOAT, NAME_Float); TOKENDEF2(TK_Double, ZCC_DOUBLE, NAME_Double); TOKENDEF2(TK_String, ZCC_STRING, NAME_String); - TOKENDEF2(TK_Vector, ZCC_VECTOR, NAME_Vector); + TOKENDEF2(TK_Vector2, ZCC_VECTOR2, NAME_Vector2); + TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3); TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name); TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map); TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 7ba48d711..dafdb93e5 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -98,6 +98,7 @@ enum EZCCTreeNodeType AST_Default, AST_FlagStmt, AST_PropertyStmt, + AST_VectorInitializer, NUM_AST_NODE_TYPES }; @@ -385,6 +386,11 @@ struct ZCC_ExprTrinary : ZCC_Expression ZCC_Expression *Right; }; +struct ZCC_VectorInitializer : ZCC_Expression +{ + ZCC_Expression *X, *Y, *Z; +}; + struct ZCC_Statement : ZCC_TreeNode { };