mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 15:22:15 +00:00
- implemented local vector variables. Currently only the definition plus initial assignment works.
- removed all vector4 handling that had already been added, now that this type can no longer be defined.
This commit is contained in:
parent
f2f365bfef
commit
9400f97189
8 changed files with 278 additions and 44 deletions
|
@ -178,8 +178,8 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type, int count)
|
||||||
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false), Final(false), Target(false)
|
: RegNum(build->Registers[type].Get(count)), RegType(type), RegCount(count), Konst(false), Fixed(false), Final(false), Target(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ void ExpEmit::Free(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
if (!Fixed && !Konst && RegType <= REGT_TYPE)
|
if (!Fixed && !Konst && RegType <= REGT_TYPE)
|
||||||
{
|
{
|
||||||
build->Registers[RegType].Return(RegNum, 1);
|
build->Registers[RegType].Return(RegNum, RegCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
if (!Fixed && !Konst)
|
if (!Fixed && !Konst)
|
||||||
{
|
{
|
||||||
|
assert(RegCount == 1);
|
||||||
bool success = build->Registers[RegType].Reuse(RegNum);
|
bool success = build->Registers[RegType].Reuse(RegNum);
|
||||||
assert(success && "Attempt to reuse a register that is already in use");
|
assert(success && "Attempt to reuse a register that is already in use");
|
||||||
}
|
}
|
||||||
|
@ -434,6 +435,200 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
FxVectorInitializer::FxVectorInitializer(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc)
|
||||||
|
:FxExpression(EFX_VectorInitializer, sc)
|
||||||
|
{
|
||||||
|
xyz[0] = x;
|
||||||
|
xyz[1] = y;
|
||||||
|
xyz[2] = z;
|
||||||
|
isConst = false;
|
||||||
|
ValueType = TypeVoid; // we do not know yet
|
||||||
|
}
|
||||||
|
|
||||||
|
FxVectorInitializer::~FxVectorInitializer()
|
||||||
|
{
|
||||||
|
for (auto &a : xyz)
|
||||||
|
SAFE_DELETE(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
FxExpression *FxVectorInitializer::Resolve(FCompileContext&ctx)
|
||||||
|
{
|
||||||
|
bool fails = false;
|
||||||
|
|
||||||
|
for (auto &a : xyz)
|
||||||
|
{
|
||||||
|
if (a != nullptr)
|
||||||
|
{
|
||||||
|
a = a->Resolve(ctx);
|
||||||
|
if (a == nullptr) fails = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (a->ValueType != TypeVector2) // a vec3 may be initialized with (vec2, z)
|
||||||
|
{
|
||||||
|
a = new FxFloatCast(a);
|
||||||
|
a = a->Resolve(ctx);
|
||||||
|
fails |= (a == nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fails)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
// at this point there are three legal cases:
|
||||||
|
// * two floats = vector2
|
||||||
|
// * three floats = vector3
|
||||||
|
// * vector2 + float = vector3
|
||||||
|
if (xyz[0]->ValueType == TypeVector2)
|
||||||
|
{
|
||||||
|
if (xyz[1]->ValueType != TypeFloat64 || xyz[2] != nullptr)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Not a valid vector");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ValueType = TypeVector3;
|
||||||
|
if (xyz[0]->ExprType == EFX_VectorInitializer)
|
||||||
|
{
|
||||||
|
// If two vector initializers are nested, unnest them now.
|
||||||
|
auto vi = static_cast<FxVectorInitializer*>(xyz[0]);
|
||||||
|
xyz[2] = xyz[1];
|
||||||
|
xyz[1] = vi->xyz[1];
|
||||||
|
xyz[0] = vi->xyz[0];
|
||||||
|
delete vi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (xyz[0]->ValueType == TypeFloat64 && xyz[1]->ValueType == TypeFloat64)
|
||||||
|
{
|
||||||
|
ValueType = xyz[2] == nullptr ? TypeVector2 : TypeVector3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Not a valid vector");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if all elements are constant. If so this can be emitted as a constant vector.
|
||||||
|
isConst = true;
|
||||||
|
for (auto &a : xyz)
|
||||||
|
{
|
||||||
|
if (a != nullptr && !a->isConstant()) isConst = false;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ExpEmit EmitKonst(VMFunctionBuilder *build, ExpEmit &emit)
|
||||||
|
{
|
||||||
|
if (emit.Konst)
|
||||||
|
{
|
||||||
|
ExpEmit out(build, REGT_FLOAT);
|
||||||
|
build->Emit(OP_LKF, out.RegNum, emit.RegNum);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
return emit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpEmit FxVectorInitializer::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
// no const handling here. Ultimstely it's too rarely used (i.e. the only fully constant vector ever allocated in ZDoom is the 0-vector in a very few places)
|
||||||
|
// and the negatives (excessive allocation of float constants) outweigh the positives (saved a few instructions)
|
||||||
|
assert(xyz[0] != nullptr);
|
||||||
|
assert(xyz[1] != nullptr);
|
||||||
|
if (ValueType == TypeVector2)
|
||||||
|
{
|
||||||
|
ExpEmit xval = EmitKonst(build, xyz[0]->Emit(build));
|
||||||
|
ExpEmit yval = EmitKonst(build, xyz[1]->Emit(build));
|
||||||
|
assert(xval.RegType == REGT_FLOAT && yval.RegType == REGT_FLOAT);
|
||||||
|
if (yval.RegNum == xval.RegNum + 1)
|
||||||
|
{
|
||||||
|
// The results are already in two continuous registers so just return them as-is.
|
||||||
|
xval.RegCount++;
|
||||||
|
return xval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The values are not in continuous registers so they need to be copied together now.
|
||||||
|
ExpEmit out(build, REGT_FLOAT, 2);
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum, xval.RegNum);
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum + 1, yval.RegNum);
|
||||||
|
xval.Free(build);
|
||||||
|
yval.Free(build);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (xyz[0]->ValueType == TypeVector2) // vec2+float
|
||||||
|
{
|
||||||
|
ExpEmit xyval = xyz[0]->Emit(build);
|
||||||
|
ExpEmit zval = EmitKonst(build, xyz[1]->Emit(build));
|
||||||
|
assert(xyval.RegType == REGT_FLOAT && xyval.RegCount == 2 && zval.RegType == REGT_FLOAT);
|
||||||
|
if (zval.RegNum == xyval.RegNum + 2)
|
||||||
|
{
|
||||||
|
// The results are already in three continuous registers so just return them as-is.
|
||||||
|
xyval.RegCount++;
|
||||||
|
return xyval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The values are not in continuous registers so they need to be copied together now.
|
||||||
|
ExpEmit out(build, REGT_FLOAT, 3);
|
||||||
|
build->Emit(OP_MOVEV2, out.RegNum, xyval.RegNum);
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum);
|
||||||
|
xyval.Free(build);
|
||||||
|
zval.Free(build);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // 3*float
|
||||||
|
{
|
||||||
|
assert(xyz[2] != nullptr);
|
||||||
|
ExpEmit xval = EmitKonst(build, xyz[0]->Emit(build));
|
||||||
|
ExpEmit yval = EmitKonst(build, xyz[1]->Emit(build));
|
||||||
|
ExpEmit zval = EmitKonst(build, xyz[2]->Emit(build));
|
||||||
|
assert(xval.RegType == REGT_FLOAT && yval.RegType == REGT_FLOAT && zval.RegType == REGT_FLOAT);
|
||||||
|
if (yval.RegNum == xval.RegNum + 1 && zval.RegNum == xval.RegNum + 2)
|
||||||
|
{
|
||||||
|
// The results are already in three continuous registers so just return them as-is.
|
||||||
|
xval.RegCount += 2;
|
||||||
|
return xval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The values are not in continuous registers so they need to be copied together now.
|
||||||
|
ExpEmit out(build, REGT_FLOAT, 3);
|
||||||
|
//Try to optimize a bit...
|
||||||
|
if (yval.RegNum == xval.RegNum + 1)
|
||||||
|
{
|
||||||
|
build->Emit(OP_MOVEV2, out.RegNum, xval.RegNum);
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum);
|
||||||
|
}
|
||||||
|
else if (zval.RegNum == yval.RegNum + 1)
|
||||||
|
{
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum, xval.RegNum);
|
||||||
|
build->Emit(OP_MOVEV2, out.RegNum+1, yval.RegNum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum, xval.RegNum);
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum + 1, yval.RegNum);
|
||||||
|
build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum);
|
||||||
|
}
|
||||||
|
xval.Free(build);
|
||||||
|
yval.Free(build);
|
||||||
|
zval.Free(build);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
FxBoolCast::FxBoolCast(FxExpression *x, bool needvalue)
|
FxBoolCast::FxBoolCast(FxExpression *x, bool needvalue)
|
||||||
: FxExpression(EFX_BoolCast, x->ScriptPosition)
|
: FxExpression(EFX_BoolCast, x->ScriptPosition)
|
||||||
{
|
{
|
||||||
|
@ -4613,7 +4808,7 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
|
|
||||||
int offsetreg = build->GetConstantInt((int)membervar->Offset);
|
int offsetreg = build->GetConstantInt((int)membervar->Offset);
|
||||||
ExpEmit loc(build, membervar->Type->GetRegType());
|
ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount());
|
||||||
|
|
||||||
if (membervar->BitValue == -1)
|
if (membervar->BitValue == -1)
|
||||||
{
|
{
|
||||||
|
@ -7118,6 +7313,7 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name,
|
||||||
ValueType = type;
|
ValueType = type;
|
||||||
VarFlags = varflags;
|
VarFlags = varflags;
|
||||||
Name = name;
|
Name = name;
|
||||||
|
RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1;
|
||||||
Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false);
|
Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7139,7 +7335,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
if (Init == nullptr)
|
if (Init == nullptr)
|
||||||
{
|
{
|
||||||
RegNum = build->Registers[ValueType->GetRegType()].Get(1);
|
RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7188,5 +7384,5 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// Release the register after the containing block gets closed
|
// Release the register after the containing block gets closed
|
||||||
assert(RegNum != -1);
|
assert(RegNum != -1);
|
||||||
build->Registers[ValueType->GetRegType()].Return(RegNum, 1);
|
build->Registers[ValueType->GetRegType()].Return(RegNum, RegCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,13 +193,13 @@ struct ExpVal
|
||||||
|
|
||||||
struct ExpEmit
|
struct ExpEmit
|
||||||
{
|
{
|
||||||
ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false), Target(false) {}
|
ExpEmit() : RegNum(0), RegType(REGT_NIL), RegCount(1), Konst(false), Fixed(false), Final(false), Target(false) {}
|
||||||
ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false), Target(false) {}
|
ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), RegCount(1), Konst(konst), Fixed(fixed), Final(false), Target(false) {}
|
||||||
ExpEmit(VMFunctionBuilder *build, int type);
|
ExpEmit(VMFunctionBuilder *build, int type, int count = 1);
|
||||||
void Free(VMFunctionBuilder *build);
|
void Free(VMFunctionBuilder *build);
|
||||||
void Reuse(VMFunctionBuilder *build);
|
void Reuse(VMFunctionBuilder *build);
|
||||||
|
|
||||||
BYTE RegNum, RegType, Konst:1, Fixed:1, Final:1, Target:1;
|
BYTE RegNum, RegType, RegCount, Konst:1, Fixed:1, Final:1, Target:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EFxType
|
enum EFxType
|
||||||
|
@ -264,6 +264,7 @@ enum EFxType
|
||||||
EFX_LocalVariableDeclaration,
|
EFX_LocalVariableDeclaration,
|
||||||
EFX_SwitchStatement,
|
EFX_SwitchStatement,
|
||||||
EFX_CaseStatement,
|
EFX_CaseStatement,
|
||||||
|
EFX_VectorInitializer,
|
||||||
EFX_COUNT
|
EFX_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -449,6 +450,25 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxVectorInitializer : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression *xyz[3];
|
||||||
|
bool isConst; // gets set to true if all element are const
|
||||||
|
|
||||||
|
public:
|
||||||
|
FxVectorInitializer(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc);
|
||||||
|
~FxVectorInitializer();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -1561,6 +1581,7 @@ class FxLocalVariableDeclaration : public FxExpression
|
||||||
FName Name;
|
FName Name;
|
||||||
FxExpression *Init;
|
FxExpression *Init;
|
||||||
int VarFlags;
|
int VarFlags;
|
||||||
|
int RegCount;
|
||||||
public:
|
public:
|
||||||
int RegNum = -1;
|
int RegNum = -1;
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ enum
|
||||||
REGT_MULTIREG = 8, // (e.g. a vector)
|
REGT_MULTIREG = 8, // (e.g. a vector)
|
||||||
REGT_ADDROF = 32, // used with PARAM: pass address of this register
|
REGT_ADDROF = 32, // used with PARAM: pass address of this register
|
||||||
|
|
||||||
REGT_NIL = 255 // parameter was omitted
|
REGT_NIL = 128 // parameter was omitted
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RET_FINAL (0x80) // Used with RET and RETI in the destination slot: this is the final return value
|
#define RET_FINAL (0x80) // Used with RET and RETI in the destination slot: this is the final return value
|
||||||
|
|
|
@ -52,7 +52,6 @@ static const char *BuiltInTypeNames[] =
|
||||||
"string",
|
"string",
|
||||||
"vector2",
|
"vector2",
|
||||||
"vector3",
|
"vector3",
|
||||||
"vector4",
|
|
||||||
"name",
|
"name",
|
||||||
"color",
|
"color",
|
||||||
"state",
|
"state",
|
||||||
|
@ -622,6 +621,16 @@ static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node)
|
||||||
|
{
|
||||||
|
ZCC_VectorInitializer *enode = (ZCC_VectorInitializer *)node;
|
||||||
|
OpenExprType(out, enode->Operation);
|
||||||
|
PrintNodes(out, enode->X);
|
||||||
|
PrintNodes(out, enode->Y);
|
||||||
|
PrintNodes(out, enode->Z);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
|
||||||
static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node)
|
static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_FuncParm *pnode = (ZCC_FuncParm *)node;
|
ZCC_FuncParm *pnode = (ZCC_FuncParm *)node;
|
||||||
|
@ -889,7 +898,8 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
|
||||||
PrintFuncDeclarator,
|
PrintFuncDeclarator,
|
||||||
PrintDefault,
|
PrintDefault,
|
||||||
PrintFlagStmt,
|
PrintFlagStmt,
|
||||||
PrintPropertyStmt
|
PrintPropertyStmt,
|
||||||
|
PrintVectorInitializer,
|
||||||
};
|
};
|
||||||
|
|
||||||
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
||||||
|
|
|
@ -945,6 +945,7 @@ func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_O
|
||||||
|
|
||||||
%type expr{ZCC_Expression *}
|
%type expr{ZCC_Expression *}
|
||||||
%type primary{ZCC_Expression *}
|
%type primary{ZCC_Expression *}
|
||||||
|
%type vectorinit{ZCC_VectorInitializer*}
|
||||||
%type unary_expr{ZCC_Expression *}
|
%type unary_expr{ZCC_Expression *}
|
||||||
%type constant{ZCC_ExprConstant *}
|
%type constant{ZCC_ExprConstant *}
|
||||||
|
|
||||||
|
@ -966,29 +967,7 @@ primary(X) ::= SUPER(T).
|
||||||
X = expr;
|
X = expr;
|
||||||
}
|
}
|
||||||
primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ }
|
primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ }
|
||||||
|
primary(X) ::= vectorinit(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(XX) ::= 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;
|
|
||||||
XX = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
primary(X) ::= LPAREN expr(A) RPAREN.
|
primary(X) ::= LPAREN expr(A) RPAREN.
|
||||||
{
|
{
|
||||||
|
@ -1039,6 +1018,30 @@ primary(X) ::= SCOPE primary(B).
|
||||||
X = expr2;
|
X = expr2;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
vectorinit(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. [DOT]
|
||||||
|
{
|
||||||
|
NEW_AST_NODE(VectorInitializer, expr, A);
|
||||||
|
expr->Operation = PEX_Vector;
|
||||||
|
expr->Type = TypeVector3;
|
||||||
|
expr->X = A;
|
||||||
|
expr->Y = B;
|
||||||
|
expr->Z = C;
|
||||||
|
XX = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vectorinit(XX) ::= LPAREN expr(A) COMMA expr(B) RPAREN. [DOT]
|
||||||
|
{
|
||||||
|
NEW_AST_NODE(VectorInitializer, expr, A);
|
||||||
|
expr->Operation = PEX_Vector;
|
||||||
|
expr->Type = TypeVector2;
|
||||||
|
expr->X = A;
|
||||||
|
expr->Y = B;
|
||||||
|
expr->Z = nullptr;
|
||||||
|
XX = expr;
|
||||||
|
}
|
||||||
|
|
||||||
/*----- Unary Expressions -----*/
|
/*----- Unary Expressions -----*/
|
||||||
|
|
||||||
unary_expr(X) ::= primary(X).
|
unary_expr(X) ::= primary(X).
|
||||||
|
|
|
@ -1387,11 +1387,6 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
||||||
retval = TypeVector3;
|
retval = TypeVector3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZCC_Vector4:
|
|
||||||
// This has almost no use, so we really shouldn't bother.
|
|
||||||
Error(field, "vector<4> not implemented for %s", name.GetChars());
|
|
||||||
return TypeError;
|
|
||||||
|
|
||||||
case ZCC_State:
|
case ZCC_State:
|
||||||
retval = TypeState;
|
retval = TypeState;
|
||||||
break;
|
break;
|
||||||
|
@ -2710,6 +2705,15 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
return new FxConditional(condition, left, right);
|
return new FxConditional(condition, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_VectorInitializer:
|
||||||
|
{
|
||||||
|
auto vecini = static_cast<ZCC_VectorInitializer *>(ast);
|
||||||
|
auto xx = ConvertNode(vecini->X);
|
||||||
|
auto yy = ConvertNode(vecini->Y);
|
||||||
|
auto zz = ConvertNode(vecini->Z);
|
||||||
|
return new FxVectorInitializer(xx, yy, zz, *ast);
|
||||||
|
}
|
||||||
|
|
||||||
case AST_LocalVarStmt:
|
case AST_LocalVarStmt:
|
||||||
{
|
{
|
||||||
auto loc = static_cast<ZCC_LocalVarStmt *>(ast);
|
auto loc = static_cast<ZCC_LocalVarStmt *>(ast);
|
||||||
|
|
|
@ -301,7 +301,8 @@ static void DoParse(int lumpnum)
|
||||||
|
|
||||||
parser = ZCCParseAlloc(malloc);
|
parser = ZCCParseAlloc(malloc);
|
||||||
ZCCParseState state;
|
ZCCParseState state;
|
||||||
#if 0 // this costs a lot of time and should only be activated when it's really needed.
|
//#define TRACE
|
||||||
|
#ifdef TRACE // this costs a lot of time and should only be activated when it's really needed.
|
||||||
FILE *f = fopen("trace.txt", "w");
|
FILE *f = fopen("trace.txt", "w");
|
||||||
char prompt = '\0';
|
char prompt = '\0';
|
||||||
ZCCParseTrace(f, &prompt);
|
ZCCParseTrace(f, &prompt);
|
||||||
|
@ -335,7 +336,7 @@ static void DoParse(int lumpnum)
|
||||||
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
|
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#ifdef TRACE
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
|
@ -120,7 +120,6 @@ enum EZCCBuiltinType
|
||||||
ZCC_String,
|
ZCC_String,
|
||||||
ZCC_Vector2,
|
ZCC_Vector2,
|
||||||
ZCC_Vector3,
|
ZCC_Vector3,
|
||||||
ZCC_Vector4,
|
|
||||||
ZCC_Name,
|
ZCC_Name,
|
||||||
|
|
||||||
ZCC_Color, // special types for ZDoom.
|
ZCC_Color, // special types for ZDoom.
|
||||||
|
|
Loading…
Reference in a new issue