summaryrefslogtreecommitdiff
path: root/modules/gdscript/gd_compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gd_compiler.cpp')
-rw-r--r--modules/gdscript/gd_compiler.cpp132
1 files changed, 102 insertions, 30 deletions
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp
index dd2834bf34..e6dd9d9ae1 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gd_compiler.cpp
@@ -60,7 +60,8 @@ bool GDCompiler::_create_unary_operator(CodeGen& codegen,const GDParser::Operato
codegen.opcodes.push_back(GDFunction::OPCODE_OPERATOR); // perform operator
codegen.opcodes.push_back(op); //which operator
codegen.opcodes.push_back(src_address_a); // argument 1
- codegen.opcodes.push_back(GDFunction::ADDR_TYPE_NIL); // argument 2 (unary only takes one parameter)
+ codegen.opcodes.push_back(src_address_a); // argument 2 (repeated)
+ //codegen.opcodes.push_back(GDFunction::ADDR_TYPE_NIL); // argument 2 (unary only takes one parameter)
return true;
}
@@ -185,51 +186,59 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
//TRY CLASS CONSTANTS
- GDScript *scr = codegen.script;
- GDNativeClass *nc=NULL;
- while(scr) {
+ GDScript *owner = codegen.script;
+ while (owner) {
- if (scr->constants.has(identifier)) {
+ GDScript *scr = owner;
+ GDNativeClass *nc=NULL;
+ while(scr) {
- //int idx=scr->constants[identifier];
- int idx = codegen.get_name_map_pos(identifier);
- return idx|(GDFunction::ADDR_TYPE_CLASS_CONSTANT<<GDFunction::ADDR_BITS); //argument (stack root)
+ if (scr->constants.has(identifier)) {
+
+ //int idx=scr->constants[identifier];
+ int idx = codegen.get_name_map_pos(identifier);
+ return idx|(GDFunction::ADDR_TYPE_CLASS_CONSTANT<<GDFunction::ADDR_BITS); //argument (stack root)
+ }
+ if (scr->native.is_valid())
+ nc=scr->native.ptr();
+ scr=scr->_base;
}
- if (scr->native.is_valid())
- nc=scr->native.ptr();
- scr=scr->_base;
- }
- // CLASS C++ Integer Constant
+ // CLASS C++ Integer Constant
- if (nc) {
+ if (nc) {
- bool success=false;
- int constant = ObjectTypeDB::get_integer_constant(nc->get_name(),identifier,&success);
- if (success) {
- Variant key=constant;
- int idx;
+ bool success=false;
+ int constant = ObjectTypeDB::get_integer_constant(nc->get_name(),identifier,&success);
+ if (success) {
+ Variant key=constant;
+ int idx;
- if (!codegen.constant_map.has(key)) {
+ if (!codegen.constant_map.has(key)) {
- idx=codegen.constant_map.size();
- codegen.constant_map[key]=idx;
+ idx=codegen.constant_map.size();
+ codegen.constant_map[key]=idx;
- } else {
- idx=codegen.constant_map[key];
+ } else {
+ idx=codegen.constant_map[key];
+ }
+
+ return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access)
}
- return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access)
}
+ owner=owner->_owner;
}
- if (codegen.script->subclasses.has(identifier)) {
+ /*
+ handled in constants now
+ if (codegen.script->subclasses.has(identifier)) {
//same with a subclass, make it a local constant.
int idx = codegen.get_constant_pos(codegen.script->subclasses[identifier]);
return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access)
- }
+ }*/
if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
@@ -452,6 +461,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
const GDParser::Node *instance = on->arguments[0];
+ bool in_static=false;
if (instance->type==GDParser::Node::TYPE_SELF) {
//room for optimization
@@ -465,7 +475,10 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
int ret;
- if (i==1) {
+ if (i==0 && on->arguments[i]->type==GDParser::Node::TYPE_SELF && codegen.function_node && codegen.function_node->_static) {
+ //static call to self
+ ret=(GDFunction::ADDR_TYPE_CLASS<<GDFunction::ADDR_BITS);
+ } else if (i==1) {
if (on->arguments[i]->type!=GDParser::Node::TYPE_IDENTIFIER) {
_set_error("Attempt to call a non-identifier.",on);
@@ -475,6 +488,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
ret=codegen.get_name_map_pos(id->name);
} else {
+
ret = _parse_expression(codegen,on->arguments[i],slevel);
if (ret<0)
return ret;
@@ -494,6 +508,34 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
codegen.opcodes.push_back(arguments[i]);
}
} break;
+ case GDParser::OperatorNode::OP_YIELD: {
+
+
+ ERR_FAIL_COND_V(on->arguments.size() && on->arguments.size()!=2,-1);
+
+ Vector<int> arguments;
+ int slevel = p_stack_level;
+ for(int i=0;i<on->arguments.size();i++) {
+
+ int ret = _parse_expression(codegen,on->arguments[i],slevel);
+ if (ret<0)
+ return ret;
+ if (ret&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
+ slevel++;
+ codegen.alloc_stack(slevel);
+ }
+ arguments.push_back(ret);
+ }
+
+ //push call bytecode
+ codegen.opcodes.push_back(arguments.size()==0?GDFunction::OPCODE_YIELD:GDFunction::OPCODE_YIELD_SIGNAL); // basic type constructor
+ for(int i=0;i<arguments.size();i++)
+ codegen.opcodes.push_back(arguments[i]); //arguments
+ codegen.opcodes.push_back(GDFunction::OPCODE_YIELD_RESUME);
+ //next will be where to place the result :)
+
+ } break;
+
//indexing operator
case GDParser::OperatorNode::OP_INDEX:
case GDParser::OperatorNode::OP_INDEX_NAMED: {
@@ -631,8 +673,8 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
case GDParser::OperatorNode::OP_BIT_OR: { if (!_create_binary_operator(codegen,on,Variant::OP_BIT_OR,p_stack_level)) return -1;} break;
case GDParser::OperatorNode::OP_BIT_XOR: { if (!_create_binary_operator(codegen,on,Variant::OP_BIT_XOR,p_stack_level)) return -1;} break;
//shift
- case GDParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break;
+ case GDParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break;
+ case GDParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break;
//assignment operators
case GDParser::OperatorNode::OP_ASSIGN_ADD:
case GDParser::OperatorNode::OP_ASSIGN_SUB:
@@ -1250,6 +1292,16 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
gdfunc->name=func_name;
gdfunc->_script=p_script;
gdfunc->source=source;
+
+#ifdef DEBUG_ENABLED
+
+ {
+ gdfunc->func_cname=(String(source)+" - "+String(func_name)).utf8();
+ gdfunc->_func_cname=gdfunc->func_cname.get_data();
+
+ }
+
+#endif
if (p_func) {
gdfunc->_initial_line=p_func->line;
} else {
@@ -1298,11 +1350,26 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
if (path!="") {
//path (and optionally subclasses)
+ if (path.is_rel_path()) {
+
+ String base = p_script->get_path();
+ if (base=="" || base.is_rel_path()) {
+ _set_error("Could not resolve relative path for parent class: "+path,p_class);
+ return ERR_FILE_NOT_FOUND;
+ }
+ path=base.get_base_dir().plus_file(path);
+ }
script = ResourceLoader::load(path);
if (script.is_null()) {
_set_error("Could not load base class: "+path,p_class);
return ERR_FILE_NOT_FOUND;
}
+ if (!script->valid) {
+
+ _set_error("Script not fully loaded (cyclic preload?): "+path,p_class);
+ return ERR_BUSY;
+ }
+ //print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid));
if (p_class->extends_class.size()) {
@@ -1405,6 +1472,9 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
}
+ //print_line("Script: "+p_script->get_path()+" indices: "+itos(p_script->member_indices.size()));
+
+
for(int i=0;i<p_class->variables.size();i++) {
StringName name = p_class->variables[i].identifier;
@@ -1452,6 +1522,8 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
Error err = _parse_class(subclass.ptr(),p_script,p_class->subclasses[i]);
if (err)
return err;
+
+ p_script->constants.insert(name,subclass); //once parsed, goes to the list of constants
p_script->subclasses.insert(name,subclass);
}