From b5222f08e8ad25064750f033150552948a494988 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 29 Oct 2016 10:16:00 +0200 Subject: [PATCH] - implemented dot and cross products (not that I'd ever expect these to become useful in a game like Doom...) --- src/scripting/codegeneration/codegen.cpp | 70 ++++++++++++++++++++++++ src/scripting/codegeneration/codegen.h | 21 +++++++ src/scripting/zscript/zcc_compile.cpp | 9 ++- 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 4c048c452..039e428ff 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3438,6 +3438,76 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) // //========================================================================== +FxDotCross::FxDotCross(int o, FxExpression *l, FxExpression *r) + : FxExpression(EFX_DotCross, l->ScriptPosition) +{ + Operator = o; + left = l; + right = r; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxDotCross::~FxDotCross() +{ + SAFE_DELETE(left); + SAFE_DELETE(right); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxDotCross::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + RESOLVE(left, ctx); + RESOLVE(right, ctx); + ABORT(right && left); + + if (!left->IsVector() || left->ValueType != right->ValueType || (Operator == TK_Cross && left->ValueType != TypeVector3)) + { + ScriptPosition.Message(MSG_ERROR, "Incompatible operants for %sproduct", Operator == TK_Cross ? "cross-" : "dot-"); + delete this; + return nullptr; + } + ValueType = Operator == TK_Cross ? (PType*)TypeVector3 : TypeFloat64; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxDotCross::Emit(VMFunctionBuilder *build) +{ + // This is not the "right" way to do these, but it works for now. + // (Problem: No information sharing is done between nodes to reduce the + // code size if you have something like a1 && a2 && a3 && ... && an.) + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + ExpEmit op1 = left->Emit(build); + ExpEmit op2 = right->Emit(build); + int op = Operator == TK_Cross ? OP_CROSSV_RR : left->ValueType == TypeVector3 ? OP_DOTV3_RR : OP_DOTV2_RR; + build->Emit(op, to.RegNum, op1.RegNum, op2.RegNum); + op1.Free(build); + op2.Free(build); + return to; +} + +//========================================================================== +// +// +// +//========================================================================== + FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f) : FxExpression(EFX_Conditional, c->ScriptPosition) { diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 01d63eaf8..570575bb9 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -228,6 +228,7 @@ enum EFxType EFX_AssignSelf, EFX_Binary, // one token fits all, the operator is enough to distinguish them. EFX_BinaryLogical, + EFX_DotCross, EFX_Conditional, EFX_Abs, EFX_ATan2, @@ -905,6 +906,26 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxBinaryLogical +// +//========================================================================== + +class FxDotCross : public FxExpression +{ +public: + int Operator; + FxExpression *left; + FxExpression *right; + + FxDotCross(int, FxExpression*, FxExpression*); + ~FxDotCross(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxConditional diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f1a06d584..294763f9b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2680,14 +2680,13 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case PEX_ArrayAccess: return new FxArrayElement(left, right); - // todo: These do not have representations in DECORATE and no implementation exists yet. - case PEX_Concat: - case PEX_Is: - - // vector operations will be done later. case PEX_CrossProduct: case PEX_DotProduct: + return new FxDotCross(tok, left, right); + // todo: These do not have representations in DECORATE and no implementation exists yet. + case PEX_Concat: + case PEX_Is: default: I_Error("Binary operator %d not implemented yet", op);