From bfef8de1bc4f7a7b9617a7b181881129033a0b0e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 11 Jan 2017 20:09:45 -0300 Subject: [PATCH] More efficient iteration syntax, and range() is converted behind the scenes to it. --- core/variant_op.cpp | 89 ++++++++++++++++++++++++++++++++++ modules/gdscript/gd_parser.cpp | 58 ++++++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 281d2e81921..3924d3af77a 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -2934,6 +2934,38 @@ bool Variant::iter_init(Variant& r_iter,bool &valid) const { valid=true; switch(type) { + case INT: { + r_iter=0; + return _data._int>0; + } break; + case REAL: { + r_iter=0.0; + return _data._real>0.0; + } break; + case VECTOR2: { + real_t from = reinterpret_cast(_data._mem)->x; + real_t to = reinterpret_cast(_data._mem)->y; + + r_iter=from; + + return from < to; + } break; + case VECTOR3: { + real_t from = reinterpret_cast(_data._mem)->x; + real_t to = reinterpret_cast(_data._mem)->y; + real_t step = reinterpret_cast(_data._mem)->z; + + r_iter=from; + + if (from == to ) { + return false; + } else if (from < to) { + return step>0.0; + } else { + return step<0.0; + } + //return true; + } break; case OBJECT: { #ifdef DEBUG_ENABLED @@ -3059,7 +3091,48 @@ bool Variant::iter_next(Variant& r_iter,bool &valid) const { valid=true; switch(type) { + case INT: { + int64_t idx = r_iter; + idx++; + if (idx >= _data._int) + return false; + r_iter = idx; + return true; + } break; + case REAL: { + + double idx = r_iter; + idx+=1.0; + if (idx >= _data._real) + return false; + r_iter = idx; + return true; + } break; + case VECTOR2: { + real_t idx = r_iter; + idx+=1.0; + if (idx>=reinterpret_cast(_data._mem)->y) + return false; + r_iter=idx; + return true; + } break; + case VECTOR3: { + real_t to = reinterpret_cast(_data._mem)->y; + real_t step = reinterpret_cast(_data._mem)->z; + + real_t idx = r_iter; + idx+=step; + + if (step<0.0 && idx <= to) + return false; + + if (step>0.0 && idx >= to) + return false; + + r_iter=idx; + return true; + } break; case OBJECT: { #ifdef DEBUG_ENABLED @@ -3204,6 +3277,22 @@ Variant Variant::iter_get(const Variant& r_iter,bool &r_valid) const { r_valid=true; switch(type) { + case INT: { + + return r_iter; + } break; + case REAL: { + + return r_iter; + } break; + case VECTOR2: { + + return r_iter; + } break; + case VECTOR3: { + + return r_iter; + } break; case OBJECT: { #ifdef DEBUG_ENABLED diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index aab69463644..6aed7c9491c 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -2004,6 +2004,64 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) { return; } + if (container->type==Node::TYPE_OPERATOR) { + + OperatorNode* op = static_cast(container); + if (op->op==OperatorNode::OP_CALL && op->arguments[0]->type==Node::TYPE_BUILT_IN_FUNCTION && static_cast(op->arguments[0])->function==GDFunctions::GEN_RANGE) { + //iterating a range, so see if range() can be optimized without allocating memory, by replacing it by vectors (which can work as iterable too!) + + Vector args; + Vector constants; + + bool constant=true; + + for(int i=1;iarguments.size();i++) { + args.push_back(op->arguments[i]); + if (constant && op->arguments[i]->type==Node::TYPE_CONSTANT) { + ConstantNode *c = static_cast(op->arguments[i]); + if (c->value.get_type()==Variant::REAL || c->value.get_type()==Variant::INT) { + constants.push_back(c->value); + } else { + constant=false; + } + } + } + + if (args.size()>0 || args.size()<4) { + + if (constant) { + + ConstantNode *cn = alloc_node(); + switch(args.size()) { + case 1: cn->value=constants[0]; break; + case 2: cn->value=Vector2(constants[0],constants[1]); break; + case 3: cn->value=Vector3(constants[0],constants[1],constants[2]); break; + } + container=cn; + } else { + OperatorNode *on = alloc_node(); + on->op=OperatorNode::OP_CALL; + + TypeNode *tn = alloc_node(); + on->arguments.push_back(tn); + + switch(args.size()) { + case 1: tn->vtype=Variant::REAL; break; + case 2: tn->vtype=Variant::VECTOR2; break; + case 3: tn->vtype=Variant::VECTOR3; break; + } + + for(int i=0;iarguments.push_back(args[i]); + } + + container=on; + } + } + } + + } + ControlFlowNode *cf_for = alloc_node(); cf_for->cf_type=ControlFlowNode::CF_FOR;