summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
Diffstat (limited to 'script')
-rw-r--r--script/SCsub16
-rw-r--r--script/gdscript/SCsub7
-rw-r--r--script/gdscript/gd_compiler.cpp1531
-rw-r--r--script/gdscript/gd_compiler.h181
-rw-r--r--script/gdscript/gd_editor.cpp781
-rw-r--r--script/gdscript/gd_functions.cpp1218
-rw-r--r--script/gdscript/gd_functions.h103
-rw-r--r--script/gdscript/gd_parser.cpp2469
-rw-r--r--script/gdscript/gd_parser.h397
-rw-r--r--script/gdscript/gd_pretty_print.cpp34
-rw-r--r--script/gdscript/gd_pretty_print.h40
-rw-r--r--script/gdscript/gd_script.cpp2222
-rw-r--r--script/gdscript/gd_script.h471
-rw-r--r--script/gdscript/gd_tokenizer.cpp973
-rw-r--r--script/gdscript/gd_tokenizer.h181
-rw-r--r--script/multiscript/SCsub7
-rw-r--r--script/multiscript/multi_script.cpp498
-rw-r--r--script/multiscript/multi_script.h157
-rw-r--r--script/register_script_types.cpp66
-rw-r--r--script/register_script_types.h38
-rw-r--r--script/script_binder.cpp13
-rw-r--r--script/script_binder.h15
22 files changed, 0 insertions, 11418 deletions
diff --git a/script/SCsub b/script/SCsub
deleted file mode 100644
index 7093dee36d..0000000000
--- a/script/SCsub
+++ /dev/null
@@ -1,16 +0,0 @@
-Import('env')
-
-env.script_sources=[]
-env.add_source_files(env.script_sources,"*.cpp")
-
-Export('env')
-
-if (env["gdscript"]=="yes"):
- SConscript('gdscript/SCsub');
-SConscript('multiscript/SCsub');
-
-lib = env.Library("script",env.script_sources, LIBSUFFIX=env['platform_libsuffix'])
-
-env.Prepend(LIBS=[lib])
-
-
diff --git a/script/gdscript/SCsub b/script/gdscript/SCsub
deleted file mode 100644
index dd812edec5..0000000000
--- a/script/gdscript/SCsub
+++ /dev/null
@@ -1,7 +0,0 @@
-Import('env')
-
-env.add_source_files(env.script_sources,"*.cpp")
-
-Export('env')
-
-
diff --git a/script/gdscript/gd_compiler.cpp b/script/gdscript/gd_compiler.cpp
deleted file mode 100644
index dd2834bf34..0000000000
--- a/script/gdscript/gd_compiler.cpp
+++ /dev/null
@@ -1,1531 +0,0 @@
-/*************************************************************************/
-/* gd_compiler.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gd_compiler.h"
-#include "gd_script.h"
-/* TODO:
-
- *AND and OR need early abort
- -Inheritance properly process (done?)
- *create built in initializer and constructor
- *assign operators
- *build arrays and dictionaries
- *call parent constructor
- */
-
-
-void GDCompiler::_set_error(const String& p_error,const GDParser::Node *p_node) {
-
- if (error!="")
- return;
-
- error=p_error;
- err_line=p_node->line;
- err_column=p_node->column;
-}
-
-bool GDCompiler::_create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level) {
-
- ERR_FAIL_COND_V(on->arguments.size()!=1,false);
-
- int src_address_a = _parse_expression(codegen,on->arguments[0],p_stack_level);
- if (src_address_a<0)
- return false;
-
- 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)
- return true;
-}
-
-bool GDCompiler::_create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level) {
-
- ERR_FAIL_COND_V(on->arguments.size()!=2,false);
-
-
- int src_address_a = _parse_expression(codegen,on->arguments[0],p_stack_level);
- if (src_address_a<0)
- return false;
- if (src_address_a&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)
- p_stack_level++; //uses stack for return, increase stack
-
- int src_address_b = _parse_expression(codegen,on->arguments[1],p_stack_level);
- if (src_address_b<0)
- return false;
-
-
- 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(src_address_b); // argument 2 (unary only takes one parameter)
- return true;
-}
-
-
-/*
-int GDCompiler::_parse_subexpression(CodeGen& codegen,const GDParser::Node *p_expression) {
-
-
- int ret = _parse_expression(codegen,p_expression);
- if (ret<0)
- return ret;
-
- if (ret&(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)) {
- codegen.stack_level++;
- codegen.check_max_stack_level();
- //stack was used, keep value
- }
-
- return ret;
-}
-*/
-
-int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser::OperatorNode *p_expression, int p_stack_level) {
-
- Variant::Operator var_op=Variant::OP_MAX;
-
- switch(p_expression->op) {
-
- case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op=Variant::OP_ADD; break;
- case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op=Variant::OP_SUBSTRACT; break;
- case GDParser::OperatorNode::OP_ASSIGN_MUL: var_op=Variant::OP_MULTIPLY; break;
- case GDParser::OperatorNode::OP_ASSIGN_DIV: var_op=Variant::OP_DIVIDE; break;
- case GDParser::OperatorNode::OP_ASSIGN_MOD: var_op=Variant::OP_MODULE; break;
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: var_op=Variant::OP_SHIFT_LEFT; break;
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: var_op=Variant::OP_SHIFT_RIGHT; break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op=Variant::OP_BIT_AND; break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op=Variant::OP_BIT_OR; break;
- case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op=Variant::OP_BIT_XOR; break;
- case GDParser::OperatorNode::OP_ASSIGN: {
-
- //none
- } break;
- default: {
-
- ERR_FAIL_V(-1);
- }
- }
-
- if (var_op==Variant::OP_MAX) {
-
- return _parse_expression(codegen,p_expression->arguments[1],p_stack_level);
- }
-
- if (!_create_binary_operator(codegen,p_expression,var_op,p_stack_level))
- return -1;
-
- int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
- codegen.alloc_stack(p_stack_level);
- return dst_addr;
-
-}
-
-int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root) {
-
-
- switch(p_expression->type) {
- //should parse variable declaration and adjust stack accordingly...
- case GDParser::Node::TYPE_IDENTIFIER: {
- //return identifier
- //wait, identifier could be a local variable or something else... careful here, must reference properly
- //as stack may be more interesting to work with
-
- //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases peformance a lot.
-
- const GDParser::IdentifierNode *in = static_cast<const GDParser::IdentifierNode*>(p_expression);
-
- StringName identifier = in->name;
-
- // TRY STACK!
- if (codegen.stack_identifiers.has(identifier)) {
-
- int pos = codegen.stack_identifiers[identifier];
- return pos|(GDFunction::ADDR_TYPE_STACK_VARIABLE<<GDFunction::ADDR_BITS);
-
- }
- //TRY ARGUMENTS!
- if (!codegen.function_node || !codegen.function_node->_static) {
-
- // TRY MEMBER VARIABLES!
-
- //static function
- if (codegen.script->member_indices.has(identifier)) {
-
- int idx = codegen.script->member_indices[identifier];
- return idx|(GDFunction::ADDR_TYPE_MEMBER<<GDFunction::ADDR_BITS); //argument (stack root)
- }
- }
-
- //TRY CLASS CONSTANTS
-
- GDScript *scr = codegen.script;
- GDNativeClass *nc=NULL;
- while(scr) {
-
- 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;
- }
-
- // CLASS C++ Integer Constant
-
- if (nc) {
-
- 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)) {
-
- idx=codegen.constant_map.size();
- codegen.constant_map[key]=idx;
-
- } else {
- idx=codegen.constant_map[key];
- }
-
- return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access)
- }
-
- }
-
- 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)) {
-
- int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
- return idx|(GDFunction::ADDR_TYPE_GLOBAL<<GDFunction::ADDR_BITS); //argument (stack root)
- }
-
- //not found, error
-
- _set_error("Identifier not found: "+String(identifier),p_expression);
-
- return -1;
-
-
- } break;
- case GDParser::Node::TYPE_CONSTANT: {
- //return constant
- const GDParser::ConstantNode *cn = static_cast<const GDParser::ConstantNode*>(p_expression);
-
-
- int idx;
-
- if (!codegen.constant_map.has(cn->value)) {
-
- idx=codegen.constant_map.size();
- codegen.constant_map[cn->value]=idx;
-
- } else {
- idx=codegen.constant_map[cn->value];
- }
-
-
- return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //argument (stack root)
-
- } break;
- case GDParser::Node::TYPE_SELF: {
- //return constant
- if (codegen.function_node && codegen.function_node->_static) {
- _set_error("'self' not present in static function!",p_expression);
- return -1;
- }
- return (GDFunction::ADDR_TYPE_SELF<<GDFunction::ADDR_BITS);
- } break;
- case GDParser::Node::TYPE_ARRAY: {
-
- const GDParser::ArrayNode *an = static_cast<const GDParser::ArrayNode*>(p_expression);
- Vector<int> values;
-
- int slevel=p_stack_level;
-
- for(int i=0;i<an->elements.size();i++) {
-
- int ret = _parse_expression(codegen,an->elements[i],slevel);
- if (ret<0)
- return ret;
- if (ret&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
- values.push_back(ret);
- }
-
- codegen.opcodes.push_back(GDFunction::OPCODE_CONSTRUCT_ARRAY);
- codegen.opcodes.push_back(values.size());
- for(int i=0;i<values.size();i++)
- codegen.opcodes.push_back(values[i]);
-
- int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
- codegen.alloc_stack(p_stack_level);
- return dst_addr;
-
- } break;
- case GDParser::Node::TYPE_DICTIONARY: {
-
- const GDParser::DictionaryNode *dn = static_cast<const GDParser::DictionaryNode*>(p_expression);
- Vector<int> values;
-
- int slevel=p_stack_level;
-
- for(int i=0;i<dn->elements.size();i++) {
-
- int ret = _parse_expression(codegen,dn->elements[i].key,slevel);
- if (ret<0)
- return ret;
- if (ret&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
- values.push_back(ret);
-
- ret = _parse_expression(codegen,dn->elements[i].value,slevel);
- if (ret<0)
- return ret;
- if (ret&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
- values.push_back(ret);
- }
-
- codegen.opcodes.push_back(GDFunction::OPCODE_CONSTRUCT_DICTIONARY);
- codegen.opcodes.push_back(dn->elements.size());
- for(int i=0;i<values.size();i++)
- codegen.opcodes.push_back(values[i]);
-
- int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
- codegen.alloc_stack(p_stack_level);
- return dst_addr;
-
- } break;
- case GDParser::Node::TYPE_OPERATOR: {
- //hell breaks loose
-
- const GDParser::OperatorNode *on = static_cast<const GDParser::OperatorNode*>(p_expression);
- switch(on->op) {
-
-
- //call/constructor operator
- case GDParser::OperatorNode::OP_PARENT_CALL: {
-
-
- ERR_FAIL_COND_V(on->arguments.size()<1,-1);
-
- const GDParser::IdentifierNode *in = (const GDParser::IdentifierNode *)on->arguments[0];
-
-
- Vector<int> arguments;
- int slevel = p_stack_level;
- for(int i=1;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(GDFunction::OPCODE_CALL_SELF_BASE); // basic type constructor
-
- codegen.opcodes.push_back(codegen.get_name_map_pos(in->name)); //instance
- codegen.opcodes.push_back(arguments.size()); //argument count
- codegen.alloc_call(arguments.size());
- for(int i=0;i<arguments.size();i++)
- codegen.opcodes.push_back(arguments[i]); //arguments
-
- } break;
- case GDParser::OperatorNode::OP_CALL: {
-
- if (on->arguments[0]->type==GDParser::Node::TYPE_TYPE) {
- //construct a basic type
- ERR_FAIL_COND_V(on->arguments.size()<1,-1);
-
- const GDParser::TypeNode *tn = (const GDParser::TypeNode *)on->arguments[0];
- int vtype = tn->vtype;
-
- Vector<int> arguments;
- int slevel = p_stack_level;
- for(int i=1;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(GDFunction::OPCODE_CONSTRUCT); // basic type constructor
- codegen.opcodes.push_back(vtype); //instance
- codegen.opcodes.push_back(arguments.size()); //argument count
- codegen.alloc_call(arguments.size());
- for(int i=0;i<arguments.size();i++)
- codegen.opcodes.push_back(arguments[i]); //arguments
-
- } else if (on->arguments[0]->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) {
- //built in function
-
- ERR_FAIL_COND_V(on->arguments.size()<1,-1);
-
-
- Vector<int> arguments;
- int slevel = p_stack_level;
- for(int i=1;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);
- }
-
-
- codegen.opcodes.push_back(GDFunction::OPCODE_CALL_BUILT_IN);
- codegen.opcodes.push_back(static_cast<const GDParser::BuiltInFunctionNode*>(on->arguments[0])->function);
- codegen.opcodes.push_back(on->arguments.size()-1);
- codegen.alloc_call(on->arguments.size()-1);
- for(int i=0;i<arguments.size();i++)
- codegen.opcodes.push_back(arguments[i]);
-
- } else {
- //regular function
- ERR_FAIL_COND_V(on->arguments.size()<2,-1);
-
- const GDParser::Node *instance = on->arguments[0];
-
- if (instance->type==GDParser::Node::TYPE_SELF) {
- //room for optimization
-
- }
-
-
- Vector<int> arguments;
- int slevel = p_stack_level;
-
- for(int i=0;i<on->arguments.size();i++) {
-
- int ret;
-
- if (i==1) {
-
- if (on->arguments[i]->type!=GDParser::Node::TYPE_IDENTIFIER) {
- _set_error("Attempt to call a non-identifier.",on);
- return -1;
- }
- GDParser::IdentifierNode *id = static_cast<GDParser::IdentifierNode*>(on->arguments[i]);
- ret=codegen.get_name_map_pos(id->name);
-
- } else {
- 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);
-
- }
-
- codegen.opcodes.push_back(p_root?GDFunction::OPCODE_CALL:GDFunction::OPCODE_CALL_RETURN); // perform operator
- codegen.opcodes.push_back(on->arguments.size()-2);
- codegen.alloc_call(on->arguments.size()-2);
- for(int i=0;i<arguments.size();i++)
- codegen.opcodes.push_back(arguments[i]);
- }
- } break;
- //indexing operator
- case GDParser::OperatorNode::OP_INDEX:
- case GDParser::OperatorNode::OP_INDEX_NAMED: {
-
- ERR_FAIL_COND_V(on->arguments.size()!=2,-1);
-
- int slevel = p_stack_level;
- bool named=(on->op==GDParser::OperatorNode::OP_INDEX_NAMED);
-
- int from = _parse_expression(codegen,on->arguments[0],slevel);
- if (from<0)
- return from;
-
- int index;
- if (named) {
-
- index=codegen.get_name_map_pos(static_cast<GDParser::IdentifierNode*>(on->arguments[1])->name);
-
- } else {
-
- if (on->arguments[1]->type==GDParser::Node::TYPE_CONSTANT && static_cast<const GDParser::ConstantNode*>(on->arguments[1])->value.get_type()==Variant::STRING) {
- //also, somehow, named (speed up anyway)
- StringName name = static_cast<const GDParser::ConstantNode*>(on->arguments[1])->value;
- index=codegen.get_name_map_pos(name);
- named=true;
-
- } else {
- //regular indexing
- if (from&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
- index = _parse_expression(codegen,on->arguments[1],slevel);
- if (index<0)
- return index;
- }
- }
-
- codegen.opcodes.push_back(named?GDFunction::OPCODE_GET_NAMED:GDFunction::OPCODE_GET); // perform operator
- codegen.opcodes.push_back(from); // argument 1
- codegen.opcodes.push_back(index); // argument 2 (unary only takes one parameter)
-
- } break;
- case GDParser::OperatorNode::OP_AND: {
-
- // AND operator with early out on failure
-
- int res = _parse_expression(codegen,on->arguments[0],p_stack_level);
- if (res<0)
- return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
- codegen.opcodes.push_back(res);
- int jump_fail_pos=codegen.opcodes.size();
- codegen.opcodes.push_back(0);
-
- res = _parse_expression(codegen,on->arguments[1],p_stack_level);
- if (res<0)
- return res;
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
- codegen.opcodes.push_back(res);
- int jump_fail_pos2=codegen.opcodes.size();
- codegen.opcodes.push_back(0);
-
- codegen.alloc_stack(p_stack_level); //it will be used..
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_TRUE);
- codegen.opcodes.push_back(p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(codegen.opcodes.size()+3);
- codegen.opcodes[jump_fail_pos]=codegen.opcodes.size();
- codegen.opcodes[jump_fail_pos2]=codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_FALSE);
- codegen.opcodes.push_back(p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- return p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS;
-
- } break;
- case GDParser::OperatorNode::OP_OR: {
-
- // OR operator with early out on success
-
- int res = _parse_expression(codegen,on->arguments[0],p_stack_level);
- if (res<0)
- return res;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF);
- codegen.opcodes.push_back(res);
- int jump_success_pos=codegen.opcodes.size();
- codegen.opcodes.push_back(0);
-
- res = _parse_expression(codegen,on->arguments[1],p_stack_level);
- if (res<0)
- return res;
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF);
- codegen.opcodes.push_back(res);
- int jump_success_pos2=codegen.opcodes.size();
- codegen.opcodes.push_back(0);
-
- codegen.alloc_stack(p_stack_level); //it will be used..
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_FALSE);
- codegen.opcodes.push_back(p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(codegen.opcodes.size()+3);
- codegen.opcodes[jump_success_pos]=codegen.opcodes.size();
- codegen.opcodes[jump_success_pos2]=codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN_TRUE);
- codegen.opcodes.push_back(p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- return p_stack_level|GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS;
-
- } break;
- //unary operators
- case GDParser::OperatorNode::OP_NEG: { if (!_create_unary_operator(codegen,on,Variant::OP_NEGATE,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_NOT: { if (!_create_unary_operator(codegen,on,Variant::OP_NOT,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_BIT_INVERT: { if (!_create_unary_operator(codegen,on,Variant::OP_BIT_NEGATE,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_PREINC: { } break; //?
- case GDParser::OperatorNode::OP_PREDEC: { } break;
- case GDParser::OperatorNode::OP_INC: { } break;
- case GDParser::OperatorNode::OP_DEC: { } break;
- //binary operators (in precedence order)
- case GDParser::OperatorNode::OP_IN: { if (!_create_binary_operator(codegen,on,Variant::OP_IN,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_EQUAL: { if (!_create_binary_operator(codegen,on,Variant::OP_EQUAL,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_NOT_EQUAL: { if (!_create_binary_operator(codegen,on,Variant::OP_NOT_EQUAL,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_LESS: { if (!_create_binary_operator(codegen,on,Variant::OP_LESS,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_LESS_EQUAL: { if (!_create_binary_operator(codegen,on,Variant::OP_LESS_EQUAL,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_GREATER: { if (!_create_binary_operator(codegen,on,Variant::OP_GREATER,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_GREATER_EQUAL: { if (!_create_binary_operator(codegen,on,Variant::OP_GREATER_EQUAL,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_ADD: { if (!_create_binary_operator(codegen,on,Variant::OP_ADD,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_SUB: { if (!_create_binary_operator(codegen,on,Variant::OP_SUBSTRACT,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_MUL: { if (!_create_binary_operator(codegen,on,Variant::OP_MULTIPLY,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_DIV: { if (!_create_binary_operator(codegen,on,Variant::OP_DIVIDE,p_stack_level)) return -1;} break;
- case GDParser::OperatorNode::OP_MOD: { if (!_create_binary_operator(codegen,on,Variant::OP_MODULE,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;
- case GDParser::OperatorNode::OP_BIT_AND: { if (!_create_binary_operator(codegen,on,Variant::OP_BIT_AND,p_stack_level)) return -1;} break;
- 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;
- //assignment operators
- case GDParser::OperatorNode::OP_ASSIGN_ADD:
- case GDParser::OperatorNode::OP_ASSIGN_SUB:
- case GDParser::OperatorNode::OP_ASSIGN_MUL:
- case GDParser::OperatorNode::OP_ASSIGN_DIV:
- case GDParser::OperatorNode::OP_ASSIGN_MOD:
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT:
- case GDParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT:
- case GDParser::OperatorNode::OP_ASSIGN_BIT_AND:
- case GDParser::OperatorNode::OP_ASSIGN_BIT_OR:
- case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR:
- case GDParser::OperatorNode::OP_ASSIGN: {
-
- ERR_FAIL_COND_V(on->arguments.size()!=2,-1);
-
-
- if (on->arguments[0]->type==GDParser::Node::TYPE_OPERATOR && (static_cast<GDParser::OperatorNode*>(on->arguments[0])->op==GDParser::OperatorNode::OP_INDEX || static_cast<GDParser::OperatorNode*>(on->arguments[0])->op==GDParser::OperatorNode::OP_INDEX_NAMED)) {
- //SET (chained) MODE!!
-
- int slevel=p_stack_level;
-
- GDParser::OperatorNode* op = static_cast<GDParser::OperatorNode*>(on->arguments[0]);
-
- /* Find chain of sets */
-
- List<GDParser::OperatorNode*> chain;
-
- {
- //create get/set chain
- GDParser::OperatorNode* n=op;
- while(true) {
-
- chain.push_back(n);
- if (n->arguments[0]->type!=GDParser::Node::TYPE_OPERATOR)
- break;
- n = static_cast<GDParser::OperatorNode*>(n->arguments[0]);
- if (n->op!=GDParser::OperatorNode::OP_INDEX && n->op!=GDParser::OperatorNode::OP_INDEX_NAMED)
- break;
- }
- }
-
- /* Chain of gets */
-
- //get at (potential) root stack pos, so it can be returned
- int prev_pos = _parse_expression(codegen,chain.back()->get()->arguments[0],slevel);
- if (prev_pos<0)
- return prev_pos;
- int retval=prev_pos;
-
- if (retval&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
-
- Vector<int> setchain;
-
- for(List<GDParser::OperatorNode*>::Element *E=chain.back();E;E=E->prev()) {
-
-
- if (E==chain.front()) //ignore first
- break;
-
- bool named = E->get()->op==GDParser::OperatorNode::OP_INDEX_NAMED;
- int key_idx;
-
- if (named) {
-
- key_idx = codegen.get_name_map_pos(static_cast<const GDParser::IdentifierNode*>(E->get()->arguments[1])->name);
- } else {
-
- GDParser::Node *key = E->get()->arguments[1];
- key_idx = _parse_expression(codegen,key,slevel);
- if (retval&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
- }
-
- if (key_idx<0)
- return key_idx;
-
- codegen.opcodes.push_back(named ? GDFunction::OPCODE_GET_NAMED : GDFunction::OPCODE_GET);
- codegen.opcodes.push_back(prev_pos);
- codegen.opcodes.push_back(key_idx);
- slevel++;
- codegen.alloc_stack(slevel);
- int dst_pos = (GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)|slevel;
- codegen.opcodes.push_back(dst_pos);
-
- //add in reverse order, since it will be reverted
- setchain.push_back(dst_pos);
- setchain.push_back(key_idx);
- setchain.push_back(prev_pos);
- setchain.push_back(named ? GDFunction::OPCODE_SET_NAMED : GDFunction::OPCODE_SET);
-
- prev_pos=dst_pos;
-
- }
-
- setchain.invert();
-
-
- int set_index;
- bool named=false;
-
-
- if (static_cast<const GDParser::OperatorNode*>(op)->op==GDParser::OperatorNode::OP_INDEX_NAMED) {
-
-
- set_index=codegen.get_name_map_pos(static_cast<const GDParser::IdentifierNode*>(op->arguments[1])->name);
- named=true;
- } else {
-
- set_index = _parse_expression(codegen,op->arguments[1],slevel+1);
- named=false;
- }
-
-
- if (set_index<0)
- return set_index;
-
- if (set_index&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
-
- int set_value = _parse_assign_right_expression(codegen,on,slevel+1);
- if (set_value<0)
- return set_value;
-
- codegen.opcodes.push_back(named?GDFunction::OPCODE_SET_NAMED:GDFunction::OPCODE_SET);
- codegen.opcodes.push_back(prev_pos);
- codegen.opcodes.push_back(set_index);
- codegen.opcodes.push_back(set_value);
-
- for(int i=0;i<setchain.size();i+=4) {
-
-
- codegen.opcodes.push_back(setchain[i+0]);
- codegen.opcodes.push_back(setchain[i+1]);
- codegen.opcodes.push_back(setchain[i+2]);
- codegen.opcodes.push_back(setchain[i+3]);
- }
-
- return retval;
-
-
- } else {
- //ASSIGNMENT MODE!!
-
- int slevel = p_stack_level;
-
- int dst_address_a = _parse_expression(codegen,on->arguments[0],slevel);
- if (dst_address_a<0)
- return -1;
-
- if (dst_address_a&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
- slevel++;
- codegen.alloc_stack(slevel);
- }
-
- int src_address_b = _parse_assign_right_expression(codegen,on,slevel);
- if (src_address_b<0)
- return -1;
-
-
-
-
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN); // perform operator
- codegen.opcodes.push_back(dst_address_a); // argument 1
- codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
- return dst_address_a; //if anything, returns wathever was assigned or correct stack position
-
- }
-
-
- } break;
- case GDParser::OperatorNode::OP_EXTENDS: {
-
- ERR_FAIL_COND_V(on->arguments.size()!=2,false);
-
-
- int slevel = p_stack_level;
-
- int src_address_a = _parse_expression(codegen,on->arguments[0],slevel);
- if (src_address_a<0)
- return -1;
-
- if (src_address_a&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)
- slevel++; //uses stack for return, increase stack
-
- int src_address_b = _parse_expression(codegen,on->arguments[1],slevel);
- if (src_address_b<0)
- return -1;
-
- codegen.opcodes.push_back(GDFunction::OPCODE_EXTENDS_TEST); // perform operator
- codegen.opcodes.push_back(src_address_a); // argument 1
- codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
-
- } break;
- default: {
-
-
- ERR_EXPLAIN("Bug in bytecode compiler, unexpected operator #"+itos(on->op)+" in parse tree while parsing expression.");
- ERR_FAIL_V(0); //unreachable code
-
- } break;
- }
-
- int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
- codegen.alloc_stack(p_stack_level);
- return dst_addr;
- } break;
- //TYPE_TYPE,
- default: {
-
- ERR_EXPLAIN("Bug in bytecode compiler, unexpected node in parse tree while parsing expression.");
- ERR_FAIL_V(-1); //unreachable code
- } break;
-
-
- }
-
- ERR_FAIL_V(-1); //unreachable code
-}
-
-
-Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level,int p_break_addr,int p_continue_addr) {
-
- codegen.push_stack_identifiers();
- int new_identifiers=0;
- codegen.current_line=p_block->line;
-
- for(int i=0;i<p_block->statements.size();i++) {
-
- const GDParser::Node *s = p_block->statements[i];
-
-
- switch(s->type) {
- case GDParser::Node::TYPE_NEWLINE: {
-
- const GDParser::NewLineNode *nl = static_cast<const GDParser::NewLineNode*>(s);
- codegen.opcodes.push_back(GDFunction::OPCODE_LINE);
- codegen.opcodes.push_back(nl->line);
- codegen.current_line=nl->line;
-
- } break;
- case GDParser::Node::TYPE_CONTROL_FLOW: {
- // try subblocks
-
- const GDParser::ControlFlowNode *cf = static_cast<const GDParser::ControlFlowNode*>(s);
-
- switch(cf->cf_type) {
-
-
- case GDParser::ControlFlowNode::CF_IF: {
-
-#ifdef DEBUG_ENABLED
- codegen.opcodes.push_back(GDFunction::OPCODE_LINE);
- codegen.opcodes.push_back(cf->line);
- codegen.current_line=cf->line;
-#endif
- int ret = _parse_expression(codegen,cf->arguments[0],p_stack_level,false);
- if (ret<0)
- return ERR_PARSE_ERROR;
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
- codegen.opcodes.push_back(ret);
- int else_addr=codegen.opcodes.size();
- codegen.opcodes.push_back(0); //temporary
-
- Error err = _parse_block(codegen,cf->body,p_stack_level,p_break_addr,p_continue_addr);
- if (err)
- return err;
-
- if (cf->body_else) {
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- int end_addr=codegen.opcodes.size();
- codegen.opcodes.push_back(0);
- codegen.opcodes[else_addr]=codegen.opcodes.size();
-
- Error err = _parse_block(codegen,cf->body_else,p_stack_level,p_break_addr,p_continue_addr);
- if (err)
- return err;
-
- codegen.opcodes[end_addr]=codegen.opcodes.size();
- } else {
- //end without else
- codegen.opcodes[else_addr]=codegen.opcodes.size();
-
- }
-
- } break;
- case GDParser::ControlFlowNode::CF_FOR: {
-
-
-
- int slevel=p_stack_level;
- int iter_stack_pos=slevel;
- int iterator_pos = (slevel++)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- int counter_pos = (slevel++)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- int container_pos = (slevel++)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
- codegen.alloc_stack(slevel);
-
- codegen.push_stack_identifiers();
- codegen.add_stack_identifier(static_cast<const GDParser::IdentifierNode*>(cf->arguments[0])->name,iter_stack_pos);
-
- int ret = _parse_expression(codegen,cf->arguments[1],slevel,false);
- if (ret<0)
- return ERR_COMPILATION_FAILED;
-
- //assign container
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSIGN);
- codegen.opcodes.push_back(container_pos);
- codegen.opcodes.push_back(ret);
-
- //begin loop
- codegen.opcodes.push_back(GDFunction::OPCODE_ITERATE_BEGIN);
- codegen.opcodes.push_back(counter_pos);
- codegen.opcodes.push_back(container_pos);
- codegen.opcodes.push_back(codegen.opcodes.size()+4);
- codegen.opcodes.push_back(iterator_pos);
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP); //skip code for next
- codegen.opcodes.push_back(codegen.opcodes.size()+8);
- //break loop
- int break_pos=codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP); //skip code for next
- codegen.opcodes.push_back(0); //skip code for next
- //next loop
- int continue_pos=codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_ITERATE);
- codegen.opcodes.push_back(counter_pos);
- codegen.opcodes.push_back(container_pos);
- codegen.opcodes.push_back(break_pos);
- codegen.opcodes.push_back(iterator_pos);
-
-
- Error err = _parse_block(codegen,cf->body,slevel,break_pos,continue_pos);
- if (err)
- return err;
-
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(continue_pos);
- codegen.opcodes[break_pos+1]=codegen.opcodes.size();
-
-
- codegen.pop_stack_identifiers();
-
- } break;
- case GDParser::ControlFlowNode::CF_WHILE: {
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(codegen.opcodes.size()+3);
- int break_addr=codegen.opcodes.size();
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(0);
- int continue_addr=codegen.opcodes.size();
-
- int ret = _parse_expression(codegen,cf->arguments[0],p_stack_level,false);
- if (ret<0)
- return ERR_PARSE_ERROR;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF_NOT);
- codegen.opcodes.push_back(ret);
- codegen.opcodes.push_back(break_addr);
- Error err = _parse_block(codegen,cf->body,p_stack_level,break_addr,continue_addr);
- if (err)
- return err;
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(continue_addr);
-
- codegen.opcodes[break_addr+1]=codegen.opcodes.size();
-
- } break;
- case GDParser::ControlFlowNode::CF_SWITCH: {
-
- } break;
- case GDParser::ControlFlowNode::CF_BREAK: {
-
- if (p_break_addr<0) {
-
- _set_error("'break'' not within loop",cf);
- return ERR_COMPILATION_FAILED;
- }
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(p_break_addr);
-
- } break;
- case GDParser::ControlFlowNode::CF_CONTINUE: {
-
- if (p_continue_addr<0) {
-
- _set_error("'continue' not within loop",cf);
- return ERR_COMPILATION_FAILED;
- }
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
- codegen.opcodes.push_back(p_continue_addr);
-
- } break;
- case GDParser::ControlFlowNode::CF_RETURN: {
-
- int ret;
-
- if (cf->arguments.size()) {
-
- ret = _parse_expression(codegen,cf->arguments[0],p_stack_level,false);
- if (ret<0)
- return ERR_PARSE_ERROR;
-
- } else {
-
- ret=GDFunction::ADDR_TYPE_NIL << GDFunction::ADDR_BITS;
- }
-
- codegen.opcodes.push_back(GDFunction::OPCODE_RETURN);
- codegen.opcodes.push_back(ret);
-
- } break;
-
- }
- } break;
- case GDParser::Node::TYPE_ASSERT: {
- // try subblocks
-
- const GDParser::AssertNode *as = static_cast<const GDParser::AssertNode*>(s);
-
- int ret = _parse_expression(codegen,as->condition,p_stack_level,false);
- if (ret<0)
- return ERR_PARSE_ERROR;
-
- codegen.opcodes.push_back(GDFunction::OPCODE_ASSERT);
- codegen.opcodes.push_back(ret);
- } break;
- case GDParser::Node::TYPE_LOCAL_VAR: {
-
-
- const GDParser::LocalVarNode *lv = static_cast<const GDParser::LocalVarNode*>(s);
-
- codegen.add_stack_identifier(lv->name,p_stack_level++);
- codegen.alloc_stack(p_stack_level);
- new_identifiers++;
-
- } break;
- default: {
- //expression
- int ret = _parse_expression(codegen,s,p_stack_level,true);
- if (ret<0)
- return ERR_PARSE_ERROR;
- } break;
-
- }
-
- }
- codegen.pop_stack_identifiers();
- return OK;
-}
-
-
-Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func) {
-
- Vector<int> bytecode;
- CodeGen codegen;
-
- codegen.class_node=p_class;
- codegen.script=p_script;
- codegen.function_node=p_func;
- codegen.stack_max=0;
- codegen.current_line=0;
- codegen.call_max=0;
- codegen.debug_stack=ScriptDebugger::get_singleton()!=NULL;
-
- int stack_level=0;
-
- if (p_func) {
- for(int i=0;i<p_func->arguments.size();i++) {
- int idx = i;
- codegen.add_stack_identifier(p_func->arguments[i],i);
- }
- stack_level=p_func->arguments.size();
- }
-
- codegen.alloc_stack(stack_level);
-
- /* Parse initializer -if applies- */
-
- bool is_initializer=false || !p_func;
-
- if (!p_func || String(p_func->name)=="_init") {
- //parse initializer for class members
- if (!p_func && p_class->extends_used && p_script->native.is_null()){
-
- //call implicit parent constructor
- codegen.opcodes.push_back(GDFunction::OPCODE_CALL_SELF_BASE);
- codegen.opcodes.push_back(codegen.get_name_map_pos("_init"));
- codegen.opcodes.push_back(0);
- codegen.opcodes.push_back((GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)|0);
-
- }
- Error err = _parse_block(codegen,p_class->initializer,stack_level);
- if (err)
- return err;
- is_initializer=true;
-
- }
-
- /* Parse default argument code -if applies- */
-
- Vector<int> defarg_addr;
- StringName func_name;
-
- if (p_func) {
- if (p_func->default_values.size()) {
-
- codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
- defarg_addr.push_back(codegen.opcodes.size());
- for(int i=0;i<p_func->default_values.size();i++) {
-
- _parse_expression(codegen,p_func->default_values[i],stack_level,true);
- defarg_addr.push_back(codegen.opcodes.size());
- }
-
-
- defarg_addr.invert();
- }
-
-
-
- Error err = _parse_block(codegen,p_func->body,stack_level);
- if (err)
- return err;
-
- func_name=p_func->name;
- } else {
- func_name="_init";
- }
-
- codegen.opcodes.push_back(GDFunction::OPCODE_END);
-
- GDFunction *gdfunc=NULL;
-
- //if (String(p_func->name)=="") { //initializer func
- // gdfunc = &p_script->initializer;
-
- //} else { //regular func
- p_script->member_functions[func_name]=GDFunction();
- gdfunc = &p_script->member_functions[func_name];
- //}
-
- if (p_func)
- gdfunc->_static=p_func->_static;
-
- //constants
- if (codegen.constant_map.size()) {
- gdfunc->_constant_count=codegen.constant_map.size();
- gdfunc->constants.resize(codegen.constant_map.size());
- gdfunc->_constants_ptr=&gdfunc->constants[0];
- const Variant *K=NULL;
- while((K=codegen.constant_map.next(K))) {
- int idx = codegen.constant_map[*K];
- gdfunc->constants[idx]=*K;
- }
- } else {
-
- gdfunc->_constants_ptr=NULL;
- gdfunc->_constant_count=0;
- }
- //global names
- if (codegen.name_map.size()) {
-
- gdfunc->global_names.resize(codegen.name_map.size());
- gdfunc->_global_names_ptr = &gdfunc->global_names[0];
- for(Map<StringName,int>::Element *E=codegen.name_map.front();E;E=E->next()) {
-
- gdfunc->global_names[E->get()]=E->key();
- }
- gdfunc->_global_names_count=gdfunc->global_names.size();
-
- } else {
- gdfunc->_global_names_ptr = NULL;
- gdfunc->_global_names_count =0;
- }
-
-
- if (codegen.opcodes.size()) {
-
- gdfunc->code=codegen.opcodes;
- gdfunc->_code_ptr=&gdfunc->code[0];
- gdfunc->_code_size=codegen.opcodes.size();
-
- } else {
-
- gdfunc->_code_ptr=NULL;
- gdfunc->_code_size=0;
- }
-
- if (defarg_addr.size()) {
-
- gdfunc->default_arguments=defarg_addr;
- gdfunc->_default_arg_count=defarg_addr.size();
- gdfunc->_default_arg_ptr=&gdfunc->default_arguments[0];
- } else {
- gdfunc->_default_arg_count=0;
- gdfunc->_default_arg_ptr=NULL;
- }
-
- gdfunc->_argument_count=p_func ? p_func->arguments.size() : 0;
- gdfunc->_stack_size=codegen.stack_max;
- gdfunc->_call_size=codegen.call_max;
- gdfunc->name=func_name;
- gdfunc->_script=p_script;
- gdfunc->source=source;
- if (p_func) {
- gdfunc->_initial_line=p_func->line;
- } else {
- gdfunc->_initial_line=0;
- }
-
- if (codegen.debug_stack)
- gdfunc->stack_debug=codegen.stack_debug;
-
- if (is_initializer)
- p_script->initializer=gdfunc;
-
-
- return OK;
-}
-
-
-
-Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class) {
-
-
- p_script->native=Ref<GDNativeClass>();
- p_script->base=Ref<GDScript>();
- p_script->_base=NULL;
- p_script->members.clear();
- p_script->constants.clear();
- p_script->member_functions.clear();
- p_script->member_indices.clear();
- p_script->member_info.clear();
- p_script->initializer=NULL;
- p_script->subclasses.clear();
- p_script->_owner=p_owner;
- p_script->tool=p_class->tool;
- p_script->name=p_class->name;
-
-
- int index_from=0;
-
- if (p_class->extends_used) {
- //do inheritance
- String path = p_class->extends_file;
-
- Ref<GDScript> script;
- Ref<GDNativeClass> native;
-
- if (path!="") {
- //path (and optionally subclasses)
-
- script = ResourceLoader::load(path);
- if (script.is_null()) {
- _set_error("Could not load base class: "+path,p_class);
- return ERR_FILE_NOT_FOUND;
- }
-
- if (p_class->extends_class.size()) {
-
- for(int i=0;i<p_class->extends_class.size();i++) {
-
- String sub = p_class->extends_class[i];
- if (script->subclasses.has(sub)) {
-
- script=script->subclasses[sub];
- } else {
-
- _set_error("Could not find subclass: "+sub,p_class);
- return ERR_FILE_NOT_FOUND;
- }
- }
- }
-
- } else {
-
- ERR_FAIL_COND_V(p_class->extends_class.size()==0,ERR_BUG);
- //look around for the subclasses
-
- String base=p_class->extends_class[0];
- GDScript *p = p_owner;
- Ref<GDScript> base_class;
-
- while(p) {
-
- if (p->subclasses.has(base)) {
-
- base_class=p->subclasses[base];
- break;
- }
- p=p->_owner;
- }
-
- if (base_class.is_valid()) {
-
- for(int i=1;i<p_class->extends_class.size();i++) {
-
- String subclass=p_class->extends_class[i];
-
- if (base_class->subclasses.has(subclass)) {
-
- base_class=base_class->subclasses[subclass];
- } else {
-
- _set_error("Could not find subclass: "+subclass,p_class);
- return ERR_FILE_NOT_FOUND;
- }
- }
-
- script=base_class;
-
-
- } else {
-
- if (p_class->extends_class.size()>1) {
-
- _set_error("Invalid inheritance (unknown class+subclasses)",p_class);
- return ERR_FILE_NOT_FOUND;
-
- }
- //if not found, try engine classes
- if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) {
-
- _set_error("Unknown class: '"+base+"'",p_class);
- return ERR_FILE_NOT_FOUND;
- }
-
- int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base];
- native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx];
- if (!native.is_valid()) {
-
- _set_error("Global not a class: '"+base+"'",p_class);
-
- return ERR_FILE_NOT_FOUND;
- }
- }
-
-
- }
-
- if (script.is_valid()) {
-
- p_script->base=script;
- p_script->_base=p_script->base.ptr();
- p_script->member_indices=script->member_indices;
-
- } else if (native.is_valid()) {
-
- p_script->native=native;
- } else {
-
- _set_error("Could not determine inheritance",p_class);
- return ERR_FILE_NOT_FOUND;
- }
-
-
- }
-
-
- for(int i=0;i<p_class->variables.size();i++) {
-
- StringName name = p_class->variables[i].identifier;
- if (p_script->member_indices.has(name)) {
- _set_error("Member '"+name+"' already exists (in current or parent class)",p_class);
- return ERR_ALREADY_EXISTS;
- }
-
- if (p_class->variables[i]._export.type!=Variant::NIL) {
-
- p_script->member_info[name]=p_class->variables[i]._export;
-#ifdef TOOLS_ENABLED
- if (p_class->variables[i].default_value.get_type()!=Variant::NIL) {
-
- p_script->member_default_values[name]=p_class->variables[i].default_value;
- }
-#endif
- }
-
- int new_idx = p_script->member_indices.size();
- p_script->member_indices[name]=new_idx;
- p_script->members.insert(name);
-
- }
-
- for(int i=0;i<p_class->constant_expressions.size();i++) {
-
- StringName name = p_class->constant_expressions[i].identifier;
- ERR_CONTINUE( p_class->constant_expressions[i].expression->type!=GDParser::Node::TYPE_CONSTANT );
-
- GDParser::ConstantNode *constant = static_cast<GDParser::ConstantNode*>(p_class->constant_expressions[i].expression);
-
- p_script->constants.insert(name,constant->value);
- //p_script->constants[constant->value].make_const();
- }
-
-
- //parse sub-classes
-
- for(int i=0;i<p_class->subclasses.size();i++) {
- StringName name = p_class->subclasses[i]->name;
-
- Ref<GDScript> subclass = memnew( GDScript );
-
- Error err = _parse_class(subclass.ptr(),p_script,p_class->subclasses[i]);
- if (err)
- return err;
- p_script->subclasses.insert(name,subclass);
-
- }
-
-
- //parse methods
-
- bool has_initializer=false;
- for(int i=0;i<p_class->functions.size();i++) {
-
- if (!has_initializer && p_class->functions[i]->name=="_init")
- has_initializer=true;
- Error err = _parse_function(p_script,p_class,p_class->functions[i]);
- if (err)
- return err;
- }
-
- //parse static methods
-
- for(int i=0;i<p_class->static_functions.size();i++) {
-
- Error err = _parse_function(p_script,p_class,p_class->static_functions[i]);
- if (err)
- return err;
- }
-
-
- if (!has_initializer) {
- //create a constructor
- Error err = _parse_function(p_script,p_class,NULL);
- if (err)
- return err;
- }
-
- return OK;
-}
-
-Error GDCompiler::compile(const GDParser *p_parser,GDScript *p_script) {
-
- err_line=-1;
- err_column=-1;
- error="";
- parser=p_parser;
- const GDParser::Node* root = parser->get_parse_tree();
- ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,ERR_INVALID_DATA);
-
- source=p_script->get_path();
-
-
-
- Error err = _parse_class(p_script,NULL,static_cast<const GDParser::ClassNode*>(root));
-
- if (err)
- return err;
-
- return OK;
-
-}
-
-String GDCompiler::get_error() const {
-
- return error;
-}
-int GDCompiler::get_error_line() const{
-
- return err_line;
-}
-int GDCompiler::get_error_column() const{
-
- return err_column;
-}
-
-GDCompiler::GDCompiler()
-{
-}
-
-
diff --git a/script/gdscript/gd_compiler.h b/script/gdscript/gd_compiler.h
deleted file mode 100644
index cda221dab0..0000000000
--- a/script/gdscript/gd_compiler.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*************************************************************************/
-/* gd_compiler.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef GD_COMPILER_H
-#define GD_COMPILER_H
-
-#include "gd_parser.h"
-#include "gd_script.h"
-
-
-class GDCompiler {
-
- const GDParser *parser;
- struct CodeGen {
-
-
- GDScript *script;
- const GDParser::ClassNode *class_node;
- const GDParser::FunctionNode *function_node;
-
-
- bool debug_stack;
-
-
- List< Map<StringName,int> > stack_id_stack;
- Map<StringName,int> stack_identifiers;
-
- List<GDFunction::StackDebug> stack_debug;
- List< Map<StringName,int> > block_identifier_stack;
- Map<StringName,int> block_identifiers;
-
-
- void add_stack_identifier(const StringName& p_id,int p_stackpos) {
-
- stack_identifiers[p_id]=p_stackpos;
- if (debug_stack) {
-
- block_identifiers[p_id]=p_stackpos;
- GDFunction::StackDebug sd;
- sd.added=true;
- sd.line=current_line;
- sd.identifier=p_id;
- sd.pos=p_stackpos;
- stack_debug.push_back(sd);
- }
- }
-
- void push_stack_identifiers() {
-
- stack_id_stack.push_back( stack_identifiers );
- if (debug_stack) {
-
- block_identifier_stack.push_back(block_identifiers);
- block_identifiers.clear();
- }
- }
-
- void pop_stack_identifiers() {
-
- stack_identifiers = stack_id_stack.back()->get();
- stack_id_stack.pop_back();
-
- if (debug_stack) {
- for (Map<StringName,int>::Element *E=block_identifiers.front();E;E=E->next()) {
-
- GDFunction::StackDebug sd;
- sd.added=false;
- sd.identifier=E->key();
- sd.line=current_line;
- sd.pos=E->get();
- stack_debug.push_back(sd);
- }
- block_identifiers=block_identifier_stack.back()->get();
- block_identifier_stack.pop_back();
- }
-
- }
-
-
- // int get_identifier_pos(const StringName& p_dentifier) const;
- HashMap<Variant,int,VariantHasher> constant_map;
- Map<StringName,int> name_map;
-
- int get_name_map_pos(const StringName& p_identifier) {
-
- int ret;
- if (!name_map.has(p_identifier)) {
- ret=name_map.size();
- name_map[p_identifier]=ret;
- } else {
- ret=name_map[p_identifier];
- }
- return ret;
- }
-
-
-
- int get_constant_pos(const Variant& p_constant) {
-
-
- if (constant_map.has(p_constant))
- return constant_map[p_constant];
- int pos = constant_map.size();
- constant_map[p_constant]=pos;
- return pos;
- }
-
- Vector<int> opcodes;
- void alloc_stack(int p_level) { if (p_level >= stack_max) stack_max=p_level+1; }
- void alloc_call(int p_params) { if (p_params >= call_max) call_max=p_params; }
-
- int current_line;
- int stack_max;
- int call_max;
- };
-
-#if 0
- void _create_index(const GDParser::OperatorNode *on);
- void _create_call(const GDParser::OperatorNode *on);
-
-
- int _parse_expression(const GDParser::Node *p_expr,CodeGen& codegen);
- void _parse_block(GDParser::BlockNode *p_block);
- void _parse_function(GDParser::FunctionNode *p_func);
- Ref<GDScript> _parse_class(GDParser::ClassNode *p_class);
-#endif
-
- void _set_error(const String& p_error,const GDParser::Node *p_node);
-
- bool _create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level);
- bool _create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level);
-
- //int _parse_subexpression(CodeGen& codegen,const GDParser::BlockNode *p_block,const GDParser::Node *p_expression);
- int _parse_assign_right_expression(CodeGen& codegen,const GDParser::OperatorNode *p_expression, int p_stack_level);
- int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false);
- Error _parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level=0,int p_break_addr=-1,int p_continue_addr=-1);
- Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func);
- Error _parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class);
- int err_line;
- int err_column;
- StringName source;
- String error;
-
-public:
-
- Error compile(const GDParser *p_parser,GDScript *p_script);
-
- String get_error() const;
- int get_error_line() const;
- int get_error_column() const;
-
- GDCompiler();
-};
-
-
-#endif // COMPILER_H
diff --git a/script/gdscript/gd_editor.cpp b/script/gdscript/gd_editor.cpp
deleted file mode 100644
index 4bb5d3206c..0000000000
--- a/script/gdscript/gd_editor.cpp
+++ /dev/null
@@ -1,781 +0,0 @@
-/*************************************************************************/
-/* gd_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gd_script.h"
-#include "gd_compiler.h"
-
-
-void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
-
- p_delimiters->push_back("#");
-
-}
-void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
-
- p_delimiters->push_back("\" \"");
- p_delimiters->push_back("' '");
-
-
-}
-String GDScriptLanguage::get_template(const String& p_class_name, const String& p_base_class_name) const {
-
- String _template = String()+
- "\nextends %BASE%\n\n"+
- "# member variables here, example:\n"+
- "# var a=2\n"+
- "# var b=\"textvar\"\n\n"+
- "func _ready():\n"+
- "\t# Initalization here\n"+
- "\tpass\n"+
- "\n"+
- "\n";
-
- return _template.replace("%BASE%",p_base_class_name);
-}
-
-
-
-
-bool GDScriptLanguage::validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path,List<String> *r_functions) const {
-
- GDParser parser;
-
- Error err = parser.parse(p_script,p_path.get_base_dir());
- if (err) {
- r_line_error=parser.get_error_line();
- r_col_error=parser.get_error_column();
- r_test_error=parser.get_error();
- return false;
- } else {
-
- const GDParser::Node *root = parser.get_parse_tree();
- ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,false);
-
- const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode*>(root);
- Map<int,String> funcs;
- for(int i=0;i<cl->functions.size();i++) {
-
- funcs[cl->functions[i]->line]=cl->functions[i]->name;
- }
-
- for(int i=0;i<cl->static_functions.size();i++) {
-
- funcs[cl->static_functions[i]->line]=cl->static_functions[i]->name;
- }
-
- for (Map<int,String>::Element *E=funcs.front();E;E=E->next()) {
-
- r_functions->push_back(E->get()+":"+itos(E->key()));
- }
-
-
- }
-
- return true;
-}
-
-bool GDScriptLanguage::has_named_classes() const {
-
- return false;
-}
-
-int GDScriptLanguage::find_function(const String& p_function,const String& p_code) const {
-
- GDTokenizer tokenizer;
- tokenizer.set_code(p_code);
- int indent=0;
- while(tokenizer.get_token()!=GDTokenizer::TK_EOF && tokenizer.get_token()!=GDTokenizer::TK_ERROR) {
-
- if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) {
- indent=tokenizer.get_token_line_indent();
- }
- if (indent==0 && tokenizer.get_token()==GDTokenizer::TK_PR_FUNCTION && tokenizer.get_token(1)==GDTokenizer::TK_IDENTIFIER) {
-
- String identifier = tokenizer.get_token_identifier(1);
- if (identifier==p_function) {
- return tokenizer.get_token_line();
- }
- }
- tokenizer.advance();
- }
- return -1;
-}
-
-Script *GDScriptLanguage::create_script() const {
-
- return memnew( GDScript );
-}
-
-/* DEBUGGER FUNCTIONS */
-
-
-bool GDScriptLanguage::debug_break_parse(const String& p_file, int p_line,const String& p_error) {
- //break because of parse error
-
- if (ScriptDebugger::get_singleton() && Thread::get_caller_ID()==Thread::get_main_ID()) {
-
- _debug_parse_err_line=p_line;
- _debug_parse_err_file=p_file;
- _debug_error=p_error;
- ScriptDebugger::get_singleton()->debug(this,false);
- return true;
- } else {
- return false;
- }
-
-}
-
-bool GDScriptLanguage::debug_break(const String& p_error,bool p_allow_continue) {
-
- if (ScriptDebugger::get_singleton() && Thread::get_caller_ID()==Thread::get_main_ID()) {
-
- _debug_parse_err_line=-1;
- _debug_parse_err_file="";
- _debug_error=p_error;
- ScriptDebugger::get_singleton()->debug(this,p_allow_continue);
- return true;
- } else {
- return false;
- }
-
-}
-
-String GDScriptLanguage::debug_get_error() const {
-
- return _debug_error;
-}
-
-int GDScriptLanguage::debug_get_stack_level_count() const {
-
- if (_debug_parse_err_line>=0)
- return 1;
-
-
- return _debug_call_stack_pos;
-}
-int GDScriptLanguage::debug_get_stack_level_line(int p_level) const {
-
- if (_debug_parse_err_line>=0)
- return _debug_parse_err_line;
-
- ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,-1);
-
- int l = _debug_call_stack_pos - p_level -1;
-
- return *(_call_stack[l].line);
-
-}
-String GDScriptLanguage::debug_get_stack_level_function(int p_level) const {
-
- if (_debug_parse_err_line>=0)
- return "";
-
- ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,"");
- int l = _debug_call_stack_pos - p_level -1;
- return _call_stack[l].function->get_name();
-}
-String GDScriptLanguage::debug_get_stack_level_source(int p_level) const {
-
- if (_debug_parse_err_line>=0)
- return _debug_parse_err_file;
-
- ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,"");
- int l = _debug_call_stack_pos - p_level -1;
- return _call_stack[l].function->get_script()->get_path();
-
-}
-void GDScriptLanguage::debug_get_stack_level_locals(int p_level,List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
-
- if (_debug_parse_err_line>=0)
- return;
-
- ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
- int l = _debug_call_stack_pos - p_level -1;
-
- GDFunction *f = _call_stack[l].function;
-
- List<Pair<StringName,int> > locals;
-
- f->debug_get_stack_member_state(*_call_stack[l].line,&locals);
- for( List<Pair<StringName,int> >::Element *E = locals.front();E;E=E->next() ) {
-
- p_locals->push_back(E->get().first);
- p_values->push_back(_call_stack[l].stack[E->get().second]);
- }
-
-}
-void GDScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p_members, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
-
- if (_debug_parse_err_line>=0)
- return;
-
- ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
- int l = _debug_call_stack_pos - p_level -1;
-
-
- GDInstance *instance = _call_stack[l].instance;
-
- if (!instance)
- return;
-
- Ref<GDScript> script = instance->get_script();
- ERR_FAIL_COND( script.is_null() );
-
-
- const Map<StringName,int>& mi = script->debug_get_member_indices();
-
- for(const Map<StringName,int>::Element *E=mi.front();E;E=E->next()) {
-
- p_members->push_back(E->key());
- p_values->push_back( instance->debug_get_member_by_index(E->get()));
- }
-
-}
-void GDScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
-
- //no globals are really reachable in gdscript
-}
-String GDScriptLanguage::debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems,int p_max_depth) {
-
- if (_debug_parse_err_line>=0)
- return "";
- return "";
-}
-
-void GDScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("gd");
-}
-
-
-void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const {
-
-
- for(int i=0;i<GDFunctions::FUNC_MAX;i++) {
-
- p_functions->push_back(GDFunctions::get_info(GDFunctions::Function(i)));
- }
-}
-
-String GDScriptLanguage::make_function(const String& p_class,const String& p_name,const StringArray& p_args) const {
-
- String s="func "+p_name+"(";
- if (p_args.size()) {
- s+=" ";
- for(int i=0;i<p_args.size();i++) {
- if (i>0)
- s+=", ";
- s+=p_args[i];
- }
- s+=" ";
- }
- s+="):\n\tpass # replace with function body\n";
-
- return s;
-
-}
-
-static void _parse_native_symbols(const StringName& p_native,bool p_static,List<String>* r_options) {
-
- if (!p_static) {
- List<MethodInfo> methods;
- ObjectTypeDB::get_method_list(p_native,&methods);
- for(List<MethodInfo>::Element *E=methods.front();E;E=E->next()) {
- if (!E->get().name.begins_with("_")) {
- r_options->push_back(E->get().name);
- }
- }
- }
-
- List<String> constants;
- ObjectTypeDB::get_integer_constant_list(p_native,&constants);
-
- for(List<String>::Element *E=constants.front();E;E=E->next()) {
- r_options->push_back(E->get());
- }
-
-}
-
-
-static bool _parse_script_symbols(const Ref<GDScript>& p_script,bool p_static,List<String>* r_options,List<String>::Element *p_indices);
-
-
-static bool _parse_completion_variant(const Variant& p_var,List<String>* r_options,List<String>::Element *p_indices) {
-
- if (p_indices) {
-
- bool ok;
- Variant si = p_var.get(p_indices->get(),&ok);
- if (!ok)
- return false;
- return _parse_completion_variant(si,r_options,p_indices->next());
- } else {
-
- switch(p_var.get_type()) {
-
-
- case Variant::DICTIONARY: {
-
- Dictionary d=p_var;
- List<Variant> vl;
- d.get_key_list(&vl);
- for (List<Variant>::Element *E=vl.front();E;E=E->next()) {
-
- if (E->get().get_type()==Variant::STRING)
- r_options->push_back(E->get());
- }
-
-
- List<MethodInfo> ml;
- p_var.get_method_list(&ml);
- for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
- r_options->push_back(E->get().name);
- }
-
- } break;
- case Variant::OBJECT: {
-
-
- Object *o=p_var;
- if (o) {
- print_line("OBJECT: "+o->get_type());
- if (p_var.is_ref() && o->cast_to<GDScript>()) {
-
- Ref<GDScript> gds = p_var;
- _parse_script_symbols(gds,true,r_options,NULL);
- } else if (o->is_type("GDNativeClass")){
-
- GDNativeClass *gnc = o->cast_to<GDNativeClass>();
- _parse_native_symbols(gnc->get_name(),false,r_options);
- } else {
-
- print_line("REGULAR BLEND");
- _parse_native_symbols(o->get_type(),false,r_options);
- }
- }
-
- } break;
- default: {
-
- List<PropertyInfo> pi;
- p_var.get_property_list(&pi);
- for(List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
- r_options->push_back(E->get().name);
- }
- List<StringName> cl;
-
- p_var.get_numeric_constants_for_type(p_var.get_type(),&cl);
- for(List<StringName>::Element *E=cl.front();E;E=E->next()) {
- r_options->push_back(E->get());
- }
-
- List<MethodInfo> ml;
- p_var.get_method_list(&ml);
- for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
- r_options->push_back(E->get().name);
- }
-
- } break;
- }
-
- return true;
- }
-
-
-}
-
-
-static void _parse_expression_node(const GDParser::Node *p_node,List<String>* r_options,List<String>::Element *p_indices) {
-
-
-
- if (p_node->type==GDParser::Node::TYPE_CONSTANT) {
-
- const GDParser::ConstantNode *cn=static_cast<const GDParser::ConstantNode *>(p_node);
- _parse_completion_variant(cn->value,r_options,p_indices?p_indices->next():NULL);
- } else if (p_node->type==GDParser::Node::TYPE_DICTIONARY) {
-
- const GDParser::DictionaryNode *dn=static_cast<const GDParser::DictionaryNode*>(p_node);
- for(int i=0;i<dn->elements.size();i++) {
-
- if (dn->elements[i].key->type==GDParser::Node::TYPE_CONSTANT) {
-
- const GDParser::ConstantNode *cn=static_cast<const GDParser::ConstantNode *>(dn->elements[i].key);
- if (cn->value.get_type()==Variant::STRING) {
-
- String str=cn->value;
- if (p_indices) {
-
- if (str==p_indices->get()) {
- _parse_expression_node(dn->elements[i].value,r_options,p_indices->next());
- return;
- }
-
- } else {
- r_options->push_back(str);
- }
- }
- }
- }
- }
-}
-
-static bool _parse_completion_block(const GDParser::BlockNode *p_block,int p_line,List<String>* r_options,List<String>::Element *p_indices) {
-
- for(int i=0;i<p_block->sub_blocks.size();i++) {
- //parse inner first
- if (p_line>=p_block->sub_blocks[i]->line && (p_line<=p_block->sub_blocks[i]->end_line || p_block->sub_blocks[i]->end_line==-1)) {
- if (_parse_completion_block(p_block->sub_blocks[i],p_line,r_options,p_indices))
- return true;
- }
- }
-
- if (p_indices) {
-
- //parse indices in expressions :|
- for (int i=0;i<p_block->statements.size();i++) {
-
- if (p_block->statements[i]->line>p_line)
- break;
-
- if (p_block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) {
-
- const GDParser::LocalVarNode *lv=static_cast<const GDParser::LocalVarNode *>(p_block->statements[i]);
- if (lv->assign && String(lv->name)==p_indices->get()) {
-
- _parse_expression_node(lv->assign,r_options,p_indices->next());
- return true;
- }
- }
- }
-
- } else {
- for(int i=0;i<p_block->variables.size();i++) {
- //parse variables second
- if (p_line>=p_block->variable_lines[i]) {
- r_options->push_back(p_block->variables[i]);
- }
- else break;
-
- }
- }
-
- return false;
-}
-
-
-static bool _parse_script_symbols(const Ref<GDScript>& p_script,bool p_static,List<String>* r_options,List<String>::Element *p_indices) {
-
- //for (Map<StringName,Ref<GDScript> >::Element ?
-
- if (!p_static && !p_indices) {
- for(const Set<StringName>::Element *E=p_script->get_members().front();E;E=E->next()) {
-
- r_options->push_back(E->get());
- }
- }
-
- for (const Map<StringName,Variant >::Element *E=p_script->get_constants().front();E;E=E->next()) {
-
- if( p_indices) {
- if (p_indices->get()==String(E->get())) {
- _parse_completion_variant(E->get(),r_options,p_indices->next());
- return true;
- }
- } else {
- r_options->push_back(E->key());
- }
- }
-
- if (!p_indices){
- for (const Map<StringName,GDFunction>::Element *E=p_script->get_member_functions().front();E;E=E->next()) {
-
- if (E->get().is_static() || !p_static)
- r_options->push_back(E->key());
- }
- }
-
- if (p_script->get_base().is_valid()){
- if (_parse_script_symbols(p_script->get_base(),p_static,r_options,p_indices))
- return true;
- } else if (p_script->get_native().is_valid() && !p_indices) {
- _parse_native_symbols(p_script->get_native()->get_name(),p_static,r_options);
- }
-
- return false;
-}
-
-
-static bool _parse_completion_class(const String& p_base_path,const GDParser::ClassNode *p_class,int p_line,List<String>* r_options,List<String>::Element *p_indices) {
-
-
- static const char*_type_names[Variant::VARIANT_MAX]={
- "null","bool","int","float","String","Vector2","Rect2","Vector3","Matrix32","Plane","Quat","AABB","Matrix3","Trasnform",
- "Color","Image","NodePath","RID","Object","InputEvent","Dictionary","Array","RawArray","IntArray","FloatArray","StringArray",
- "Vector2Array","Vector3Array","ColorArray"};
-
- if (p_indices && !p_indices->next()) {
- for(int i=0;i<Variant::VARIANT_MAX;i++) {
-
- if (p_indices->get()==_type_names[i]) {
-
- List<StringName> ic;
-
- Variant::get_numeric_constants_for_type(Variant::Type(i),&ic);
- for(List<StringName>::Element *E=ic.front();E;E=E->next()) {
- r_options->push_back(E->get());
- }
- return true;
- }
- }
- }
-
-
-
- for(int i=0;i<p_class->subclasses.size();i++) {
-
- if (p_line>=p_class->subclasses[i]->line && (p_line<=p_class->subclasses[i]->end_line || p_class->subclasses[i]->end_line==-1)) {
-
- if (_parse_completion_class(p_base_path,p_class->subclasses[i],p_line,r_options,p_indices))
- return true;
- }
- }
-
- bool in_static_func=false;
-
- for(int i=0;i<p_class->functions.size();i++) {
-
- const GDParser::FunctionNode *fu = p_class->functions[i];
-
- if (p_line>=fu->body->line && (p_line<=fu->body->end_line || fu->body->end_line==-1)) {
- //if in function, first block stuff from outer to inner
- if (_parse_completion_block(fu->body,p_line,r_options,p_indices))
- return true;
- //then function arguments
- if (!p_indices) {
- for(int j=0;j<fu->arguments.size();j++) {
-
- r_options->push_back(fu->arguments[j]);
- }
- }
- }
-
- }
-
- for(int i=0;i<p_class->static_functions.size();i++) {
-
- const GDParser::FunctionNode *fu = p_class->static_functions[i];
-
- if (p_line>=fu->body->line && (p_line<=fu->body->end_line || fu->body->end_line==-1)) {
-
- //if in function, first block stuff from outer to inne
- if (_parse_completion_block(fu->body,p_line,r_options,p_indices))
- return true;
- //then function arguments
- if (!p_indices) {
- for(int j=0;j<fu->arguments.size();j++) {
-
- r_options->push_back(fu->arguments[j]);
- }
- }
-
- in_static_func=true;
- }
-
- }
-
-
- //add all local names
- if (!p_indices) {
-
- if (!in_static_func) {
-
- for(int i=0;i<p_class->variables.size();i++) {
-
- r_options->push_back(p_class->variables[i].identifier);
- }
- }
-
- for(int i=0;i<p_class->constant_expressions.size();i++) {
-
- r_options->push_back(p_class->constant_expressions[i].identifier);
- }
-
- if (!in_static_func) {
- for(int i=0;i<p_class->functions.size();i++) {
-
- r_options->push_back(p_class->functions[i]->name);
- }
- }
-
- for(int i=0;i<p_class->static_functions.size();i++) {
-
- r_options->push_back(p_class->static_functions[i]->name);
- }
- }
-
-
- if (p_class->extends_used) {
- //do inheritance
- String path = p_class->extends_file;
-
- Ref<GDScript> script;
- Ref<GDNativeClass> native;
-
- if (path!="") {
- //path (and optionally subclasses)
-
- script = ResourceLoader::load(path);
- if (script.is_null()) {
- return false;
- }
-
- if (p_class->extends_class.size()) {
-
- for(int i=0;i<p_class->extends_class.size();i++) {
-
- String sub = p_class->extends_class[i];
- if (script->get_subclasses().has(sub)) {
-
- script=script->get_subclasses()[sub];
- } else {
-
- return false;
- }
- }
- }
-
- } else {
-
- ERR_FAIL_COND_V(p_class->extends_class.size()==0,false);
- //look around for the subclasses
-
- String base=p_class->extends_class[0];
- Ref<GDScript> base_class;
-#if 0
- while(p) {
-
- if (p->subclasses.has(base)) {
-
- base_class=p->subclasses[base];
- break;
- }
- p=p->_owner;
- }
-
- if (base_class.is_valid()) {
-
- for(int i=1;i<p_class->extends_class.size();i++) {
-
- String subclass=p_class->extends_class[i];
-
- if (base_class->subclasses.has(subclass)) {
-
- base_class=base_class->subclasses[subclass];
- } else {
-
- _set_error("Could not find subclass: "+subclass,p_class);
- return ERR_FILE_NOT_FOUND;
- }
- }
-
-
- } else {
-#endif
- if (p_class->extends_class.size()>1) {
-
- return false;
-
- }
- //if not found, try engine classes
- if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) {
- return false;
- }
-
- int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base];
- native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx];
- if (!native.is_valid()) {
- return false;
- }
-#if 0
- }
-#endif
-
- }
-
- if (script.is_valid()) {
- if (_parse_script_symbols(script,in_static_func,r_options,p_indices))
- return true;
-
- } else if (native.is_valid() && !p_indices) {
-
- _parse_native_symbols(native->get_name(),in_static_func,r_options);
- }
- }
-
- return false;
-
-}
-
-
-Error GDScriptLanguage::complete_keyword(const String& p_code, int p_line, const String& p_base_path, const String& p_base, List<String>* r_options) {
-
- GDParser p;
- Error err = p.parse(p_code,p_base_path);
- // don't care much about error I guess
- const GDParser::Node* root = p.get_parse_tree();
- ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,ERR_INVALID_DATA);
-
- const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode*>(root);
-
- List<String> indices;
- Vector<String> spl = p_base.split(".");
-
- for(int i=0;i<spl.size()-1;i++) {
- indices.push_back(spl[i]);
- }
-
- if (_parse_completion_class(p_base,cl,p_line,r_options,indices.front()))
- return OK;
- //and the globals x_x?
- for(Map<StringName,int>::Element *E=globals.front();E;E=E->next()) {
- if (!indices.empty()) {
- if (String(E->key())==indices.front()->get()) {
-
- _parse_completion_variant(global_array[E->get()],r_options,indices.front()->next());
-
- return OK;
- }
- } else {
- r_options->push_back(E->key());
- }
- }
-
- return OK;
-}
-
diff --git a/script/gdscript/gd_functions.cpp b/script/gdscript/gd_functions.cpp
deleted file mode 100644
index 2930d9322c..0000000000
--- a/script/gdscript/gd_functions.cpp
+++ /dev/null
@@ -1,1218 +0,0 @@
-/*************************************************************************/
-/* gd_functions.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gd_functions.h"
-#include "math_funcs.h"
-#include "object_type_db.h"
-#include "reference.h"
-#include "gd_script.h"
-#include "os/os.h"
-
-const char *GDFunctions::get_func_name(Function p_func) {
-
- ERR_FAIL_INDEX_V(p_func,FUNC_MAX,"");
-
- static const char *_names[FUNC_MAX]={
- "sin",
- "cos",
- "tan",
- "sinh",
- "cosh",
- "tanh",
- "asin",
- "acos",
- "atan",
- "atan2",
- "sqrt",
- "fmod",
- "fposmod",
- "floor",
- "ceil",
- "round",
- "abs",
- "sign",
- "pow",
- "log",
- "exp",
- "is_nan",
- "is_inf",
- "ease",
- "decimals",
- "stepify",
- "lerp",
- "dectime",
- "randomize",
- "randi",
- "randf",
- "rand_range",
- "rand_seed",
- "deg2rad",
- "rad2deg",
- "linear2db",
- "db2linear",
- "max",
- "min",
- "clamp",
- "nearest_po2",
- "weakref",
- "convert",
- "typeof",
- "str",
- "print",
- "printt",
- "printerr",
- "printraw",
- "range",
- "load",
- "inst2dict",
- "dict2inst",
- "print_stack",
- };
-
- return _names[p_func];
-
-}
-
-void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Variant &r_ret,Variant::CallError &r_error) {
-
- r_error.error=Variant::CallError::CALL_OK;
-#ifdef DEBUG_ENABLED
-
-#define VALIDATE_ARG_COUNT(m_count) \
- if (p_arg_count<m_count) {\
- r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;\
- r_error.argument=m_count;\
- return;\
- }\
- if (p_arg_count>m_count) {\
- r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;\
- r_error.argument=m_count;\
- return;\
- }
-
-#define VALIDATE_ARG_NUM(m_arg) \
- if (!p_args[m_arg]->is_num()) {\
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;\
- r_error.argument=m_arg;\
- r_error.expected=Variant::REAL;\
- return;\
- }
-
-#else
-
-#define VALIDATE_ARG_COUNT(m_count)
-#define VALIDATE_ARG_NUM(m_arg)
-#endif
-
- //using a switch, so the compiler generates a jumptable
-
- switch(p_func) {
-
- case MATH_SIN: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::sin(*p_args[0]);
- } break;
- case MATH_COS: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::cos(*p_args[0]);
- } break;
- case MATH_TAN: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::tan(*p_args[0]);
- } break;
- case MATH_SINH: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::sinh(*p_args[0]);
- } break;
- case MATH_COSH: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::cosh(*p_args[0]);
- } break;
- case MATH_TANH: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::tanh(*p_args[0]);
- } break;
- case MATH_ASIN: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::asin(*p_args[0]);
- } break;
- case MATH_ACOS: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::acos(*p_args[0]);
- } break;
- case MATH_ATAN: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::atan(*p_args[0]);
- } break;
- case MATH_ATAN2: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- r_ret=Math::atan2(*p_args[0],*p_args[1]);
- } break;
- case MATH_SQRT: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::sqrt(*p_args[0]);
- } break;
- case MATH_FMOD: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- r_ret=Math::fmod(*p_args[0],*p_args[1]);
- } break;
- case MATH_FPOSMOD: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- r_ret=Math::fposmod(*p_args[0],*p_args[1]);
- } break;
- case MATH_FLOOR: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::floor(*p_args[0]);
- } break;
- case MATH_CEIL: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::ceil(*p_args[0]);
- } break;
- case MATH_ROUND: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::round(*p_args[0]);
- } break;
- case MATH_ABS: {
- VALIDATE_ARG_COUNT(1);
- if (p_args[0]->get_type()==Variant::INT) {
-
- int64_t i = *p_args[0];
- r_ret=ABS(i);
- } else if (p_args[0]->get_type()==Variant::REAL) {
-
- real_t r = *p_args[0];
- r_ret=Math::abs(r);
- } else {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::REAL;
- }
- } break;
- case MATH_SIGN: {
- VALIDATE_ARG_COUNT(1);
- if (p_args[0]->get_type()==Variant::INT) {
-
- int64_t i = *p_args[0];
- r_ret= i < 0 ? -1 : ( i > 0 ? +1 : 0);
- } else if (p_args[0]->get_type()==Variant::REAL) {
-
- real_t r = *p_args[0];
- r_ret= r < 0.0 ? -1.0 : ( r > 0.0 ? +1.0 : 0.0);
- } else {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::REAL;
- }
- } break;
- case MATH_POW: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- r_ret=Math::pow(*p_args[0],*p_args[1]);
- } break;
- case MATH_LOG: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::log(*p_args[0]);
- } break;
- case MATH_EXP: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::exp(*p_args[0]);
- } break;
- case MATH_ISNAN: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::is_nan(*p_args[0]);
- } break;
- case MATH_ISINF: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::is_inf(*p_args[0]);
- } break;
- case MATH_EASE: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- r_ret=Math::ease(*p_args[0],*p_args[1]);
- } break;
- case MATH_DECIMALS: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::decimals(*p_args[0]);
- } break;
- case MATH_STEPIFY: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- r_ret=Math::stepify(*p_args[0],*p_args[1]);
- } break;
- case MATH_LERP: {
- VALIDATE_ARG_COUNT(3);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- r_ret=Math::lerp(*p_args[0],*p_args[1],*p_args[2]);
- } break;
- case MATH_DECTIME: {
- VALIDATE_ARG_COUNT(3);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- r_ret=Math::dectime(*p_args[0],*p_args[1],*p_args[2]);
- } break;
- case MATH_RANDOMIZE: {
- Math::randomize();
- r_ret=Variant();
- } break;
- case MATH_RAND: {
- r_ret=Math::rand();
- } break;
- case MATH_RANDF: {
- r_ret=Math::randf();
- } break;
- case MATH_RANDOM: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- r_ret=Math::random(*p_args[0],*p_args[1]);
- } break;
- case MATH_RANDSEED: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- uint32_t seed=*p_args[0];
- int ret = Math::rand_from_seed(&seed);
- Array reta;
- reta.push_back(ret);
- reta.push_back(seed);
- r_ret=reta;
-
- } break;
- case MATH_DEG2RAD: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::deg2rad(*p_args[0]);
- } break;
- case MATH_RAD2DEG: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::rad2deg(*p_args[0]);
- } break;
- case MATH_LINEAR2DB: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::linear2db(*p_args[0]);
- } break;
- case MATH_DB2LINEAR: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- r_ret=Math::db2linear(*p_args[0]);
- } break;
- case LOGIC_MAX: {
- VALIDATE_ARG_COUNT(2);
- if (p_args[0]->get_type()==Variant::INT && p_args[1]->get_type()==Variant::INT) {
-
- int64_t a = *p_args[0];
- int64_t b = *p_args[1];
- r_ret=MAX(a,b);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
-
- real_t a = *p_args[0];
- real_t b = *p_args[1];
-
- r_ret=MAX(a,b);
- }
-
- } break;
- case LOGIC_MIN: {
- VALIDATE_ARG_COUNT(2);
- if (p_args[0]->get_type()==Variant::INT && p_args[1]->get_type()==Variant::INT) {
-
- int64_t a = *p_args[0];
- int64_t b = *p_args[1];
- r_ret=MIN(a,b);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
-
- real_t a = *p_args[0];
- real_t b = *p_args[1];
-
- r_ret=MIN(a,b);
- }
- } break;
- case LOGIC_CLAMP: {
- VALIDATE_ARG_COUNT(3);
- if (p_args[0]->get_type()==Variant::INT && p_args[1]->get_type()==Variant::INT && p_args[2]->get_type()==Variant::INT) {
-
- int64_t a = *p_args[0];
- int64_t b = *p_args[1];
- int64_t c = *p_args[2];
- r_ret=CLAMP(a,b,c);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
-
- real_t a = *p_args[0];
- real_t b = *p_args[1];
- real_t c = *p_args[2];
-
- r_ret=CLAMP(a,b,c);
- }
- } break;
- case LOGIC_NEAREST_PO2: {
- VALIDATE_ARG_COUNT(1);
- VALIDATE_ARG_NUM(0);
- int64_t num = *p_args[0];
- r_ret = nearest_power_of_2(num);
- } break;
- case OBJ_WEAKREF: {
- VALIDATE_ARG_COUNT(1);
- if (p_args[0]->get_type()!=Variant::OBJECT) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::OBJECT;
- return;
-
- }
-
- if (p_args[0]->is_ref()) {
-
- REF r = *p_args[0];
- if (!r.is_valid()) {
- r_ret=Variant();
- return;
- }
-
- Ref<WeakRef> wref = memnew( WeakRef );
- wref->set_ref(r);
- r_ret=wref;
- } else {
- Object *obj = *p_args[0];
- if (!obj) {
- r_ret=Variant();
- return;
- }
- Ref<WeakRef> wref = memnew( WeakRef );
- wref->set_obj(obj);
- r_ret=wref;
- }
-
-
-
-
- } break;
- case TYPE_CONVERT: {
- VALIDATE_ARG_COUNT(2);
- VALIDATE_ARG_NUM(1);
- int type=*p_args[1];
- if (type<0 || type>=Variant::VARIANT_MAX) {
-
- ERR_PRINT("Invalid type argument to convert()");
- r_ret=Variant::NIL;
-
- } else {
-
-
- r_ret=Variant::construct(Variant::Type(type),p_args,1,r_error);
- }
- } break;
- case TYPE_OF: {
-
- VALIDATE_ARG_COUNT(1);
- r_ret = p_args[0]->get_type();
-
- } break;
- case TEXT_STR: {
-
- String str;
- for(int i=0;i<p_arg_count;i++) {
-
- String os = p_args[i]->operator String();;
- if (i==0)
- str=os;
- else
- str+=os;
- }
-
- r_ret=str;
-
- } break;
- case TEXT_PRINT: {
-
- String str;
- for(int i=0;i<p_arg_count;i++) {
-
- str+=p_args[i]->operator String();
- }
-
- //str+="\n";
- print_line(str);
- r_ret=Variant();
-
-
- } break;
- case TEXT_PRINT_TABBED: {
-
- String str;
- for(int i=0;i<p_arg_count;i++) {
-
- if (i)
- str+="\t";
- str+=p_args[i]->operator String();
- }
-
- //str+="\n";
- print_line(str);
- r_ret=Variant();
-
-
- } break;
-
- case TEXT_PRINTERR: {
-
- String str;
- for(int i=0;i<p_arg_count;i++) {
-
- str+=p_args[i]->operator String();
- }
-
- //str+="\n";
- OS::get_singleton()->printerr("%s\n",str.utf8().get_data());
- r_ret=Variant();
-
- } break;
- case TEXT_PRINTRAW: {
- String str;
- for(int i=0;i<p_arg_count;i++) {
-
- str+=p_args[i]->operator String();
- }
-
- //str+="\n";
- OS::get_singleton()->print("%s\n",str.utf8().get_data());
- r_ret=Variant();
-
- } break;
- case GEN_RANGE: {
-
-
-
- switch(p_arg_count) {
-
- case 0: {
-
- r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument=1;
-
- } break;
- case 1: {
-
- VALIDATE_ARG_NUM(0);
- int count=*p_args[0];
- Array arr(true);
- if (count<=0) {
- r_ret=arr;
- return;
- }
- Error err = arr.resize(count);
- if (err!=OK) {
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- r_ret=Variant();
- return;
- }
-
- for(int i=0;i<count;i++) {
- arr[i]=i;
- }
-
- r_ret=arr;
- } break;
- case 2: {
-
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
-
- int from=*p_args[0];
- int to=*p_args[1];
-
- Array arr(true);
- if (from>=to) {
- r_ret=arr;
- return;
- }
- Error err = arr.resize(to-from);
- if (err!=OK) {
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- r_ret=Variant();
- return;
- }
- for(int i=from;i<to;i++)
- arr[i-from]=i;
- r_ret=arr;
- } break;
- case 3: {
-
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
-
- int from=*p_args[0];
- int to=*p_args[1];
- int incr=*p_args[2];
- if (incr==0) {
-
- ERR_EXPLAIN("step argument is zero!");
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- ERR_FAIL();
- }
-
- Array arr(true);
- if (from>=to && incr>0) {
- r_ret=arr;
- return;
- }
- if (from<=to && incr<0) {
- r_ret=arr;
- return;
- }
-
- //calculate how many
- int count=0;
- if (incr>0) {
-
- count=((to-from-1)/incr)+1;
- } else {
-
- count=((from-to-1)/-incr)+1;
- }
-
-
- Error err = arr.resize(count);
-
- if (err!=OK) {
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- r_ret=Variant();
- return;
- }
-
- if (incr>0) {
- int idx=0;
- for(int i=from;i<to;i+=incr) {
- arr[idx++]=i;
- }
- } else {
-
- int idx=0;
- for(int i=from;i>to;i+=incr) {
- arr[idx++]=i;
- }
- }
-
- r_ret=arr;
- } break;
- default: {
-
- r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
- r_error.argument=3;
- } break;
- }
-
- } break;
- case RESOURCE_LOAD: {
- VALIDATE_ARG_COUNT(1);
- if (p_args[0]->get_type()!=Variant::STRING) {
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_ret=Variant();
- }
- r_ret=ResourceLoader::load(*p_args[0]);
-
- }
- case INST2DICT: {
-
- VALIDATE_ARG_COUNT(1);
-
- if (p_args[0]->get_type()==Variant::NIL) {
- r_ret=Variant();
- } else if (p_args[0]->get_type()!=Variant::OBJECT) {
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_ret=Variant();
- } else {
-
- Object *obj = *p_args[0];
- if (!obj) {
- r_ret=Variant();
-
- } else if (!obj->get_script_instance() || obj->get_script_instance()->get_language()!=GDScriptLanguage::get_singleton()) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::DICTIONARY;
- ERR_PRINT("Not a script with an instance");
-
- } else {
-
- GDInstance *ins = static_cast<GDInstance*>(obj->get_script_instance());
- Ref<GDScript> base = ins->get_script();
- if (base.is_null()) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::DICTIONARY;
- ERR_PRINT("Not based on a script");
- return;
-
- }
-
-
- GDScript *p = base.ptr();
- Vector<StringName> sname;
-
- while(p->_owner) {
-
- sname.push_back(p->name);
- p=p->_owner;
- }
- sname.invert();
-
-
- if (!p->path.is_resource_file()) {
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::DICTIONARY;
- print_line("PATH: "+p->path);
- ERR_PRINT("Not based on a resource file");
-
- return;
- }
-
- NodePath cp(sname,Vector<StringName>(),false);
-
- Dictionary d(true);
- d["@subpath"]=cp;
- d["@path"]=p->path;
-
-
- p = base.ptr();
-
- while(p) {
-
- for(Set<StringName>::Element *E=p->members.front();E;E=E->next()) {
-
- Variant value;
- if (ins->get(E->get(),value)) {
-
- String k = E->get();
- if (!d.has(k)) {
- d[k]=value;
- }
- }
- }
-
- p=p->_base;
- }
-
- r_ret=d;
-
- }
- }
-
- } break;
- case DICT2INST: {
-
- VALIDATE_ARG_COUNT(1);
-
- if (p_args[0]->get_type()!=Variant::DICTIONARY) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::DICTIONARY;
- return;
- }
-
- Dictionary d = *p_args[0];
-
- if (!d.has("@path")) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::OBJECT;
- return;
- }
-
- Ref<Script> scr = ResourceLoader::load(d["@path"]);
- if (!scr.is_valid()) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::OBJECT;
- return;
- }
-
- Ref<GDScript> gdscr = scr;
-
- if (!gdscr.is_valid()) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::OBJECT;
- return;
- }
-
- NodePath sub;
- if (d.has("@subpath")) {
- sub=d["@subpath"];
- }
-
- for(int i=0;i<sub.get_name_count();i++) {
-
- gdscr = gdscr->subclasses[ sub.get_name(i)];
- if (!gdscr.is_valid()) {
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument=0;
- r_error.expected=Variant::OBJECT;
- return;
- }
- }
-
-
- r_ret = gdscr->_new(NULL,0,r_error);
-
- } break;
-
- case PRINT_STACK: {
-
- ScriptLanguage* script = GDScriptLanguage::get_singleton();
- for (int i=0; i < script->debug_get_stack_level_count(); i++) {
-
- print_line("Frame "+itos(i)+" - "+script->debug_get_stack_level_source(i)+":"+itos(script->debug_get_stack_level_line(i))+" in function '"+script->debug_get_stack_level_function(i)+"'");
- };
- } break;
-
- case FUNC_MAX: {
-
- ERR_FAIL_V();
- } break;
-
- }
-
-}
-
-bool GDFunctions::is_deterministic(Function p_func) {
-
- //man i couldn't have chosen a worse function name,
- //way too controversial..
-
- switch(p_func) {
-
- case MATH_SIN:
- case MATH_COS:
- case MATH_TAN:
- case MATH_SINH:
- case MATH_COSH:
- case MATH_TANH:
- case MATH_ASIN:
- case MATH_ACOS:
- case MATH_ATAN:
- case MATH_ATAN2:
- case MATH_SQRT:
- case MATH_FMOD:
- case MATH_FPOSMOD:
- case MATH_FLOOR:
- case MATH_CEIL:
- case MATH_ROUND:
- case MATH_ABS:
- case MATH_SIGN:
- case MATH_POW:
- case MATH_LOG:
- case MATH_EXP:
- case MATH_ISNAN:
- case MATH_ISINF:
- case MATH_EASE:
- case MATH_DECIMALS:
- case MATH_STEPIFY:
- case MATH_LERP:
- case MATH_DECTIME:
- case MATH_DEG2RAD:
- case MATH_RAD2DEG:
- case MATH_LINEAR2DB:
- case MATH_DB2LINEAR:
- case LOGIC_MAX:
- case LOGIC_MIN:
- case LOGIC_CLAMP:
- case LOGIC_NEAREST_PO2:
- case TYPE_CONVERT:
- case TYPE_OF:
- case TEXT_STR:
-// enable for debug only, otherwise not desirable - case GEN_RANGE:
- return true;
- default:
- return false;
-
- }
-
- return false;
-
-
-}
-
-MethodInfo GDFunctions::get_info(Function p_func) {
-
-#ifdef TOOLS_ENABLED
- //using a switch, so the compiler generates a jumptable
-
- switch(p_func) {
-
- case MATH_SIN: {
- MethodInfo mi("sin",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
-
- } break;
- case MATH_COS: {
- MethodInfo mi("cos",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_TAN: {
- MethodInfo mi("tan",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_SINH: {
- MethodInfo mi("sinh",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_COSH: {
- MethodInfo mi("cosh",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_TANH: {
- MethodInfo mi("tanh",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ASIN: {
- MethodInfo mi("asin",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ACOS: {
- MethodInfo mi("acos",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ATAN: {
- MethodInfo mi("atan",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ATAN2: {
- MethodInfo mi("atan2",PropertyInfo(Variant::REAL,"x"),PropertyInfo(Variant::REAL,"y"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_SQRT: {
- MethodInfo mi("sqrt",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_FMOD: {
- MethodInfo mi("fmod",PropertyInfo(Variant::REAL,"x"),PropertyInfo(Variant::REAL,"y"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_FPOSMOD: {
- MethodInfo mi("fposmod",PropertyInfo(Variant::REAL,"x"),PropertyInfo(Variant::REAL,"y"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_FLOOR: {
- MethodInfo mi("floor",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_CEIL: {
- MethodInfo mi("ceil",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ROUND: {
- MethodInfo mi("round",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ABS: {
- MethodInfo mi("abs",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_SIGN: {
- MethodInfo mi("sign",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_POW: {
- MethodInfo mi("pow",PropertyInfo(Variant::REAL,"x"),PropertyInfo(Variant::REAL,"y"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_LOG: {
- MethodInfo mi("log",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_EXP: {
- MethodInfo mi("exp",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ISNAN: {
- MethodInfo mi("isnan",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_ISINF: {
- MethodInfo mi("isinf",PropertyInfo(Variant::REAL,"s"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_EASE: {
- MethodInfo mi("ease",PropertyInfo(Variant::REAL,"s"),PropertyInfo(Variant::REAL,"curve"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_DECIMALS: {
- MethodInfo mi("decimals",PropertyInfo(Variant::REAL,"step"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_STEPIFY: {
- MethodInfo mi("stepify",PropertyInfo(Variant::REAL,"s"),PropertyInfo(Variant::REAL,"step"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_LERP: {
- MethodInfo mi("lerp",PropertyInfo(Variant::REAL,"a"),PropertyInfo(Variant::REAL,"b"), PropertyInfo(Variant::REAL,"c"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_DECTIME: {
- MethodInfo mi("dectime",PropertyInfo(Variant::REAL,"value"),PropertyInfo(Variant::REAL,"amount"),PropertyInfo(Variant::REAL,"step"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_RANDOMIZE: {
- MethodInfo mi("randomize");
- mi.return_val.type=Variant::NIL;
- return mi;
- } break;
- case MATH_RAND: {
- MethodInfo mi("rand");
- mi.return_val.type=Variant::INT;
- return mi;
- } break;
- case MATH_RANDF: {
- MethodInfo mi("randf");
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_RANDOM: {
- MethodInfo mi("rand_range",PropertyInfo(Variant::REAL,"from"),PropertyInfo(Variant::REAL,"to"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_RANDSEED: {
- MethodInfo mi("rand_seed",PropertyInfo(Variant::REAL,"seed"));
- mi.return_val.type=Variant::ARRAY;
- return mi;
- } break;
- case MATH_DEG2RAD: {
- MethodInfo mi("deg2rad",PropertyInfo(Variant::REAL,"deg"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_RAD2DEG: {
- MethodInfo mi("rad2deg",PropertyInfo(Variant::REAL,"rad"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_LINEAR2DB: {
- MethodInfo mi("linear2db",PropertyInfo(Variant::REAL,"nrg"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case MATH_DB2LINEAR: {
- MethodInfo mi("db2linear",PropertyInfo(Variant::REAL,"db"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case LOGIC_MAX: {
- MethodInfo mi("max",PropertyInfo(Variant::REAL,"a"),PropertyInfo(Variant::REAL,"b"));
- mi.return_val.type=Variant::REAL;
- return mi;
-
- } break;
- case LOGIC_MIN: {
- MethodInfo mi("min",PropertyInfo(Variant::REAL,"a"),PropertyInfo(Variant::REAL,"b"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case LOGIC_CLAMP: {
- MethodInfo mi("clamp",PropertyInfo(Variant::REAL,"val"),PropertyInfo(Variant::REAL,"min"),PropertyInfo(Variant::REAL,"max"));
- mi.return_val.type=Variant::REAL;
- return mi;
- } break;
- case LOGIC_NEAREST_PO2: {
- MethodInfo mi("nearest_po2",PropertyInfo(Variant::INT,"val"));
- mi.return_val.type=Variant::INT;
- return mi;
- } break;
- case OBJ_WEAKREF: {
-
- MethodInfo mi("weakref",PropertyInfo(Variant::OBJECT,"obj"));
- mi.return_val.type=Variant::OBJECT;
- return mi;
-
- } break;
- case TYPE_CONVERT: {
-
- MethodInfo mi("convert",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::INT,"type"));
- mi.return_val.type=Variant::OBJECT;
- return mi;
- } break;
- case TYPE_OF: {
- MethodInfo mi("typeof",PropertyInfo(Variant::NIL,"what"));
- mi.return_val.type=Variant::INT;
- };
- case TEXT_STR: {
-
- MethodInfo mi("str",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::NIL,"..."));
- mi.return_val.type=Variant::STRING;
- return mi;
-
- } break;
- case TEXT_PRINT: {
-
- MethodInfo mi("print",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::NIL,"..."));
- mi.return_val.type=Variant::NIL;
- return mi;
-
- } break;
- case TEXT_PRINT_TABBED: {
-
- MethodInfo mi("printt",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::NIL,"..."));
- mi.return_val.type=Variant::NIL;
- return mi;
-
- } break;
- case TEXT_PRINTERR: {
-
- MethodInfo mi("printerr",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::NIL,"..."));
- mi.return_val.type=Variant::NIL;
- return mi;
-
- } break;
- case TEXT_PRINTRAW: {
-
- MethodInfo mi("printraw",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::NIL,"..."));
- mi.return_val.type=Variant::NIL;
- return mi;
-
- } break;
- case GEN_RANGE: {
-
- MethodInfo mi("range",PropertyInfo(Variant::NIL,"..."));
- mi.return_val.type=Variant::ARRAY;
- return mi;
- } break;
- case RESOURCE_LOAD: {
-
- MethodInfo mi("load",PropertyInfo(Variant::STRING,"path"));
- mi.return_val.type=Variant::OBJECT;
- return mi;
- } break;
- case INST2DICT: {
-
- MethodInfo mi("inst2dict",PropertyInfo(Variant::OBJECT,"inst"));
- mi.return_val.type=Variant::DICTIONARY;
- return mi;
- } break;
- case DICT2INST: {
-
- MethodInfo mi("dict2inst",PropertyInfo(Variant::DICTIONARY,"dict"));
- mi.return_val.type=Variant::OBJECT;
- return mi;
- } break;
-
- case PRINT_STACK: {
- MethodInfo mi("print_stack");
- mi.return_val.type=Variant::NIL;
- return mi;
- } break;
-
- case FUNC_MAX: {
-
- ERR_FAIL_V(MethodInfo());
- } break;
-
- }
-#endif
-
- return MethodInfo();
-}
diff --git a/script/gdscript/gd_functions.h b/script/gdscript/gd_functions.h
deleted file mode 100644
index 2ab397d18a..0000000000
--- a/script/gdscript/gd_functions.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*************************************************************************/
-/* gd_functions.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef GD_FUNCTIONS_H
-#define GD_FUNCTIONS_H
-
-#include "variant.h"
-
-class GDFunctions {
-public:
-
- enum Function {
- MATH_SIN,
- MATH_COS,
- MATH_TAN,
- MATH_SINH,
- MATH_COSH,
- MATH_TANH,
- MATH_ASIN,
- MATH_ACOS,
- MATH_ATAN,
- MATH_ATAN2,
- MATH_SQRT,
- MATH_FMOD,
- MATH_FPOSMOD,
- MATH_FLOOR,
- MATH_CEIL,
- MATH_ROUND,
- MATH_ABS,
- MATH_SIGN,
- MATH_POW,
- MATH_LOG,
- MATH_EXP,
- MATH_ISNAN,
- MATH_ISINF,
- MATH_EASE,
- MATH_DECIMALS,
- MATH_STEPIFY,
- MATH_LERP,
- MATH_DECTIME,
- MATH_RANDOMIZE,
- MATH_RAND,
- MATH_RANDF,
- MATH_RANDOM,
- MATH_RANDSEED,
- MATH_DEG2RAD,
- MATH_RAD2DEG,
- MATH_LINEAR2DB,
- MATH_DB2LINEAR,
- LOGIC_MAX,
- LOGIC_MIN,
- LOGIC_CLAMP,
- LOGIC_NEAREST_PO2,
- OBJ_WEAKREF,
- TYPE_CONVERT,
- TYPE_OF,
- TEXT_STR,
- TEXT_PRINT,
- TEXT_PRINT_TABBED,
- TEXT_PRINTERR,
- TEXT_PRINTRAW,
- GEN_RANGE,
- RESOURCE_LOAD,
- INST2DICT,
- DICT2INST,
- PRINT_STACK,
- FUNC_MAX
-
- };
-
- static const char *get_func_name(Function p_func);
- static void call(Function p_func,const Variant **p_args,int p_arg_count,Variant &r_ret,Variant::CallError &r_error);
- static bool is_deterministic(Function p_func);
- static MethodInfo get_info(Function p_func);
-
-};
-
-#endif // GD_FUNCTIONS_H
diff --git a/script/gdscript/gd_parser.cpp b/script/gdscript/gd_parser.cpp
deleted file mode 100644
index e558ceb416..0000000000
--- a/script/gdscript/gd_parser.cpp
+++ /dev/null
@@ -1,2469 +0,0 @@
-/*************************************************************************/
-/* gd_parser.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gd_parser.h"
-#include "print_string.h"
-#include "io/resource_loader.h"
-/* TODO:
-
- *Property reduce constant expressions
- *Implement missing operators in variant?
- *constructor
- */
-
-/*
- todo:
- fix post ++,--
- make sure ++,-- don't work on constant expressions
- seems passing parent node as param is not needed
- */
-
-template<class T>
-T* GDParser::alloc_node() {
-
- T *t = memnew( T);
-
- t->next=list;
- list=t;
-
- if (!head)
- head=t;
-
- t->line=tokenizer.get_token_line();
- t->column=tokenizer.get_token_column();
- return t;
-
-}
-
-bool GDParser::_end_statement() {
-
- if (tokenizer.get_token()==GDTokenizer::TK_SEMICOLON) {
- tokenizer.advance();
- return true; //handle next
- } else if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE || tokenizer.get_token()==GDTokenizer::TK_EOF) {
- return true; //will be handled properly
- }
-
- return false;
-}
-
-bool GDParser::_enter_indent_block(BlockNode* p_block) {
-
-
- if (tokenizer.get_token()!=GDTokenizer::TK_COLON) {
-
- _set_error("':' expected at end of line.");
- return false;
- }
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_NEWLINE) {
-
- _set_error("newline expected after ':'.");
- return false;
- }
-
- while(true) {
-
- if (tokenizer.get_token()!=GDTokenizer::TK_NEWLINE) {
- return false; //wtf
- } else if (tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE) {
-
- int indent = tokenizer.get_token_line_indent();
- int current = tab_level.back()->get();
- if (indent<=current)
- return false;
-
- tab_level.push_back(indent);
- tokenizer.advance();
- return true;
-
- } else if (p_block) {
-
- NewLineNode *nl = alloc_node<NewLineNode>();
- nl->line=tokenizer.get_token_line();
- p_block->statements.push_back(nl);
-
- }
-
- tokenizer.advance(); // go to next newline
- }
-}
-
-bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static) {
-
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) {
- tokenizer.advance();
- } else {
-
- while(true) {
-
-
- Node*arg = _parse_expression(p_parent,p_static);
- if (!arg)
- return false;
-
- p_args.push_back(arg);
-
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) {
- tokenizer.advance();
- break;
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_COMMA) {
-
- if (tokenizer.get_token(1)==GDTokenizer::TK_PARENTHESIS_CLOSE) {
-
- _set_error("Expression expected");
- return false;
- }
-
- tokenizer.advance();
- } else {
- // something is broken
- _set_error("Expected ',' or ')'");
- return false;
- }
-
- }
- }
-
- return true;
-
-}
-
-
-
-GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_allow_assign) {
-
-// Vector<Node*> expressions;
-// Vector<OperatorNode::Operator> operators;
-
- Vector<Expression> expression;
-
- Node *expr=NULL;
-
- while(true) {
-
-
- /*****************/
- /* Parse Operand */
- /*****************/
-
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) {
- //subexpression ()
- tokenizer.advance();
- Node* subexpr = _parse_expression(p_parent,p_static);
- if (!subexpr)
- return NULL;
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
-
- _set_error("Expected ')' in expression");
- return NULL;
- }
-
- tokenizer.advance();
- expr=subexpr;
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT) {
-
- //constant defined by tokenizer
- ConstantNode *constant = alloc_node<ConstantNode>();
- constant->value=tokenizer.get_token_constant();
- tokenizer.advance();
- expr=constant;
- } else if (tokenizer.get_token()==GDTokenizer::TK_PR_PRELOAD) {
-
- //constant defined by tokenizer
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after 'preload'");
- return NULL;
- }
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) {
- _set_error("Expected string constant as 'preload' argument.");
- return NULL;
- }
-
-
- String path = tokenizer.get_token_constant();
- if (!path.is_abs_path() && base_path!="")
- path=base_path+"/"+path;
-
- Ref<Resource> res = ResourceLoader::load(path);
- if (!res.is_valid()) {
- _set_error("Can't preload resource at path: "+path);
- return NULL;
- }
-
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' after 'preload' path");
- return NULL;
- }
-
- ConstantNode *constant = alloc_node<ConstantNode>();
- constant->value=res;
- tokenizer.advance();
-
- expr=constant;
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_SELF) {
-
- if (p_static) {
- _set_error("'self'' not allowed in static function or constant expression");
- return NULL;
- }
- //constant defined by tokenizer
- SelfNode *self = alloc_node<SelfNode>();
- tokenizer.advance();
- expr=self;
- } else if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE && tokenizer.get_token(1)==GDTokenizer::TK_PERIOD) {
-
- Variant::Type bi_type = tokenizer.get_token_type();
- tokenizer.advance(2);
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("Built-in type constant expected after '.'");
- return NULL;
- }
- StringName identifier = tokenizer.get_token_identifier();
- if (!Variant::has_numeric_constant(bi_type,identifier)) {
-
- _set_error("Static constant '"+identifier.operator String()+"' not present in built-in type "+Variant::get_type_name(bi_type)+".");
- return NULL;
- }
-
- ConstantNode *cn = alloc_node<ConstantNode>();
- cn->value=Variant::get_numeric_constant_value(bi_type,identifier);
- expr=cn;
- tokenizer.advance();
-
- } else if (tokenizer.get_token(1)==GDTokenizer::TK_PARENTHESIS_OPEN && (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE || tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER || tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_FUNC)) {
- //function or constructor
-
- OperatorNode *op = alloc_node<OperatorNode>();
- op->op=OperatorNode::OP_CALL;
-
- if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE) {
-
- TypeNode *tn = alloc_node<TypeNode>();
- tn->vtype=tokenizer.get_token_type();
- op->arguments.push_back(tn);
- } else if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_FUNC) {
-
- BuiltInFunctionNode *bn = alloc_node<BuiltInFunctionNode>();
- bn->function=tokenizer.get_token_built_in_func();
- op->arguments.push_back(bn);
- } else {
-
- SelfNode *self = alloc_node<SelfNode>();
- op->arguments.push_back(self);
-
- IdentifierNode* id = alloc_node<IdentifierNode>();
- id->name=tokenizer.get_token_identifier();
- op->arguments.push_back(id);
- }
-
- tokenizer.advance(2);
- if (!_parse_arguments(op,op->arguments,p_static))
- return NULL;
-
- expr=op;
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER) {
- //identifier (reference)
-
- IdentifierNode *id = alloc_node<IdentifierNode>();
- id->name=tokenizer.get_token_identifier();
- tokenizer.advance();
- expr=id;
-
- } else if (/*tokenizer.get_token()==GDTokenizer::TK_OP_ADD ||*/ tokenizer.get_token()==GDTokenizer::TK_OP_SUB || tokenizer.get_token()==GDTokenizer::TK_OP_NOT || tokenizer.get_token()==GDTokenizer::TK_OP_BIT_INVERT) {
-
- //single prefix operators like !expr -expr ++expr --expr
- OperatorNode *op = alloc_node<OperatorNode>();
-
- Expression e;
- e.is_op=true;
-
- switch(tokenizer.get_token()) {
- case GDTokenizer::TK_OP_SUB: e.op=OperatorNode::OP_NEG; break;
- case GDTokenizer::TK_OP_NOT: e.op=OperatorNode::OP_NOT; break;
- case GDTokenizer::TK_OP_BIT_INVERT: e.op=OperatorNode::OP_BIT_INVERT;; break;
- default: {}
- }
-
-
- tokenizer.advance();
-
- if (e.op!=OperatorNode::OP_NOT && tokenizer.get_token()==GDTokenizer::TK_OP_NOT) {
- _set_error("Misplaced 'not'.");
- return NULL;
- }
-
- expression.push_back(e);
- continue; //only exception, must continue...
-
- /*
- Node *subexpr=_parse_expression(op,p_static);
- if (!subexpr)
- return NULL;
- op->arguments.push_back(subexpr);
- expr=op;*/
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_BRACKET_OPEN) {
- // array
- tokenizer.advance();
-
- ArrayNode *arr = alloc_node<ArrayNode>();
- bool expecting_comma=false;
-
- while(true) {
-
- if (tokenizer.get_token()==GDTokenizer::TK_EOF) {
-
- _set_error("Unterminated array");
- return NULL;
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_BRACKET_CLOSE) {
- tokenizer.advance();
- break;
- } else if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) {
-
- tokenizer.advance(); //ignore newline
- } else if (tokenizer.get_token()==GDTokenizer::TK_COMMA) {
- if (!expecting_comma) {
- _set_error("expression or ']' expected");
- return NULL;
- }
-
- expecting_comma=false;
- tokenizer.advance(); //ignore newline
- } else {
- //parse expression
- if (expecting_comma) {
- _set_error("',' or ']' expected");
- return NULL;
- }
- Node *n = _parse_expression(arr,p_static);
- if (!n)
- return NULL;
- arr->elements.push_back(n);
- expecting_comma=true;
- }
- }
-
- expr=arr;
- } else if (tokenizer.get_token()==GDTokenizer::TK_CURLY_BRACKET_OPEN) {
- // array
- tokenizer.advance();
-
- DictionaryNode *dict = alloc_node<DictionaryNode>();
-
- enum DictExpect {
-
- DICT_EXPECT_KEY,
- DICT_EXPECT_COLON,
- DICT_EXPECT_VALUE,
- DICT_EXPECT_COMMA
-
- };
-
- Node *key=NULL;
-
- DictExpect expecting=DICT_EXPECT_KEY;
-
- while(true) {
-
- if (tokenizer.get_token()==GDTokenizer::TK_EOF) {
-
- _set_error("Unterminated dictionary");
- return NULL;
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_CURLY_BRACKET_CLOSE) {
-
- if (expecting==DICT_EXPECT_COLON) {
- _set_error("':' expected");
- return NULL;
- }
- if (expecting==DICT_EXPECT_VALUE) {
- _set_error("value expected");
- return NULL;
- }
- tokenizer.advance();
- break;
- } else if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) {
-
- tokenizer.advance(); //ignore newline
- } else if (tokenizer.get_token()==GDTokenizer::TK_COMMA) {
-
- if (expecting==DICT_EXPECT_KEY) {
- _set_error("key or '}' expected");
- return NULL;
- }
- if (expecting==DICT_EXPECT_VALUE) {
- _set_error("value expected");
- return NULL;
- }
- if (expecting==DICT_EXPECT_COLON) {
- _set_error("':' expected");
- return NULL;
- }
-
- expecting=DICT_EXPECT_KEY;
- tokenizer.advance(); //ignore newline
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_COLON) {
-
- if (expecting==DICT_EXPECT_KEY) {
- _set_error("key or '}' expected");
- return NULL;
- }
- if (expecting==DICT_EXPECT_VALUE) {
- _set_error("value expected");
- return NULL;
- }
- if (expecting==DICT_EXPECT_COMMA) {
- _set_error("',' or '}' expected");
- return NULL;
- }
-
- expecting=DICT_EXPECT_VALUE;
- tokenizer.advance(); //ignore newline
- } else {
-
- if (expecting==DICT_EXPECT_COMMA) {
- _set_error("',' or '}' expected");
- return NULL;
- }
- if (expecting==DICT_EXPECT_COLON) {
- _set_error("':' expected");
- return NULL;
- }
-
- if (expecting==DICT_EXPECT_KEY) {
-
- if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token(1)==GDTokenizer::TK_OP_ASSIGN) {
- //lua style identifier, easier to write
- ConstantNode *cn = alloc_node<ConstantNode>();
- cn->value = tokenizer.get_token_identifier();
- key = cn;
- tokenizer.advance(2);
- expecting=DICT_EXPECT_VALUE;
- } else {
- //python/js style more flexible
- key = _parse_expression(dict,p_static);
- if (!key)
- return NULL;
- expecting=DICT_EXPECT_COLON;
- }
- }
-
- if (expecting==DICT_EXPECT_VALUE) {
- Node *value = _parse_expression(dict,p_static);
- if (!value)
- return NULL;
- expecting=DICT_EXPECT_COMMA;
-
- DictionaryNode::Pair pair;
- pair.key=key;
- pair.value=value;
- dict->elements.push_back(pair);
- key=NULL;
-
- }
-
- }
- }
-
- expr=dict;
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_PERIOD && tokenizer.get_token(1)==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) {
- // parent call
-
- tokenizer.advance(); //goto identifier
- OperatorNode *op = alloc_node<OperatorNode>();
- op->op=OperatorNode::OP_PARENT_CALL;
-
-
- /*SelfNode *self = alloc_node<SelfNode>();
- op->arguments.push_back(self);
- forbidden for now */
-
- IdentifierNode* id = alloc_node<IdentifierNode>();
- id->name=tokenizer.get_token_identifier();
- op->arguments.push_back(id);
-
- tokenizer.advance(2);
- if (!_parse_arguments(op,op->arguments,p_static))
- return NULL;
-
- expr=op;
-
- } else {
-
- //find list [ or find dictionary {
-
- print_line("found bug?");
-
- _set_error("Error parsing expression, misplaced: "+String(tokenizer.get_token_name(tokenizer.get_token())));
- return NULL; //nothing
- }
-
- if (!expr) {
- ERR_EXPLAIN("GDParser bug, couldn't figure out what expression is..");
- ERR_FAIL_COND_V(!expr,NULL);
- }
-
-
- /******************/
- /* Parse Indexing */
- /******************/
-
-
- while (true) {
-
- //expressions can be indexed any number of times
-
- if (tokenizer.get_token()==GDTokenizer::TK_PERIOD) {
-
- //indexing using "."
-
- if (tokenizer.get_token(1)!=GDTokenizer::TK_IDENTIFIER && tokenizer.get_token(1)!=GDTokenizer::TK_BUILT_IN_FUNC ) {
- _set_error("Expected identifier as member");
- return NULL;
- } else if (tokenizer.get_token(2)==GDTokenizer::TK_PARENTHESIS_OPEN) {
- //call!!
- OperatorNode * op = alloc_node<OperatorNode>();
- op->op=OperatorNode::OP_CALL;
-
- IdentifierNode * id = alloc_node<IdentifierNode>();
- if (tokenizer.get_token(1)==GDTokenizer::TK_BUILT_IN_FUNC ) {
- //small hack so built in funcs don't obfuscate methods
-
- id->name=GDFunctions::get_func_name(tokenizer.get_token_built_in_func(1));
- } else {
- id->name=tokenizer.get_token_identifier(1);
- }
-
- op->arguments.push_back(expr); // call what
- op->arguments.push_back(id); // call func
- //get arguments
- tokenizer.advance(3);
- if (!_parse_arguments(op,op->arguments,p_static))
- return NULL;
- expr=op;
-
- } else {
- //simple indexing!
- OperatorNode * op = alloc_node<OperatorNode>();
- op->op=OperatorNode::OP_INDEX_NAMED;
-
- IdentifierNode * id = alloc_node<IdentifierNode>();
- id->name=tokenizer.get_token_identifier(1);
-
- op->arguments.push_back(expr);
- op->arguments.push_back(id);
-
- expr=op;
-
- tokenizer.advance(2);
- }
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_BRACKET_OPEN) {
- //indexing using "[]"
- OperatorNode * op = alloc_node<OperatorNode>();
- op->op=OperatorNode::OP_INDEX;
-
- tokenizer.advance(1);
-
- Node *subexpr = _parse_expression(op,p_static);
- if (!subexpr) {
- return NULL;
- }
-
- if (tokenizer.get_token()!=GDTokenizer::TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return NULL;
- }
-
- op->arguments.push_back(expr);
- op->arguments.push_back(subexpr);
- tokenizer.advance(1);
- expr=op;
-
- } else
- break;
- }
-
- /******************/
- /* Parse Operator */
- /******************/
-
-
- Expression e;
- e.is_op=false;
- e.node=expr;
- expression.push_back(e);
-
- // determine which operator is next
-
- OperatorNode::Operator op;
- bool valid=true;
-
-//assign, if allowed is only alowed on the first operator
-#define _VALIDATE_ASSIGN if (!p_allow_assign) { _set_error("Unexpected assign."); return NULL; } p_allow_assign=false;
- switch(tokenizer.get_token()) { //see operator
-
- case GDTokenizer::TK_OP_IN: op=OperatorNode::OP_IN; break;
- case GDTokenizer::TK_OP_EQUAL: op=OperatorNode::OP_EQUAL ; break;
- case GDTokenizer::TK_OP_NOT_EQUAL: op=OperatorNode::OP_NOT_EQUAL ; break;
- case GDTokenizer::TK_OP_LESS: op=OperatorNode::OP_LESS ; break;
- case GDTokenizer::TK_OP_LESS_EQUAL: op=OperatorNode::OP_LESS_EQUAL ; break;
- case GDTokenizer::TK_OP_GREATER: op=OperatorNode::OP_GREATER ; break;
- case GDTokenizer::TK_OP_GREATER_EQUAL: op=OperatorNode::OP_GREATER_EQUAL ; break;
- case GDTokenizer::TK_OP_AND: op=OperatorNode::OP_AND ; break;
- case GDTokenizer::TK_OP_OR: op=OperatorNode::OP_OR ; break;
- case GDTokenizer::TK_OP_ADD: op=OperatorNode::OP_ADD ; break;
- case GDTokenizer::TK_OP_SUB: op=OperatorNode::OP_SUB ; break;
- case GDTokenizer::TK_OP_MUL: op=OperatorNode::OP_MUL ; break;
- case GDTokenizer::TK_OP_DIV: op=OperatorNode::OP_DIV ; break;
- case GDTokenizer::TK_OP_MOD: op=OperatorNode::OP_MOD ; break;
- //case GDTokenizer::TK_OP_NEG: op=OperatorNode::OP_NEG ; break;
- case GDTokenizer::TK_OP_SHIFT_LEFT: op=OperatorNode::OP_SHIFT_LEFT ; break;
- case GDTokenizer::TK_OP_SHIFT_RIGHT: op=OperatorNode::OP_SHIFT_RIGHT ; break;
- case GDTokenizer::TK_OP_ASSIGN: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN ; break;
- case GDTokenizer::TK_OP_ASSIGN_ADD: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_ADD ; break;
- case GDTokenizer::TK_OP_ASSIGN_SUB: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_SUB ; break;
- case GDTokenizer::TK_OP_ASSIGN_MUL: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_MUL ; break;
- case GDTokenizer::TK_OP_ASSIGN_DIV: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_DIV ; break;
- case GDTokenizer::TK_OP_ASSIGN_MOD: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_MOD ; break;
- case GDTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_SHIFT_LEFT; ; break;
- case GDTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_SHIFT_RIGHT; ; break;
- case GDTokenizer::TK_OP_ASSIGN_BIT_AND: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_BIT_AND ; break;
- case GDTokenizer::TK_OP_ASSIGN_BIT_OR: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_BIT_OR ; break;
- case GDTokenizer::TK_OP_ASSIGN_BIT_XOR: _VALIDATE_ASSIGN op=OperatorNode::OP_ASSIGN_BIT_XOR ; break;
- case GDTokenizer::TK_OP_BIT_AND: op=OperatorNode::OP_BIT_AND ; break;
- case GDTokenizer::TK_OP_BIT_OR: op=OperatorNode::OP_BIT_OR ; break;
- case GDTokenizer::TK_OP_BIT_XOR: op=OperatorNode::OP_BIT_XOR ; break;
- case GDTokenizer::TK_PR_EXTENDS: op=OperatorNode::OP_EXTENDS; break;
- default: valid=false; break;
- }
-
- if (valid) {
- e.is_op=true;
- e.op=op;
- expression.push_back(e);
- tokenizer.advance();
- } else {
- break;
- }
-
- }
-
- /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */
-
-
- while(expression.size()>1) {
-
- int next_op=-1;
- int min_priority=0xFFFFF;
- bool is_unary=false;
-
- for(int i=0;i<expression.size();i++) {
-
-
-
- if (!expression[i].is_op) {
-
- continue;
- }
-
- int priority;
-
- bool unary=false;
-
- switch(expression[i].op) {
-
- case OperatorNode::OP_EXTENDS: priority=-1; break; //before anything
-
- case OperatorNode::OP_BIT_INVERT: priority=0; unary=true; break;
- case OperatorNode::OP_NEG: priority=1; unary=true; break;
-
- case OperatorNode::OP_MUL: priority=2; break;
- case OperatorNode::OP_DIV: priority=2; break;
- case OperatorNode::OP_MOD: priority=2; break;
-
- case OperatorNode::OP_ADD: priority=3; break;
- case OperatorNode::OP_SUB: priority=3; break;
-
- case OperatorNode::OP_SHIFT_LEFT: priority=4; break;
- case OperatorNode::OP_SHIFT_RIGHT: priority=4; break;
-
- case OperatorNode::OP_BIT_AND: priority=5; break;
- case OperatorNode::OP_BIT_XOR: priority=6; break;
- case OperatorNode::OP_BIT_OR: priority=7; break;
-
- case OperatorNode::OP_LESS: priority=8; break;
- case OperatorNode::OP_LESS_EQUAL: priority=8; break;
- case OperatorNode::OP_GREATER: priority=8; break;
- case OperatorNode::OP_GREATER_EQUAL: priority=8; break;
-
- case OperatorNode::OP_EQUAL: priority=8; break;
- case OperatorNode::OP_NOT_EQUAL: priority=8; break;
-
- case OperatorNode::OP_IN: priority=10; break;
-
- case OperatorNode::OP_NOT: priority=11; unary=true; break;
- case OperatorNode::OP_AND: priority=12; break;
- case OperatorNode::OP_OR: priority=13; break;
-
- // ?: = 10
-
- case OperatorNode::OP_ASSIGN: priority=14; break;
- case OperatorNode::OP_ASSIGN_ADD: priority=14; break;
- case OperatorNode::OP_ASSIGN_SUB: priority=14; break;
- case OperatorNode::OP_ASSIGN_MUL: priority=14; break;
- case OperatorNode::OP_ASSIGN_DIV: priority=14; break;
- case OperatorNode::OP_ASSIGN_MOD: priority=14; break;
- case OperatorNode::OP_ASSIGN_SHIFT_LEFT: priority=14; break;
- case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: priority=14; break;
- case OperatorNode::OP_ASSIGN_BIT_AND: priority=14; break;
- case OperatorNode::OP_ASSIGN_BIT_OR: priority=14; break;
- case OperatorNode::OP_ASSIGN_BIT_XOR: priority=14; break;
-
-
- default: {
- _set_error("GDParser bug, invalid operator in expression: "+itos(expression[i].op));
- return NULL;
- }
-
- }
-
- if (priority<min_priority) {
- // < is used for left to right (default)
- // <= is used for right to left
- next_op=i;
- min_priority=priority;
- is_unary=unary;
- }
-
- }
-
-
- if (next_op==-1) {
-
-
- _set_error("Yet another parser bug....");
- ERR_FAIL_COND_V(next_op==-1,NULL);
- }
-
-
- // OK! create operator..
- if (is_unary) {
-
- int expr_pos=next_op;
- while(expression[expr_pos].is_op) {
-
- expr_pos++;
- if (expr_pos==expression.size()) {
- //can happen..
- _set_error("Unexpected end of expression..");
- return NULL;
- }
- }
-
- //consecutively do unary opeators
- for(int i=expr_pos-1;i>=next_op;i--) {
-
- OperatorNode *op = alloc_node<OperatorNode>();
- op->op=expression[i].op;
- op->arguments.push_back(expression[i+1].node);
- expression[i].is_op=false;
- expression[i].node=op;
- expression.remove(i+1);
- }
-
-
- } else {
-
- if (next_op <1 || next_op>=(expression.size()-1)) {
- _set_error("Parser bug..");
- ERR_FAIL_V(NULL);
- }
-
- OperatorNode *op = alloc_node<OperatorNode>();
- op->op=expression[next_op].op;
-
- if (expression[next_op-1].is_op) {
-
- _set_error("Parser bug..");
- ERR_FAIL_V(NULL);
- }
-
- if (expression[next_op+1].is_op) {
- // this is not invalid and can really appear
- // but it becomes invalid anyway because no binary op
- // can be followed by an unary op in a valid combination,
- // due to how precedence works, unaries will always dissapear first
-
- _set_error("Parser bug..");
-
- }
-
-
- op->arguments.push_back(expression[next_op-1].node); //expression goes as left
- op->arguments.push_back(expression[next_op+1].node); //next expression goes as right
-
- //replace all 3 nodes by this operator and make it an expression
- expression[next_op-1].node=op;
- expression.remove(next_op);
- expression.remove(next_op);
- }
-
- }
-
- return expression[0].node;
-
-}
-
-
-GDParser::Node* GDParser::_reduce_expression(Node *p_node,bool p_to_const) {
-
- switch(p_node->type) {
-
- case Node::TYPE_BUILT_IN_FUNCTION: {
- //many may probably be optimizable
- return p_node;
- } break;
- case Node::TYPE_ARRAY: {
-
- ArrayNode *an = static_cast<ArrayNode*>(p_node);
- bool all_constants=true;
-
- for(int i=0;i<an->elements.size();i++) {
-
- an->elements[i]=_reduce_expression(an->elements[i],p_to_const);
- if (an->elements[i]->type!=Node::TYPE_CONSTANT)
- all_constants=false;
- }
-
- if (all_constants && p_to_const) {
- //reduce constant array expression
-
- ConstantNode *cn = alloc_node<ConstantNode>();
- Array arr(!p_to_const);
- arr.resize(an->elements.size());
- for(int i=0;i<an->elements.size();i++) {
- ConstantNode *acn = static_cast<ConstantNode*>(an->elements[i]);
- arr[i]=acn->value;
-
- }
- cn->value=arr;
- return cn;
- }
-
- return an;
-
- } break;
- case Node::TYPE_DICTIONARY: {
-
- DictionaryNode *dn = static_cast<DictionaryNode*>(p_node);
- bool all_constants=true;
-
- for(int i=0;i<dn->elements.size();i++) {
-
- dn->elements[i].key=_reduce_expression(dn->elements[i].key,p_to_const);
- if (dn->elements[i].key->type!=Node::TYPE_CONSTANT)
- all_constants=false;
- dn->elements[i].value=_reduce_expression(dn->elements[i].value,p_to_const);
- if (dn->elements[i].value->type!=Node::TYPE_CONSTANT)
- all_constants=false;
-
- }
-
- if (all_constants && p_to_const) {
- //reduce constant array expression
-
- ConstantNode *cn = alloc_node<ConstantNode>();
- Dictionary dict(!p_to_const);
- for(int i=0;i<dn->elements.size();i++) {
- ConstantNode *key_c = static_cast<ConstantNode*>(dn->elements[i].key);
- ConstantNode *value_c = static_cast<ConstantNode*>(dn->elements[i].value);
-
- dict[key_c->value]=value_c->value;
-
- }
- cn->value=dict;
- return cn;
- }
-
- return dn;
-
-
- } break;
- case Node::TYPE_OPERATOR: {
-
- OperatorNode *op=static_cast<OperatorNode*>(p_node);
-
- bool all_constants=true;
- int last_not_constant=-1;
-
- for(int i=0;i<op->arguments.size();i++) {
-
- op->arguments[i]=_reduce_expression(op->arguments[i],p_to_const);
- if (op->arguments[i]->type!=Node::TYPE_CONSTANT) {
- all_constants=false;
- last_not_constant=i;
- }
- }
-
- if (op->op==OperatorNode::OP_EXTENDS) {
- //nothing much
- return op;
-
- } if (op->op==OperatorNode::OP_PARENT_CALL) {
- //nothing much
- return op;
-
- } else if (op->op==OperatorNode::OP_CALL) {
- //can reduce base type constructors
- if ((op->arguments[0]->type==Node::TYPE_TYPE || (op->arguments[0]->type==Node::TYPE_BUILT_IN_FUNCTION && GDFunctions::is_deterministic( static_cast<BuiltInFunctionNode*>(op->arguments[0])->function))) && last_not_constant==0) {
-
- //native type constructor or intrinsic function
- const Variant **vptr=NULL;
- Vector<Variant*> ptrs;
- if (op->arguments.size()>1) {
-
- ptrs.resize(op->arguments.size()-1);
- for(int i=0;i<ptrs.size();i++) {
-
-
- ConstantNode *cn = static_cast<ConstantNode*>(op->arguments[i+1]);
- ptrs[i]=&cn->value;
- }
-
- vptr=(const Variant**)&ptrs[0];
-
-
- }
-
- Variant::CallError ce;
- Variant v;
-
- if (op->arguments[0]->type==Node::TYPE_TYPE) {
- TypeNode *tn = static_cast<TypeNode*>(op->arguments[0]);
- v = Variant::construct(tn->vtype,vptr,ptrs.size(),ce);
-
- } else {
- GDFunctions::Function func = static_cast<BuiltInFunctionNode*>(op->arguments[0])->function;
- GDFunctions::call(func,vptr,ptrs.size(),v,ce);
- }
-
-
- if (ce.error!=Variant::CallError::CALL_OK) {
-
- String errwhere;
- if (op->arguments[0]->type==Node::TYPE_TYPE) {
- TypeNode *tn = static_cast<TypeNode*>(op->arguments[0]);
- errwhere="'"+Variant::get_type_name(tn->vtype)+"'' constructor";
-
- } else {
- GDFunctions::Function func = static_cast<BuiltInFunctionNode*>(op->arguments[0])->function;
- errwhere=String("'")+GDFunctions::get_func_name(func)+"'' intrinsic function";
-
- }
-
- switch(ce.error) {
-
- case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT: {
-
- _set_error("Invalid argument (#"+itos(ce.argument+1)+") for "+errwhere+".");
-
- } break;
- case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
-
- _set_error("Too many arguments for "+errwhere+".");
- } break;
- case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
-
- _set_error("Too few arguments for "+errwhere+".");
- } break;
- default: {
- _set_error("Invalid arguments for "+errwhere+".");
-
- } break;
- }
-
- return p_node;
- }
-
- ConstantNode *cn = alloc_node<ConstantNode>();
- cn->value=v;
- return cn;
-
- } else if (op->arguments[0]->type==Node::TYPE_BUILT_IN_FUNCTION && last_not_constant==0) {
-
-
-
-
-
- }
-
- return op; //don't reduce yet
- } else if (op->op==OperatorNode::OP_INDEX) {
- //can reduce indices into constant arrays or dictionaries
-
- if (all_constants) {
-
- ConstantNode *ca = static_cast<ConstantNode*>(op->arguments[0]);
- ConstantNode *cb = static_cast<ConstantNode*>(op->arguments[1]);
-
-
-
- bool valid;
-
- Variant v = ca->value.get(cb->value,&valid);
- if (!valid) {
- _set_error("invalid index in constant expression");
- return op;
- }
-
- ConstantNode *cn = alloc_node<ConstantNode>();
- cn->value=v;
- return cn;
-
- } else if (op->arguments[0]->type==Node::TYPE_CONSTANT && op->arguments[1]->type==Node::TYPE_IDENTIFIER) {
-
- ConstantNode *ca = static_cast<ConstantNode*>(op->arguments[0]);
- IdentifierNode *ib = static_cast<IdentifierNode*>(op->arguments[1]);
-
- bool valid;
- Variant v = ca->value.get_named(ib->name,&valid);
- if (!valid) {
- _set_error("invalid index '"+String(ib->name)+"' in constant expression");
- return op;
- }
-
- ConstantNode *cn = alloc_node<ConstantNode>();
- cn->value=v;
- return cn;
-
- }
-
- return op;
- }
-
- //validate assignment (don't assign to cosntant expression
- switch(op->op) {
-
- case OperatorNode::OP_ASSIGN:
- case OperatorNode::OP_ASSIGN_ADD:
- case OperatorNode::OP_ASSIGN_SUB:
- case OperatorNode::OP_ASSIGN_MUL:
- case OperatorNode::OP_ASSIGN_DIV:
- case OperatorNode::OP_ASSIGN_MOD:
- case OperatorNode::OP_ASSIGN_SHIFT_LEFT:
- case OperatorNode::OP_ASSIGN_SHIFT_RIGHT:
- case OperatorNode::OP_ASSIGN_BIT_AND:
- case OperatorNode::OP_ASSIGN_BIT_OR:
- case OperatorNode::OP_ASSIGN_BIT_XOR: {
-
- if (op->arguments[0]->type==Node::TYPE_CONSTANT) {
- _set_error("Can't assign to constant");
- return op;
- }
-
- } break;
- default: { break; }
- }
- //now se if all are constants
- if (!all_constants)
- return op; //nothing to reduce from here on
-#define _REDUCE_UNARY(m_vop)\
- bool valid=false;\
- Variant res;\
- Variant::evaluate(m_vop,static_cast<ConstantNode*>(op->arguments[0])->value,Variant(),res,valid);\
- if (!valid) {\
- _set_error("Invalid operand for unary operator");\
- return p_node;\
- }\
- ConstantNode *cn = alloc_node<ConstantNode>();\
- cn->value=res;\
- return cn;
-
-#define _REDUCE_BINARY(m_vop)\
- bool valid=false;\
- Variant res;\
- Variant::evaluate(m_vop,static_cast<ConstantNode*>(op->arguments[0])->value,static_cast<ConstantNode*>(op->arguments[1])->value,res,valid);\
- if (!valid) {\
- _set_error("Invalid operands for operator");\
- return p_node;\
- }\
- ConstantNode *cn = alloc_node<ConstantNode>();\
- cn->value=res;\
- return cn;
-
- switch(op->op) {
-
- //unary operators
- case OperatorNode::OP_NEG: { _REDUCE_UNARY(Variant::OP_NEGATE); } break;
- case OperatorNode::OP_NOT: { _REDUCE_UNARY(Variant::OP_NOT); } break;
- case OperatorNode::OP_BIT_INVERT: { _REDUCE_UNARY(Variant::OP_BIT_NEGATE); } break;
- //binary operators (in precedence order)
- case OperatorNode::OP_IN: { _REDUCE_BINARY(Variant::OP_IN); } break;
- case OperatorNode::OP_EQUAL: { _REDUCE_BINARY(Variant::OP_EQUAL); } break;
- case OperatorNode::OP_NOT_EQUAL: { _REDUCE_BINARY(Variant::OP_NOT_EQUAL); } break;
- case OperatorNode::OP_LESS: { _REDUCE_BINARY(Variant::OP_LESS); } break;
- case OperatorNode::OP_LESS_EQUAL: { _REDUCE_BINARY(Variant::OP_LESS_EQUAL); } break;
- case OperatorNode::OP_GREATER: { _REDUCE_BINARY(Variant::OP_GREATER); } break;
- case OperatorNode::OP_GREATER_EQUAL: { _REDUCE_BINARY(Variant::OP_GREATER_EQUAL); } break;
- case OperatorNode::OP_AND: { _REDUCE_BINARY(Variant::OP_AND); } break;
- case OperatorNode::OP_OR: { _REDUCE_BINARY(Variant::OP_OR); } break;
- case OperatorNode::OP_ADD: { _REDUCE_BINARY(Variant::OP_ADD); } break;
- case OperatorNode::OP_SUB: { _REDUCE_BINARY(Variant::OP_SUBSTRACT); } break;
- case OperatorNode::OP_MUL: { _REDUCE_BINARY(Variant::OP_MULTIPLY); } break;
- case OperatorNode::OP_DIV: { _REDUCE_BINARY(Variant::OP_DIVIDE); } break;
- case OperatorNode::OP_MOD: { _REDUCE_BINARY(Variant::OP_MODULE); } break;
- case OperatorNode::OP_SHIFT_LEFT: { _REDUCE_BINARY(Variant::OP_SHIFT_LEFT); } break;
- case OperatorNode::OP_SHIFT_RIGHT: { _REDUCE_BINARY(Variant::OP_SHIFT_RIGHT); } break;
- case OperatorNode::OP_BIT_AND: { _REDUCE_BINARY(Variant::OP_BIT_AND); } break;
- case OperatorNode::OP_BIT_OR: { _REDUCE_BINARY(Variant::OP_BIT_OR); } break;
- case OperatorNode::OP_BIT_XOR: { _REDUCE_BINARY(Variant::OP_BIT_XOR); } break;
- default: { ERR_FAIL_V(op); }
- }
-
- ERR_FAIL_V(op);
- } break;
- default: {
- return p_node;
- } break;
-
- }
-}
-
-GDParser::Node* GDParser::_parse_and_reduce_expression(Node *p_parent,bool p_static,bool p_reduce_const,bool p_allow_assign) {
-
- Node* expr=_parse_expression(p_parent,p_static,p_allow_assign);
- if (!expr || error_set)
- return NULL;
- expr = _reduce_expression(expr,p_reduce_const);
- if (!expr || error_set)
- return NULL;
- return expr;
-}
-
-void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
-
- int indent_level = tab_level.back()->get();
-
-
-#ifdef DEBUG_ENABLED
-
- NewLineNode *nl = alloc_node<NewLineNode>();
-
- nl->line=tokenizer.get_token_line();
- p_block->statements.push_back(nl);
-#endif
-
- while(true) {
-
- GDTokenizer::Token token = tokenizer.get_token();
- if (error_set)
- return;
-
- if (indent_level>tab_level.back()->get()) {
- p_block->end_line=tokenizer.get_token_line();
- return; //go back a level
- }
-
- switch(token) {
-
-
- case GDTokenizer::TK_EOF:
- p_block->end_line=tokenizer.get_token_line();
- case GDTokenizer::TK_ERROR: {
- return; //go back
-
- //end of file!
-
- } break;
- case GDTokenizer::TK_NEWLINE: {
-
- NewLineNode *nl = alloc_node<NewLineNode>();
- nl->line=tokenizer.get_token_line();
- p_block->statements.push_back(nl);
-
- if (!_parse_newline()) {
- if (!error_set) {
- p_block->end_line=tokenizer.get_token_line();
- }
- return;
- }
- } break;
- case GDTokenizer::TK_CF_PASS: {
- if (tokenizer.get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE ) {
-
- _set_error("Expected ';' or <NewLine>.");
- return;
- }
- tokenizer.advance();
- } break;
- case GDTokenizer::TK_PR_VAR: {
- //variale declaration and (eventual) initialization
-
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("Expected identifier for local variable name.");
- return;
- }
- StringName n = tokenizer.get_token_identifier();
- tokenizer.advance();
-
- p_block->variables.push_back(n); //line?
- p_block->variable_lines.push_back(tokenizer.get_token_line());
-
-
- //must know when the local variable is declared
- LocalVarNode *lv = alloc_node<LocalVarNode>();
- lv->name=n;
- p_block->statements.push_back(lv);
-
- Node *assigned=NULL;
-
- if (tokenizer.get_token()==GDTokenizer::TK_OP_ASSIGN) {
-
- tokenizer.advance();
- Node *subexpr=NULL;
-
- subexpr = _parse_and_reduce_expression(p_block,p_static);
- if (!subexpr)
- return;
-
- lv->assign=subexpr;
- assigned=subexpr;
- } else {
-
- ConstantNode *c = alloc_node<ConstantNode>();
- c->value=Variant();
- assigned = c;
-
- }
- IdentifierNode *id = alloc_node<IdentifierNode>();
- id->name=n;
-
-
- OperatorNode *op = alloc_node<OperatorNode>();
- op->op=OperatorNode::OP_ASSIGN;
- op->arguments.push_back(id);
- op->arguments.push_back(assigned);
- p_block->statements.push_back(op);
-
- _end_statement();
-
-
- } break;
- case GDTokenizer::TK_CF_IF: {
-
- tokenizer.advance();
- Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
- return;
-
- ControlFlowNode *cf_if = alloc_node<ControlFlowNode>();
-
- cf_if->cf_type=ControlFlowNode::CF_IF;
- cf_if->arguments.push_back(condition);
-
- cf_if->body = alloc_node<BlockNode>();
- p_block->sub_blocks.push_back(cf_if->body);
-
- if (!_enter_indent_block(cf_if->body)) {
- p_block->end_line=tokenizer.get_token_line();
- return;
- }
-
- _parse_block(cf_if->body,p_static);
- if (error_set)
- return;
- p_block->statements.push_back(cf_if);
-
- while(true) {
-
- while(tokenizer.get_token()==GDTokenizer::TK_NEWLINE) {
- tokenizer.advance();
- }
-
- if (tab_level.back()->get() < indent_level) { //not at current indent level
- p_block->end_line=tokenizer.get_token_line();
- return;
- }
-
- if (tokenizer.get_token()==GDTokenizer::TK_CF_ELIF) {
-
- if (tab_level.back()->get() > indent_level) {
-
- _set_error("Invalid indent");
- return;
- }
-
- tokenizer.advance();
-
- cf_if->body_else=alloc_node<BlockNode>();
- p_block->sub_blocks.push_back(cf_if->body_else);
-
- ControlFlowNode *cf_else = alloc_node<ControlFlowNode>();
- cf_else->cf_type=ControlFlowNode::CF_IF;
-
- //condition
- Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
- return;
- cf_else->arguments.push_back(condition);
- cf_else->cf_type=ControlFlowNode::CF_IF;
-
- cf_if->body_else->statements.push_back(cf_else);
- cf_if=cf_else;
- cf_if->body=alloc_node<BlockNode>();
- p_block->sub_blocks.push_back(cf_if->body);
-
-
- if (!_enter_indent_block(cf_if->body)) {
- p_block->end_line=tokenizer.get_token_line();
- return;
- }
-
- _parse_block(cf_else->body,p_static);
- if (error_set)
- return;
-
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_CF_ELSE) {
-
- if (tab_level.back()->get() > indent_level) {
-
- _set_error("Invalid indent");
- return;
- }
-
-
- tokenizer.advance();
- cf_if->body_else=alloc_node<BlockNode>();
- p_block->sub_blocks.push_back(cf_if->body_else);
-
- if (!_enter_indent_block(cf_if->body_else)) {
- p_block->end_line=tokenizer.get_token_line();
- return;
- }
- _parse_block(cf_if->body_else,p_static);
- if (error_set)
- return;
-
-
- break; //after else, exit
-
- } else
- break;
-
- }
-
-
- } break;
- case GDTokenizer::TK_CF_WHILE: {
-
- tokenizer.advance();
- Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
- return;
-
- ControlFlowNode *cf_while = alloc_node<ControlFlowNode>();
-
- cf_while->cf_type=ControlFlowNode::CF_WHILE;
- cf_while->arguments.push_back(condition);
-
- cf_while->body = alloc_node<BlockNode>();
- p_block->sub_blocks.push_back(cf_while->body);
-
- if (!_enter_indent_block(cf_while->body)) {
- p_block->end_line=tokenizer.get_token_line();
- return;
- }
-
- _parse_block(cf_while->body,p_static);
- if (error_set)
- return;
- p_block->statements.push_back(cf_while);
- } break;
- case GDTokenizer::TK_CF_FOR: {
-
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("identifier expected after 'for'");
- }
-
- IdentifierNode *id = alloc_node<IdentifierNode>();
- id->name=tokenizer.get_token_identifier();
-
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_OP_IN) {
- _set_error("'in' expected after identifier");
- return;
- }
-
- tokenizer.advance();
-
- Node *container = _parse_and_reduce_expression(p_block,p_static);
- if (!container)
- return;
-
- ControlFlowNode *cf_for = alloc_node<ControlFlowNode>();
-
- cf_for->cf_type=ControlFlowNode::CF_FOR;
- cf_for->arguments.push_back(id);
- cf_for->arguments.push_back(container);
-
- cf_for->body = alloc_node<BlockNode>();
- p_block->sub_blocks.push_back(cf_for->body);
-
- if (!_enter_indent_block(cf_for->body)) {
- p_block->end_line=tokenizer.get_token_line();
- return;
- }
-
- _parse_block(cf_for->body,p_static);
- if (error_set)
- return;
- p_block->statements.push_back(cf_for);
- } break;
- case GDTokenizer::TK_CF_CONTINUE: {
-
- tokenizer.advance();
- ControlFlowNode *cf_continue = alloc_node<ControlFlowNode>();
- cf_continue->cf_type=ControlFlowNode::CF_CONTINUE;
- p_block->statements.push_back(cf_continue);
- if (!_end_statement()) {
- _set_error("Expected end of statement (continue)");
- return;
- }
- } break;
- case GDTokenizer::TK_CF_BREAK: {
-
- tokenizer.advance();
- ControlFlowNode *cf_break = alloc_node<ControlFlowNode>();
- cf_break->cf_type=ControlFlowNode::CF_BREAK;
- p_block->statements.push_back(cf_break);
- if (!_end_statement()) {
- _set_error("Expected end of statement (break)");
- return;
- }
- } break;
- case GDTokenizer::TK_CF_RETURN: {
-
- tokenizer.advance();
- ControlFlowNode *cf_return = alloc_node<ControlFlowNode>();
- cf_return->cf_type=ControlFlowNode::CF_RETURN;
-
-
-
- if (tokenizer.get_token()==GDTokenizer::TK_SEMICOLON || tokenizer.get_token()==GDTokenizer::TK_NEWLINE || tokenizer.get_token()==GDTokenizer::TK_EOF) {
- //expect end of statement
- p_block->statements.push_back(cf_return);
- if (!_end_statement()) {
- return;
- }
- } else {
- //expect expression
- Node *retexpr = _parse_and_reduce_expression(p_block,p_static);
- if (!retexpr)
- return;
- cf_return->arguments.push_back(retexpr);
- p_block->statements.push_back(cf_return);
- if (!_end_statement()) {
- _set_error("Expected end of statement after return expression.");
- return;
- }
- }
-
-
- } break;
- case GDTokenizer::TK_PR_ASSERT: {
-
- tokenizer.advance();
- Node *condition = _parse_and_reduce_expression(p_block,p_static);
- if (!condition)
- return;
- AssertNode *an = alloc_node<AssertNode>();
- an->condition=condition;
- p_block->statements.push_back(an);
-
- if (!_end_statement()) {
- _set_error("Expected end of statement after assert.");
- return;
- }
- } break;
- default: {
-
- Node *expression = _parse_and_reduce_expression(p_block,p_static,false,true);
- if (!expression)
- return;
- p_block->statements.push_back(expression);
- if (!_end_statement()) {
- _set_error("Expected end of statement after expression.");
- return;
- }
-
- } break;
- /*
- case GDTokenizer::TK_CF_LOCAL: {
-
- if (tokenizer.get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE ) {
-
- _set_error("Expected ';' or <NewLine>.");
- }
- tokenizer.advance();
- } break;
- */
-
- }
- }
-
-}
-
-bool GDParser::_parse_newline() {
-
- if (tokenizer.get_token(1)!=GDTokenizer::TK_EOF && tokenizer.get_token(1)!=GDTokenizer::TK_NEWLINE) {
-
- int indent = tokenizer.get_token_line_indent();
- int current_indent = tab_level.back()->get();
-
- if (indent>current_indent) {
- _set_error("Unexpected indent.");
- return false;
- }
-
- if (indent<current_indent) {
-
- while(indent<current_indent) {
-
- //exit block
- if (tab_level.size()==1) {
- _set_error("Invalid indent. BUG?");
- return false;
- }
-
- tab_level.pop_back();
-
- if (tab_level.back()->get()<indent) {
-
- _set_error("Unindent does not match any outer indentation level.");
- return false;
- }
- current_indent = tab_level.back()->get();
- }
-
- tokenizer.advance();
- return false;
- }
- }
-
- tokenizer.advance();
- return true;
-
-}
-
-
-void GDParser::_parse_extends(ClassNode *p_class) {
-
-
- if (p_class->extends_used) {
-
- _set_error("'extends' already used for this class.");
- return;
- }
-
- if (!p_class->constant_expressions.empty() || !p_class->subclasses.empty() || !p_class->functions.empty() || !p_class->variables.empty()) {
-
- _set_error("'extends' must be used before anything else.");
- return;
- }
-
- p_class->extends_used=true;
-
- //see if inheritance happens from a file
- tokenizer.advance();
-
- if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT) {
-
- Variant constant = tokenizer.get_token_constant();
- if (constant.get_type()!=Variant::STRING) {
-
- _set_error("'extends' constant must be a string.");
- return;
- }
-
- p_class->extends_file=constant;
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PERIOD) {
- return;
- } else
- tokenizer.advance();
-
- }
-
- while(true) {
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("Invalid 'extends' syntax, expected string constant (path) and/or identifier (parent class).");
- return;
- }
-
- StringName identifier=tokenizer.get_token_identifier();
- p_class->extends_class.push_back(identifier);
-
- tokenizer.advance(1);
- if (tokenizer.get_token()!=GDTokenizer::TK_PERIOD)
- return;
- }
-
-}
-
-void GDParser::_parse_class(ClassNode *p_class) {
-
- int indent_level = tab_level.back()->get();
-
- while(true) {
-
- GDTokenizer::Token token = tokenizer.get_token();
- if (error_set)
- return;
-
- if (indent_level>tab_level.back()->get()) {
- p_class->end_line=tokenizer.get_token_line();
- return; //go back a level
- }
-
- switch(token) {
-
- case GDTokenizer::TK_EOF:
- p_class->end_line=tokenizer.get_token_line();
- case GDTokenizer::TK_ERROR: {
- return; //go back
- //end of file!
- } break;
- case GDTokenizer::TK_NEWLINE: {
- if (!_parse_newline()) {
- if (!error_set) {
- p_class->end_line=tokenizer.get_token_line();
- }
- return;
- }
- } break;
- case GDTokenizer::TK_PR_EXTENDS: {
-
- _parse_extends(p_class);
- if (error_set)
- return;
- _end_statement();
-
-
- } break;
- case GDTokenizer::TK_PR_TOOL: {
-
- if (p_class->tool) {
-
- _set_error("tool used more than once");
- return;
- }
-
- p_class->tool=true;
- tokenizer.advance();
-
- } break;
- case GDTokenizer::TK_PR_CLASS: {
- //class inside class :D
-
- StringName name;
- StringName extends;
-
- if (tokenizer.get_token(1)!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("'class' syntax: 'class <Name>:' or 'class <Name> extends <BaseClass>:'");
- return;
- }
- name = tokenizer.get_token_identifier(1);
- tokenizer.advance(2);
-
- ClassNode *newclass = alloc_node<ClassNode>();
- newclass->initializer = alloc_node<BlockNode>();
- newclass->name=name;
-
- p_class->subclasses.push_back(newclass);
-
-
- if (tokenizer.get_token()==GDTokenizer::TK_PR_EXTENDS) {
-
- _parse_extends(newclass);
- if (error_set)
- return;
- }
-
- if (!_enter_indent_block()) {
-
- _set_error("Indented block expected.");
- return;
- }
- _parse_class(newclass);
-
- } break;
- /* this is for functions....
- case GDTokenizer::TK_CF_PASS: {
-
- tokenizer.advance(1);
- } break;
- */
- case GDTokenizer::TK_PR_STATIC: {
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_PR_FUNCTION) {
-
- _set_error("Expected 'func'.");
- return;
- }
-
- }; //fallthrough to function
- case GDTokenizer::TK_PR_FUNCTION: {
-
- bool _static=false;
-
- if (tokenizer.get_token(-1)==GDTokenizer::TK_PR_STATIC) {
-
- _static=true;
- }
-
-
- if (tokenizer.get_token(1)!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("Expected identifier after 'func' (syntax: 'func <identifier>([arguments]):' ).");
- return;
- }
-
- StringName name = tokenizer.get_token_identifier(1);
-
- for(int i=0;i<p_class->functions.size();i++) {
- if (p_class->functions[i]->name==name) {
- _set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->functions[i]->line)+").");
- }
- }
- for(int i=0;i<p_class->static_functions.size();i++) {
- if (p_class->static_functions[i]->name==name) {
- _set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->static_functions[i]->line)+").");
- }
- }
- tokenizer.advance(2);
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) {
-
- _set_error("Expected '(' after identifier (syntax: 'func <identifier>([arguments]):' ).");
- return;
- }
-
- tokenizer.advance();
-
- Vector<StringName> arguments;
- Vector<Node*> default_values;
-
- int fnline = tokenizer.get_token_line();
-
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
- //has arguments
- bool defaulting=false;
- while(true) {
-
- if (tokenizer.get_token()==GDTokenizer::TK_PR_VAR) {
-
- tokenizer.advance(); //var before the identifier is allowed
- }
-
-
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("Expected identifier for argument.");
- return;
- }
-
- StringName argname=tokenizer.get_token_identifier();
- arguments.push_back(argname);
-
- tokenizer.advance();
-
- if (defaulting && tokenizer.get_token()!=GDTokenizer::TK_OP_ASSIGN) {
-
- _set_error("Default parameter expected.");
- return;
- }
-
- //tokenizer.advance();
-
-
- if (tokenizer.get_token()==GDTokenizer::TK_OP_ASSIGN) {
- defaulting=true;
- tokenizer.advance(1);
- Node *defval=NULL;
-
- defval=_parse_and_reduce_expression(p_class,_static);
- if (!defval || error_set)
- return;
-
- OperatorNode *on = alloc_node<OperatorNode>();
- on->op=OperatorNode::OP_ASSIGN;
-
- IdentifierNode *in = alloc_node<IdentifierNode>();
- in->name=argname;
-
- on->arguments.push_back(in);
- on->arguments.push_back(defval);
- /* no ..
- if (defval->type!=Node::TYPE_CONSTANT) {
-
- _set_error("default argument must be constant");
- }
- */
- default_values.push_back(on);
- }
-
- if (tokenizer.get_token()==GDTokenizer::TK_COMMA) {
- tokenizer.advance();
- continue;
- } else if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
-
- _set_error("Expected ',' or ')'.");
- return;
- }
-
- break;
- }
-
-
- }
-
- tokenizer.advance();
-
- BlockNode *block = alloc_node<BlockNode>();
-
- if (name=="_init") {
-
- if (p_class->extends_used) {
-
- OperatorNode *cparent = alloc_node<OperatorNode>();
- cparent->op=OperatorNode::OP_PARENT_CALL;
- block->statements.push_back(cparent);
-
- IdentifierNode *id = alloc_node<IdentifierNode>();
- id->name="_init";
- cparent->arguments.push_back(id);
-
- if (tokenizer.get_token()==GDTokenizer::TK_PERIOD) {
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) {
- _set_error("expected '(' for parent constructor arguments.");
- }
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
- //has arguments
- while(true) {
-
- Node *arg = _parse_and_reduce_expression(p_class,_static);
- cparent->arguments.push_back(arg);
-
- if (tokenizer.get_token()==GDTokenizer::TK_COMMA) {
- tokenizer.advance();
- continue;
- } else if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
-
- _set_error("Expected ',' or ')'.");
- return;
- }
-
- break;
-
- }
- }
-
- tokenizer.advance();
- }
- } else {
-
-
- if (tokenizer.get_token()==GDTokenizer::TK_PERIOD) {
-
- _set_error("Parent constructor call found for a class without inheritance.");
- return;
- }
-
- }
- }
-
- if (!_enter_indent_block(block)) {
-
- _set_error("Indented block expected.");
- return;
- }
-
- FunctionNode *function = alloc_node<FunctionNode>();
- function->name=name;
- function->arguments=arguments;
- function->default_values=default_values;
- function->_static=_static;
- function->line=fnline;
-
-
- if (_static)
- p_class->static_functions.push_back(function);
- else
- p_class->functions.push_back(function);
-
-
- _parse_block(block,_static);
- function->body=block;
- //arguments
- } break;
- case GDTokenizer::TK_PR_EXPORT: {
-
- tokenizer.advance();
-
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) {
-
- tokenizer.advance();
- if (tokenizer.get_token()==GDTokenizer::TK_BUILT_IN_TYPE) {
-
- Variant::Type type = tokenizer.get_token_type();
- if (type==Variant::NIL) {
- _set_error("Can't export null type.");
- return;
- }
- current_export.type=type;
- tokenizer.advance();
- if (tokenizer.get_token()==GDTokenizer::TK_COMMA) {
- // hint expected next!
- tokenizer.advance();
- switch(current_export.type) {
-
-
- case Variant::INT: {
-
- if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT && tokenizer.get_token_constant().get_type()==Variant::STRING) {
- //enumeration
- current_export.hint=PROPERTY_HINT_ENUM;
- bool first=true;
- while(true) {
-
- if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) {
-
- current_export=PropertyInfo();
- _set_error("Expected a string constant in enumeration hint.");
- }
-
- String c = tokenizer.get_token_constant();
- if (!first)
- current_export.hint_string+=",";
- else
- first=false;
-
- current_export.hint_string+=c.xml_escape();
-
- tokenizer.advance();
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE)
- break;
-
- if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) {
- current_export=PropertyInfo();
- _set_error("Expected ')' or ',' in enumeration hint.");
- }
-
- tokenizer.advance();
-
- }
-
- break;
- }
-
- };
- case Variant::REAL: {
-
- if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer.get_token_constant().is_num()) {
-
- current_export=PropertyInfo();
- _set_error("Expected a range in numeric hint.");
-
- }
- //enumeration
- current_export.hint=PROPERTY_HINT_RANGE;
-
- current_export.hint_string=tokenizer.get_token_constant().operator String();
- tokenizer.advance();
-
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE) {
- current_export.hint_string="0,"+current_export.hint_string;
- break;
- }
-
- if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) {
-
- current_export=PropertyInfo();
- _set_error("Expected ',' or ')' in numeric range hint.");
- }
-
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer.get_token_constant().is_num()) {
-
- current_export=PropertyInfo();
- _set_error("Expected a number as upper bound in numeric range hint.");
- }
-
- current_export.hint_string+=","+tokenizer.get_token_constant().operator String();
- tokenizer.advance();
-
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE)
- break;
-
- if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) {
-
- current_export=PropertyInfo();
- _set_error("Expected ',' or ')' in numeric range hint.");
- }
-
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || !tokenizer.get_token_constant().is_num()) {
-
- current_export=PropertyInfo();
- _set_error("Expected a number as step in numeric range hint.");
- }
-
- current_export.hint_string+=","+tokenizer.get_token_constant().operator String();
- tokenizer.advance();
-
- } break;
- case Variant::STRING: {
-
- if (tokenizer.get_token()==GDTokenizer::TK_CONSTANT && tokenizer.get_token_constant().get_type()==Variant::STRING) {
- //enumeration
- current_export.hint=PROPERTY_HINT_ENUM;
- bool first=true;
- while(true) {
-
- if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) {
-
- current_export=PropertyInfo();
- _set_error("Expected a string constant in enumeration hint.");
- }
-
- String c = tokenizer.get_token_constant();
- if (!first)
- current_export.hint_string+=",";
- else
- first=false;
-
- current_export.hint_string+=c.xml_escape();
- tokenizer.advance();
- if (tokenizer.get_token()==GDTokenizer::TK_PARENTHESIS_CLOSE)
- break;
-
- if (tokenizer.get_token()!=GDTokenizer::TK_COMMA) {
- current_export=PropertyInfo();
- _set_error("Expected ')' or ',' in enumeration hint.");
- return;
- }
- tokenizer.advance();
-
- }
-
- break;
- }
-
- if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token_identifier()=="DIR") {
-
- current_export.hint=PROPERTY_HINT_DIR;
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
- return;
- }
- break;
- }
-
- if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer.get_token_identifier()=="FILE") {
-
- current_export.hint=PROPERTY_HINT_FILE;
- tokenizer.advance();
-
- if (tokenizer.get_token()==GDTokenizer::TK_COMMA) {
-
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_CONSTANT || tokenizer.get_token_constant().get_type()!=Variant::STRING) {
-
- _set_error("Expected string constant with filter");
- return;
- }
- current_export.hint_string=tokenizer.get_token_constant();
- tokenizer.advance();
-
- }
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
- return;
- }
- break;
- }
- } break;
- case Variant::COLOR: {
-
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER ) {
-
- current_export=PropertyInfo();
- _set_error("Color type hint expects RGB or RGBA as hints");
- return;
- }
-
- String identifier = tokenizer.get_token_identifier();
- if (identifier=="RGB") {
- current_export.hint=PROPERTY_HINT_COLOR_NO_ALPHA;
- } else if (identifier=="RGBA") {
- //none
- } else {
- current_export=PropertyInfo();
- _set_error("Color type hint expects RGB or RGBA as hints");
- return;
- }
- tokenizer.advance();
-
- } break;
- default: {
-
- current_export=PropertyInfo();
- _set_error("Type '"+Variant::get_type_name(type)+"' can't take hints.");
- return;
- } break;
- }
-
- }
-
- } else if (tokenizer.get_token()==GDTokenizer::TK_IDENTIFIER) {
-
- String identifier = tokenizer.get_token_identifier();
- if (!ObjectTypeDB::is_type(identifier,"Resource")) {
-
- current_export=PropertyInfo();
- _set_error("Export hint not a type or resource.");
- }
-
- current_export.type=Variant::OBJECT;
- current_export.hint=PROPERTY_HINT_RESOURCE_TYPE;
- current_export.hint_string=identifier;
-
- tokenizer.advance();
- }
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
-
- current_export=PropertyInfo();
- _set_error("Expected ')' or ',' after export hint.");
- return;
-
- }
-
- tokenizer.advance();
-
- }
-
- if (tokenizer.get_token()!=GDTokenizer::TK_PR_VAR) {
-
- current_export=PropertyInfo();
- _set_error("Expected 'var'.");
- return;
- }
-
- }; //fallthrough to var
- case GDTokenizer::TK_PR_VAR: {
- //variale declaration and (eventual) initialization
-
- ClassNode::Member member;
- bool autoexport = tokenizer.get_token(-1)==GDTokenizer::TK_PR_EXPORT;
- if (current_export.type!=Variant::NIL) {
- member._export=current_export;
- current_export=PropertyInfo();
- }
-
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("Expected identifier for member variable name.");
- return;
- }
-
- member.identifier=tokenizer.get_token_identifier();
- member._export.name=member.identifier;
- tokenizer.advance();
-
- p_class->variables.push_back(member);
-
- if (tokenizer.get_token()!=GDTokenizer::TK_OP_ASSIGN) {
-
- if (autoexport) {
-
- _set_error("Type-less export needs a constant expression assigned to infer type.");
- return;
- }
- break;
- }
-#ifdef DEBUG_ENABLED
- int line = tokenizer.get_token_line();
-#endif
- tokenizer.advance();
-
- Node *subexpr=NULL;
-
- subexpr = _parse_and_reduce_expression(p_class,false);
- if (!subexpr)
- return;
-
- if (autoexport) {
- if (subexpr->type==Node::TYPE_ARRAY) {
-
- p_class->variables[p_class->variables.size()-1]._export.type=Variant::ARRAY;
-
- } else if (subexpr->type==Node::TYPE_DICTIONARY) {
-
- p_class->variables[p_class->variables.size()-1]._export.type=Variant::DICTIONARY;
-
- } else {
-
- if (subexpr->type!=Node::TYPE_CONSTANT) {
-
- _set_error("Type-less export needs a constant expression assigned to infer type.");
- return;
- }
-
- ConstantNode *cn = static_cast<ConstantNode*>(subexpr);
- if (cn->value.get_type()==Variant::NIL) {
-
- _set_error("Can't accept a null constant expression for infering export type.");
- return;
- }
- p_class->variables[p_class->variables.size()-1]._export.type=cn->value.get_type();
- }
- }
-#ifdef TOOLS_ENABLED
- if (subexpr->type==Node::TYPE_CONSTANT && p_class->variables[p_class->variables.size()-1]._export.type!=Variant::NIL) {
-
- ConstantNode *cn = static_cast<ConstantNode*>(subexpr);
- if (cn->value.get_type()!=Variant::NIL) {
- p_class->variables[p_class->variables.size()-1].default_value=cn->value;
- }
- }
-#endif
-
-
-
- IdentifierNode *id = alloc_node<IdentifierNode>();
- id->name=member.identifier;
-
- OperatorNode *op = alloc_node<OperatorNode>();
- op->op=OperatorNode::OP_ASSIGN;
- op->arguments.push_back(id);
- op->arguments.push_back(subexpr);
-
-#ifdef DEBUG_ENABLED
- NewLineNode *nl = alloc_node<NewLineNode>();
- nl->line=line;
- p_class->initializer->statements.push_back(nl);
-#endif
- p_class->initializer->statements.push_back(op);
-
- _end_statement();
-
- } break;
- case GDTokenizer::TK_PR_CONST: {
- //variale declaration and (eventual) initialization
-
- ClassNode::Constant constant;
-
- tokenizer.advance();
- if (tokenizer.get_token()!=GDTokenizer::TK_IDENTIFIER) {
-
- _set_error("Expected name (identifier) for constant.");
- return;
- }
-
- constant.identifier=tokenizer.get_token_identifier();
- tokenizer.advance();
-
- if (tokenizer.get_token()!=GDTokenizer::TK_OP_ASSIGN) {
- _set_error("Constant expects assignment.");
- return;
- }
-
- tokenizer.advance();
-
- Node *subexpr=NULL;
-
- subexpr = _parse_and_reduce_expression(p_class,true,true);
- if (!subexpr)
- return;
-
- if (subexpr->type!=Node::TYPE_CONSTANT) {
- _set_error("Expected constant expression");
- }
- constant.expression=subexpr;
-
- p_class->constant_expressions.push_back(constant);
-
- _end_statement();
-
-
- } break;
-
-
- default: {
-
- _set_error(String()+"Unexpected token: "+tokenizer.get_token_name(tokenizer.get_token())+":"+tokenizer.get_token_identifier());
- return;
-
- } break;
-
- }
-
- }
-
-
-}
-
-
-void GDParser::_set_error(const String& p_error, int p_line, int p_column) {
-
-
- if (error_set)
- return; //allow no further errors
-
- error=p_error;
- error_line=p_line<0?tokenizer.get_token_line():p_line;
- error_column=p_column<0?tokenizer.get_token_column():p_column;
- error_set=true;
-}
-
-String GDParser::get_error() const {
-
- return error;
-}
-
-int GDParser::get_error_line() const {
-
- return error_line;
-}
-int GDParser::get_error_column() const {
-
- return error_column;
-}
-
-
-Error GDParser::parse(const String& p_code,const String& p_base_path) {
-
- base_path=p_base_path;
-
- tokenizer.set_code(p_code);
-
- clear();
-
- //assume class
- ClassNode *main_class = alloc_node<ClassNode>();
- main_class->initializer = alloc_node<BlockNode>();
-
- _parse_class(main_class);
-
- if (tokenizer.get_token()==GDTokenizer::TK_ERROR) {
- error_set=false;
- _set_error("Parse Error: "+tokenizer.get_token_error());
- }
-
- if (error_set) {
-
- return ERR_PARSE_ERROR;
- }
- return OK;
-}
-
-const GDParser::Node *GDParser::get_parse_tree() const {
-
- return head;
-}
-
-void GDParser::clear() {
-
- while(list) {
-
- Node *l=list;
- list=list->next;
- memdelete(l);
- }
-
- head=NULL;
- list=NULL;
-
- error_set=false;
- tab_level.clear();
- tab_level.push_back(0);
- error_line=0;
- error_column=0;
- current_export.type=Variant::NIL;
- error="";
-
-}
-
-GDParser::GDParser() {
-
- head=NULL;
- list=NULL;
- clear();
-
-}
-
-GDParser::~GDParser() {
-
- clear();
-}
diff --git a/script/gdscript/gd_parser.h b/script/gdscript/gd_parser.h
deleted file mode 100644
index 8011495340..0000000000
--- a/script/gdscript/gd_parser.h
+++ /dev/null
@@ -1,397 +0,0 @@
-/*************************************************************************/
-/* gd_parser.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef GD_PARSER_H
-#define GD_PARSER_H
-
-#include "gd_tokenizer.h"
-#include "gd_functions.h"
-#include "map.h"
-#include "object.h"
-
-class GDParser {
-public:
-
- struct Node {
-
- enum Type {
- TYPE_CLASS,
- TYPE_FUNCTION,
- TYPE_BUILT_IN_FUNCTION,
- TYPE_BLOCK,
- TYPE_IDENTIFIER,
- TYPE_TYPE,
- TYPE_CONSTANT,
- TYPE_ARRAY,
- TYPE_DICTIONARY,
- TYPE_SELF,
- TYPE_OPERATOR,
- TYPE_CONTROL_FLOW,
- TYPE_LOCAL_VAR,
- TYPE_ASSERT,
- TYPE_NEWLINE,
- };
-
- Node * next;
- int line;
- int column;
- Type type;
-
- virtual ~Node() {}
- };
-
- struct FunctionNode;
- struct BlockNode;
-
- struct ClassNode : public Node {
-
- bool tool;
- StringName name;
- bool extends_used;
- StringName extends_file;
- Vector<StringName> extends_class;
-
- struct Member {
- PropertyInfo _export;
-#ifdef TOOLS_ENABLED
- Variant default_value;
-#endif
- StringName identifier;
- };
- struct Constant {
- StringName identifier;
- Node *expression;
- };
-
- Vector<ClassNode*> subclasses;
- Vector<Member> variables;
- Vector<Constant> constant_expressions;
- Vector<FunctionNode*> functions;
- Vector<FunctionNode*> static_functions;
- BlockNode *initializer;
- //Vector<Node*> initializers;
- int end_line;
-
- ClassNode() { tool=false; type=TYPE_CLASS; extends_used=false; end_line=-1;}
- };
-
-
-
- struct FunctionNode : public Node {
-
- bool _static;
- StringName name;
- Vector<StringName> arguments;
- Vector<Node*> default_values;
- BlockNode *body;
-
- FunctionNode() { type=TYPE_FUNCTION; _static=false; }
-
- };
-
- struct BlockNode : public Node {
-
- Map<StringName,int> locals;
- List<Node*> statements;
- Vector<StringName> variables;
- Vector<int> variable_lines;
-
- //the following is useful for code completion
- List<BlockNode*> sub_blocks;
- int end_line;
- BlockNode() { type=TYPE_BLOCK; end_line=-1;}
- };
-
- struct TypeNode : public Node {
-
- Variant::Type vtype;
- TypeNode() { type=TYPE_TYPE; }
- };
- struct BuiltInFunctionNode : public Node {
- GDFunctions::Function function;
- BuiltInFunctionNode() { type=TYPE_BUILT_IN_FUNCTION; }
- };
-
- struct IdentifierNode : public Node {
-
- StringName name;
- IdentifierNode() { type=TYPE_IDENTIFIER; }
- };
-
- struct LocalVarNode : public Node {
-
- StringName name;
- Node *assign;
- LocalVarNode() { type=TYPE_LOCAL_VAR; assign=NULL;}
- };
-
- struct ConstantNode : public Node {
- Variant value;
- ConstantNode() { type=TYPE_CONSTANT; }
- };
-
- struct ArrayNode : public Node {
-
- Vector<Node*> elements;
- ArrayNode() { type=TYPE_ARRAY; }
- };
-
-
- struct DictionaryNode : public Node {
-
- struct Pair {
-
- Node *key;
- Node *value;
- };
-
- Vector<Pair> elements;
- DictionaryNode() { type=TYPE_DICTIONARY; }
- };
-
- struct SelfNode : public Node {
- SelfNode() { type=TYPE_SELF; }
- };
-
- struct OperatorNode : public Node {
- enum Operator {
- //call/constructor operator
- OP_CALL,
- OP_PARENT_CALL,
- OP_EXTENDS,
- //indexing operator
- OP_INDEX,
- OP_INDEX_NAMED,
- //unary operators
- OP_NEG,
- OP_NOT,
- OP_BIT_INVERT,
- OP_PREINC,
- OP_PREDEC,
- OP_INC,
- OP_DEC,
- //binary operators (in precedence order)
- OP_IN,
- OP_EQUAL,
- OP_NOT_EQUAL,
- OP_LESS,
- OP_LESS_EQUAL,
- OP_GREATER,
- OP_GREATER_EQUAL,
- OP_AND,
- OP_OR,
- OP_ADD,
- OP_SUB,
- OP_MUL,
- OP_DIV,
- OP_MOD,
- OP_SHIFT_LEFT,
- OP_SHIFT_RIGHT,
- OP_ASSIGN,
- OP_ASSIGN_ADD,
- OP_ASSIGN_SUB,
- OP_ASSIGN_MUL,
- OP_ASSIGN_DIV,
- OP_ASSIGN_MOD,
- OP_ASSIGN_SHIFT_LEFT,
- OP_ASSIGN_SHIFT_RIGHT,
- OP_ASSIGN_BIT_AND,
- OP_ASSIGN_BIT_OR,
- OP_ASSIGN_BIT_XOR,
- OP_BIT_AND,
- OP_BIT_OR,
- OP_BIT_XOR
- };
-
- Operator op;
-
- Vector<Node*> arguments;
- OperatorNode() { type=TYPE_OPERATOR; }
- };
-
- struct ControlFlowNode : public Node {
- enum CFType {
- CF_IF,
- CF_FOR,
- CF_WHILE,
- CF_SWITCH,
- CF_BREAK,
- CF_CONTINUE,
- CF_RETURN
- };
-
- CFType cf_type;
- Vector<Node*> arguments;
- BlockNode *body;
- BlockNode *body_else;
-
- ControlFlowNode *_else; //used for if
- ControlFlowNode() { type=TYPE_CONTROL_FLOW; cf_type=CF_IF; body=NULL; body_else=NULL;}
- };
-
- struct AssertNode : public Node {
- Node* condition;
- AssertNode() { type=TYPE_ASSERT; }
- };
- struct NewLineNode : public Node {
- int line;
- NewLineNode() { type=TYPE_NEWLINE; }
- };
-
-
- struct Expression {
-
- bool is_op;
- union {
- OperatorNode::Operator op;
- Node *node;
- };
- };
-
-
-/*
- struct OperatorNode : public Node {
-
- DataType return_cache;
- Operator op;
- Vector<Node*> arguments;
- virtual DataType get_datatype() const { return return_cache; }
-
- OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; }
- };
-
- struct VariableNode : public Node {
-
- DataType datatype_cache;
- StringName name;
- virtual DataType get_datatype() const { return datatype_cache; }
-
- VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; }
- };
-
- struct ConstantNode : public Node {
-
- DataType datatype;
- Variant value;
- virtual DataType get_datatype() const { return datatype; }
-
- ConstantNode() { type=TYPE_CONSTANT; }
- };
-
- struct BlockNode : public Node {
-
- Map<StringName,DataType> variables;
- List<Node*> statements;
- BlockNode() { type=TYPE_BLOCK; }
- };
-
- struct ControlFlowNode : public Node {
-
- FlowOperation flow_op;
- Vector<Node*> statements;
- ControlFlowNode() { type=TYPE_CONTROL_FLOW; flow_op=FLOW_OP_IF;}
- };
-
- struct MemberNode : public Node {
-
- DataType datatype;
- StringName name;
- Node* owner;
- virtual DataType get_datatype() const { return datatype; }
- MemberNode() { type=TYPE_MEMBER; }
- };
-
-
- struct ProgramNode : public Node {
-
- struct Function {
- StringName name;
- FunctionNode*function;
- };
-
- Map<StringName,DataType> builtin_variables;
- Map<StringName,DataType> preexisting_variables;
-
- Vector<Function> functions;
- BlockNode *body;
-
- ProgramNode() { type=TYPE_PROGRAM; }
- };
-*/
-private:
-
-
- GDTokenizer tokenizer;
-
-
- Node *head;
- Node *list;
- template<class T>
- T* alloc_node();
-
- bool error_set;
- String error;
- int error_line;
- int error_column;
-
- List<int> tab_level;
-
- String base_path;
-
- PropertyInfo current_export;
-
- void _set_error(const String& p_error, int p_line=-1, int p_column=-1);
-
-
- bool _parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_static);
- bool _enter_indent_block(BlockNode *p_block=NULL);
- bool _parse_newline();
- Node* _parse_expression(Node *p_parent,bool p_static,bool p_allow_assign=false);
- Node* _reduce_expression(Node *p_node,bool p_to_const=false);
- Node* _parse_and_reduce_expression(Node *p_parent,bool p_static,bool p_reduce_const=false,bool p_allow_assign=false);
-
- void _parse_block(BlockNode *p_block,bool p_static);
- void _parse_extends(ClassNode *p_class);
- void _parse_class(ClassNode *p_class);
- bool _end_statement();
-
-public:
-
- String get_error() const;
- int get_error_line() const;
- int get_error_column() const;
- Error parse(const String& p_code,const String& p_base_path="");
-
- const Node *get_parse_tree() const;
-
- void clear();
- GDParser();
- ~GDParser();
-};
-
-#endif // PARSER_H
diff --git a/script/gdscript/gd_pretty_print.cpp b/script/gdscript/gd_pretty_print.cpp
deleted file mode 100644
index a5a993bb3a..0000000000
--- a/script/gdscript/gd_pretty_print.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*************************************************************************/
-/* gd_pretty_print.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gd_pretty_print.h"
-
-GDPrettyPrint::GDPrettyPrint() {
-
-
-}
diff --git a/script/gdscript/gd_pretty_print.h b/script/gdscript/gd_pretty_print.h
deleted file mode 100644
index fbf002295b..0000000000
--- a/script/gdscript/gd_pretty_print.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*************************************************************************/
-/* gd_pretty_print.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef GD_PRETTY_PRINT_H
-#define GD_PRETTY_PRINT_H
-
-
-
-
-class GDPrettyPrint {
-public:
- GDPrettyPrint();
-};
-
-#endif // GD_PRETTY_PRINT_H
diff --git a/script/gdscript/gd_script.cpp b/script/gdscript/gd_script.cpp
deleted file mode 100644
index 5679e1e066..0000000000
--- a/script/gdscript/gd_script.cpp
+++ /dev/null
@@ -1,2222 +0,0 @@
-/*************************************************************************/
-/* gd_script.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gd_script.h"
-#include "globals.h"
-#include "global_constants.h"
-#include "gd_compiler.h"
-#include "os/file_access.h"
-
-/* TODO:
-
- *populate globals
- *do checks as close to debugger as possible (but don't do debugger)
- *const check plz
- *check arguments and default arguments in GDFunction
- -get property list in instance?
- *missing opcodes
- -const checks
- -make thread safe
- */
-
-
-
-Variant *GDFunction::_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self, Variant *p_stack,String& r_error) const{
-
- int address = p_address&ADDR_MASK;
-
- //sequential table (jump table generated by compiler)
- switch((p_address&ADDR_TYPE_MASK)>>ADDR_BITS) {
-
- case ADDR_TYPE_SELF: {
-
- if (!p_instance) {
- r_error="Cannot access self without instance.";
- return NULL;
- }
- return &self;
- } break;
- case ADDR_TYPE_MEMBER: {
- //member indexing is O(1)
- if (!p_instance) {
- r_error="Cannot access member without instance.";
- return NULL;
- }
- return &p_instance->members[address];
- } break;
- case ADDR_TYPE_CLASS_CONSTANT: {
-
- //todo change to index!
- GDScript *s=p_script;
- ERR_FAIL_INDEX_V(address,_global_names_count,NULL);
- const StringName *sn = &_global_names_ptr[address];
-
- while(s) {
- Map<StringName,Variant>::Element *E=s->constants.find(*sn);
- if (E) {
- return &E->get();
- }
- s=s->_base;
- }
-
-
- ERR_EXPLAIN("GDCompiler bug..");
- ERR_FAIL_V(NULL);
- } break;
- case ADDR_TYPE_LOCAL_CONSTANT: {
- ERR_FAIL_INDEX_V(address,_constant_count,NULL);
- return &_constants_ptr[address];
- } break;
- case ADDR_TYPE_STACK:
- case ADDR_TYPE_STACK_VARIABLE: {
- ERR_FAIL_INDEX_V(address,_stack_size,NULL);
- return &p_stack[address];
- } break;
- case ADDR_TYPE_GLOBAL: {
-
-
- ERR_FAIL_INDEX_V(address,GDScriptLanguage::get_singleton()->get_global_array_size(),NULL);
-
-
- return &GDScriptLanguage::get_singleton()->get_global_array()[address];
- } break;
- case ADDR_TYPE_NIL: {
- return &nil;
- } break;
- }
-
- ERR_EXPLAIN("Bad Code! (Addressing Mode)");
- ERR_FAIL_V(NULL);
- return NULL;
-}
-
-
-String GDFunction::_get_call_error(const Variant::CallError& p_err, const String& p_where,const Variant**argptrs) const {
-
-
-
- String err_text;
-
- if (p_err.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
- int errorarg=p_err.argument;
- err_text="Invalid type in "+p_where+". Cannot convert argument "+itos(errorarg+1)+" from "+Variant::get_type_name(argptrs[errorarg]->get_type())+" to "+Variant::get_type_name(p_err.expected)+".";
- } else if (p_err.error==Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
- err_text="Invalid call to "+p_where+". Expected "+itos(p_err.argument)+" arguments.";
- } else if (p_err.error==Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
- err_text="Invalid call to "+p_where+". Expected "+itos(p_err.argument)+" arguments.";
- } else if (p_err.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) {
- err_text="Invalid call. Unexisting "+p_where+".";
- } else if (p_err.error==Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
- err_text="Attempt to call "+p_where+" on a null instance.";
- } else {
- err_text="Bug, call error: #"+itos(p_err.error);
- }
-
- return err_text;
-
-}
-
-static String _get_var_type(const Variant* p_type) {
-
- String basestr;
-
- if (p_type->get_type()==Variant::OBJECT) {
- Object *bobj = *p_type;
- if (!bobj) {
- basestr = "null instance";
- } else {
-#ifdef DEBUG_ENABLED
- if (ObjectDB::instance_validate(bobj)) {
- if (bobj->get_script_instance())
- basestr= bobj->get_type()+" ("+bobj->get_script_instance()->get_script()->get_path().get_file()+")";
- else
- basestr = bobj->get_type();
- } else {
- basestr="previously freed instance";
- }
-
-#else
- basestr="Object";
-#endif
- }
-
- } else {
- basestr = Variant::get_type_name(p_type->get_type());
- }
-
- return basestr;
-
-}
-
-Variant GDFunction::call(GDInstance *p_instance,const Variant **p_args, int p_argcount,Variant::CallError& r_err) {
-
-
- if (!_code_ptr) {
-
- return Variant();
- }
-
- r_err.error=Variant::CallError::CALL_OK;
-
- Variant self;
- Variant retvalue;
- Variant *stack = NULL;
- Variant **call_args;
- int defarg=0;
-
-#ifdef DEBUG_ENABLED
-
- //GDScriptLanguage::get_singleton()->calls++;
-
-#endif
-
- if (p_argcount!=_argument_count) {
-
- if (p_argcount>_argument_count) {
-
- r_err.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
- r_err.argument=_argument_count;
-
- return Variant();
- } else if (p_argcount < _argument_count - _default_arg_count) {
-
- r_err.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_err.argument=_argument_count - _default_arg_count;
- return Variant();
- } else {
-
- defarg=_argument_count-p_argcount;
- }
- }
-
- uint32_t alloca_size = sizeof(Variant*)*_call_size + sizeof(Variant)*_stack_size;
-
- if (alloca_size) {
-
- uint8_t *aptr = (uint8_t*)alloca(alloca_size);
-
- if (_stack_size) {
-
- stack=(Variant*)aptr;
- for(int i=0;i<p_argcount;i++)
- memnew_placement(&stack[i],Variant(*p_args[i]));
- for(int i=p_argcount;i<_stack_size;i++)
- memnew_placement(&stack[i],Variant);
- } else {
- stack=NULL;
- }
-
- if (_call_size) {
-
- call_args = (Variant**)&aptr[sizeof(Variant)*_stack_size];
- } else {
-
- call_args=NULL;
- }
-
-
- } else {
- stack=NULL;
- call_args=NULL;
- }
-
-
- GDScript *_class;
-
- if (p_instance) {
- if (p_instance->base_ref && static_cast<Reference*>(p_instance->owner)->is_referenced()) {
-
- self=REF(static_cast<Reference*>(p_instance->owner));
- } else {
- self=p_instance->owner;
- }
- _class=p_instance->script.ptr();
- } else {
- _class=_script;
- }
-
- int ip=0;
- int line=_initial_line;
- String err_text;
-
-
-
-#ifdef DEBUG_ENABLED
-
- if (ScriptDebugger::get_singleton())
- GDScriptLanguage::get_singleton()->enter_function(p_instance,this,stack,&ip,&line);
-
-#define CHECK_SPACE(m_space)\
- ERR_BREAK((ip+m_space)>_code_size)
-
-#define GET_VARIANT_PTR(m_v,m_code_ofs) \
- Variant *m_v; \
- m_v = _get_variant(_code_ptr[ip+m_code_ofs],p_instance,_class,self,stack,err_text);\
- if (!m_v)\
- break;
-
-
-#else
-#define CHECK_SPACE(m_space)
-#define GET_VARIANT_PTR(m_v,m_code_ofs) \
- Variant *m_v; \
- m_v = _get_variant(_code_ptr[ip+m_code_ofs],p_instance,_class,self,stack,err_text);
-
-#endif
-
-
-
- bool exit_ok=false;
-
- while(ip<_code_size) {
-
-
- int last_opcode=_code_ptr[ip];
- switch(_code_ptr[ip]) {
-
- case OPCODE_OPERATOR: {
-
- CHECK_SPACE(5);
-
- bool valid;
- Variant::Operator op = (Variant::Operator)_code_ptr[ip+1];
- ERR_BREAK(op>=Variant::OP_MAX);
-
- GET_VARIANT_PTR(a,2);
- GET_VARIANT_PTR(b,3);
- GET_VARIANT_PTR(dst,4);
-
- Variant::evaluate(op,*a,*b,*dst,valid);
- if (!valid) {
- if (false && dst->get_type()==Variant::STRING) {
- //return a string when invalid with the error
- err_text=*dst;
- } else {
- err_text="Invalid operands '"+Variant::get_type_name(a->get_type())+"' and '"+Variant::get_type_name(b->get_type())+"' in operator '"+Variant::get_operator_name(op)+"'.";
- }
- break;
- }
-
- ip+=5;
-
- } continue;
- case OPCODE_EXTENDS_TEST: {
-
- CHECK_SPACE(4);
-
- GET_VARIANT_PTR(a,1);
- GET_VARIANT_PTR(b,2);
- GET_VARIANT_PTR(dst,3);
-
-#ifdef DEBUG_ENABLED
-
- if (a->get_type()!=Variant::OBJECT || a->operator Object*()==NULL) {
-
- err_text="Left operand of 'extends' is not an instance of anything.";
- break;
-
- }
- if (b->get_type()!=Variant::OBJECT || b->operator Object*()==NULL) {
-
- err_text="Right operand of 'extends' is not a class.";
- break;
-
- }
-#endif
-
-
- Object *obj_A = *a;
- Object *obj_B = *b;
-
-
- GDScript *scr_B = obj_B->cast_to<GDScript>();
-
- bool extends_ok=false;
-
- if (scr_B) {
- //if B is a script, the only valid condition is that A has an instance which inherits from the script
- //in other situation, this shoul return false.
-
- if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language()==GDScriptLanguage::get_singleton()) {
-
- GDInstance *ins = static_cast<GDInstance*>(obj_A->get_script_instance());
- GDScript *cmp = ins->script.ptr();
- //bool found=false;
- while(cmp) {
-
- if (cmp==scr_B) {
- //inherits from script, all ok
- extends_ok=true;
- break;
-
- }
-
- cmp=cmp->_base;
- }
-
- }
- } else {
-
- GDNativeClass *nc= obj_B->cast_to<GDNativeClass>();
-
- if (!nc) {
-
- err_text="Right operand of 'extends' is not a class (type: '"+obj_B->get_type()+"').";
- break;
- }
-
- extends_ok=ObjectTypeDB::is_type(obj_A->get_type_name(),nc->get_name());
- }
-
- *dst=extends_ok;
- ip+=4;
-
- } continue;
- case OPCODE_SET: {
-
- CHECK_SPACE(3);
-
- GET_VARIANT_PTR(dst,1);
- GET_VARIANT_PTR(index,2);
- GET_VARIANT_PTR(value,3);
-
- bool valid;
- dst->set(*index,*value,&valid);
-
- if (!valid) {
- String v = index->operator String();
- if (v!="") {
- v="'"+v+"'";
- } else {
- v="of type '"+_get_var_type(index)+"'";
- }
- err_text="Invalid set index "+v+" (on base: '"+_get_var_type(dst)+"').";
- break;
- }
-
- ip+=4;
- } continue;
- case OPCODE_GET: {
-
- CHECK_SPACE(3);
-
- GET_VARIANT_PTR(src,1);
- GET_VARIANT_PTR(index,2);
- GET_VARIANT_PTR(dst,3);
-
- bool valid;
- *dst = src->get(*index,&valid);
-
- if (!valid) {
- String v = index->operator String();
- if (v!="") {
- v="'"+v+"'";
- } else {
- v="of type '"+_get_var_type(index)+"'";
- }
- err_text="Invalid get index "+v+" (on base: '"+_get_var_type(src)+"').";
- break;
- }
- ip+=4;
- } continue;
- case OPCODE_SET_NAMED: {
-
- CHECK_SPACE(3);
-
- GET_VARIANT_PTR(dst,1);
- GET_VARIANT_PTR(value,3);
-
- int indexname = _code_ptr[ip+2];
-
- ERR_BREAK(indexname<0 || indexname>=_global_names_count);
- const StringName *index = &_global_names_ptr[indexname];
-
- bool valid;
- dst->set_named(*index,*value,&valid);
-
- if (!valid) {
- String err_type;
- err_text="Invalid set index '"+String(*index)+"' (on base: '"+_get_var_type(dst)+"').";
- break;
- }
-
- ip+=4;
- } continue;
- case OPCODE_GET_NAMED: {
-
-
- CHECK_SPACE(3);
-
- GET_VARIANT_PTR(src,1);
- GET_VARIANT_PTR(dst,3);
-
- int indexname = _code_ptr[ip+2];
-
- ERR_BREAK(indexname<0 || indexname>=_global_names_count);
- const StringName *index = &_global_names_ptr[indexname];
-
- bool valid;
- *dst = src->get_named(*index,&valid);
-
- if (!valid) {
- err_text="Invalid get index '"+index->operator String()+"' (on base: '"+_get_var_type(src)+"').";
- break;
- }
-
- ip+=4;
- } continue;
- case OPCODE_ASSIGN: {
-
- CHECK_SPACE(3);
- GET_VARIANT_PTR(dst,1);
- GET_VARIANT_PTR(src,2);
-
- *dst = *src;
-
- ip+=3;
-
- } continue;
- case OPCODE_ASSIGN_TRUE: {
-
- CHECK_SPACE(2);
- GET_VARIANT_PTR(dst,1);
-
- *dst = true;
-
- ip+=2;
- } continue;
- case OPCODE_ASSIGN_FALSE: {
-
- CHECK_SPACE(2);
- GET_VARIANT_PTR(dst,1);
-
- *dst = false;
-
- ip+=2;
- } continue;
- case OPCODE_CONSTRUCT: {
-
- CHECK_SPACE(2);
- Variant::Type t=Variant::Type(_code_ptr[ip+1]);
- int argc=_code_ptr[ip+2];
- CHECK_SPACE(argc+2);
- Variant **argptrs = call_args;
- for(int i=0;i<argc;i++) {
- GET_VARIANT_PTR(v,3+i);
- argptrs[i]=v;
- }
-
- GET_VARIANT_PTR(dst,3+argc);
- Variant::CallError err;
- *dst = Variant::construct(t,(const Variant**)argptrs,argc,err);
-
- if (err.error!=Variant::CallError::CALL_OK) {
-
- err_text=_get_call_error(err,"'"+Variant::get_type_name(t)+"' constructor",(const Variant**)argptrs);
- break;
- }
-
- ip+=4+argc;
- //construct a basic type
- } continue;
- case OPCODE_CONSTRUCT_ARRAY: {
-
- CHECK_SPACE(1);
- int argc=_code_ptr[ip+1];
- Array array(true); //arrays are always shared
- array.resize(argc);
- CHECK_SPACE(argc+2);
-
- for(int i=0;i<argc;i++) {
- GET_VARIANT_PTR(v,2+i);
- array[i]=*v;
-
- }
-
- GET_VARIANT_PTR(dst,2+argc);
-
- *dst=array;
-
- ip+=3+argc;
-
- } continue;
- case OPCODE_CONSTRUCT_DICTIONARY: {
-
- CHECK_SPACE(1);
- int argc=_code_ptr[ip+1];
- Dictionary dict(true); //arrays are always shared
-
- CHECK_SPACE(argc*2+2);
-
- for(int i=0;i<argc;i++) {
-
- GET_VARIANT_PTR(k,2+i*2+0);
- GET_VARIANT_PTR(v,2+i*2+1);
- dict[*k]=*v;
-
- }
-
- GET_VARIANT_PTR(dst,2+argc*2);
-
- *dst=dict;
-
- ip+=3+argc*2;
-
- } continue;
- case OPCODE_CALL_RETURN:
- case OPCODE_CALL: {
-
-
- CHECK_SPACE(4);
- bool call_ret = _code_ptr[ip]==OPCODE_CALL_RETURN;
-
- int argc=_code_ptr[ip+1];
- GET_VARIANT_PTR(base,2);
- int nameg=_code_ptr[ip+3];
-
- ERR_BREAK(nameg<0 || nameg>=_global_names_count);
- const StringName *methodname = &_global_names_ptr[nameg];
-
- ERR_BREAK(argc<0);
- ip+=4;
- CHECK_SPACE(argc+1);
- Variant **argptrs = call_args;
-
- for(int i=0;i<argc;i++) {
- GET_VARIANT_PTR(v,i);
- argptrs[i]=v;
- }
-
- Variant::CallError err;
- if (call_ret) {
-
- GET_VARIANT_PTR(ret,argc);
- *ret = base->call(*methodname,(const Variant**)argptrs,argc,err);
- } else {
-
- base->call(*methodname,(const Variant**)argptrs,argc,err);
- }
-
- if (err.error!=Variant::CallError::CALL_OK) {
-
-
- String methodstr = *methodname;
- String basestr = _get_var_type(base);
-
- if (methodstr=="call") {
- if (argc>=1) {
- methodstr=String(*argptrs[0])+" (via call)";
- if (err.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {
- err.argument-=1;
- }
- }
- }
- err_text=_get_call_error(err,"function '"+methodstr+"' in base '"+basestr+"'",(const Variant**)argptrs);
- break;
- }
-
- //_call_func(NULL,base,*methodname,ip,argc,p_instance,stack);
- ip+=argc+1;
-
- } continue;
- case OPCODE_CALL_BUILT_IN: {
-
- CHECK_SPACE(4);
-
- GDFunctions::Function func = GDFunctions::Function(_code_ptr[ip+1]);
- int argc=_code_ptr[ip+2];
- ERR_BREAK(argc<0);
-
- ip+=3;
- CHECK_SPACE(argc+1);
- Variant **argptrs = call_args;
-
- for(int i=0;i<argc;i++) {
- GET_VARIANT_PTR(v,i);
- argptrs[i]=v;
- }
-
- GET_VARIANT_PTR(dst,argc);
-
- Variant::CallError err;
-
- GDFunctions::call(func,(const Variant**)argptrs,argc,*dst,err);
-
- if (err.error!=Variant::CallError::CALL_OK) {
-
-
- String methodstr = GDFunctions::get_func_name(func);
- err_text=_get_call_error(err,"built-in function '"+methodstr+"'",(const Variant**)argptrs);
- break;
- }
- ip+=argc+1;
-
- } continue;
- case OPCODE_CALL_SELF: {
-
-
- } break;
- case OPCODE_CALL_SELF_BASE: {
-
- CHECK_SPACE(2);
- int self_fun = _code_ptr[ip+1];
-#ifdef DEBUG_ENABLED
-
- if (self_fun<0 || self_fun>=_global_names_count) {
-
- err_text="compiler bug, function name not found";
- break;
- }
-#endif
- const StringName *methodname = &_global_names_ptr[self_fun];
-
- int argc=_code_ptr[ip+2];
-
- CHECK_SPACE(2+argc+1);
-
- Variant **argptrs = call_args;
-
- for(int i=0;i<argc;i++) {
- GET_VARIANT_PTR(v,i+3);
- argptrs[i]=v;
- }
-
- GET_VARIANT_PTR(dst,argc+3);
-
- const GDScript *gds = _script;
-
-
- const Map<StringName,GDFunction>::Element *E=NULL;
- while (gds->base.ptr()) {
- gds=gds->base.ptr();
- E=gds->member_functions.find(*methodname);
- if (E)
- break;
- }
-
- Variant::CallError err;
-
- if (E) {
-
- *dst=((GDFunction*)&E->get())->call(p_instance,(const Variant**)argptrs,argc,err);
- } else if (gds->native.ptr()) {
-
- if (*methodname!=GDScriptLanguage::get_singleton()->strings._init) {
-
- MethodBind *mb = ObjectTypeDB::get_method(gds->native->get_name(),*methodname);
- if (!mb) {
- err.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- } else {
- *dst=mb->call(p_instance->owner,(const Variant**)argptrs,argc,err);
- }
- } else {
- err.error=Variant::CallError::CALL_OK;
- }
- } else {
-
- if (*methodname!=GDScriptLanguage::get_singleton()->strings._init) {
- err.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- } else {
- err.error=Variant::CallError::CALL_OK;
- }
- }
-
-
- if (err.error!=Variant::CallError::CALL_OK) {
-
-
- String methodstr = *methodname;
- err_text=_get_call_error(err,"function '"+methodstr+"'",(const Variant**)argptrs);
-
- break;
- }
-
- ip+=4+argc;
-
- } continue;
- case OPCODE_JUMP: {
-
- CHECK_SPACE(2);
- int to = _code_ptr[ip+1];
-
- ERR_BREAK(to<0 || to>_code_size);
- ip=to;
-
- } continue;
- case OPCODE_JUMP_IF: {
-
- CHECK_SPACE(3);
-
- GET_VARIANT_PTR(test,1);
-
- bool valid;
- bool result = test->booleanize(valid);
-#ifdef DEBUG_ENABLED
- if (!valid) {
-
- err_text="cannot evaluate conditional expression of type: "+Variant::get_type_name(test->get_type());
- break;
- }
-#endif
- if (result) {
- int to = _code_ptr[ip+2];
- ERR_BREAK(to<0 || to>_code_size);
- ip=to;
- continue;
- }
- ip+=3;
- } continue;
- case OPCODE_JUMP_IF_NOT: {
-
- CHECK_SPACE(3);
-
- GET_VARIANT_PTR(test,1);
-
- bool valid;
- bool result = test->booleanize(valid);
-#ifdef DEBUG_ENABLED
- if (!valid) {
-
- err_text="cannot evaluate conditional expression of type: "+Variant::get_type_name(test->get_type());
- break;
- }
-#endif
- if (!result) {
- int to = _code_ptr[ip+2];
- ERR_BREAK(to<0 || to>_code_size);
- ip=to;
- continue;
- }
- ip+=3;
- } continue;
- case OPCODE_JUMP_TO_DEF_ARGUMENT: {
-
- CHECK_SPACE(2);
- ip=_default_arg_ptr[defarg];
-
- } continue;
- case OPCODE_RETURN: {
-
- CHECK_SPACE(2);
- GET_VARIANT_PTR(r,1);
- retvalue=*r;
- exit_ok=true;
-
- } break;
- case OPCODE_ITERATE_BEGIN: {
-
- CHECK_SPACE(8); //space for this an regular iterate
-
- GET_VARIANT_PTR(counter,1);
- GET_VARIANT_PTR(container,2);
-
- bool valid;
- if (!container->iter_init(*counter,valid)) {
- if (!valid) {
- err_text="Unable to iterate on object of type "+Variant::get_type_name(container->get_type())+"'.";
- break;
- }
- int jumpto=_code_ptr[ip+3];
- ERR_BREAK(jumpto<0 || jumpto>_code_size);
- ip=jumpto;
- continue;
- }
- GET_VARIANT_PTR(iterator,4);
-
-
- *iterator=container->iter_get(*counter,valid);
- if (!valid) {
- err_text="Unable to obtain iterator object of type "+Variant::get_type_name(container->get_type())+"'.";
- break;
- }
-
-
- ip+=5; //skip regular iterate which is always next
-
- } continue;
- case OPCODE_ITERATE: {
-
- CHECK_SPACE(4);
-
- GET_VARIANT_PTR(counter,1);
- GET_VARIANT_PTR(container,2);
-
- bool valid;
- if (!container->iter_next(*counter,valid)) {
- if (!valid) {
- err_text="Unable to iterate on object of type "+Variant::get_type_name(container->get_type())+"' (type changed since first iteration?).";
- break;
- }
- int jumpto=_code_ptr[ip+3];
- ERR_BREAK(jumpto<0 || jumpto>_code_size);
- ip=jumpto;
- continue;
- }
- GET_VARIANT_PTR(iterator,4);
-
- *iterator=container->iter_get(*counter,valid);
- if (!valid) {
- err_text="Unable to obtain iterator object of type "+Variant::get_type_name(container->get_type())+"' (but was obtained on first iteration?).";
- break;
- }
-
- ip+=5; //loop again
- } continue;
- case OPCODE_ASSERT: {
- CHECK_SPACE(2);
- GET_VARIANT_PTR(test,1);
-
-#ifdef DEBUG_ENABLED
- bool valid;
- bool result = test->booleanize(valid);
-
-
- if (!valid) {
-
- err_text="cannot evaluate conditional expression of type: "+Variant::get_type_name(test->get_type());
- break;
- }
-
-
- if (!result) {
-
- err_text="Assertion failed.";
- break;
- }
-
-#endif
-
- ip+=2;
- } continue;
- case OPCODE_LINE: {
- CHECK_SPACE(2);
-
- line=_code_ptr[ip+1];
- ip+=2;
-
- if (ScriptDebugger::get_singleton()) {
- // line
- bool do_break=false;
-
- if (ScriptDebugger::get_singleton()->get_lines_left()>0) {
-
- if (ScriptDebugger::get_singleton()->get_depth()<=0)
- ScriptDebugger::get_singleton()->set_lines_left( ScriptDebugger::get_singleton()->get_lines_left() -1 );
- if (ScriptDebugger::get_singleton()->get_lines_left()<=0)
- do_break=true;
- }
-
- if (ScriptDebugger::get_singleton()->is_breakpoint(line,source))
- do_break=true;
-
- if (do_break) {
- GDScriptLanguage::get_singleton()->debug_break("Breakpoint",true);
- }
-
- ScriptDebugger::get_singleton()->line_poll();
-
- }
- } continue;
- case OPCODE_END: {
-
- exit_ok=true;
- break;
-
- } break;
- default: {
-
- err_text="Illegal opcode "+itos(_code_ptr[ip])+" at address "+itos(ip);
- } break;
-
- }
-
- if (exit_ok)
- break;
- //error
- // function, file, line, error, explanation
- String err_file;
- if (p_instance)
- err_file=p_instance->script->path;
- else if (_class)
- err_file=_class->path;
- if (err_file=="")
- err_file="<built-in>";
- String err_func = name;
- if (p_instance && p_instance->script->name!="")
- err_func=p_instance->script->name+"."+err_func;
- int err_line=line;
- if (err_text=="") {
- err_text="Internal Script Error! - opcode #"+itos(last_opcode)+" (report please).";
- }
-
- if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) {
- // debugger break did not happen
-
- _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,err_text.utf8().get_data());
- }
-
-
- break;
- }
-
- if (ScriptDebugger::get_singleton())
- GDScriptLanguage::get_singleton()->exit_function();
-
-
- if (_stack_size) {
- //free stack
- for(int i=0;i<_stack_size;i++)
- stack[i].~Variant();
- }
-
- return retvalue;
-
-}
-
-const int* GDFunction::get_code() const {
-
- return _code_ptr;
-}
-int GDFunction::get_code_size() const{
-
- return _code_size;
-}
-
-Variant GDFunction::get_constant(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,constants.size(),"<errconst>");
- return constants[p_idx];
-}
-
-StringName GDFunction::get_global_name(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,global_names.size(),"<errgname>");
- return global_names[p_idx];
-}
-
-int GDFunction::get_default_argument_count() const {
-
- return default_arguments.size();
-}
-int GDFunction::get_default_argument_addr(int p_arg) const{
-
- ERR_FAIL_INDEX_V(p_arg,default_arguments.size(),-1);
- return default_arguments[p_arg];
-}
-
-
-StringName GDFunction::get_name() const {
-
- return name;
-}
-
-int GDFunction::get_max_stack_size() const {
-
- return _stack_size;
-}
-
-struct _GDFKC {
-
- int order;
- List<int> pos;
-};
-
-struct _GDFKCS {
-
- int order;
- StringName id;
- int pos;
-
- bool operator<(const _GDFKCS &p_r) const {
-
- return order<p_r.order;
- }
-};
-
-void GDFunction::debug_get_stack_member_state(int p_line,List<Pair<StringName,int> > *r_stackvars) const {
-
-
- int oc=0;
- Map<StringName,_GDFKC> sdmap;
- for( const List<StackDebug>::Element *E=stack_debug.front();E;E=E->next()) {
-
- const StackDebug &sd=E->get();
- if (sd.line>p_line)
- break;
-
- if (sd.added) {
-
- if (!sdmap.has(sd.identifier)) {
- _GDFKC d;
- d.order=oc++;
- d.pos.push_back(sd.pos);
- sdmap[sd.identifier]=d;
-
- } else {
- sdmap[sd.identifier].pos.push_back(sd.pos);
- }
- } else {
-
-
- ERR_CONTINUE(!sdmap.has(sd.identifier));
-
- sdmap[sd.identifier].pos.pop_back();
- if (sdmap[sd.identifier].pos.empty())
- sdmap.erase(sd.identifier);
- }
-
- }
-
-
- List<_GDFKCS> stackpositions;
- for(Map<StringName,_GDFKC>::Element *E=sdmap.front();E;E=E->next() ) {
-
- _GDFKCS spp;
- spp.id=E->key();
- spp.order=E->get().order;
- spp.pos=E->get().pos.back()->get();
- stackpositions.push_back(spp);
- }
-
- stackpositions.sort();
-
- for(List<_GDFKCS>::Element *E=stackpositions.front();E;E=E->next()) {
-
- Pair<StringName,int> p;
- p.first=E->get().id;
- p.second=E->get().pos;
- r_stackvars->push_back(p);
- }
-
-
-}
-
-#if 0
-void GDFunction::clear() {
-
- name=StringName();
- constants.clear();
- _stack_size=0;
- code.clear();
- _constants_ptr=NULL;
- _constant_count=0;
- _global_names_ptr=NULL;
- _global_names_count=0;
- _code_ptr=NULL;
- _code_size=0;
-
-}
-#endif
-GDFunction::GDFunction() {
-
- _stack_size=0;
- _call_size=0;
- name="<anonymous>";
-
-}
-
-GDNativeClass::GDNativeClass(const StringName& p_name) {
-
- name=p_name;
-}
-
-/*void GDNativeClass::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount){
-
-
-}*/
-
-
-bool GDNativeClass::_get(const StringName& p_name,Variant &r_ret) const {
-
- bool ok;
- int v = ObjectTypeDB::get_integer_constant(name, p_name, &ok);
-
- if (ok) {
- r_ret=v;
- return true;
- } else {
- return false;
- }
-}
-
-
-void GDNativeClass::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("new"),&GDNativeClass::_new);
-
-}
-
-Variant GDNativeClass::_new() {
-
- Object *o = instance();
- if (!o) {
- ERR_EXPLAIN("Class type: '"+String(name)+"' is not instantiable.");
- ERR_FAIL_COND_V(!o,Variant());
- }
-
- Reference *ref = o->cast_to<Reference>();
- if (ref) {
- return REF(ref);
- } else {
- return o;
- }
-
-}
-
-Object *GDNativeClass::instance() {
-
- return ObjectTypeDB::instance(name);
-}
-
-
-
-GDInstance* GDScript::_create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref) {
-
-
- /* STEP 1, CREATE */
-
- GDInstance* instance = memnew( GDInstance );
- instance->base_ref=p_isref;
- instance->members.resize(member_indices.size());
- instance->script=Ref<GDScript>(this);
- instance->owner=p_owner;
- instance->owner->set_script_instance(instance);
-
- /* STEP 2, INITIALIZE AND CONSRTUCT */
-
- instances.insert(instance->owner);
-
- Variant::CallError err;
- initializer->call(instance,p_args,p_argcount,err);
-
- if (err.error!=Variant::CallError::CALL_OK) {
- instance->script=Ref<GDScript>();
- instances.erase(p_owner);
- memdelete(instance);
- ERR_FAIL_COND_V(err.error!=Variant::CallError::CALL_OK, NULL); //error consrtucting
- }
-
- //@TODO make thread safe
- return instance;
-
-}
-
-Variant GDScript::_new(const Variant** p_args,int p_argcount,Variant::CallError& r_error) {
-
- /* STEP 1, CREATE */
-
- r_error.error=Variant::CallError::CALL_OK;
- REF ref;
- Object *owner=NULL;
-
- GDScript *_baseptr=this;
- while (_baseptr->_base) {
- _baseptr=_baseptr->_base;
- }
-
- if (_baseptr->native.ptr()) {
- owner=_baseptr->native->instance();
- } else {
- owner=memnew( Reference ); //by default, no base means use reference
- }
-
- Reference *r=owner->cast_to<Reference>();
- if (r) {
- ref=REF(r);
- }
-
-
- GDInstance* instance = _create_instance(p_args,p_argcount,owner,r!=NULL);
- if (!instance) {
- if (ref.is_null()) {
- memdelete(owner); //no owner, sorry
- }
- return Variant();
- }
-
- if (ref.is_valid()) {
- return ref;
- } else {
- return owner;
- }
-}
-
-bool GDScript::can_instance() const {
-
- return valid; //any script in GDscript can instance
-}
-
-StringName GDScript::get_instance_base_type() const {
-
- if (native.is_valid())
- return native->get_name();
- if (base.is_valid())
- return base->get_instance_base_type();
- return StringName();
-}
-
-struct _GDScriptMemberSort {
-
- int index;
- StringName name;
- _FORCE_INLINE_ bool operator<(const _GDScriptMemberSort& p_member) const { return index < p_member.index; }
-
-};
-
-
-#ifdef TOOLS_ENABLED
-
-
-void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
-
- placeholders.erase(p_placeholder);
-}
-
-void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {
-
-
- List<PropertyInfo> plist;
- GDScript *scr=this;
-
- Map<StringName,Variant> default_values;
- while(scr) {
-
- Vector<_GDScriptMemberSort> msort;
- for(Map<StringName,PropertyInfo>::Element *E=scr->member_info.front();E;E=E->next()) {
-
- _GDScriptMemberSort ms;
- ERR_CONTINUE(!scr->member_indices.has(E->key()));
- ms.index=scr->member_indices[E->key()];
- ms.name=E->key();
-
- msort.push_back(ms);
-
- }
-
- msort.sort();
- msort.invert();
- for(int i=0;i<msort.size();i++) {
-
- plist.push_front(scr->member_info[msort[i].name]);
- if (scr->member_default_values.has(msort[i].name))
- default_values[msort[i].name]=scr->member_default_values[msort[i].name];
- else {
- Variant::CallError err;
- default_values[msort[i].name]=Variant::construct(scr->member_info[msort[i].name].type,NULL,0,err);
- }
- }
-
- scr=scr->_base;
- }
-
-
- p_placeholder->update(plist,default_values);
-
-}
-#endif
-ScriptInstance* GDScript::instance_create(Object *p_this) {
-
- if (!tool && !ScriptServer::is_scripting_enabled()) {
-
-#ifdef TOOLS_ENABLED
-
- //instance a fake script for editing the values
- //plist.invert();
-
- /*print_line("CREATING PLACEHOLDER");
- for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
- print_line(E->get().name);
- }*/
- PlaceHolderScriptInstance *si = memnew( PlaceHolderScriptInstance(GDScriptLanguage::get_singleton(),Ref<Script>(this),p_this) );
- placeholders.insert(si);
- _update_placeholder(si);
- return si;
-#else
- return NULL;
-#endif
- }
-
- GDScript *top=this;
- while(top->_base)
- top=top->_base;
-
- if (top->native.is_valid()) {
- if (!ObjectTypeDB::is_type(p_this->get_type_name(),top->native->get_name())) {
-
- if (ScriptDebugger::get_singleton()) {
- GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),0,"Script inherits from native type '"+String(top->native->get_name())+"', so it can't be instanced in object of type: '"+p_this->get_type()+"'");
- }
- ERR_EXPLAIN("Script inherits from native type '"+String(top->native->get_name())+"', so it can't be instanced in object of type: '"+p_this->get_type()+"'");
- ERR_FAIL_V(NULL);
-
- }
- }
-
- return _create_instance(NULL,0,p_this,p_this->cast_to<Reference>());
-
-}
-bool GDScript::instance_has(const Object *p_this) const {
-
- return instances.has((Object*)p_this);
-}
-
-bool GDScript::has_source_code() const {
-
- return source!="";
-}
-String GDScript::get_source_code() const {
-
- return source;
-}
-void GDScript::set_source_code(const String& p_code) {
-
- source=p_code;
-
-}
-
-void GDScript::_set_subclass_path(Ref<GDScript>& p_sc,const String& p_path) {
-
- p_sc->path=p_path;
- for(Map<StringName,Ref<GDScript> >::Element *E=p_sc->subclasses.front();E;E=E->next()) {
-
- _set_subclass_path(E->get(),p_path);
- }
-}
-
-Error GDScript::reload() {
-
-
- ERR_FAIL_COND_V(instances.size(),ERR_ALREADY_IN_USE);
-
- String basedir=path;
-
- if (basedir=="")
- basedir==get_path();
-
- if (basedir!="")
- basedir=basedir.get_base_dir();
-
-
-
- valid=false;
- GDParser parser;
- Error err = parser.parse(source,basedir);
- if (err) {
- if (ScriptDebugger::get_singleton()) {
- GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),parser.get_error_line(),"Parser Error: "+parser.get_error());
- }
- _err_print_error("GDScript::reload",path.empty()?"built-in":(const char*)path.utf8().get_data(),parser.get_error_line(),("Parse Error: "+parser.get_error()).utf8().get_data());
- ERR_FAIL_V(ERR_PARSE_ERROR);
- }
-
- GDCompiler compiler;
- err = compiler.compile(&parser,this);
-
- if (err) {
- if (ScriptDebugger::get_singleton()) {
- GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),compiler.get_error_line(),"Parser Error: "+compiler.get_error());
- }
- _err_print_error("GDScript::reload",path.empty()?"built-in":(const char*)path.utf8().get_data(),compiler.get_error_line(),("Compile Error: "+compiler.get_error()).utf8().get_data());
- ERR_FAIL_V(ERR_COMPILATION_FAILED);
- }
-
- valid=true;
-
- for(Map<StringName,Ref<GDScript> >::Element *E=subclasses.front();E;E=E->next()) {
-
- _set_subclass_path(E->get(),path);
- }
-
-#ifdef TOOLS_ENABLED
- for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
-
- _update_placeholder(E->get());
- }
-#endif
- return OK;
-}
-
-String GDScript::get_node_type() const {
-
- return ""; // ?
-}
-
-ScriptLanguage *GDScript::get_language() const {
-
- return GDScriptLanguage::get_singleton();
-}
-
-
-Variant GDScript::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {
-
-
- GDScript *top=this;
- while(top) {
-
- Map<StringName,GDFunction>::Element *E=top->member_functions.find(p_method);
- if (E) {
-
- if (!E->get().is_static()) {
- WARN_PRINT(String("Can't call non-static function: '"+String(p_method)+"' in script.").utf8().get_data());
- }
-
- return E->get().call(NULL,p_args,p_argcount,r_error);
- }
- top=top->_base;
- }
-
- //none found, regular
-
- return Script::call(p_method,p_args,p_argcount,r_error);
-
-}
-
-bool GDScript::_get(const StringName& p_name,Variant &r_ret) const {
-
- {
-
-
- const GDScript *top=this;
- while(top) {
-
- {
- const Map<StringName,Variant>::Element *E=top->constants.find(p_name);
- if (E) {
-
- r_ret= E->get();
- return true;
- }
- }
-
- {
- const Map<StringName,Ref<GDScript> >::Element *E=subclasses.find(p_name);
- if (E) {
-
- r_ret=E->get();
- return true;
- }
- }
- top=top->_base;
- }
-
- if (p_name==GDScriptLanguage::get_singleton()->strings._script_source) {
-
- r_ret=get_source_code();
- return true;
- }
- }
-
-
-
- return false;
-
-}
-bool GDScript::_set(const StringName& p_name, const Variant& p_value) {
-
- if (p_name==GDScriptLanguage::get_singleton()->strings._script_source) {
-
- set_source_code(p_value);
- reload();
- } else
- return false;
-
- return true;
-}
-
-void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const {
-
- p_properties->push_back( PropertyInfo(Variant::STRING,"script/source",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
-}
-
-
-void GDScript::_bind_methods() {
-
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo("new"));
-
-}
-
-Error GDScript::load_source_code(const String& p_path) {
-
-
- DVector<uint8_t> sourcef;
- Error err;
- FileAccess *f=FileAccess::open(p_path,FileAccess::READ,&err);
- if (err) {
-
- ERR_FAIL_COND_V(err,err);
- }
-
- int len = f->get_len();
- sourcef.resize(len+1);
- DVector<uint8_t>::Write w = sourcef.write();
- int r = f->get_buffer(w.ptr(),len);
- f->close();
- memdelete(f);
- ERR_FAIL_COND_V(r!=len,ERR_CANT_OPEN);
- w[len]=0;
-
- String s;
- if (s.parse_utf8((const char*)w.ptr())) {
-
- ERR_EXPLAIN("Script '"+p_path+"' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode.");
- ERR_FAIL_V(ERR_INVALID_DATA);
- }
-
- source=s;
- path=p_path;
- return OK;
-
-}
-
-
-const Map<StringName,GDFunction>& GDScript::debug_get_member_functions() const {
-
- return member_functions;
-}
-
-
-
-StringName GDScript::debug_get_member_by_index(int p_idx) const {
-
-
- for(const Map<StringName,int>::Element *E=member_indices.front();E;E=E->next()) {
-
- if (E->get()==p_idx)
- return E->key();
- }
-
- return "<error>";
-}
-
-
-Ref<GDScript> GDScript::get_base() const {
-
- return base;
-}
-
-GDScript::GDScript() {
-
-
- valid=false;
- subclass_count=0;
- initializer=NULL;
- _base=NULL;
- _owner=NULL;
- tool=false;
-}
-
-
-
-
-
-//////////////////////////////
-// INSTANCE //
-//////////////////////////////
-
-
-bool GDInstance::set(const StringName& p_name, const Variant& p_value) {
-
- //member
- {
- const Map<StringName,int>::Element *E = script->member_indices.find(p_name);
- if (E) {
- members[E->get()]=p_value;
- return true;
-
- }
- }
-
- GDScript *sptr=script.ptr();
- while(sptr) {
-
-
- Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
- if (E) {
-
- Variant name=p_name;
- const Variant *args[2]={&name,&p_value};
-
- Variant::CallError err;
- Variant ret = E->get().call(this,(const Variant**)args,2,err);
- if (err.error==Variant::CallError::CALL_OK && ret.get_type()==Variant::BOOL && ret.operator bool())
- return true;
- }
- sptr = sptr->_base;
- }
-
- return false;
-}
-
-bool GDInstance::get(const StringName& p_name, Variant &r_ret) const {
-
-
-
- const GDScript *sptr=script.ptr();
- while(sptr) {
-
- {
- const Map<StringName,int>::Element *E = script->member_indices.find(p_name);
- if (E) {
- r_ret=members[E->get()];
- return true; //index found
-
- }
- }
-
- {
- const Map<StringName,Variant>::Element *E = script->constants.find(p_name);
- if (E) {
- r_ret=E->get();
- return true; //index found
-
- }
- }
-
- {
- const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
- if (E) {
-
- Variant name=p_name;
- const Variant *args[1]={&name};
-
- Variant::CallError err;
- Variant ret = const_cast<GDFunction*>(&E->get())->call(const_cast<GDInstance*>(this),(const Variant**)args,1,err);
- if (err.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) {
- r_ret=ret;
- return true;
- }
- }
- }
- sptr = sptr->_base;
- }
-
- return false;
-
-}
-void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
- // exported members, not doen yet!
-
- const GDScript *sptr=script.ptr();
- List<PropertyInfo> props;
-
- while(sptr) {
-
-
- const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
- if (E) {
-
-
- Variant::CallError err;
- Variant ret = const_cast<GDFunction*>(&E->get())->call(const_cast<GDInstance*>(this),NULL,0,err);
- if (err.error==Variant::CallError::CALL_OK) {
-
- if (ret.get_type()!=Variant::ARRAY) {
-
- ERR_EXPLAIN("Wrong type for _get_property list, must be an array of dictionaries.");
- ERR_FAIL();
- }
- Array arr = ret;
- for(int i=0;i<arr.size();i++) {
-
- Dictionary d = arr[i];
- ERR_CONTINUE(!d.has("name"));
- ERR_CONTINUE(!d.has("type"));
- PropertyInfo pinfo;
- pinfo.type = Variant::Type( d["type"].operator int());
- ERR_CONTINUE(pinfo.type<0 || pinfo.type>=Variant::VARIANT_MAX );
- pinfo.name = d["name"];
- ERR_CONTINUE(pinfo.name=="");
- if (d.has("hint"))
- pinfo.hint=PropertyHint(d["hint"].operator int());
- if (d.has("hint_string"))
- pinfo.hint_string=d["hint_string"];
- if (d.has("usage"))
- pinfo.usage=d["usage"];
-
- props.push_back(pinfo);
-
- }
-
- }
- }
-
- //instance a fake script for editing the values
-
- Vector<_GDScriptMemberSort> msort;
- for(Map<StringName,PropertyInfo>::Element *E=sptr->member_info.front();E;E=E->next()) {
-
- _GDScriptMemberSort ms;
- ERR_CONTINUE(!sptr->member_indices.has(E->key()));
- ms.index=sptr->member_indices[E->key()];
- ms.name=E->key();
- msort.push_back(ms);
-
- }
-
- msort.sort();
- msort.invert();
- for(int i=0;i<msort.size();i++) {
-
- props.push_front(sptr->member_info[msort[i].name]);
-
- }
-#if 0
- if (sptr->member_functions.has("_get_property_list")) {
-
- Variant::CallError err;
- GDFunction *f = const_cast<GDFunction*>(&sptr->member_functions["_get_property_list"]);
- Variant plv = f->call(const_cast<GDInstance*>(this),NULL,0,err);
-
- if (plv.get_type()!=Variant::ARRAY) {
-
- ERR_PRINT("_get_property_list: expected array returned");
- } else {
-
- Array pl=plv;
-
- for(int i=0;i<pl.size();i++) {
-
- Dictionary p = pl[i];
- PropertyInfo pinfo;
- if (!p.has("name")) {
- ERR_PRINT("_get_property_list: expected 'name' key of type string.")
- continue;
- }
- if (!p.has("type")) {
- ERR_PRINT("_get_property_list: expected 'type' key of type integer.")
- continue;
- }
- pinfo.name=p["name"];
- pinfo.type=Variant::Type(int(p["type"]));
- if (p.has("hint"))
- pinfo.hint=PropertyHint(int(p["hint"]));
- if (p.has("hint_string"))
- pinfo.hint_string=p["hint_string"];
- if (p.has("usage"))
- pinfo.usage=p["usage"];
-
-
- props.push_back(pinfo);
- }
- }
- }
-#endif
-
- sptr = sptr->_base;
- }
-
- //props.invert();
-
- for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
-
- p_properties->push_back(E->get());
- }
-}
-
-void GDInstance::get_method_list(List<MethodInfo> *p_list) const {
-
- const GDScript *sptr=script.ptr();
- while(sptr) {
-
- for (Map<StringName,GDFunction>::Element *E = sptr->member_functions.front();E;E=E->next()) {
-
- MethodInfo mi;
- mi.name=E->key();
- for(int i=0;i<E->get().get_argument_count();i++)
- mi.arguments.push_back(PropertyInfo(Variant::NIL,"arg"+itos(i)));
- p_list->push_back(mi);
- }
- sptr = sptr->_base;
- }
-
-}
-
-bool GDInstance::has_method(const StringName& p_method) const {
-
- const GDScript *sptr=script.ptr();
- while(sptr) {
- const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);
- if (E)
- return true;
- sptr = sptr->_base;
- }
-
- return false;
-}
-Variant GDInstance::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {
-
- //printf("calling %ls:%i method %ls\n", script->get_path().c_str(), -1, String(p_method).c_str());
-
- GDScript *sptr=script.ptr();
- while(sptr) {
- Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);
- if (E) {
- return E->get().call(this,p_args,p_argcount,r_error);
- }
- sptr = sptr->_base;
- }
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
-}
-
-void GDInstance::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount) {
-
- GDScript *sptr=script.ptr();
- Variant::CallError ce;
-
- while(sptr) {
- Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);
- if (E) {
- E->get().call(this,p_args,p_argcount,ce);
- }
- sptr = sptr->_base;
- }
-
-}
-
-
-void GDInstance::_ml_call_reversed(GDScript *sptr,const StringName& p_method,const Variant** p_args,int p_argcount) {
-
- if (sptr->_base)
- _ml_call_reversed(sptr->_base,p_method,p_args,p_argcount);
-
- Variant::CallError ce;
-
- Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);
- if (E) {
- E->get().call(this,p_args,p_argcount,ce);
- }
-
-}
-
-void GDInstance::call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount) {
-
- if (script.ptr()) {
- _ml_call_reversed(script.ptr(),p_method,p_args,p_argcount);
- }
-}
-
-void GDInstance::notification(int p_notification) {
-
- //notification is not virutal, it gets called at ALL levels just like in C.
- Variant value=p_notification;
- const Variant *args[1]={&value };
-
- GDScript *sptr=script.ptr();
- while(sptr) {
- Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
- if (E) {
- Variant::CallError err;
- E->get().call(this,args,1,err);
- if (err.error!=Variant::CallError::CALL_OK) {
- //print error about notification call
-
- }
- }
- sptr = sptr->_base;
- }
-
-}
-
-Ref<Script> GDInstance::get_script() const {
-
- return script;
-}
-
-ScriptLanguage *GDInstance::get_language() {
-
- return GDScriptLanguage::get_singleton();
-}
-
-
-GDInstance::GDInstance() {
- owner=NULL;
- base_ref=false;
-}
-
-GDInstance::~GDInstance() {
- if (script.is_valid() && owner) {
- script->instances.erase(owner);
- }
-}
-
-/************* SCRIPT LANGUAGE **************/
-/************* SCRIPT LANGUAGE **************/
-/************* SCRIPT LANGUAGE **************/
-/************* SCRIPT LANGUAGE **************/
-/************* SCRIPT LANGUAGE **************/
-
-GDScriptLanguage *GDScriptLanguage::singleton=NULL;
-
-
-String GDScriptLanguage::get_name() const {
-
- return "GDScript";
-}
-
-/* LANGUAGE FUNCTIONS */
-
-void GDScriptLanguage::_add_global(const StringName& p_name,const Variant& p_value) {
-
-
- if (globals.has(p_name)) {
- //overwrite existing
- global_array[globals[p_name]]=p_value;
- return;
- }
- globals[p_name]=global_array.size();
- global_array.push_back(p_value);
- _global_array=global_array.ptr();
-}
-
-void GDScriptLanguage::init() {
-
-
- //populate global constants
- int gcc=GlobalConstants::get_global_constant_count();
- for(int i=0;i<gcc;i++) {
-
- _add_global(StaticCString::create(GlobalConstants::get_global_constant_name(i)),GlobalConstants::get_global_constant_value(i));
- }
-
- _add_global(StaticCString::create("PI"),Math_PI);
-
- //populate native classes
-
- List<String> class_list;
- ObjectTypeDB::get_type_list(&class_list);
- for(List<String>::Element *E=class_list.front();E;E=E->next()) {
-
- StringName n = E->get();
- String s = String(n);
- if (s.begins_with("_"))
- n=s.substr(1,s.length());
-
- if (globals.has(n))
- continue;
- Ref<GDNativeClass> nc = memnew( GDNativeClass(E->get()) );
- _add_global(n,nc);
- }
-
- //populate singletons
-
- List<Globals::Singleton> singletons;
- Globals::get_singleton()->get_singletons(&singletons);
- for(List<Globals::Singleton>::Element *E=singletons.front();E;E=E->next()) {
-
- _add_global(E->get().name,E->get().ptr);
- }
-}
-
-String GDScriptLanguage::get_type() const {
-
- return "GDScript";
-}
-String GDScriptLanguage::get_extension() const {
-
- return "gd";
-}
-Error GDScriptLanguage::execute_file(const String& p_path) {
-
- // ??
- return OK;
-}
-void GDScriptLanguage::finish() {
-
-
-}
-
-
-void GDScriptLanguage::frame() {
-
-// print_line("calls: "+itos(calls));
- calls=0;
-}
-
-/* EDITOR FUNCTIONS */
-void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
-
- static const char *_reserved_words[]={
- "break",
- "class",
- "continue",
- "const",
- "else",
- "elif",
- "enum",
- "extends" ,
- "for" ,
- "func" ,
- "if" ,
- "in" ,
- "varl",
- "null" ,
- "return" ,
- "self" ,
- "while" ,
- "true" ,
- "false" ,
- "tool",
- "var",
- "pass",
- "and",
- "or",
- "export",
- 0};
-
-
- const char **w=_reserved_words;
-
-
- while (*w) {
-
- p_words->push_back(*w);
- w++;
- }
-
- for(int i=0;i<GDFunctions::FUNC_MAX;i++) {
- p_words->push_back(GDFunctions::get_func_name(GDFunctions::Function(i)));
- }
-
-}
-
-GDScriptLanguage::GDScriptLanguage() {
-
- calls=0;
- ERR_FAIL_COND(singleton);
- singleton=this;
- strings._init = StaticCString::create("_init");
- strings._notification = StaticCString::create("_notification");
- strings._set= StaticCString::create("_set");
- strings._get= StaticCString::create("_get");
- strings._get_property_list= StaticCString::create("_get_property_list");
- strings._script_source=StaticCString::create("script/source");
- _debug_parse_err_line=-1;
- _debug_parse_err_file="";
-
- _debug_call_stack_pos=0;
- int dmcs=GLOBAL_DEF("debug/script_max_call_stack",1024);
- if (ScriptDebugger::get_singleton()) {
- //debugging enabled!
-
- _debug_max_call_stack = dmcs;
- if (_debug_max_call_stack<1024)
- _debug_max_call_stack=1024;
- _call_stack = memnew_arr( CallLevel, _debug_max_call_stack+1 );
-
- } else {
- _debug_max_call_stack=0;
- _call_stack=NULL;
- }
-
-}
-
-
-GDScriptLanguage::~GDScriptLanguage() {
-
- if (_call_stack) {
- memdelete_arr(_call_stack);
- }
- singleton=NULL;
-}
-
-/*************** RESOURCE ***************/
-
-RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_original_path) {
-
- GDScript *script = memnew( GDScript );
-
- Ref<GDScript> scriptres(script);
-
- Error err = script->load_source_code(p_path);
-
- if (err!=OK) {
-
- ERR_FAIL_COND_V(err!=OK, RES());
- }
-
- script->set_script_path(p_original_path); // script needs this.
- script->set_path(p_original_path);
- //script->set_name(p_path.get_file());
-
- script->reload();
-
- return scriptres;
-}
-void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("gd");
-}
-
-bool ResourceFormatLoaderGDScript::handles_type(const String& p_type) const {
-
- return (p_type=="Script" || p_type=="GDScript");
-}
-
-String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const {
-
- if (p_path.extension().to_lower()=="gd")
- return "GDScript";
- return "";
-}
-
-
-Error ResourceFormatSaverGDScript::save(const String &p_path,const RES& p_resource,uint32_t p_flags) {
-
- Ref<GDScript> sqscr = p_resource;
- ERR_FAIL_COND_V(sqscr.is_null(),ERR_INVALID_PARAMETER);
-
- String source = sqscr->get_source_code();
-
- Error err;
- FileAccess *file = FileAccess::open(p_path,FileAccess::WRITE,&err);
-
-
- if (err) {
-
- ERR_FAIL_COND_V(err,err);
- }
-
- file->store_string(source);
-
- file->close();
- memdelete(file);
- return OK;
-}
-
-void ResourceFormatSaverGDScript::get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const {
-
- if (p_resource->cast_to<GDScript>()) {
- p_extensions->push_back("gd");
- }
-
-}
-bool ResourceFormatSaverGDScript::recognize(const RES& p_resource) const {
-
- return p_resource->cast_to<GDScript>()!=NULL;
-}
diff --git a/script/gdscript/gd_script.h b/script/gdscript/gd_script.h
deleted file mode 100644
index bb9beaaf56..0000000000
--- a/script/gdscript/gd_script.h
+++ /dev/null
@@ -1,471 +0,0 @@
-/*************************************************************************/
-/* gd_script.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef GD_SCRIPT_H
-#define GD_SCRIPT_H
-
-#include "script_language.h"
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "os/thread.h"
-#include "pair.h"
-class GDInstance;
-class GDScript;
-
-class GDFunction {
-public:
-
- enum Opcode {
- OPCODE_OPERATOR,
- OPCODE_EXTENDS_TEST,
- OPCODE_SET,
- OPCODE_GET,
- OPCODE_SET_NAMED,
- OPCODE_GET_NAMED,
- OPCODE_ASSIGN,
- OPCODE_ASSIGN_TRUE,
- OPCODE_ASSIGN_FALSE,
- OPCODE_CONSTRUCT, //only for basic types!!
- OPCODE_CONSTRUCT_ARRAY,
- OPCODE_CONSTRUCT_DICTIONARY,
- OPCODE_CALL,
- OPCODE_CALL_RETURN,
- OPCODE_CALL_BUILT_IN,
- OPCODE_CALL_SELF,
- OPCODE_CALL_SELF_BASE,
- OPCODE_JUMP,
- OPCODE_JUMP_IF,
- OPCODE_JUMP_IF_NOT,
- OPCODE_JUMP_TO_DEF_ARGUMENT,
- OPCODE_RETURN,
- OPCODE_ITERATE_BEGIN,
- OPCODE_ITERATE,
- OPCODE_ASSERT,
- OPCODE_LINE,
- OPCODE_END
- };
-
- enum Address {
- ADDR_BITS=24,
- ADDR_MASK=((1<<ADDR_BITS)-1),
- ADDR_TYPE_MASK=~ADDR_MASK,
- ADDR_TYPE_SELF=0,
- ADDR_TYPE_MEMBER=1,
- ADDR_TYPE_CLASS_CONSTANT=2,
- ADDR_TYPE_LOCAL_CONSTANT=3,
- ADDR_TYPE_STACK=4,
- ADDR_TYPE_STACK_VARIABLE=5,
- ADDR_TYPE_GLOBAL=6,
- ADDR_TYPE_NIL=7
- };
-
- struct StackDebug {
-
- int line;
- int pos;
- bool added;
- StringName identifier;
- };
-
-private:
-friend class GDCompiler;
-
- StringName source;
-
- mutable Variant nil;
- mutable Variant *_constants_ptr;
- int _constant_count;
- const StringName *_global_names_ptr;
- int _global_names_count;
- const int *_default_arg_ptr;
- int _default_arg_count;
- const int *_code_ptr;
- int _code_size;
- int _argument_count;
- int _stack_size;
- int _call_size;
- int _initial_line;
- bool _static;
- GDScript *_script;
-
- StringName name;
- Vector<Variant> constants;
- Vector<StringName> global_names;
- Vector<int> default_arguments;
-
- Vector<int> code;
-
- List<StackDebug> stack_debug;
-
- _FORCE_INLINE_ Variant *_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self,Variant *p_stack,String& r_error) const;
- _FORCE_INLINE_ String _get_call_error(const Variant::CallError& p_err, const String& p_where,const Variant**argptrs) const;
-
-
-public:
-
-
- _FORCE_INLINE_ bool is_static() const { return _static; }
-
- const int* get_code() const; //used for debug
- int get_code_size() const;
- Variant get_constant(int p_idx) const;
- StringName get_global_name(int p_idx) const;
- StringName get_name() const;
- int get_max_stack_size() const;
- int get_default_argument_count() const;
- int get_default_argument_addr(int p_idx) const;
- GDScript *get_script() const { return _script; }
-
- void debug_get_stack_member_state(int p_line,List<Pair<StringName,int> > *r_stackvars) const;
-
- _FORCE_INLINE_ bool is_empty() const { return _code_size==0; }
-
- int get_argument_count() const { return _argument_count; }
- Variant call(GDInstance *p_instance,const Variant **p_args, int p_argcount,Variant::CallError& r_err);
-
- GDFunction();
-};
-
-
-class GDNativeClass : public Reference {
-
- OBJ_TYPE(GDNativeClass,Reference);
-
- StringName name;
-protected:
-
- bool _get(const StringName& p_name,Variant &r_ret) const;
- static void _bind_methods();
-
-public:
-
- _FORCE_INLINE_ const StringName& get_name() const { return name; }
- Variant _new();
- Object *instance();
- GDNativeClass(const StringName& p_name);
-};
-
-
-class GDScript : public Script {
-
-
- OBJ_TYPE(GDScript,Script);
- bool tool;
- bool valid;
-
-
-friend class GDInstance;
-friend class GDFunction;
-friend class GDCompiler;
-friend class GDFunctions;
- Ref<GDNativeClass> native;
- Ref<GDScript> base;
- GDScript *_base; //fast pointer access
- GDScript *_owner; //for subclasses
-
- Set<StringName> members; //members are just indices to the instanced script.
- Map<StringName,Variant> constants;
- Map<StringName,GDFunction> member_functions;
- Map<StringName,int> member_indices; //members are just indices to the instanced script.
- Map<StringName,Ref<GDScript> > subclasses;
-
-#ifdef TOOLS_ENABLED
- Map<StringName,Variant> member_default_values;
-#endif
- Map<StringName,PropertyInfo> member_info;
-
- GDFunction *initializer; //direct pointer to _init , faster to locate
-
- int subclass_count;
- Set<Object*> instances;
- //exported members
- String source;
- String path;
- String name;
-
-
- GDInstance* _create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref);
-
- void _set_subclass_path(Ref<GDScript>& p_sc,const String& p_path);
-
-#ifdef TOOLS_ENABLED
- Set<PlaceHolderScriptInstance*> placeholders;
- void _update_placeholder(PlaceHolderScriptInstance *p_placeholder);
- virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder);
-#endif
-
-
-protected:
- bool _get(const StringName& p_name,Variant &r_ret) const;
- bool _set(const StringName& p_name, const Variant& p_value);
- void _get_property_list(List<PropertyInfo> *p_properties) const;
-
- Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error);
-// void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
-
- static void _bind_methods();
-public:
-
-
- const Map<StringName,Ref<GDScript> >& get_subclasses() const { return subclasses; }
- const Map<StringName,Variant >& get_constants() const { return constants; }
- const Set<StringName>& get_members() const { return members; }
- const Map<StringName,GDFunction>& get_member_functions() const { return member_functions; }
- const Ref<GDNativeClass>& get_native() const { return native; }
-
-
- bool is_tool() const { return tool; }
- Ref<GDScript> get_base() const;
-
- const Map<StringName,int>& debug_get_member_indices() const { return member_indices; }
- const Map<StringName,GDFunction>& debug_get_member_functions() const; //this is debug only
- StringName debug_get_member_by_index(int p_idx) const;
-
- Variant _new(const Variant** p_args,int p_argcount,Variant::CallError& r_error);
- virtual bool can_instance() const;
-
- virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so
- virtual ScriptInstance* instance_create(Object *p_this);
- virtual bool instance_has(const Object *p_this) const;
-
- virtual bool has_source_code() const;
- virtual String get_source_code() const;
- virtual void set_source_code(const String& p_code);
- virtual Error reload();
-
- virtual String get_node_type() const;
- void set_script_path(const String& p_path) { path=p_path; } //because subclasses need a path too...
- Error load_source_code(const String& p_path);
-
- virtual ScriptLanguage *get_language() const;
-
- GDScript();
-};
-
-class GDInstance : public ScriptInstance {
-friend class GDScript;
-friend class GDFunction;
-friend class GDFunctions;
-
- Object *owner;
- Ref<GDScript> script;
- Vector<Variant> members;
- bool base_ref;
-
- void _ml_call_reversed(GDScript *sptr,const StringName& p_method,const Variant** p_args,int p_argcount);
-
-public:
-
- virtual bool set(const StringName& p_name, const Variant& p_value);
- virtual bool get(const StringName& p_name, Variant &r_ret) const;
- virtual void get_property_list(List<PropertyInfo> *p_properties) const;
-
- virtual void get_method_list(List<MethodInfo> *p_list) const;
- virtual bool has_method(const StringName& p_method) const;
- virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error);
- virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
- virtual void call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount);
-
- Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
-
- virtual void notification(int p_notification);
-
- virtual Ref<Script> get_script() const;
-
- virtual ScriptLanguage *get_language();
-
- void set_path(const String& p_path);
-
-
- GDInstance();
- ~GDInstance();
-
-};
-
-class GDScriptLanguage : public ScriptLanguage {
-
- static GDScriptLanguage *singleton;
-
- Variant* _global_array;
- Vector<Variant> global_array;
- Map<StringName,int> globals;
-
-
- struct CallLevel {
-
- Variant *stack;
- GDFunction *function;
- GDInstance *instance;
- int *ip;
- int *line;
-
- };
-
-
- int _debug_parse_err_line;
- String _debug_parse_err_file;
- String _debug_error;
- int _debug_call_stack_pos;
- int _debug_max_call_stack;
- CallLevel *_call_stack;
-
- void _add_global(const StringName& p_name,const Variant& p_value);
-
-
-public:
-
- int calls;
-
- bool debug_break(const String& p_error,bool p_allow_continue=true);
- bool debug_break_parse(const String& p_file, int p_line,const String& p_error);
-
- _FORCE_INLINE_ void enter_function(GDInstance *p_instance,GDFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) {
-
- if (Thread::get_main_ID()!=Thread::get_caller_ID())
- return; //no support for other threads than main for now
-
- if (ScriptDebugger::get_singleton()->get_lines_left()>0 && ScriptDebugger::get_singleton()->get_depth()>=0)
- ScriptDebugger::get_singleton()->set_depth( ScriptDebugger::get_singleton()->get_depth() +1 );
-
- if (_debug_call_stack_pos >= _debug_max_call_stack) {
- //stack overflow
- _debug_error="Stack Overflow (Stack Size: "+itos(_debug_max_call_stack)+")";
- ScriptDebugger::get_singleton()->debug(this);
- return;
- }
-
- _call_stack[_debug_call_stack_pos].stack=p_stack;
- _call_stack[_debug_call_stack_pos].instance=p_instance;
- _call_stack[_debug_call_stack_pos].function=p_function;
- _call_stack[_debug_call_stack_pos].ip=p_ip;
- _call_stack[_debug_call_stack_pos].line=p_line;
- _debug_call_stack_pos++;
- }
-
- _FORCE_INLINE_ void exit_function() {
-
- if (Thread::get_main_ID()!=Thread::get_caller_ID())
- return; //no support for other threads than main for now
-
- if (ScriptDebugger::get_singleton()->get_lines_left()>0 && ScriptDebugger::get_singleton()->get_depth()>=0)
- ScriptDebugger::get_singleton()->set_depth( ScriptDebugger::get_singleton()->get_depth() -1 );
-
- if (_debug_call_stack_pos==0) {
-
- _debug_error="Stack Underflow (Engine Bug)";
- ScriptDebugger::get_singleton()->debug(this);
- return;
- }
-
- _debug_call_stack_pos--;
- }
-
-
- struct {
-
- StringName _init;
- StringName _notification;
- StringName _set;
- StringName _get;
- StringName _get_property_list;
- StringName _script_source;
-
- } strings;
-
-
- _FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); }
- _FORCE_INLINE_ Variant* get_global_array() { return _global_array; }
- _FORCE_INLINE_ const Map<StringName,int>& get_global_map() { return globals; }
-
- _FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; }
-
- virtual String get_name() const;
-
- /* LANGUAGE FUNCTIONS */
- virtual void init();
- virtual String get_type() const;
- virtual String get_extension() const;
- virtual Error execute_file(const String& p_path) ;
- virtual void finish();
-
- /* EDITOR FUNCTIONS */
- virtual void get_reserved_words(List<String> *p_words) const;
- virtual void get_comment_delimiters(List<String> *p_delimiters) const;
- virtual void get_string_delimiters(List<String> *p_delimiters) const;
- virtual String get_template(const String& p_class_name, const String& p_base_class_name) const;
- virtual bool validate(const String& p_script,int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path="",List<String> *r_functions=NULL) const;
- virtual Script *create_script() const;
- virtual bool has_named_classes() const;
- virtual int find_function(const String& p_function,const String& p_code) const;
- virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const;
- virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path,const String& p_keyword, List<String>* r_options);
-
- /* DEBUGGER FUNCTIONS */
-
- virtual String debug_get_error() const;
- virtual int debug_get_stack_level_count() const;
- virtual int debug_get_stack_level_line(int p_level) const;
- virtual String debug_get_stack_level_function(int p_level) const;
- virtual String debug_get_stack_level_source(int p_level) const;
- virtual void debug_get_stack_level_locals(int p_level,List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1);
- virtual void debug_get_stack_level_members(int p_level,List<String> *p_members, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1);
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1);
- virtual String debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems=-1,int p_max_depth=-1);
-
- virtual void frame();
-
- virtual void get_public_functions(List<MethodInfo> *p_functions) const;
- /* LOADER FUNCTIONS */
-
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
-
- GDScriptLanguage();
- ~GDScriptLanguage();
-};
-
-
-class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
-public:
-
- virtual RES load(const String &p_path,const String& p_original_path="");
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual bool handles_type(const String& p_type) const;
- virtual String get_resource_type(const String &p_path) const;
-
-};
-
-class ResourceFormatSaverGDScript : public ResourceFormatSaver {
-public:
-
- virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
- virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
- virtual bool recognize(const RES& p_resource) const;
-
-};
-
-#endif // GD_SCRIPT_H
diff --git a/script/gdscript/gd_tokenizer.cpp b/script/gdscript/gd_tokenizer.cpp
deleted file mode 100644
index f7320799a5..0000000000
--- a/script/gdscript/gd_tokenizer.cpp
+++ /dev/null
@@ -1,973 +0,0 @@
-/*************************************************************************/
-/* gd_tokenizer.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "gd_tokenizer.h"
-#include "print_string.h"
-#include "gd_functions.h"
-const char* GDTokenizer::token_names[TK_MAX]={
-"Empty",
-"Identifier",
-"Constant",
-"Self",
-"Built-In Type",
-"Built-In Func",
-"In",
-"'=='",
-"'!='",
-"'<'",
-"'<='",
-"'>'",
-"'>='",
-"'and'",
-"'or'",
-"'not'",
-"'+'",
-"'-'",
-"'*'",
-"'/'",
-"'%'",
-"'<<'",
-"'>>'",
-"'='",
-"'+='",
-"'-='",
-"'*='",
-"'/='",
-"'%='",
-"'<<='",
-"'>>='",
-"'&='",
-"'|='",
-"'^='",
-"'&'",
-"'|'",
-"'^'",
-"'~'",
-//"Plus Plus",
-//"Minus Minus",
-"if",
-"elif",
-"else",
-"for",
-"do",
-"while",
-"switch",
-"case",
-"break",
-"continue",
-"pass",
-"return",
-"func",
-"class",
-"extends",
-"tool",
-"static",
-"export",
-"const",
-"var",
-"preload",
-"assert",
-"'['",
-"']'",
-"'{'",
-"'}'",
-"'('",
-"')'",
-"','",
-"';'",
-"'.'",
-"'?'",
-"':'",
-"'\\n'",
-"Error",
-"EOF"};
-
-const char *GDTokenizer::get_token_name(Token p_token) {
-
- ERR_FAIL_INDEX_V(p_token,TK_MAX,"<error>");
- return token_names[p_token];
-}
-
-static bool _is_text_char(CharType c) {
-
- return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
-}
-
-static bool _is_number(CharType c) {
-
- return (c>='0' && c<='9');
-}
-
-static bool _is_hex(CharType c) {
-
- return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F');
-}
-
-void GDTokenizer::_make_token(Token p_type) {
-
- TokenData &tk=tk_rb[tk_rb_pos];
-
- tk.type=p_type;
- tk.line=line;
- tk.col=column;
-
- tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE;
-}
-void GDTokenizer::_make_identifier(const StringName& p_identifier) {
-
- TokenData &tk=tk_rb[tk_rb_pos];
-
- tk.type=TK_IDENTIFIER;
- tk.identifier=p_identifier;
- tk.line=line;
- tk.col=column;
-
- tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE;
-
-}
-
-void GDTokenizer::_make_built_in_func(GDFunctions::Function p_func) {
-
- TokenData &tk=tk_rb[tk_rb_pos];
-
- tk.type=TK_BUILT_IN_FUNC;
- tk.func=p_func;
- tk.line=line;
- tk.col=column;
-
- tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE;
-
-}
-void GDTokenizer::_make_constant(const Variant& p_constant) {
-
- TokenData &tk=tk_rb[tk_rb_pos];
-
- tk.type=TK_CONSTANT;
- tk.constant=p_constant;
- tk.line=line;
- tk.col=column;
-
- tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE;
-
-}
-
-void GDTokenizer::_make_type(const Variant::Type& p_type) {
-
-
- TokenData &tk=tk_rb[tk_rb_pos];
-
- tk.type=TK_BUILT_IN_TYPE;
- tk.vtype=p_type;
- tk.line=line;
- tk.col=column;
-
- tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE;
-
-}
-
-
-void GDTokenizer::_make_error(const String& p_error) {
-
- error_flag=true;
- last_error=p_error;
-
- TokenData &tk=tk_rb[tk_rb_pos];
- tk.type=TK_ERROR;
- tk.constant=p_error;
- tk.line=line;
- tk.col=column;
- tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE;
-
-}
-
-
-void GDTokenizer::_make_newline(int p_spaces) {
-
- TokenData &tk=tk_rb[tk_rb_pos];
- tk.type=TK_NEWLINE;
- tk.constant=p_spaces;
- tk.line=line;
- tk.col=column;
- tk_rb_pos=(tk_rb_pos+1)%TK_RB_SIZE;
-}
-
-void GDTokenizer::_advance() {
-
- if (error_flag) {
- //parser broke
- _make_error(last_error);
- return;
- }
-
- if (code_pos>=len) {
- _make_token(TK_EOF);
- return;
- }
-#define GETCHAR(m_ofs) ((m_ofs+code_pos)>=len?0:_code[m_ofs+code_pos])
-#define INCPOS(m_amount) { code_pos+=m_amount; column+=m_amount; }
- while (true) {
-
-
- bool is_node_path=false;
-
- switch(GETCHAR(0)) {
- case 0:
- _make_token(TK_EOF);
- break;
- case '\t':
- case '\r':
- case ' ':
- INCPOS(1);
- continue;
- case '\n': {
- line++;
- INCPOS(1);
- column=0;
- int i=0;
- while(GETCHAR(i)==' ' || GETCHAR(i)=='\t') {
- i++;
- }
-
- _make_newline(i);
- return;
- }
-#if 1 //py style tokenizer
- case '#': { // line comment skip
-
- while(GETCHAR(0)!='\n') {
- code_pos++;
- if (GETCHAR(0)==0) { //end of file
- _make_error("Unterminated Comment");
- return;
- }
- }
- INCPOS(1);
- column=0;
- line++;
- int i=0;
- while(GETCHAR(i)==' ' || GETCHAR(i)=='\t') {
- i++;
- }
- _make_newline(i);
- return;
-
- } break;
-#endif
- case '/': {
-
- switch(GETCHAR(1)) {
-#if 0 // c style tokenizer
- case '*': { // block comment
- int pos = code_pos+2;
- int new_line=line;
- int new_col=column+2;
-
- while(true) {
- if (_code[pos]=='0') {
- _make_error("Unterminated Comment");
- code_pos=pos;
- return;
- }
- if (_code[pos]=='*' && _code[pos+1]=='/') {
- new_col+=2;
- pos+=2; //compensate
- break;
- } else if (_code[pos]=='\n') {
- new_line++;
- new_col=0;
- } else {
- new_col++;
- }
- pos++;
- }
-
- column=new_col;
- line=new_line;
- code_pos=pos;
- continue;
-
- } break;
- case '/': { // line comment skip
-
- while(GETCHAR(0)!='\n') {
- code_pos++;
- if (GETCHAR(0)==0) { //end of file
- _make_error("Unterminated Comment");
- return;
- }
- }
- INCPOS(1);
- column=0;
- line++;
- continue;
-
- } break;
-#endif
- case '=': { // diveq
-
- _make_token(TK_OP_ASSIGN_DIV);
- INCPOS(1);
-
- } break;
- default:
- _make_token(TK_OP_DIV);
-
- }
- } break;
- case '=': {
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_EQUAL);
- INCPOS(1);
-
- } else
- _make_token(TK_OP_ASSIGN);
-
- } break;
- case '<': {
- if (GETCHAR(1)=='=') {
-
- _make_token(TK_OP_LESS_EQUAL);
- INCPOS(1);
- } else if (GETCHAR(1)=='<') {
- if (GETCHAR(2)=='=') {
- _make_token(TK_OP_ASSIGN_SHIFT_LEFT);
- INCPOS(1);
- } else {
- _make_token(TK_OP_SHIFT_LEFT);
- }
- INCPOS(1);
- } else
- _make_token(TK_OP_LESS);
-
- } break;
- case '>': {
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_GREATER_EQUAL);
- INCPOS(1);
- } else if (GETCHAR(1)=='>') {
- if (GETCHAR(2)=='=') {
- _make_token(TK_OP_ASSIGN_SHIFT_RIGHT);
- INCPOS(1);
-
- } else {
- _make_token(TK_OP_SHIFT_RIGHT);
- }
- INCPOS(1);
- } else {
- _make_token(TK_OP_GREATER);
- }
-
- } break;
- case '!': {
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_NOT_EQUAL);
- INCPOS(1);
- } else {
- _make_token(TK_OP_NOT);
- }
-
- } break;
- //case '"' //string - no strings in shader
- //case '\'' //string - no strings in shader
- case '{':
- _make_token(TK_CURLY_BRACKET_OPEN);
- break;
- case '}':
- _make_token(TK_CURLY_BRACKET_CLOSE);
- break;
- case '[':
- _make_token(TK_BRACKET_OPEN);
- break;
- case ']':
- _make_token(TK_BRACKET_CLOSE);
- break;
- case '(':
- _make_token(TK_PARENTHESIS_OPEN);
- break;
- case ')':
- _make_token(TK_PARENTHESIS_CLOSE);
- break;
- case ',':
- _make_token(TK_COMMA);
- break;
- case ';':
- _make_token(TK_SEMICOLON);
- break;
- case '?':
- _make_token(TK_QUESTION_MARK);
- break;
- case ':':
- _make_token(TK_COLON); //for methods maybe but now useless.
- break;
- case '^': {
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_ASSIGN_BIT_XOR);
- INCPOS(1);
- } else {
- _make_token(TK_OP_BIT_XOR);
- }
-
- } break;
- case '~':
- _make_token(TK_OP_BIT_INVERT);
- break;
- case '&': {
- if (GETCHAR(1)=='&') {
-
- _make_token(TK_OP_AND);
- INCPOS(1);
- } else if (GETCHAR(1)=='=') {
- _make_token(TK_OP_ASSIGN_BIT_AND);
- INCPOS(1);
- } else {
- _make_token(TK_OP_BIT_AND);
- }
- } break;
- case '|': {
- if (GETCHAR(1)=='|') {
-
- _make_token(TK_OP_OR);
- INCPOS(1);
- } else if (GETCHAR(1)=='=') {
- _make_token(TK_OP_ASSIGN_BIT_OR);
- INCPOS(1);
- } else {
- _make_token(TK_OP_BIT_OR);
- }
- } break;
- case '*': {
-
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_ASSIGN_MUL);
- INCPOS(1);
- } else {
- _make_token(TK_OP_MUL);
- }
- } break;
- case '+': {
-
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_ASSIGN_ADD);
- INCPOS(1);
- //} else if (GETCHAR(1)=='+') {
- // _make_token(TK_OP_PLUS_PLUS);
- // INCPOS(1);
- } else {
- _make_token(TK_OP_ADD);
- }
-
- } break;
- case '-': {
-
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_ASSIGN_SUB);
- INCPOS(1);
- //} else if (GETCHAR(1)=='-') {
- // _make_token(TK_OP_MINUS_MINUS);
- // INCPOS(1);
- } else {
- _make_token(TK_OP_SUB);
- }
- } break;
- case '%': {
-
- if (GETCHAR(1)=='=') {
- _make_token(TK_OP_ASSIGN_MOD);
- INCPOS(1);
- } else {
- _make_token(TK_OP_MOD);
- }
- } break;
- case '@':
- if (CharType(GETCHAR(1))!='"') {
- _make_error("Unexpected '@'");
- return;
- }
- INCPOS(1);
- is_node_path=true;
- case '"': {
-
- int i=1;
- String str;
- while(true) {
- if (CharType(GETCHAR(i)==0)) {
-
- _make_error("Unterminated String");
- return;
- } else if (CharType(GETCHAR(i)=='"')) {
- break;
- } else if (CharType(GETCHAR(i)=='\\')) {
- //escaped characters...
- i++;
- CharType next = GETCHAR(i);
- if (next==0) {
- _make_error("Unterminated String");
- return;
- }
- CharType res=0;
-
- switch(next) {
-
- case 'a': res=7; break;
- case 'b': res=8; break;
- case 't': res=9; break;
- case 'n': res=10; break;
- case 'v': res=11; break;
- case 'f': res=12; break;
- case 'r': res=13; break;
- case '\'': res='\''; break;
- case '\"': res='\"'; break;
- case '\\': res='\\'; break;
- case 'x': {
- //hexnumbarh - oct is deprecated
-
- int read=0;
- for(int j=0;j<4;j++) {
- CharType c = GETCHAR(i+j);
- if (c==0) {
- _make_error("Unterminated String");
- return;
- }
- if (!_is_hex(c)) {
- if (j==0 || !(j&1)) {
- _make_error("Malformed hex constant in string");
- return;
- } else
- break;
- }
- CharType v;
- if (c>='0' && c<='9') {
- v=c-'0';
- } else if (c>='a' && c<='f') {
- v=c-'a';
- v+=10;
- } else if (c>='A' && c<='F') {
- v=c-'A';
- v+=10;
- } else {
- ERR_PRINT("BUG");
- v=0;
- }
-
- res<<=4;
- res|=v;
-
- read++;
- }
- i+=read-1;
-
-
- } break;
- default: {
-
- _make_error("Invalid escape sequence");
- return;
- } break;
- }
-
- str+=res;
-
- } else {
- str+=CharType(GETCHAR(i));
- }
- i++;
- }
- INCPOS(i);
-
- if (is_node_path) {
- _make_constant(NodePath(str));
- } else {
- _make_constant(str);
- }
-
- } break;
- default: {
-
- if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) {
- // parse number
- bool period_found=false;
- bool exponent_found=false;
- bool hexa_found=false;
- bool sign_found=false;
-
- String str;
- int i=0;
-
- while(true) {
- if (GETCHAR(i)=='.') {
- if (period_found || exponent_found) {
- _make_error("Invalid numeric constant at '.'");
- return;
- }
- period_found=true;
- } else if (GETCHAR(i)=='x') {
- if (hexa_found || str.length()!=1 || !( (i==1 && str[0]=='0') || (i==2 && str[1]=='0' && str[0]=='-') ) ) {
- _make_error("Invalid numeric constant at 'x'");
- return;
- }
- hexa_found=true;
- } else if (!hexa_found && GETCHAR(i)=='e') {
- if (hexa_found || exponent_found) {
- _make_error("Invalid numeric constant at 'e'");
- return;
- }
- exponent_found=true;
- } else if (_is_number(GETCHAR(i))) {
- //all ok
- } else if (hexa_found && _is_hex(GETCHAR(i))) {
-
- } else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) {
- if (sign_found) {
- _make_error("Invalid numeric constant at '-'");
- return;
- }
- sign_found=true;
- } else
- break;
-
- str+=CharType(GETCHAR(i));
- i++;
- }
-
- if (!( _is_number(str[str.length()-1]) || (hexa_found && _is_hex(str[str.length()-1])))) {
- _make_error("Invalid numeric constant: "+str);
- return;
- }
-
- INCPOS(str.length());
- if (hexa_found) {
- int val = str.hex_to_int();
- _make_constant(val);
- } else if (period_found) {
- real_t val = str.to_double();
- //print_line("*%*%*%*% to convert: "+str+" result: "+rtos(val));
- _make_constant(val);
- } else {
- int val = str.to_int();
- _make_constant(val);
-
- }
-
- return;
- }
-
- if (GETCHAR(0)=='.') {
- //parse period
- _make_token(TK_PERIOD);
- break;
- }
-
- if (_is_text_char(GETCHAR(0))) {
- // parse identifier
- String str;
- str+=CharType(GETCHAR(0));
-
- int i=1;
- while(_is_text_char(GETCHAR(i))) {
- str+=CharType(GETCHAR(i));
- i++;
- }
-
- bool identifier=false;
-
- if (str=="null") {
- _make_constant(Variant());
-
- } else if (str=="true") {
- _make_constant(true);
-
- } else if (str=="false") {
- _make_constant(false);
- } else {
-
- bool found=false;
-
- struct _bit { Variant::Type type; const char *text;};
- //built in types
-
- static const _bit type_list[]={
- //types
- {Variant::BOOL,"bool"},
- {Variant::INT,"int"},
- {Variant::REAL,"float"},
- {Variant::STRING,"String"},
- {Variant::VECTOR2,"vec2"},
- {Variant::VECTOR2,"Vector2"},
- {Variant::RECT2,"Rect2"},
- {Variant::MATRIX32,"Matrix32"},
- {Variant::MATRIX32,"mat32"},
- {Variant::VECTOR3,"vec3"},
- {Variant::VECTOR3,"Vector3"},
- {Variant::_AABB,"AABB"},
- {Variant::_AABB,"Rect3"},
- {Variant::PLANE,"Plane"},
- {Variant::QUAT,"Quat"},
- {Variant::MATRIX3,"mat3"},
- {Variant::MATRIX3,"Matrix3"},
- {Variant::TRANSFORM,"trn"},
- {Variant::TRANSFORM,"Transform"},
- {Variant::COLOR,"Color"},
- {Variant::IMAGE,"Image"},
- {Variant::_RID,"RID"},
- {Variant::OBJECT,"Object"},
- {Variant::INPUT_EVENT,"InputEvent"},
- {Variant::DICTIONARY,"dict"},
- {Variant::DICTIONARY,"Dictionary"},
- {Variant::ARRAY,"Array"},
- {Variant::RAW_ARRAY,"RawArray"},
- {Variant::INT_ARRAY,"IntArray"},
- {Variant::REAL_ARRAY,"FloatArray"},
- {Variant::STRING_ARRAY,"StringArray"},
- {Variant::VECTOR2_ARRAY,"Vector2Array"},
- {Variant::VECTOR3_ARRAY,"Vector3Array"},
- {Variant::COLOR_ARRAY,"ColorArray"},
- {Variant::VARIANT_MAX,NULL},
- };
-
- {
-
-
- int idx=0;
-
- while(type_list[idx].text) {
-
- if (str==type_list[idx].text) {
- _make_type(type_list[idx].type);
- found=true;
- break;
- }
- idx++;
- }
- }
-
- if (!found) {
-
- //built in func?
-
- for(int i=0;i<GDFunctions::FUNC_MAX;i++) {
-
- if (str==GDFunctions::get_func_name(GDFunctions::Function(i))) {
-
- _make_built_in_func(GDFunctions::Function(i));
- found=true;
- break;
- }
- }
-
- //keywor
- }
-
- if (!found) {
-
-
- struct _kws { Token token; const char *text;};
-
- static const _kws keyword_list[]={
- //ops
- {TK_OP_IN,"in"},
- {TK_OP_NOT,"not"},
- {TK_OP_OR,"or"},
- {TK_OP_AND,"and"},
- //func
- {TK_PR_FUNCTION,"func"},
- {TK_PR_FUNCTION,"function"},
- {TK_PR_CLASS,"class"},
- {TK_PR_EXTENDS,"extends"},
- {TK_PR_TOOL,"tool"},
- {TK_PR_STATIC,"static"},
- {TK_PR_EXPORT,"export"},
- {TK_PR_VAR,"var"},
- {TK_PR_PRELOAD,"preload"},
- {TK_PR_ASSERT,"assert"},
- {TK_PR_CONST,"const"},
- //controlflow
- {TK_CF_IF,"if"},
- {TK_CF_ELIF,"elif"},
- {TK_CF_ELSE,"else"},
- {TK_CF_FOR,"for"},
- {TK_CF_WHILE,"while"},
- {TK_CF_DO,"do"},
- {TK_CF_SWITCH,"switch"},
- {TK_CF_BREAK,"break"},
- {TK_CF_CONTINUE,"continue"},
- {TK_CF_RETURN,"return"},
- {TK_CF_PASS,"pass"},
- {TK_SELF,"self"},
- {TK_ERROR,NULL}
- };
-
- int idx=0;
- found=false;
-
- while(keyword_list[idx].text) {
-
- if (str==keyword_list[idx].text) {
- _make_token(keyword_list[idx].token);
- found=true;
- break;
- }
- idx++;
- }
- }
-
- if (!found)
- identifier=true;
- }
-
-
- if (identifier) {
- _make_identifier(str);
- }
- INCPOS(str.length());
- return;
- }
-
- _make_error("Unknown character");
- return;
-
- } break;
- }
-
- INCPOS(1);
- break;
- }
-
-}
-
-void GDTokenizer::set_code(const String& p_code) {
-
- code=p_code;
- len = p_code.length();
- if (len) {
- _code=&code[0];
- } else {
- _code=NULL;
- }
- code_pos=0;
- line=1; //it is stand-ar-ized that lines begin in 1 in code..
- column=0;
- tk_rb_pos=0;
- error_flag=false;
- last_error="";
- for(int i=0;i<MAX_LOOKAHEAD+1;i++)
- _advance();
-}
-
-GDTokenizer::Token GDTokenizer::get_token(int p_offset) const {
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, TK_ERROR);
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, TK_ERROR);
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- return tk_rb[ofs].type;
-}
-
-int GDTokenizer::get_token_line(int p_offset) const {
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, -1);
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, -1);
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- return tk_rb[ofs].line;
-}
-
-int GDTokenizer::get_token_column(int p_offset) const {
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, -1);
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, -1);
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- return tk_rb[ofs].col;
-}
-
-const Variant& GDTokenizer::get_token_constant(int p_offset) const {
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, tk_rb[0].constant);
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, tk_rb[0].constant);
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- ERR_FAIL_COND_V(tk_rb[ofs].type!=TK_CONSTANT,tk_rb[0].constant);
- return tk_rb[ofs].constant;
-}
-StringName GDTokenizer::get_token_identifier(int p_offset) const {
-
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, StringName());
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, StringName());
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- ERR_FAIL_COND_V(tk_rb[ofs].type!=TK_IDENTIFIER,StringName());
- return tk_rb[ofs].identifier;
-
-}
-
-GDFunctions::Function GDTokenizer::get_token_built_in_func(int p_offset) const {
-
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, GDFunctions::FUNC_MAX);
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, GDFunctions::FUNC_MAX);
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- ERR_FAIL_COND_V(tk_rb[ofs].type!=TK_BUILT_IN_FUNC,GDFunctions::FUNC_MAX);
- return tk_rb[ofs].func;
-
-}
-
-Variant::Type GDTokenizer::get_token_type(int p_offset) const {
-
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, Variant::NIL);
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, Variant::NIL);
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- ERR_FAIL_COND_V(tk_rb[ofs].type!=TK_BUILT_IN_TYPE,Variant::NIL);
- return tk_rb[ofs].vtype;
-
-}
-
-
-int GDTokenizer::get_token_line_indent(int p_offset) const {
-
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, 0);
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, 0);
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- ERR_FAIL_COND_V(tk_rb[ofs].type!=TK_NEWLINE,0);
- return tk_rb[ofs].constant;
-
-}
-
-String GDTokenizer::get_token_error(int p_offset) const {
-
- ERR_FAIL_COND_V( p_offset <= -MAX_LOOKAHEAD, String());
- ERR_FAIL_COND_V( p_offset >= MAX_LOOKAHEAD, String());
-
- int ofs = (TK_RB_SIZE + tk_rb_pos + p_offset - MAX_LOOKAHEAD -1)%TK_RB_SIZE;
- ERR_FAIL_COND_V(tk_rb[ofs].type!=TK_ERROR,String());
- return tk_rb[ofs].constant;
-}
-
-void GDTokenizer::advance(int p_amount) {
-
- ERR_FAIL_COND( p_amount <=0 );
- for(int i=0;i<p_amount;i++)
- _advance();
-}
diff --git a/script/gdscript/gd_tokenizer.h b/script/gdscript/gd_tokenizer.h
deleted file mode 100644
index 24ee2be7ad..0000000000
--- a/script/gdscript/gd_tokenizer.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*************************************************************************/
-/* gd_tokenizer.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef GD_TOKENIZER_H
-#define GD_TOKENIZER_H
-
-#include "ustring.h"
-#include "variant.h"
-#include "string_db.h"
-#include "gd_functions.h"
-class GDTokenizer {
-public:
-
- enum Token {
-
- TK_EMPTY,
- TK_IDENTIFIER,
- TK_CONSTANT,
- TK_SELF,
- TK_BUILT_IN_TYPE,
- TK_BUILT_IN_FUNC,
- TK_OP_IN,
- TK_OP_EQUAL,
- TK_OP_NOT_EQUAL,
- TK_OP_LESS,
- TK_OP_LESS_EQUAL,
- TK_OP_GREATER,
- TK_OP_GREATER_EQUAL,
- TK_OP_AND,
- TK_OP_OR,
- TK_OP_NOT,
- TK_OP_ADD,
- TK_OP_SUB,
- TK_OP_MUL,
- TK_OP_DIV,
- TK_OP_MOD,
- TK_OP_SHIFT_LEFT,
- TK_OP_SHIFT_RIGHT,
- TK_OP_ASSIGN,
- TK_OP_ASSIGN_ADD,
- TK_OP_ASSIGN_SUB,
- TK_OP_ASSIGN_MUL,
- TK_OP_ASSIGN_DIV,
- TK_OP_ASSIGN_MOD,
- TK_OP_ASSIGN_SHIFT_LEFT,
- TK_OP_ASSIGN_SHIFT_RIGHT,
- TK_OP_ASSIGN_BIT_AND,
- TK_OP_ASSIGN_BIT_OR,
- TK_OP_ASSIGN_BIT_XOR,
- TK_OP_BIT_AND,
- TK_OP_BIT_OR,
- TK_OP_BIT_XOR,
- TK_OP_BIT_INVERT,
- //TK_OP_PLUS_PLUS,
- //TK_OP_MINUS_MINUS,
- TK_CF_IF,
- TK_CF_ELIF,
- TK_CF_ELSE,
- TK_CF_FOR,
- TK_CF_DO,
- TK_CF_WHILE,
- TK_CF_SWITCH,
- TK_CF_CASE,
- TK_CF_BREAK,
- TK_CF_CONTINUE,
- TK_CF_PASS,
- TK_CF_RETURN,
- TK_PR_FUNCTION,
- TK_PR_CLASS,
- TK_PR_EXTENDS,
- TK_PR_TOOL,
- TK_PR_STATIC,
- TK_PR_EXPORT,
- TK_PR_CONST,
- TK_PR_VAR,
- TK_PR_PRELOAD,
- TK_PR_ASSERT,
- TK_BRACKET_OPEN,
- TK_BRACKET_CLOSE,
- TK_CURLY_BRACKET_OPEN,
- TK_CURLY_BRACKET_CLOSE,
- TK_PARENTHESIS_OPEN,
- TK_PARENTHESIS_CLOSE,
- TK_COMMA,
- TK_SEMICOLON,
- TK_PERIOD,
- TK_QUESTION_MARK,
- TK_COLON,
- TK_NEWLINE,
- TK_ERROR,
- TK_EOF,
- TK_MAX
- };
-
-
-
-private:
-
- static const char* token_names[TK_MAX];
- enum {
- MAX_LOOKAHEAD=4,
- TK_RB_SIZE=MAX_LOOKAHEAD*2+1
-
- };
-
- struct TokenData {
- Token type;
- StringName identifier; //for identifier types
- Variant constant; //for constant types
- union {
- Variant::Type vtype; //for type types
- GDFunctions::Function func; //function for built in functions
- };
- int line,col;
- TokenData() { type = TK_EMPTY; line=col=0; vtype=Variant::NIL; }
- };
-
- void _make_token(Token p_type);
- void _make_newline(int p_spaces=0);
- void _make_identifier(const StringName& p_identifier);
- void _make_built_in_func(GDFunctions::Function p_func);
- void _make_constant(const Variant& p_constant);
- void _make_type(const Variant::Type& p_type);
- void _make_error(const String& p_error);
-
- String code;
- int len;
- int code_pos;
- const CharType *_code;
- int line;
- int column;
- TokenData tk_rb[TK_RB_SIZE*2+1];
- int tk_rb_pos;
- String last_error;
- bool error_flag;
-
- void _advance();
-public:
-
- static const char *get_token_name(Token p_token);
-
- void set_code(const String& p_code);
- Token get_token(int p_offset=0) const;
- const Variant& get_token_constant(int p_offset=0) const;
- StringName get_token_identifier(int p_offset=0) const;
- GDFunctions::Function get_token_built_in_func(int p_offset=0) const;
- Variant::Type get_token_type(int p_offset=0) const;
- int get_token_line(int p_offset=0) const;
- int get_token_column(int p_offset=0) const;
- int get_token_line_indent(int p_offset=0) const;
-
- String get_token_error(int p_offset=0) const;
- void advance(int p_amount=1);
-};
-
-#endif // TOKENIZER_H
diff --git a/script/multiscript/SCsub b/script/multiscript/SCsub
deleted file mode 100644
index dd812edec5..0000000000
--- a/script/multiscript/SCsub
+++ /dev/null
@@ -1,7 +0,0 @@
-Import('env')
-
-env.add_source_files(env.script_sources,"*.cpp")
-
-Export('env')
-
-
diff --git a/script/multiscript/multi_script.cpp b/script/multiscript/multi_script.cpp
deleted file mode 100644
index 1924cf2a6e..0000000000
--- a/script/multiscript/multi_script.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-/*************************************************************************/
-/* multi_script.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "multi_script.h"
-
-bool MultiScriptInstance::set(const StringName& p_name, const Variant& p_value) {
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- bool found = sarr[i]->set(p_name,p_value);
- if (found)
- return true;
- }
-
- if (String(p_name).begins_with("script_")) {
- bool valid;
- owner->set(p_name,p_value,&valid);
- return valid;
- }
- return false;
-
-}
-
-bool MultiScriptInstance::get(const StringName& p_name, Variant &r_ret) const{
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- bool found = sarr[i]->get(p_name,r_ret);
- if (found)
- return true;
- }
- if (String(p_name).begins_with("script_")) {
- bool valid;
- r_ret=owner->get(p_name,&valid);
- return valid;
- }
- return false;
-
-}
-void MultiScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const{
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
-
- Set<String> existing;
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- List<PropertyInfo> pl;
- sarr[i]->get_property_list(&pl);
-
- for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
-
- if (existing.has(E->get().name))
- continue;
-
- p_properties->push_back(E->get());
- existing.insert(E->get().name);
- }
- }
-
- p_properties->push_back( PropertyInfo(Variant::NIL,"Scripts",PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_CATEGORY) );
-
- for(int i=0;i<owner->scripts.size();i++) {
-
- p_properties->push_back( PropertyInfo(Variant::OBJECT,"script_"+String::chr('a'+i),PROPERTY_HINT_RESOURCE_TYPE,"Script",PROPERTY_USAGE_EDITOR) );
-
- }
-
- if (owner->scripts.size()<25) {
-
- p_properties->push_back( PropertyInfo(Variant::OBJECT,"script_"+String::chr('a'+(owner->scripts.size())),PROPERTY_HINT_RESOURCE_TYPE,"Script",PROPERTY_USAGE_EDITOR) );
- }
-
-}
-
-void MultiScriptInstance::get_method_list(List<MethodInfo> *p_list) const{
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
-
- Set<StringName> existing;
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- List<MethodInfo> ml;
- sarr[i]->get_method_list(&ml);
-
- for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) {
-
- if (existing.has(E->get().name))
- continue;
-
- p_list->push_back(E->get());
- existing.insert(E->get().name);
- }
- }
-
-}
-bool MultiScriptInstance::has_method(const StringName& p_method) const{
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- if (sarr[i]->has_method(p_method))
- return true;
- }
-
- return false;
-
-}
-
-Variant MultiScriptInstance::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- Variant r = sarr[i]->call(p_method,p_args,p_argcount,r_error);
- if (r_error.error==Variant::CallError::CALL_OK)
- return r;
- else if (r_error.error!=Variant::CallError::CALL_ERROR_INVALID_METHOD)
- return r;
- }
-
- r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
-
-}
-
-void MultiScriptInstance::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount){
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- sarr[i]->call_multilevel(p_method,p_args,p_argcount);
- }
-
-
-}
-void MultiScriptInstance::notification(int p_notification){
-
- ScriptInstance **sarr = instances.ptr();
- int sc = instances.size();
-
- for(int i=0;i<sc;i++) {
-
- if (!sarr[i])
- continue;
-
- sarr[i]->notification(p_notification);
- }
-
-}
-
-
-Ref<Script> MultiScriptInstance::get_script() const {
-
- return owner;
-}
-
-ScriptLanguage *MultiScriptInstance::get_language() {
-
- return MultiScriptLanguage::get_singleton();
-}
-
-MultiScriptInstance::~MultiScriptInstance() {
-
- owner->remove_instance(object);
-}
-
-
-///////////////////
-
-
-bool MultiScript::is_tool() const {
-
- for(int i=0;i<scripts.size();i++) {
-
- if (scripts[i]->is_tool())
- return true;
- }
-
- return false;
-}
-
-bool MultiScript::_set(const StringName& p_name, const Variant& p_value) {
-
- _THREAD_SAFE_METHOD_
-
- String s = String(p_name);
- if (s.begins_with("script_")) {
-
- int idx = s[7];
- if (idx==0)
- return false;
- idx-='a';
-
- ERR_FAIL_COND_V(idx<0,false);
-
- Ref<Script> s = p_value;
-
- if (idx<scripts.size()) {
-
-
- if (s.is_null())
- remove_script(idx);
- else
- set_script(idx,s);
- } else if (idx==scripts.size()) {
- if (s.is_null())
- return false;
- add_script(s);
- } else
- return false;
-
- return true;
- }
-
- return false;
-}
-
-bool MultiScript::_get(const StringName& p_name,Variant &r_ret) const{
-
- _THREAD_SAFE_METHOD_
-
- String s = String(p_name);
- if (s.begins_with("script_")) {
-
- int idx = s[7];
- if (idx==0)
- return false;
- idx-='a';
-
- ERR_FAIL_COND_V(idx<0,false);
-
- if (idx<scripts.size()) {
-
- r_ret=get_script(idx);
- return true;
- } else if (idx==scripts.size()) {
- r_ret=Ref<Script>();
- return true;
- }
- }
-
- return false;
-}
-void MultiScript::_get_property_list( List<PropertyInfo> *p_list) const{
-
- _THREAD_SAFE_METHOD_
-
- for(int i=0;i<scripts.size();i++) {
-
- p_list->push_back( PropertyInfo(Variant::OBJECT,"script_"+String::chr('a'+i),PROPERTY_HINT_RESOURCE_TYPE,"Script") );
-
- }
-
- if (scripts.size()<25) {
-
- p_list->push_back( PropertyInfo(Variant::OBJECT,"script_"+String::chr('a'+(scripts.size())),PROPERTY_HINT_RESOURCE_TYPE,"Script") );
- }
-}
-
-void MultiScript::set_script(int p_idx,const Ref<Script>& p_script ) {
-
- _THREAD_SAFE_METHOD_
-
- ERR_FAIL_INDEX(p_idx,scripts.size());
- ERR_FAIL_COND( p_script.is_null() );
-
- scripts[p_idx]=p_script;
- Ref<Script> s=p_script;
-
- for (Map<Object*,MultiScriptInstance*>::Element *E=instances.front();E;E=E->next()) {
-
-
- MultiScriptInstance*msi=E->get();
- ScriptInstance *si = msi->instances[p_idx];
- if (si) {
- msi->instances[p_idx]=NULL;
- memdelete(si);
- }
-
- if (p_script->can_instance())
- msi->instances[p_idx]=s->instance_create(msi->object);
-
- }
-
-
-}
-
-
-Ref<Script> MultiScript::get_script(int p_idx) const{
-
- _THREAD_SAFE_METHOD_
-
- ERR_FAIL_INDEX_V(p_idx,scripts.size(),Ref<Script>());
-
- return scripts[p_idx];
-
-}
-void MultiScript::add_script(const Ref<Script>& p_script){
-
- _THREAD_SAFE_METHOD_
- ERR_FAIL_COND( p_script.is_null() );
- scripts.push_back(p_script);
- Ref<Script> s=p_script;
-
- for (Map<Object*,MultiScriptInstance*>::Element *E=instances.front();E;E=E->next()) {
-
-
- MultiScriptInstance*msi=E->get();
-
- if (p_script->can_instance())
- msi->instances.push_back( s->instance_create(msi->object) );
- else
- msi->instances.push_back(NULL);
-
- msi->object->_change_notify();
-
- }
-
-
- _change_notify();
-}
-
-
-void MultiScript::remove_script(int p_idx) {
-
- _THREAD_SAFE_METHOD_
-
- ERR_FAIL_INDEX(p_idx,scripts.size());
-
- scripts.remove(p_idx);
-
- for (Map<Object*,MultiScriptInstance*>::Element *E=instances.front();E;E=E->next()) {
-
-
- MultiScriptInstance*msi=E->get();
- ScriptInstance *si = msi->instances[p_idx];
- msi->instances.remove(p_idx);
- if (si) {
- memdelete(si);
- }
-
- msi->object->_change_notify();
- }
-
-
-}
-
-
-void MultiScript::remove_instance(Object *p_object) {
-
- _THREAD_SAFE_METHOD_
- instances.erase(p_object);
-}
-
-bool MultiScript::can_instance() const {
-
- return true;
-}
-
-StringName MultiScript::get_instance_base_type() const {
-
- return StringName();
-}
-ScriptInstance* MultiScript::instance_create(Object *p_this) {
-
- _THREAD_SAFE_METHOD_
- MultiScriptInstance *msi = memnew( MultiScriptInstance );
- msi->object=p_this;
- msi->owner=this;
- for(int i=0;i<scripts.size();i++) {
-
- ScriptInstance *si;
-
- if (scripts[i]->can_instance())
- si = scripts[i]->instance_create(p_this);
- else
- si=NULL;
-
- msi->instances.push_back(si);
- }
-
- instances[p_this]=msi;
- p_this->_change_notify();
- return msi;
-}
-bool MultiScript::instance_has(const Object *p_this) const {
-
- _THREAD_SAFE_METHOD_
- return instances.has((Object*)p_this);
-}
-
-bool MultiScript::has_source_code() const {
-
- return false;
-}
-String MultiScript::get_source_code() const {
-
- return "";
-}
-void MultiScript::set_source_code(const String& p_code) {
-
-
-}
-Error MultiScript::reload() {
-
- for(int i=0;i<scripts.size();i++)
- scripts[i]->reload();
-
- return OK;
-}
-
-String MultiScript::get_node_type() const {
-
- return "";
-}
-
-void MultiScript::_bind_methods() {
-
-
-}
-
-ScriptLanguage *MultiScript::get_language() const {
-
- return MultiScriptLanguage::get_singleton();
-}
-
-
-///////////////
-
-MultiScript::MultiScript() {
-}
-
-
-MultiScriptLanguage *MultiScriptLanguage::singleton=NULL;
diff --git a/script/multiscript/multi_script.h b/script/multiscript/multi_script.h
deleted file mode 100644
index a67cedc56b..0000000000
--- a/script/multiscript/multi_script.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*************************************************************************/
-/* multi_script.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef MULTI_SCRIPT_H
-#define MULTI_SCRIPT_H
-
-#include "script_language.h"
-#include "os/thread_safe.h"
-
-class MultiScript;
-
-class MultiScriptInstance : public ScriptInstance {
-friend class MultiScript;
- mutable Vector<ScriptInstance*> instances;
- Object *object;
- mutable MultiScript *owner;
-
-public:
- virtual bool set(const StringName& p_name, const Variant& p_value);
- virtual bool get(const StringName& p_name, Variant &r_ret) const;
- virtual void get_property_list(List<PropertyInfo> *p_properties) const;
-
- virtual void get_method_list(List<MethodInfo> *p_list) const;
- virtual bool has_method(const StringName& p_method) const;
- virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error);
- virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
- virtual void notification(int p_notification);
-
-
- virtual Ref<Script> get_script() const;
-
- virtual ScriptLanguage *get_language();
- virtual ~MultiScriptInstance();
-};
-
-
-class MultiScript : public Script {
-
- _THREAD_SAFE_CLASS_
-friend class MultiScriptInstance;
- OBJ_TYPE( MultiScript,Script);
-
- Vector<Ref<Script> > scripts;
-
- Map<Object*,MultiScriptInstance*> instances;
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
- static void _bind_methods();
-
-public:
-
- void remove_instance(Object *p_object);
- virtual bool can_instance() const;
-
- virtual StringName get_instance_base_type() const;
- virtual ScriptInstance* instance_create(Object *p_this);
- virtual bool instance_has(const Object *p_this) const;
-
- virtual bool has_source_code() const;
- virtual String get_source_code() const;
- virtual void set_source_code(const String& p_code);
- virtual Error reload();
-
- virtual bool is_tool() const;
-
- virtual String get_node_type() const;
-
-
- void set_script(int p_idx,const Ref<Script>& p_script );
- Ref<Script> get_script(int p_idx) const;
- void remove_script(int p_idx);
- void add_script(const Ref<Script>& p_script);
-
- virtual ScriptLanguage *get_language() const;
-
- MultiScript();
-};
-
-
-class MultiScriptLanguage : public ScriptLanguage {
-
- static MultiScriptLanguage *singleton;
-public:
-
- static _FORCE_INLINE_ MultiScriptLanguage *get_singleton() { return singleton; }
- virtual String get_name() const { return "MultiScript"; }
-
- /* LANGUAGE FUNCTIONS */
- virtual void init() {}
- virtual String get_type() const { return "MultiScript"; }
- virtual String get_extension() const { return ""; }
- virtual Error execute_file(const String& p_path) { return OK; }
- virtual void finish() {}
-
- /* EDITOR FUNCTIONS */
- virtual void get_reserved_words(List<String> *p_words) const {}
- virtual void get_comment_delimiters(List<String> *p_delimiters) const {}
- virtual void get_string_delimiters(List<String> *p_delimiters) const {}
- virtual String get_template(const String& p_class_name, const String& p_base_class_name) const { return ""; }
- virtual bool validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error,const String& p_path="",List<String>* r_fn=NULL) const { return true; }
- virtual Script *create_script() const { return memnew( MultiScript ); }
- virtual bool has_named_classes() const { return false; }
- virtual int find_function(const String& p_function,const String& p_code) const { return -1; }
- virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const { return ""; }
-
- /* DEBUGGER FUNCTIONS */
-
- virtual String debug_get_error() const { return ""; }
- virtual int debug_get_stack_level_count() const { return 0; }
- virtual int debug_get_stack_level_line(int p_level) const { return 0; }
- virtual String debug_get_stack_level_function(int p_level) const { return ""; }
- virtual String debug_get_stack_level_source(int p_level) const { return ""; }
- virtual void debug_get_stack_level_locals(int p_level,List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1) {}
- virtual void debug_get_stack_level_members(int p_level,List<String> *p_members, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1) {}
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1) {}
- virtual String debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems=-1,int p_max_depth=-1) { return ""; }
-
- /* LOADER FUNCTIONS */
-
- virtual void get_recognized_extensions(List<String> *p_extensions) const {}
- virtual void get_public_functions(List<MethodInfo> *p_functions) const {}
-
- MultiScriptLanguage() { singleton=this; }
- virtual ~MultiScriptLanguage() {};
-};
-
-
-#endif // MULTI_SCRIPT_H
diff --git a/script/register_script_types.cpp b/script/register_script_types.cpp
deleted file mode 100644
index 1927cd5c1f..0000000000
--- a/script/register_script_types.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*************************************************/
-/* register_script_types.cpp */
-/*************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/*************************************************/
-/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
-/* All Rights Reserved. */
-/*************************************************/
-
-#include "register_script_types.h"
-
-#include "script/gdscript/gd_script.h"
-#include "script/multiscript/multi_script.h"
-#include "io/resource_loader.h"
-
-
-
-#ifdef GDSCRIPT_ENABLED
-GDScriptLanguage *script_language_gd=NULL;
-ResourceFormatLoaderGDScript *resource_loader_gd=NULL;
-ResourceFormatSaverGDScript *resource_saver_gd=NULL;
-#endif
-
-static MultiScriptLanguage *script_multi_script=NULL;
-
-void register_script_types() {
-
-#ifdef GDSCRIPT_ENABLED
-
- script_language_gd=memnew( GDScriptLanguage );
- script_language_gd->init();
- ScriptServer::register_language(script_language_gd);
- ObjectTypeDB::register_type<GDScript>();
- resource_loader_gd=memnew( ResourceFormatLoaderGDScript );
- ResourceLoader::add_resource_format_loader(resource_loader_gd);
- resource_saver_gd=memnew( ResourceFormatSaverGDScript );
- ResourceSaver::add_resource_format_saver(resource_saver_gd);
-#endif
-
-
- script_multi_script = memnew( MultiScriptLanguage );
- ScriptServer::register_language(script_multi_script);
- ObjectTypeDB::register_type<MultiScript>();
-
-
-}
-void unregister_script_types() {
-
-
-
-
-#ifdef GDSCRIPT_ENABLED
- if (script_language_gd)
- memdelete( script_language_gd );
- if (resource_loader_gd)
- memdelete( resource_loader_gd );
- if (resource_saver_gd)
- memdelete( resource_saver_gd );
-
-#endif
-
- if (script_multi_script);
- memdelete(script_multi_script);
-}
diff --git a/script/register_script_types.h b/script/register_script_types.h
deleted file mode 100644
index eec0cfe539..0000000000
--- a/script/register_script_types.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*************************************************************************/
-/* register_script_types.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef REGISTER_SCRIPT_TYPES_H
-#define REGISTER_SCRIPT_TYPES_H
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-void register_script_types();
-void unregister_script_types();
-
-#endif
diff --git a/script/script_binder.cpp b/script/script_binder.cpp
deleted file mode 100644
index 63c6d1d050..0000000000
--- a/script/script_binder.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-/*************************************************/
-/* script_binder.cpp */
-/*************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/*************************************************/
-/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
-/* All Rights Reserved. */
-/*************************************************/
-
-#include "script_binder.h"
-
diff --git a/script/script_binder.h b/script/script_binder.h
deleted file mode 100644
index c3167a901d..0000000000
--- a/script/script_binder.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*************************************************/
-/* script_binder.h */
-/*************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/*************************************************/
-/* Source code within this file is: */
-/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
-/* All Rights Reserved. */
-/*************************************************/
-
-#ifndef SCRIPT_BINDER_H
-#define SCRIPT_BINDER_H
-
-#endif // SCRIPT_BINDER_H