From f720073b317c45d1da8f1cca2ad34345c551b12f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 23 Jan 2017 01:37:43 +0100 Subject: [PATCH] - removed all code that was only there to implement the broken Simplifier that just got removed. --- src/CMakeLists.txt | 1 - src/dobjtype.cpp | 153 -------- src/dobjtype.h | 61 --- src/scripting/zscript/ast.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 382 +------------------ src/scripting/zscript/zcc_compile.h | 16 +- src/scripting/zscript/zcc_expr.cpp | 530 -------------------------- src/scripting/zscript/zcc_parser.cpp | 3 - src/scripting/zscript/zcc_parser.h | 39 -- 9 files changed, 17 insertions(+), 1170 deletions(-) delete mode 100644 src/scripting/zscript/zcc_expr.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 870275324..55d728097 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1211,7 +1211,6 @@ set (PCH_SOURCES scripting/vm/vmframe.cpp scripting/zscript/ast.cpp scripting/zscript/zcc_compile.cpp - scripting/zscript/zcc_expr.cpp scripting/zscript/zcc_parser.cpp sfmt/SFMT.cpp ) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 2d41a57e3..c3ab87e11 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -240,159 +240,6 @@ size_t PType::PropagateMark() return marked + Super::PropagateMark(); } -//========================================================================== -// -// PType :: AddConversion -// -//========================================================================== - -bool PType::AddConversion(PType *target, void (*convertconst)(ZCC_ExprConstant *, class FSharedStringArena &)) -{ - // Make sure a conversion hasn't already been registered - for (unsigned i = 0; i < Conversions.Size(); ++i) - { - if (Conversions[i].TargetType == target) - return false; - } - Conversions.Push(Conversion(target, convertconst)); - return true; -} - -//========================================================================== -// -// PType :: FindConversion -// -// Returns <0 if there is no path to target. Otherwise, returns the distance -// to target and fills slots (if non-NULL) with the necessary conversions -// to get there. A result of 0 means this is the target. -// -//========================================================================== - -int PType::FindConversion(PType *target, const PType::Conversion **slots, int numslots) -{ - if (this == target) - { - return 0; - } - // The queue is implemented as a ring buffer - VisitQueue queue; - VisitedNodeSet visited; - - // Use a breadth-first search to find the shortest path to the target. - MarkPred(NULL, -1, -1); - queue.Push(this); - visited.Insert(this); - while (!queue.IsEmpty()) - { - PType *t = queue.Pop(); - if (t == target) - { // found it - if (slots != NULL) - { - if (t->Distance >= numslots) - { // Distance is too far for the output - return -2; - } - t->FillConversionPath(slots); - } - return t->Distance + 1; - } - for (unsigned i = 0; i < t->Conversions.Size(); ++i) - { - PType *succ = t->Conversions[i].TargetType; - if (!visited.Check(succ)) - { - succ->MarkPred(t, i, t->Distance + 1); - visited.Insert(succ); - queue.Push(succ); - } - } - } - return -1; -} - -//========================================================================== -// -// PType :: FillConversionPath -// -// Traces backwards from the target type to the original type and fills in -// the conversions necessary to get between them. slots must point to an -// array large enough to contain the entire path. -// -//========================================================================== - -void PType::FillConversionPath(const PType::Conversion **slots) -{ - for (PType *node = this; node->Distance >= 0; node = node->PredType) - { - assert(node->PredType != NULL); - slots[node->Distance] = &node->PredType->Conversions[node->PredConv]; - } -} - -//========================================================================== -// -// PType :: VisitQueue :: Push -// -//========================================================================== - -void PType::VisitQueue::Push(PType *type) -{ - Queue[In] = type; - Advance(In); - assert(!IsEmpty() && "Queue overflowed"); -} - -//========================================================================== -// -// PType :: VisitQueue :: Pop -// -//========================================================================== - -PType *PType::VisitQueue::Pop() -{ - if (IsEmpty()) - { - return NULL; - } - PType *node = Queue[Out]; - Advance(Out); - return node; -} - -//========================================================================== -// -// PType :: VisitedNodeSet :: Insert -// -//========================================================================== - -void PType::VisitedNodeSet::Insert(PType *node) -{ - assert(!Check(node) && "Node was already inserted"); - size_t buck = Hash(node) & (countof(Buckets) - 1); - node->VisitNext = Buckets[buck]; - Buckets[buck] = node; -} - -//========================================================================== -// -// PType :: VisitedNodeSet :: Check -// -//========================================================================== - -bool PType::VisitedNodeSet::Check(const PType *node) -{ - size_t buck = Hash(node) & (countof(Buckets) - 1); - for (const PType *probe = Buckets[buck]; probe != NULL; probe = probe->VisitNext) - { - if (probe == node) - { - return true; - } - } - return false; -} - //========================================================================== // // PType :: WriteValue diff --git a/src/dobjtype.h b/src/dobjtype.h index 96c1a05e0..7054095bd 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -214,15 +214,6 @@ public: typedef PClassType MetaClass; MetaClass *GetClass() const; - struct Conversion - { - Conversion(PType *target, void (*convert)(ZCC_ExprConstant *, class FSharedStringArena &)) - : TargetType(target), ConvertConstant(convert) {} - - PType *TargetType; - void (*ConvertConstant)(ZCC_ExprConstant *val, class FSharedStringArena &strdump); - }; - unsigned int Size; // this type's size unsigned int Align; // this type's preferred alignment PType *HashNext; // next type in this type table @@ -235,10 +226,6 @@ public: virtual ~PType(); virtual bool isNumeric() { return false; } - bool AddConversion(PType *target, void (*convertconst)(ZCC_ExprConstant *, class FSharedStringArena &)); - - int FindConversion(PType *target, const Conversion **slots, int numslots); - // Writes the value of a variable of this type at (addr) to an archive, preceded by // a tag indicating its type. The tag is there so that variable types can be changed // without completely breaking savegames, provided that the change isn't between @@ -318,54 +305,6 @@ public: size_t PropagateMark(); static void StaticInit(); - -private: - // Stuff for type conversion searches - class VisitQueue - { - public: - VisitQueue() : In(0), Out(0) {} - void Push(PType *type); - PType *Pop(); - bool IsEmpty() { return In == Out; } - - private: - // This is a fixed-sized ring buffer. - PType *Queue[64]; - int In, Out; - - void Advance(int &ptr) - { - ptr = (ptr + 1) & (countof(Queue) - 1); - } - }; - - class VisitedNodeSet - { - public: - VisitedNodeSet() { memset(Buckets, 0, sizeof(Buckets)); } - void Insert(PType *node); - bool Check(const PType *node); - - private: - PType *Buckets[32]; - - size_t Hash(const PType *type) { return size_t(type) >> 4; } - }; - - TArray Conversions; - PType *PredType; - PType *VisitNext; - short PredConv; - short Distance; - - void MarkPred(PType *pred, int conv, int dist) - { - PredType = pred; - PredConv = conv; - Distance = dist; - } - void FillConversionPath(const Conversion **slots); }; // Not-really-a-type types -------------------------------------------------- diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index b29e1eeb2..586601890 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -513,7 +513,7 @@ static void OpenExprType(FLispString &out, EZCCExprType type) if (unsigned(type) < PEX_COUNT_OF) { - mysnprintf(buf, countof(buf), "expr-%s", ZCC_OpInfo[type].OpName); + mysnprintf(buf, countof(buf), "expr %d", type); } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 83b93cafb..519db4d7e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -86,6 +86,20 @@ int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls) return static_cast(ex)->GetValue().GetInt(); } +FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PStruct *cls) +{ + FCompileContext ctx(cls, false); + FxExpression *ex = new FxStringCast(ConvertNode(node)); + ex = ex->Resolve(ctx); + if (ex == nullptr) return ""; + if (!ex->isConstant()) + { + ex->ScriptPosition.Message(MSG_ERROR, "Expression is not constant"); + return ""; + } + return static_cast(ex)->GetValue().GetString(); +} + //========================================================================== // @@ -822,300 +836,6 @@ bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work) } -//========================================================================== -// -// ZCCCompiler :: Simplify -// -// For an expression, -// Evaluate operators whose arguments are both constants, replacing it -// with a new constant. -// For a binary operator with one constant argument, put it on the right- -// hand operand, where permitted. -// Perform automatic type promotion. -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::Simplify(ZCC_Expression *root, PSymbolTable *sym, bool wantconstant) -{ - SimplifyingConstant = wantconstant; - return DoSimplify(root, sym); -} - -ZCC_Expression *ZCCCompiler::DoSimplify(ZCC_Expression *root, PSymbolTable *sym) -{ - if (root->NodeType == AST_ExprUnary) - { - return SimplifyUnary(static_cast(root), sym); - } - else if (root->NodeType == AST_ExprBinary) - { - return SimplifyBinary(static_cast(root), sym); - } - else if (root->Operation == PEX_ID) - { - return IdentifyIdentifier(static_cast(root), sym); - } - else if (root->Operation == PEX_MemberAccess) - { - return SimplifyMemberAccess(static_cast(root), sym); - } - else if (root->Operation == PEX_FuncCall) - { - return SimplifyFunctionCall(static_cast(root), sym); - } - return root; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyUnary -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *sym) -{ - unary->Operand = DoSimplify(unary->Operand, sym); - if (unary->Operand->Type == nullptr) - { - return unary; - } - ZCC_OpProto *op = PromoteUnary(unary->Operation, unary->Operand); - if (op == NULL) - { // Oh, poo! - unary->Type = TypeError; - } - else if (unary->Operand->Operation == PEX_ConstValue) - { - return op->EvalConst1(static_cast(unary->Operand)); - } - return unary; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyBinary -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *sym) -{ - binary->Left = DoSimplify(binary->Left, sym); - binary->Right = DoSimplify(binary->Right, sym); - if (binary->Left->Type == nullptr || binary->Right->Type == nullptr) - { - // We do not know yet what this is so we cannot promote it (yet.) - return binary; - } - ZCC_OpProto *op = PromoteBinary(binary->Operation, binary->Left, binary->Right); - if (op == NULL) - { - binary->Type = TypeError; - } - else if (binary->Left->Operation == PEX_ConstValue && - binary->Right->Operation == PEX_ConstValue) - { - return op->EvalConst2(static_cast(binary->Left), - static_cast(binary->Right), AST.Strings); - } - return binary; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyMemberAccess -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, PSymbolTable *symt) -{ - PSymbolTable *symtable; - - // TBD: Is it safe to simplify the left side here when not processing a constant? - dotop->Left = DoSimplify(dotop->Left, symt); - - if (dotop->Left->Operation == PEX_TypeRef) - { // Type refs can be evaluated now. - PType *ref = static_cast(dotop->Left)->RefType; - PSymbol *sym = ref->Symbols.FindSymbolInTable(dotop->Right, symtable); - if (sym != nullptr) - { - ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable); - if (expr != nullptr) - { - return expr; - } - } - } - else if (dotop->Left->Operation == PEX_Super) - { - symt = symt->GetParentTable(); - if (symt != nullptr) - { - PSymbol *sym = symt->FindSymbolInTable(dotop->Right, symtable); - if (sym != nullptr) - { - ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable); - if (expr != nullptr) - { - return expr; - } - } - } - } - return dotop; -} - -//========================================================================== -// -// ZCCCompiler :: SimplifyFunctionCall -// -// This may replace a function call with cast(s), since they look like the -// same thing to the parser. -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSymbolTable *sym) -{ - ZCC_FuncParm *parm; - int parmcount = 0; - - parm = callop->Parameters; - if (parm != NULL) - { - do - { - parmcount++; - assert(parm->NodeType == AST_FuncParm); - parm->Value = DoSimplify(parm->Value, sym); - parm = static_cast(parm->SiblingNext); - } - while (parm != callop->Parameters); - } - // Only simplify the 'function' part if we want to retrieve a constant. - // This is necessary to evaluate the type casts, but for actual functions - // the simplification process is destructive and has to be avoided. - if (SimplifyingConstant) - { - callop->Function = DoSimplify(callop->Function, sym); - } - // If the left side is a type ref, then this is actually a cast - // and not a function call. - if (callop->Function->Operation == PEX_TypeRef) - { - if (parmcount != 1) - { - Error(callop, "Type cast requires one parameter"); - callop->ToErrorNode(); - } - else - { - PType *dest = static_cast(callop->Function)->RefType; - const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; - int routelen = parm->Value->Type->FindConversion(dest, route, countof(route)); - if (routelen < 0) - { - ///FIXME: Need real type names - Error(callop, "Cannot convert %s to %s", parm->Value->Type->DescriptiveName(), dest->DescriptiveName()); - callop->ToErrorNode(); - } - else - { - ZCC_Expression *val = ApplyConversion(parm->Value, route, routelen); - assert(val->Type == dest); - return val; - } - } - } - return callop; -} - -//========================================================================== -// -// ZCCCompiler :: PromoteUnary -// -// Converts the operand into a format preferred by the operator. -// -//========================================================================== - -ZCC_OpProto *ZCCCompiler::PromoteUnary(EZCCExprType op, ZCC_Expression *&expr) -{ - if (expr->Type == TypeError) - { - return NULL; - } - const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; - int routelen = countof(route); - ZCC_OpProto *proto = ZCC_OpInfo[op].FindBestProto(expr->Type, route, routelen); - - if (proto != NULL) - { - expr = ApplyConversion(expr, route, routelen); - } - return proto; -} - -//========================================================================== -// -// ZCCCompiler :: PromoteBinary -// -// Converts the operands into a format (hopefully) compatible with the -// operator. -// -//========================================================================== - -ZCC_OpProto *ZCCCompiler::PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right) -{ - // If either operand is of type 'error', the result is also 'error' - if (left->Type == TypeError || right->Type == TypeError) - { - return NULL; - } - const PType::Conversion *route1[CONVERSION_ROUTE_SIZE], *route2[CONVERSION_ROUTE_SIZE]; - int route1len = countof(route1), route2len = countof(route2); - ZCC_OpProto *proto = ZCC_OpInfo[op].FindBestProto(left->Type, route1, route1len, right->Type, route2, route2len); - if (proto != NULL) - { - left = ApplyConversion(left, route1, route1len); - right = ApplyConversion(right, route2, route2len); - } - return proto; -} - -//========================================================================== -// -// ZCCCompiler :: ApplyConversion -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen) -{ - for (int i = 0; i < routelen; ++i) - { - if (expr->Operation != PEX_ConstValue) - { - expr = AddCastNode(route[i]->TargetType, expr); - } - else - { - route[i]->ConvertConstant(static_cast(expr), AST.Strings); - } - } - return expr; -} - -//========================================================================== -// -// ZCCCompiler :: AddCastNode -// -//========================================================================== - -ZCC_Expression *ZCCCompiler::AddCastNode(PType *type, ZCC_Expression *expr) -{ - assert(expr->Operation != PEX_ConstValue && "Expression must not be constant"); - // TODO: add a node here - return expr; -} - //========================================================================== // // ZCCCompiler :: IdentifyIdentifier @@ -1781,78 +1501,6 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, return baseType; } -//========================================================================== -// -// ZCCCompiler :: GetInt - Input must be a constant expression -// -//========================================================================== - -int ZCCCompiler::GetInt(ZCC_Expression *expr) -{ - if (expr->Type == TypeError) - { - return 0; - } - const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; - int routelen = expr->Type->FindConversion(TypeSInt32, route, countof(route)); - if (routelen < 0) - { - Error(expr, "Cannot convert to integer"); - return 0; - } - else - { - if (expr->Type->IsKindOf(RUNTIME_CLASS(PFloat))) - { - Warn(expr, "Truncation of floating point value"); - } - auto ex = static_cast(ApplyConversion(expr, route, routelen)); - return ex->IntVal; - } -} - -double ZCCCompiler::GetDouble(ZCC_Expression *expr) -{ - if (expr->Type == TypeError) - { - return 0; - } - const PType::Conversion *route[CONVERSION_ROUTE_SIZE]; - int routelen = expr->Type->FindConversion(TypeFloat64, route, countof(route)); - if (routelen < 0) - { - Error(expr, "Cannot convert to float"); - return 0; - } - else - { - auto ex = static_cast(ApplyConversion(expr, route, routelen)); - return ex->DoubleVal; - } -} - -const char *ZCCCompiler::GetString(ZCC_Expression *expr, bool silent) -{ - if (expr->Type == TypeError) - { - return nullptr; - } - else if (expr->Type->IsKindOf(RUNTIME_CLASS(PString))) - { - return static_cast(expr)->StringVal->GetChars(); - } - else if (expr->Type->IsKindOf(RUNTIME_CLASS(PName))) - { - // Ugh... What a mess... - return FName(ENamedName(static_cast(expr)->IntVal)).GetChars(); - } - else - { - if (!silent) Error(expr, "Cannot convert to string"); - return nullptr; - } -} - //========================================================================== // // Parses an actor property's parameters and calls the handler @@ -2921,7 +2569,7 @@ void ZCCCompiler::CompileStates() auto l = sl->Lights; do { - AddStateLight(&state, GetString(l)); + AddStateLight(&state, StringConstFromNode(l, c->Type())); l = static_cast(l->SiblingNext); } while (l != sl->Lights); } diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index d0284263a..c01d8f339 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -92,6 +92,7 @@ public: private: int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls); + FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PStruct *cls); void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer); void CreateStructTypes(); @@ -115,9 +116,6 @@ private: void ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *flg, Baggage &bag); void DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *pex, AActor *defaults, Baggage &bag); void DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *pex, AActor *defaults, Baggage &bag); - int GetInt(ZCC_Expression *expr); - double GetDouble(ZCC_Expression *expr); - const char *GetString(ZCC_Expression *expr, bool silent = false); void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass); void InitFunctions(); @@ -132,18 +130,6 @@ private: PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false); - ZCC_Expression *Simplify(ZCC_Expression *root, PSymbolTable *Symbols, bool wantconstant); - ZCC_Expression *DoSimplify(ZCC_Expression *root, PSymbolTable *Symbols); - ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary, PSymbolTable *Symbols); - ZCC_Expression *SimplifyBinary(ZCC_ExprBinary *binary, PSymbolTable *Symbols); - ZCC_Expression *SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop, PSymbolTable *Symbols); - ZCC_Expression *SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSymbolTable *Symbols); - ZCC_OpProto *PromoteUnary(EZCCExprType op, ZCC_Expression *&expr); - ZCC_OpProto *PromoteBinary(EZCCExprType op, ZCC_Expression *&left, ZCC_Expression *&right); - - ZCC_Expression *ApplyConversion(ZCC_Expression *expr, const PType::Conversion **route, int routelen); - ZCC_Expression *AddCastNode(PType *type, ZCC_Expression *expr); - ZCC_Expression *IdentifyIdentifier(ZCC_ExprID *idnode, PSymbolTable *sym); ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table); ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode); diff --git a/src/scripting/zscript/zcc_expr.cpp b/src/scripting/zscript/zcc_expr.cpp deleted file mode 100644 index 0c2c6baee..000000000 --- a/src/scripting/zscript/zcc_expr.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/* -** zcc_expr.cpp -** -**--------------------------------------------------------------------------- -** Copyright -2016 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include "dobject.h" -#include "sc_man.h" -#include "c_console.h" -#include "c_dispatch.h" -#include "w_wad.h" -#include "cmdlib.h" -#include "m_alloc.h" -#include "zcc_parser.h" -#include "templates.h" -#include "math/cmath.h" - -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) - -static void FtoD(ZCC_ExprConstant *expr, FSharedStringArena &str_arena); - -ZCC_OpInfoType ZCC_OpInfo[PEX_COUNT_OF] = -{ -#define xx(a,z) { #a, NULL }, -#include "zcc_exprlist.h" -}; - -// Structures used for initializing operator overloads -struct OpProto1 -{ - EZCCExprType Op; - PType **Type; - EvalConst1op EvalConst; -}; - -struct OpProto2 -{ - EZCCExprType Op; - PType **Res, **Ltype, **Rtype; - EvalConst2op EvalConst; -}; - -static struct FreeOpInfoProtos -{ - ~FreeOpInfoProtos() - { - for (size_t i = 0; i < countof(ZCC_OpInfo); ++i) - { - ZCC_OpInfo[i].FreeAllProtos(); - } - } -} ProtoFreeer; - -void ZCC_OpInfoType::FreeAllProtos() -{ - for (ZCC_OpProto *proto = Protos, *next = NULL; proto != NULL; proto = next) - { - next = proto->Next; - delete proto; - } - Protos = NULL; -} - -void ZCC_OpInfoType::AddProto(PType *res, PType *optype, EvalConst1op evalconst) -{ - ZCC_OpProto *proto = new ZCC_OpProto(res, optype, NULL); - proto->EvalConst1 = evalconst; - proto->Next = Protos; - Protos = proto; -} - -void ZCC_OpInfoType::AddProto(PType *res, PType *ltype, PType *rtype, EvalConst2op evalconst) -{ - assert(ltype != NULL); - ZCC_OpProto *proto = new ZCC_OpProto(res, ltype, rtype); - proto->EvalConst2 = evalconst; - proto->Next = Protos; - Protos = proto; -} - -//========================================================================== -// -// ZCC_OpInfoType :: FindBestProto (Unary) -// -// Finds the "best" prototype for this operand type. Best is defined as the -// one that requires the fewest conversions. Also returns the conversion -// route necessary to get from the input type to the desired type. -// -//========================================================================== - -ZCC_OpProto *ZCC_OpInfoType::FindBestProto(PType *optype, const PType::Conversion **route, int &numslots) -{ - assert(optype != NULL); - - const PType::Conversion *routes[2][CONVERSION_ROUTE_SIZE]; - const PType::Conversion **best_route = NULL; - int cur_route = 0; - ZCC_OpProto *best_proto = NULL; - int best_dist = INT_MAX; - - // Find the best prototype. - for (ZCC_OpProto *proto = Protos; best_dist != 0 && proto != NULL; proto = proto->Next) - { - if (proto->Type2 != NULL) - { // Not a unary prototype. - continue; - } - int dist = optype->FindConversion(proto->Type1, routes[cur_route], CONVERSION_ROUTE_SIZE); - if (dist >= 0 && dist < best_dist) - { - best_dist = dist; - best_proto = proto; - best_route = routes[cur_route]; - cur_route ^= 1; - } - } - // Copy best conversion route to the caller's array. - if (best_route != NULL && route != NULL && numslots > 0) - { - numslots = MIN(numslots, best_dist); - if (numslots > 0) - { - memcpy(route, best_route, sizeof(*route) * numslots); - } - } - return best_proto; -} - -//========================================================================== -// -// ZCC_OpInfoType :: FindBestProto (Binary) -// -// Finds the "best" prototype for the given operand types. Here, best is -// defined as the one that requires the fewest conversions for *one* of the -// operands. For prototypes with matching distances, the first one found -// is used. ZCC_InitOperators() initializes the prototypes in order such -// that this will result in the precedences: double > uint > int -// -//========================================================================== - -ZCC_OpProto *ZCC_OpInfoType::FindBestProto( - PType *left, const PType::Conversion **route1, int &numslots1, - PType *right, const PType::Conversion **route2, int &numslots2) -{ - assert(left != NULL && right != NULL); - - const PType::Conversion *routes[2][2][CONVERSION_ROUTE_SIZE]; - const PType::Conversion **best_route1 = NULL, **best_route2 = NULL; - int cur_route1 = 0, cur_route2 = 0; - int best_dist1 = INT_MAX, best_dist2 = INT_MAX; - - ZCC_OpProto *best_proto = NULL; - int best_low_dist = INT_MAX; - - for (ZCC_OpProto *proto = Protos; best_low_dist != 0 && proto != NULL; proto = proto->Next) - { - if (proto->Type2 == NULL) - { // Not a binary prototype - continue; - } - int dist1 = left->FindConversion(proto->Type1, routes[0][cur_route1], CONVERSION_ROUTE_SIZE); - int dist2 = right->FindConversion(proto->Type2, routes[1][cur_route2], CONVERSION_ROUTE_SIZE); - if (dist1 < 0 || dist2 < 0) - { // one or both operator types are unreachable - continue; - } - // Do not count F32->F64 conversions in the distance comparisons. If we do, then - // [[float32 (op) int]] will choose the integer version instead of the floating point - // version, which we do not want. - int test_dist1 = dist1, test_dist2 = dist2; - if (test_dist1 > 0 && routes[0][cur_route1][0]->ConvertConstant == FtoD) - { - test_dist1--; - } - if (test_dist2 > 0 && routes[1][cur_route2][0]->ConvertConstant == FtoD) - { - test_dist2--; - } - int dist = MIN(test_dist1, test_dist2); - if (dist < best_low_dist) - { - best_low_dist = dist; - best_proto = proto; - best_dist1 = dist1; - best_dist2 = dist2; - best_route1 = routes[0][cur_route1]; - best_route2 = routes[1][cur_route2]; - cur_route1 ^= 1; - cur_route2 ^= 1; - } - } - // Copy best conversion route to the caller's arrays. - if (best_route1 != NULL && route1 != NULL && numslots1 > 0) - { - numslots1 = MIN(numslots1, best_dist1); - if (numslots1 > 0) - { - memcpy(route1, best_route1, sizeof(*route1) * numslots1); - } - } - if (best_route2 != NULL && route2 != NULL && numslots2 > 0) - { - numslots2 = MIN(numslots2, best_dist2); - if (numslots2 > 0) - { - memcpy(route2, best_route2, sizeof(*route2) * numslots2); - } - } - return best_proto; -} - -static ZCC_ExprConstant *EvalIdentity(ZCC_ExprConstant *val) -{ - return val; -} - - -static ZCC_ExprConstant *EvalConcat(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &strings) -{ - FString str = *l->StringVal + *r->StringVal; - l->StringVal = strings.Alloc(str); - return l; -} - -static ZCC_ExprConstant *EvalLTGTEQSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->IntVal < r->IntVal ? -1 : l->IntVal == r->IntVal ? 0 : 1; - return l; -} - -static ZCC_ExprConstant *EvalLTGTEQUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->UIntVal < r->UIntVal ? -1 : l->UIntVal == r->UIntVal ? 0 : 1; - l->Type = TypeSInt32; - return l; -} - -static ZCC_ExprConstant *EvalLTGTEQFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &) -{ - l->IntVal = l->DoubleVal < r->DoubleVal ? -1 : l->DoubleVal == r->DoubleVal ? 0 : 1; - l->Type = TypeSInt32; - return l; -} - -void ZCC_InitOperators() -{ - // Prototypes are added from lowest to highest conversion precedence. - - // Unary operators - static const OpProto1 UnaryOpInit[] = - { - { PEX_PostInc , (PType **)&TypeSInt32, EvalIdentity }, - { PEX_PostInc , (PType **)&TypeUInt32, EvalIdentity }, - { PEX_PostInc , (PType **)&TypeFloat64, EvalIdentity }, - - { PEX_PostDec , (PType **)&TypeSInt32, EvalIdentity }, - { PEX_PostDec , (PType **)&TypeUInt32, EvalIdentity }, - { PEX_PostDec , (PType **)&TypeFloat64, EvalIdentity }, - - { PEX_PreInc , (PType **)&TypeSInt32, [](auto *val) { val->IntVal += 1; return val; } }, - { PEX_PreInc , (PType **)&TypeUInt32, [](auto *val) { val->UIntVal += 1; return val; } }, - { PEX_PreInc , (PType **)&TypeFloat64, [](auto *val) { val->DoubleVal += 1; return val; } }, - - { PEX_PreDec , (PType **)&TypeSInt32, [](auto *val) { val->IntVal -= 1; return val; } }, - { PEX_PreDec , (PType **)&TypeUInt32, [](auto *val) { val->UIntVal -= 1; return val; } }, - { PEX_PreDec , (PType **)&TypeFloat64, [](auto *val) { val->DoubleVal -= 1; return val; } }, - - { PEX_Negate , (PType **)&TypeSInt32, [](auto *val) { val->IntVal = -val->IntVal; return val; } }, - { PEX_Negate , (PType **)&TypeFloat64, [](auto *val) { val->DoubleVal = -val->DoubleVal; return val; } }, - - { PEX_AntiNegate , (PType **)&TypeSInt32, EvalIdentity }, - { PEX_AntiNegate , (PType **)&TypeUInt32, EvalIdentity }, - { PEX_AntiNegate , (PType **)&TypeFloat64, EvalIdentity }, - - { PEX_BitNot , (PType **)&TypeSInt32, [](auto *val) { val->IntVal = ~val->IntVal; return val; } }, - { PEX_BitNot , (PType **)&TypeUInt32, [](auto *val) { val->UIntVal = ~val->UIntVal; return val; } }, - - { PEX_BoolNot , (PType **)&TypeBool, [](auto *val) { val->IntVal = !val->IntVal; return val; } }, - }; - for (size_t i = 0; i < countof(UnaryOpInit); ++i) - { - ZCC_OpInfo[UnaryOpInit[i].Op].AddProto(*UnaryOpInit[i].Type, *UnaryOpInit[i].Type, UnaryOpInit[i].EvalConst); - } - - // Binary operators - static const OpProto2 BinaryOpInit[] = - { - { PEX_Add , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal += r->IntVal; return l; } }, - { PEX_Add , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal += r->UIntVal; return l; } }, - { PEX_Add , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal += r->DoubleVal; return l; } }, - - { PEX_Sub , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal -= r->IntVal; return l; } }, - { PEX_Sub , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal -= r->UIntVal; return l; } }, - { PEX_Sub , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal -= r->DoubleVal; return l; } }, - - { PEX_Mul , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal *= r->IntVal; return l; } }, - { PEX_Mul , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal *= r->UIntVal; return l; } }, - { PEX_Mul , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal *= r->DoubleVal; return l; } }, - - { PEX_Div , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal /= r->IntVal; return l; } }, - { PEX_Div , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal /= r->UIntVal; return l; } }, - { PEX_Div , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal /= r->DoubleVal; return l; } }, - - { PEX_Mod , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal %= r->IntVal; return l; } }, - { PEX_Mod , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal %= r->UIntVal; return l; } }, - { PEX_Mod , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = luai_nummod(l->DoubleVal, r->DoubleVal); return l; } }, - - { PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = g_pow(l->DoubleVal, r->DoubleVal); return l; } }, - - { PEX_Concat , (PType **)&TypeString, (PType **)&TypeString, (PType **)&TypeString, EvalConcat }, - - { PEX_BitAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal &= r->IntVal; return l; } }, - { PEX_BitAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal &= r->UIntVal; return l; } }, - - { PEX_BitOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal |= r->IntVal; return l; } }, - { PEX_BitOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal |= r->UIntVal; return l; } }, - - { PEX_BitXor , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal ^= r->IntVal; return l; } }, - { PEX_BitXor , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal ^= r->UIntVal; return l; } }, - - { PEX_BoolAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal && r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_BoolAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal && r->UIntVal; l->Type = TypeBool; return l; } }, - - { PEX_BoolOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal || r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_BoolOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal || r->UIntVal; l->Type = TypeBool; return l; } }, - - { PEX_LeftShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal <<= r->UIntVal; return l; } }, - { PEX_LeftShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal <<= r->UIntVal; return l; } }, - - { PEX_RightShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal >>= r->UIntVal; return l; } }, - { PEX_RightShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal >>= r->UIntVal; return l; } }, - - { PEX_LT , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal < r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_LT , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal < r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_LT , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal < r->DoubleVal; l->Type = TypeBool; return l; } }, - - { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal <= r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal <= r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal <= r->DoubleVal; l->Type = TypeBool; return l; } }, - - { PEX_GT , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal > r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_GT , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal > r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_GT , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal > r->DoubleVal; l->Type = TypeBool; return l; } }, - - { PEX_GTEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal >= r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_GTEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal >= r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_GTEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal >= r->DoubleVal; l->Type = TypeBool; return l; } }, - - { PEX_NEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal != r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_NEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal != r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_NEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal != r->DoubleVal; l->Type = TypeBool; return l; } }, - - { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->IntVal == r->IntVal; l->Type = TypeBool; return l; } }, - { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->IntVal = l->UIntVal == r->UIntVal; l->Type = TypeBool; return l; } }, - { PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->IntVal = l->DoubleVal == r->DoubleVal; l->Type = TypeBool; return l; } }, - - { PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalLTGTEQSInt32 }, - { PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalLTGTEQUInt32 }, - { PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalLTGTEQFloat64 }, - }; - for (size_t i = 0; i < countof(BinaryOpInit); ++i) - { - ZCC_OpInfo[BinaryOpInit[i].Op].AddProto(*BinaryOpInit[i].Res, *BinaryOpInit[i].Ltype, *BinaryOpInit[i].Rtype, BinaryOpInit[i].EvalConst); - } -} - -static void IntToS32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - // Integers always fill out the full sized 32-bit field, so converting - // from a smaller sized integer to a 32-bit one is as simple as changing - // the type field. - expr->Type = TypeSInt32; -} - -static void S32toS8(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->IntVal = ((expr->IntVal << 24) >> 24); - expr->Type = TypeSInt8; -} - -static void S32toS16(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->IntVal = ((expr->IntVal << 16) >> 16); - expr->Type = TypeSInt16; -} - -static void S32toU8(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->IntVal &= 0xFF; - expr->Type = TypeUInt8; -} - -static void S32toU16(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->IntVal &= 0xFFFF; - expr->Type = TypeUInt16; -} - -static void S32toU32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->Type = TypeUInt32; -} - -static void S32toD(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->DoubleVal = expr->IntVal; - expr->Type = TypeFloat64; -} - -static void DtoS32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->IntVal = (int)expr->DoubleVal; - expr->Type = TypeSInt32; -} - -static void U32toD(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->DoubleVal = expr->UIntVal; - expr->Type = TypeFloat64; -} - -static void DtoU32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - expr->UIntVal = (unsigned int)expr->DoubleVal; - expr->Type = TypeUInt32; -} - -static void FtoD(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - // Constant single precision numbers are stored as doubles. - assert(expr->Type == TypeFloat32); - expr->Type = TypeFloat64; -} - -static void DtoF(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - // Truncate double precision to single precision. - float poop = (float)expr->DoubleVal; - expr->DoubleVal = poop; - expr->Type = TypeFloat32; -} - -static void S32toS(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - char str[16]; - int len = mysnprintf(str, countof(str), "%i", expr->IntVal); - expr->StringVal = str_arena.Alloc(str, len); - expr->Type = TypeString; -} - -static void U32toS(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - char str[16]; - int len = mysnprintf(str, countof(str), "%u", expr->UIntVal); - expr->StringVal = str_arena.Alloc(str, len); - expr->Type = TypeString; -} - -static void DtoS(ZCC_ExprConstant *expr, FSharedStringArena &str_arena) -{ - // Convert to a string with enough precision such that converting - // back to a double will not lose any data. - char str[64]; - IGNORE_FORMAT_PRE - int len = mysnprintf(str, countof(str), "%H", expr->DoubleVal); - IGNORE_FORMAT_POST - expr->StringVal = str_arena.Alloc(str, len); - expr->Type = TypeString; -} - -//========================================================================== -// -// ZCC_InitConversions -// -//========================================================================== - -void ZCC_InitConversions() -{ - TypeUInt8->AddConversion(TypeSInt32, IntToS32); - TypeSInt8->AddConversion(TypeSInt32, IntToS32); - TypeUInt16->AddConversion(TypeSInt32, IntToS32); - TypeSInt16->AddConversion(TypeSInt32, IntToS32); - - TypeUInt32->AddConversion(TypeSInt32, IntToS32); - TypeUInt32->AddConversion(TypeFloat64, U32toD); - TypeUInt32->AddConversion(TypeString, U32toS); - - TypeSInt32->AddConversion(TypeUInt8, S32toU8); - TypeSInt32->AddConversion(TypeSInt8, S32toS8); - TypeSInt32->AddConversion(TypeSInt16, S32toS16); - TypeSInt32->AddConversion(TypeUInt16, S32toU16); - TypeSInt32->AddConversion(TypeUInt32, S32toU32); - TypeSInt32->AddConversion(TypeFloat64, S32toD); - TypeSInt32->AddConversion(TypeString, S32toS); - - TypeFloat32->AddConversion(TypeFloat64, FtoD); - - TypeFloat64->AddConversion(TypeUInt32, DtoU32); - TypeFloat64->AddConversion(TypeSInt32, DtoS32); - TypeFloat64->AddConversion(TypeFloat32, DtoF); - TypeFloat64->AddConversion(TypeString, DtoS); -} diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 95f75aea6..78458876a 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -408,9 +408,6 @@ void ParseScripts() { InitTokenMap(); } - ZCC_InitOperators(); - ZCC_InitConversions(); - int lump, lastlump = 0; FScriptPosition::ResetErrorCounter(); diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index b80686bb0..95bafd54f 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -527,47 +527,8 @@ struct ZCC_FlagStmt : ZCC_Statement bool set; }; -typedef ZCC_ExprConstant *(*EvalConst1op)(ZCC_ExprConstant *); -typedef ZCC_ExprConstant *(*EvalConst2op)(ZCC_ExprConstant *, ZCC_ExprConstant *, FSharedStringArena &); - -struct ZCC_OpProto -{ - ZCC_OpProto *Next; - PType *ResType; - PType *Type1; - PType *Type2; - union - { - EvalConst1op EvalConst1; - EvalConst2op EvalConst2; - }; - - ZCC_OpProto(PType *res, PType *t1, PType *t2) - : ResType(res), Type1(t1), Type2(t2) {} -}; - -struct ZCC_OpInfoType -{ - const char *OpName; - ZCC_OpProto *Protos; - - void AddProto(PType *res, PType *optype, EvalConst1op evalconst); - void AddProto(PType *res, PType *left, PType *right, EvalConst2op evalconst); - - ZCC_OpProto *FindBestProto(PType *optype, const PType::Conversion **route, int &numslots); - ZCC_OpProto *FindBestProto(PType *left, const PType::Conversion **route1, int &numslots, - PType *right, const PType::Conversion **route2, int &numslots2); - - void FreeAllProtos(); -}; - -#define CONVERSION_ROUTE_SIZE 8 - FString ZCC_PrintAST(ZCC_TreeNode *root); -void ZCC_InitOperators(); - -extern ZCC_OpInfoType ZCC_OpInfo[PEX_COUNT_OF]; struct ZCC_AST {