Bladeren bron

More efficient iteration syntax, and range() is converted behind the scenes to it.

Juan Linietsky 8 jaren geleden
bovenliggende
commit
bfef8de1bc
2 gewijzigde bestanden met toevoegingen van 147 en 0 verwijderingen
  1. 89 0
      core/variant_op.cpp
  2. 58 0
      modules/gdscript/gd_parser.cpp

+ 89 - 0
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<const Vector2*>(_data._mem)->x;
+			real_t to = reinterpret_cast<const Vector2*>(_data._mem)->y;
+
+			r_iter=from;
+
+			return from < to;
+		} break;
+		case VECTOR3: {
+			real_t from = reinterpret_cast<const Vector3*>(_data._mem)->x;
+			real_t to = reinterpret_cast<const Vector3*>(_data._mem)->y;
+			real_t step = reinterpret_cast<const Vector3*>(_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<const Vector2*>(_data._mem)->y)
+				return false;
+			r_iter=idx;
+			return true;
+		} break;
+		case VECTOR3: {
+			real_t to = reinterpret_cast<const Vector3*>(_data._mem)->y;
+			real_t step = reinterpret_cast<const Vector3*>(_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

+ 58 - 0
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<OperatorNode*>(container);
+					if (op->op==OperatorNode::OP_CALL && op->arguments[0]->type==Node::TYPE_BUILT_IN_FUNCTION && static_cast<BuiltInFunctionNode*>(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<Node*> args;
+						Vector<double> constants;
+
+						bool constant=true;
+
+						for(int i=1;i<op->arguments.size();i++) {
+							args.push_back(op->arguments[i]);
+							if (constant && op->arguments[i]->type==Node::TYPE_CONSTANT) {
+								ConstantNode *c = static_cast<ConstantNode*>(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<ConstantNode>();
+								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<OperatorNode>();
+								on->op=OperatorNode::OP_CALL;
+
+								TypeNode *tn = alloc_node<TypeNode>();
+								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;i<args.size();i++) {
+									on->arguments.push_back(args[i]);
+								}
+
+								container=on;
+							}
+						}
+					}
+
+				}
+
 				ControlFlowNode *cf_for = alloc_node<ControlFlowNode>();
 
 				cf_for->cf_type=ControlFlowNode::CF_FOR;