More efficient iteration syntax, and range() is converted behind the scenes to it.
This commit is contained in:
parent
41821ba11d
commit
bfef8de1bc
2 changed files with 147 additions and 0 deletions
|
@ -2934,6 +2934,38 @@ bool Variant::iter_init(Variant& r_iter,bool &valid) const {
|
||||||
|
|
||||||
valid=true;
|
valid=true;
|
||||||
switch(type) {
|
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: {
|
case OBJECT: {
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
@ -3059,7 +3091,48 @@ bool Variant::iter_next(Variant& r_iter,bool &valid) const {
|
||||||
|
|
||||||
valid=true;
|
valid=true;
|
||||||
switch(type) {
|
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: {
|
case OBJECT: {
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
@ -3204,6 +3277,22 @@ Variant Variant::iter_get(const Variant& r_iter,bool &r_valid) const {
|
||||||
|
|
||||||
r_valid=true;
|
r_valid=true;
|
||||||
switch(type) {
|
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: {
|
case OBJECT: {
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
|
@ -2004,6 +2004,64 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
||||||
return;
|
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>();
|
ControlFlowNode *cf_for = alloc_node<ControlFlowNode>();
|
||||||
|
|
||||||
cf_for->cf_type=ControlFlowNode::CF_FOR;
|
cf_for->cf_type=ControlFlowNode::CF_FOR;
|
||||||
|
|
Loading…
Reference in a new issue