mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
- implemented the 'is' operator (i.e. class type check.)
This commit is contained in:
parent
78a18acf46
commit
ac1c022911
4 changed files with 158 additions and 33 deletions
|
@ -673,13 +673,14 @@ xx(PlayerClass)
|
||||||
xx(Wi_NoAutostartMap)
|
xx(Wi_NoAutostartMap)
|
||||||
|
|
||||||
// Decorate compatibility functions
|
// Decorate compatibility functions
|
||||||
xx(DecoRandom)
|
xx(BuiltinTypeCheck)
|
||||||
xx(DecoFRandom)
|
xx(BuiltinRandom)
|
||||||
xx(DecoCallLineSpecial)
|
xx(BuiltinFRandom)
|
||||||
xx(DecoNameToClass)
|
xx(BuiltinCallLineSpecial)
|
||||||
|
xx(BuiltinNameToClass)
|
||||||
xx(BuiltinFindMultiNameState)
|
xx(BuiltinFindMultiNameState)
|
||||||
xx(BuiltinFindSingleNameState)
|
xx(BuiltinFindSingleNameState)
|
||||||
xx(DecoHandleRuntimeState)
|
xx(BuiltinHandleRuntimeState)
|
||||||
xx(Damage)
|
xx(Damage)
|
||||||
|
|
||||||
// basic type names
|
// basic type names
|
||||||
|
|
|
@ -203,23 +203,24 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FindDecorateBuiltinFunction
|
// FindBuiltinFunction
|
||||||
//
|
//
|
||||||
// Returns the symbol for a decorate utility function. If not found, create
|
// Returns the symbol for a decorate utility function. If not found, create
|
||||||
// it and install it in Actor.
|
// it and install it a local symbol table.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
static PSymbolTable Builtins;
|
||||||
|
|
||||||
static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func)
|
static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func)
|
||||||
{
|
{
|
||||||
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(funcname, false);
|
PSymbol *sym = Builtins.FindSymbol(funcname, false);
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
{
|
{
|
||||||
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
|
PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname);
|
||||||
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
|
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
|
||||||
symfunc->Function = calldec;
|
symfunc->Function = calldec;
|
||||||
sym = symfunc;
|
sym = symfunc;
|
||||||
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
|
Builtins.AddSymbol(sym);
|
||||||
}
|
}
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
@ -3615,9 +3616,6 @@ FxExpression *FxDotCross::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
ExpEmit FxDotCross::Emit(VMFunctionBuilder *build)
|
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 to(build, ValueType->GetRegType(), ValueType->GetRegCount());
|
||||||
ExpEmit op1 = left->Emit(build);
|
ExpEmit op1 = left->Emit(build);
|
||||||
ExpEmit op2 = right->Emit(build);
|
ExpEmit op2 = right->Emit(build);
|
||||||
|
@ -3634,6 +3632,108 @@ ExpEmit FxDotCross::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
FxTypeCheck::FxTypeCheck(FxExpression *l, FxExpression *r)
|
||||||
|
: FxExpression(EFX_TypeCheck, l->ScriptPosition)
|
||||||
|
{
|
||||||
|
left = new FxTypeCast(l, NewPointer(RUNTIME_CLASS(DObject)), false);
|
||||||
|
right = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), r);
|
||||||
|
EmitTail = false;
|
||||||
|
ValueType = TypeBool;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxTypeCheck::~FxTypeCheck()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(left);
|
||||||
|
SAFE_DELETE(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx)
|
||||||
|
{
|
||||||
|
CHECKRESOLVED();
|
||||||
|
RESOLVE(left, ctx);
|
||||||
|
RESOLVE(right, ctx);
|
||||||
|
ABORT(right && left);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PPrototype *FxTypeCheck::ReturnProto()
|
||||||
|
{
|
||||||
|
EmitTail = true;
|
||||||
|
return FxExpression::ReturnProto();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int BuiltinTypeCheck(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||||
|
{
|
||||||
|
assert(numparam == 2);
|
||||||
|
PARAM_POINTER_AT(0, obj, DObject);
|
||||||
|
PARAM_CLASS_AT(1, cls, DObject);
|
||||||
|
ACTION_RETURN_BOOL(obj->IsKindOf(cls));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
ExpEmit out(build, REGT_INT);
|
||||||
|
EmitParameter(build, left, ScriptPosition);
|
||||||
|
EmitParameter(build, right, ScriptPosition);
|
||||||
|
|
||||||
|
|
||||||
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck);
|
||||||
|
|
||||||
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
|
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||||
|
auto callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
|
||||||
|
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||||
|
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
||||||
|
|
||||||
|
if (EmitTail)
|
||||||
|
{
|
||||||
|
ExpEmit call;
|
||||||
|
call.Final = true;
|
||||||
|
return call;
|
||||||
|
}
|
||||||
|
|
||||||
|
build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f)
|
FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f)
|
||||||
: FxExpression(EFX_Conditional, c->ScriptPosition)
|
: FxExpression(EFX_Conditional, c->ScriptPosition)
|
||||||
{
|
{
|
||||||
|
@ -4278,7 +4378,7 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int DecoRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
int BuiltinRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||||
{
|
{
|
||||||
assert(numparam >= 1 && numparam <= 3);
|
assert(numparam >= 1 && numparam <= 3);
|
||||||
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
||||||
|
@ -4309,7 +4409,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// Call DecoRandom to generate a random number.
|
// Call DecoRandom to generate a random number.
|
||||||
VMFunction *callfunc;
|
VMFunction *callfunc;
|
||||||
PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||||
|
@ -4428,9 +4528,9 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
assert(choices.Size() > 0);
|
assert(choices.Size() > 0);
|
||||||
|
|
||||||
// Call DecoRandom to generate a random number.
|
// Call BuiltinRandom to generate a random number.
|
||||||
VMFunction *callfunc;
|
VMFunction *callfunc;
|
||||||
PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||||
|
@ -4528,7 +4628,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int DecoFRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
int BuiltinFRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||||
{
|
{
|
||||||
assert(numparam == 1 || numparam == 3);
|
assert(numparam == 1 || numparam == 3);
|
||||||
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
||||||
|
@ -4553,9 +4653,9 @@ int DecoFRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultpar
|
||||||
|
|
||||||
ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// Call the DecoFRandom function to generate a floating point random number..
|
// Call the BuiltinFRandom function to generate a floating point random number..
|
||||||
VMFunction *callfunc;
|
VMFunction *callfunc;
|
||||||
PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoFRandom, DecoFRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||||
|
@ -4647,9 +4747,9 @@ FxExpression *FxRandom2::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// Call the DecoRandom function to generate the random number.
|
// Call the BuiltinRandom function to generate the random number.
|
||||||
VMFunction *callfunc;
|
VMFunction *callfunc;
|
||||||
PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoRandom, DecoRandom);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||||
|
@ -5836,7 +5936,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
int BuiltinCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||||
{
|
{
|
||||||
assert(numparam > 2 && numparam < 8);
|
assert(numparam > 2 && numparam < 8);
|
||||||
assert(param[0].Type == REGT_INT);
|
assert(param[0].Type == REGT_INT);
|
||||||
|
@ -5885,9 +5985,9 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Call the DecoCallLineSpecial function to perform the desired special.
|
// Call the BuiltinCallLineSpecial function to perform the desired special.
|
||||||
VMFunction *callfunc;
|
VMFunction *callfunc;
|
||||||
PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoCallLineSpecial, DecoCallLineSpecial);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||||
|
@ -7347,7 +7447,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int DecoNameToClass(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
int BuiltinNameToClass(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||||
{
|
{
|
||||||
assert(numparam == 2);
|
assert(numparam == 2);
|
||||||
assert(numret == 1);
|
assert(numret == 1);
|
||||||
|
@ -7380,9 +7480,9 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
||||||
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum);
|
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum);
|
||||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype), ATAG_OBJECT));
|
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype), ATAG_OBJECT));
|
||||||
|
|
||||||
// Call the DecoNameToClass function to convert from 'name' to class.
|
// Call the BuiltinNameToClass function to convert from 'name' to class.
|
||||||
VMFunction *callfunc;
|
VMFunction *callfunc;
|
||||||
PSymbol *sym = FindDecorateBuiltinFunction(NAME_DecoNameToClass, DecoNameToClass);
|
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass);
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||||
|
@ -7487,7 +7587,7 @@ static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
static int BuiltinHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||||
{
|
{
|
||||||
PARAM_PROLOGUE;
|
PARAM_PROLOGUE;
|
||||||
PARAM_OBJECT(stateowner, AActor);
|
PARAM_OBJECT(stateowner, AActor);
|
||||||
|
@ -7522,7 +7622,7 @@ ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build)
|
||||||
VMFunction *callfunc;
|
VMFunction *callfunc;
|
||||||
PSymbol *sym;
|
PSymbol *sym;
|
||||||
|
|
||||||
sym = FindDecorateBuiltinFunction(NAME_DecoHandleRuntimeState, DecoHandleRuntimeState);
|
sym = FindBuiltinFunction(NAME_BuiltinHandleRuntimeState, BuiltinHandleRuntimeState);
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||||
|
@ -7702,11 +7802,11 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
if (names.Size() == 1)
|
if (names.Size() == 1)
|
||||||
{
|
{
|
||||||
sym = FindDecorateBuiltinFunction(NAME_BuiltinFindSingleNameState, BuiltinFindSingleNameState);
|
sym = FindBuiltinFunction(NAME_BuiltinFindSingleNameState, BuiltinFindSingleNameState);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sym = FindDecorateBuiltinFunction(NAME_BuiltinFindMultiNameState, BuiltinFindMultiNameState);
|
sym = FindBuiltinFunction(NAME_BuiltinFindMultiNameState, BuiltinFindMultiNameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||||
|
|
|
@ -267,6 +267,7 @@ enum EFxType
|
||||||
EFX_CaseStatement,
|
EFX_CaseStatement,
|
||||||
EFX_VectorInitializer,
|
EFX_VectorInitializer,
|
||||||
EFX_VectorBuiltin,
|
EFX_VectorBuiltin,
|
||||||
|
EFX_TypeCheck,
|
||||||
EFX_COUNT
|
EFX_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -929,6 +930,27 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FxBinaryLogical
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxTypeCheck : public FxExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FxExpression *left;
|
||||||
|
FxExpression *right;
|
||||||
|
bool EmitTail;
|
||||||
|
|
||||||
|
FxTypeCheck(FxExpression*, FxExpression*);
|
||||||
|
~FxTypeCheck();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
PPrototype *ReturnProto();
|
||||||
|
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxConditional
|
// FxConditional
|
||||||
|
|
|
@ -2690,9 +2690,11 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
case PEX_DotProduct:
|
case PEX_DotProduct:
|
||||||
return new FxDotCross(tok, left, right);
|
return new FxDotCross(tok, left, right);
|
||||||
|
|
||||||
|
case PEX_Is:
|
||||||
|
return new FxTypeCheck(left, right);
|
||||||
|
|
||||||
// todo: These do not have representations in DECORATE and no implementation exists yet.
|
// todo: These do not have representations in DECORATE and no implementation exists yet.
|
||||||
case PEX_Concat:
|
case PEX_Concat:
|
||||||
case PEX_Is:
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
I_Error("Binary operator %d not implemented yet", op);
|
I_Error("Binary operator %d not implemented yet", op);
|
||||||
|
|
Loading…
Reference in a new issue