test_gdscript.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  1. /*************************************************************************/
  2. /* test_gdscript.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "test_gdscript.h"
  30. #include "os/main_loop.h"
  31. #include "os/os.h"
  32. #include "os/file_access.h"
  33. #ifdef GDSCRIPT_ENABLED
  34. #include "modules/gdscript/gd_tokenizer.h"
  35. #include "modules/gdscript/gd_parser.h"
  36. #include "modules/gdscript/gd_compiler.h"
  37. #include "modules/gdscript/gd_script.h"
  38. namespace TestGDScript {
  39. static void _print_indent(int p_ident,const String& p_text) {
  40. String txt;
  41. for(int i=0;i<p_ident;i++) {
  42. txt+='\t';
  43. }
  44. print_line(txt+p_text);
  45. }
  46. static String _parser_extends(const GDParser::ClassNode *p_class) {
  47. String txt="extends ";
  48. if (String(p_class->extends_file)!="") {
  49. txt+="\""+p_class->extends_file+"\"";
  50. if (p_class->extends_class.size())
  51. txt+=".";
  52. }
  53. for(int i=0;i<p_class->extends_class.size();i++) {
  54. if (i!=0)
  55. txt+=".";
  56. txt+=p_class->extends_class[i];
  57. }
  58. return txt;
  59. }
  60. static String _parser_expr(const GDParser::Node *p_expr) {
  61. String txt;
  62. switch(p_expr->type) {
  63. case GDParser::Node::TYPE_IDENTIFIER: {
  64. const GDParser::IdentifierNode *id_node = static_cast<const GDParser::IdentifierNode *>(p_expr);
  65. txt=id_node->name;
  66. } break;
  67. case GDParser::Node::TYPE_CONSTANT: {
  68. const GDParser::ConstantNode *c_node = static_cast<const GDParser::ConstantNode *>(p_expr);
  69. if (c_node->value.get_type()==Variant::STRING)
  70. txt="\""+String(c_node->value)+"\"";
  71. else
  72. txt=c_node->value;
  73. } break;
  74. case GDParser::Node::TYPE_SELF: {
  75. txt="self";
  76. } break;
  77. case GDParser::Node::TYPE_ARRAY: {
  78. const GDParser::ArrayNode *arr_node = static_cast<const GDParser::ArrayNode *>(p_expr);
  79. txt+="[";
  80. for(int i=0;i<arr_node->elements.size();i++) {
  81. if (i>0)
  82. txt+=", ";
  83. txt+=_parser_expr(arr_node->elements[i]);
  84. }
  85. txt+="]";
  86. } break;
  87. case GDParser::Node::TYPE_DICTIONARY: {
  88. const GDParser::DictionaryNode *dict_node = static_cast<const GDParser::DictionaryNode *>(p_expr);
  89. txt+="{";
  90. for(int i=0;i<dict_node->elements.size();i++) {
  91. if (i>0)
  92. txt+=", ";
  93. const GDParser::DictionaryNode::Pair &p = dict_node->elements[i];
  94. txt+=_parser_expr(p.key);
  95. txt+=":";
  96. txt+=_parser_expr(p.value);
  97. }
  98. txt+="}";
  99. } break;
  100. case GDParser::Node::TYPE_OPERATOR: {
  101. const GDParser::OperatorNode *c_node = static_cast<const GDParser::OperatorNode *>(p_expr);
  102. switch(c_node->op) {
  103. case GDParser::OperatorNode::OP_PARENT_CALL:
  104. txt+=".";
  105. case GDParser::OperatorNode::OP_CALL: {
  106. ERR_FAIL_COND_V(c_node->arguments.size()<1,"");
  107. String func_name;
  108. const GDParser::Node *nfunc = c_node->arguments[0];
  109. int arg_ofs=0;
  110. if (nfunc->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) {
  111. const GDParser::BuiltInFunctionNode *bif_node = static_cast<const GDParser::BuiltInFunctionNode *>(nfunc);
  112. func_name=GDFunctions::get_func_name(bif_node->function);
  113. arg_ofs=1;
  114. } else if (nfunc->type==GDParser::Node::TYPE_TYPE) {
  115. const GDParser::TypeNode *t_node = static_cast<const GDParser::TypeNode *>(nfunc);
  116. func_name=Variant::get_type_name(t_node->vtype);
  117. arg_ofs=1;
  118. } else {
  119. ERR_FAIL_COND_V(c_node->arguments.size()<2,"");
  120. nfunc = c_node->arguments[1];
  121. ERR_FAIL_COND_V(nfunc->type!=GDParser::Node::TYPE_IDENTIFIER,"");
  122. if (c_node->arguments[0]->type!=GDParser::Node::TYPE_SELF)
  123. func_name=_parser_expr(c_node->arguments[0])+".";
  124. func_name+=_parser_expr(nfunc);
  125. arg_ofs=2;
  126. }
  127. txt+=func_name+"(";
  128. for(int i=arg_ofs;i<c_node->arguments.size();i++) {
  129. const GDParser::Node *arg=c_node->arguments[i];
  130. if (i>arg_ofs)
  131. txt+=", ";
  132. txt+=_parser_expr(arg);
  133. }
  134. txt+=")";
  135. } break;
  136. case GDParser::OperatorNode::OP_INDEX: {
  137. ERR_FAIL_COND_V(c_node->arguments.size()!=2,"");
  138. //index with []
  139. txt=_parser_expr(c_node->arguments[0])+"["+_parser_expr(c_node->arguments[1])+"]";
  140. } break;
  141. case GDParser::OperatorNode::OP_INDEX_NAMED: {
  142. ERR_FAIL_COND_V(c_node->arguments.size()!=2,"");
  143. txt=_parser_expr(c_node->arguments[0])+"."+_parser_expr(c_node->arguments[1]);
  144. } break;
  145. case GDParser::OperatorNode::OP_NEG: { txt="-"+_parser_expr(c_node->arguments[0]); } break;
  146. case GDParser::OperatorNode::OP_NOT: { txt="not "+_parser_expr(c_node->arguments[0]); } break;
  147. case GDParser::OperatorNode::OP_BIT_INVERT: { txt="~"+_parser_expr(c_node->arguments[0]); } break;
  148. case GDParser::OperatorNode::OP_PREINC: {} break;
  149. case GDParser::OperatorNode::OP_PREDEC: {} break;
  150. case GDParser::OperatorNode::OP_INC: {} break;
  151. case GDParser::OperatorNode::OP_DEC: {} break;
  152. case GDParser::OperatorNode::OP_IN: { txt=_parser_expr(c_node->arguments[0])+" in "+_parser_expr(c_node->arguments[1]); } break;
  153. case GDParser::OperatorNode::OP_EQUAL: { txt=_parser_expr(c_node->arguments[0])+"=="+_parser_expr(c_node->arguments[1]); } break;
  154. case GDParser::OperatorNode::OP_NOT_EQUAL: { txt=_parser_expr(c_node->arguments[0])+"!="+_parser_expr(c_node->arguments[1]); } break;
  155. case GDParser::OperatorNode::OP_LESS: { txt=_parser_expr(c_node->arguments[0])+"<"+_parser_expr(c_node->arguments[1]); } break;
  156. case GDParser::OperatorNode::OP_LESS_EQUAL: { txt=_parser_expr(c_node->arguments[0])+"<="+_parser_expr(c_node->arguments[1]); } break;
  157. case GDParser::OperatorNode::OP_GREATER: { txt=_parser_expr(c_node->arguments[0])+">"+_parser_expr(c_node->arguments[1]); } break;
  158. case GDParser::OperatorNode::OP_GREATER_EQUAL: { txt=_parser_expr(c_node->arguments[0])+">="+_parser_expr(c_node->arguments[1]); } break;
  159. case GDParser::OperatorNode::OP_AND: { txt=_parser_expr(c_node->arguments[0])+" and "+_parser_expr(c_node->arguments[1]); } break;
  160. case GDParser::OperatorNode::OP_OR: { txt=_parser_expr(c_node->arguments[0])+" or "+_parser_expr(c_node->arguments[1]); } break;
  161. case GDParser::OperatorNode::OP_ADD: { txt=_parser_expr(c_node->arguments[0])+"+"+_parser_expr(c_node->arguments[1]); } break;
  162. case GDParser::OperatorNode::OP_SUB: { txt=_parser_expr(c_node->arguments[0])+"-"+_parser_expr(c_node->arguments[1]); } break;
  163. case GDParser::OperatorNode::OP_MUL: { txt=_parser_expr(c_node->arguments[0])+"*"+_parser_expr(c_node->arguments[1]); } break;
  164. case GDParser::OperatorNode::OP_DIV: { txt=_parser_expr(c_node->arguments[0])+"/"+_parser_expr(c_node->arguments[1]); } break;
  165. case GDParser::OperatorNode::OP_MOD: { txt=_parser_expr(c_node->arguments[0])+"%"+_parser_expr(c_node->arguments[1]); } break;
  166. case GDParser::OperatorNode::OP_SHIFT_LEFT: { txt=_parser_expr(c_node->arguments[0])+"<<"+_parser_expr(c_node->arguments[1]); } break;
  167. case GDParser::OperatorNode::OP_SHIFT_RIGHT: { txt=_parser_expr(c_node->arguments[0])+">>"+_parser_expr(c_node->arguments[1]); } break;
  168. case GDParser::OperatorNode::OP_ASSIGN: { txt=_parser_expr(c_node->arguments[0])+"="+_parser_expr(c_node->arguments[1]); } break;
  169. case GDParser::OperatorNode::OP_ASSIGN_ADD: { txt=_parser_expr(c_node->arguments[0])+"+="+_parser_expr(c_node->arguments[1]); } break;
  170. case GDParser::OperatorNode::OP_ASSIGN_SUB: { txt=_parser_expr(c_node->arguments[0])+"-="+_parser_expr(c_node->arguments[1]); } break;
  171. case GDParser::OperatorNode::OP_ASSIGN_MUL: { txt=_parser_expr(c_node->arguments[0])+"*="+_parser_expr(c_node->arguments[1]); } break;
  172. case GDParser::OperatorNode::OP_ASSIGN_DIV: { txt=_parser_expr(c_node->arguments[0])+"/="+_parser_expr(c_node->arguments[1]); } break;
  173. case GDParser::OperatorNode::OP_ASSIGN_MOD: { txt=_parser_expr(c_node->arguments[0])+"%="+_parser_expr(c_node->arguments[1]); } break;
  174. case GDParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT:{ txt=_parser_expr(c_node->arguments[0])+"<<="+_parser_expr(c_node->arguments[1]); } break;
  175. case GDParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: { txt=_parser_expr(c_node->arguments[0])+">>="+_parser_expr(c_node->arguments[1]); } break;
  176. case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: { txt=_parser_expr(c_node->arguments[0])+"&="+_parser_expr(c_node->arguments[1]); } break;
  177. case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: { txt=_parser_expr(c_node->arguments[0])+"|="+_parser_expr(c_node->arguments[1]); } break;
  178. case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: { txt=_parser_expr(c_node->arguments[0])+"^="+_parser_expr(c_node->arguments[1]); } break;
  179. case GDParser::OperatorNode::OP_BIT_AND: { txt=_parser_expr(c_node->arguments[0])+"&"+_parser_expr(c_node->arguments[1]); } break;;
  180. case GDParser::OperatorNode::OP_BIT_OR: { txt=_parser_expr(c_node->arguments[0])+"|"+_parser_expr(c_node->arguments[1]); } break;
  181. case GDParser::OperatorNode::OP_BIT_XOR: { txt=_parser_expr(c_node->arguments[0])+"^"+_parser_expr(c_node->arguments[1]); } break;
  182. default: {}
  183. }
  184. } break;
  185. case GDParser::Node::TYPE_NEWLINE: {
  186. //skippie
  187. } break;
  188. default: {
  189. String error="Parser bug at "+itos(p_expr->line)+", invalid expression type: "+itos(p_expr->type);
  190. ERR_EXPLAIN(error);
  191. ERR_FAIL_V("");
  192. }
  193. }
  194. return txt;
  195. //return "("+txt+")";
  196. }
  197. static void _parser_show_block(const GDParser::BlockNode *p_block,int p_indent) {
  198. for(int i=0;i<p_block->statements.size();i++) {
  199. const GDParser::Node *statement=p_block->statements[i];
  200. switch(statement->type) {
  201. case GDParser::Node::TYPE_CONTROL_FLOW: {
  202. const GDParser::ControlFlowNode *cf_node = static_cast<const GDParser::ControlFlowNode *>(statement);
  203. switch(cf_node->cf_type) {
  204. case GDParser::ControlFlowNode::CF_IF: {
  205. ERR_FAIL_COND(cf_node->arguments.size()!=1);
  206. String txt;
  207. txt+="if ";
  208. txt+=_parser_expr(cf_node->arguments[0]);
  209. txt+=":";
  210. _print_indent(p_indent,txt);
  211. ERR_FAIL_COND(!cf_node->body);
  212. _parser_show_block(cf_node->body,p_indent+1);
  213. if (cf_node->body_else) {
  214. _print_indent(p_indent,"else:");
  215. _parser_show_block(cf_node->body_else,p_indent+1);
  216. }
  217. } break;
  218. case GDParser::ControlFlowNode::CF_FOR: {
  219. ERR_FAIL_COND(cf_node->arguments.size()!=2);
  220. String txt;
  221. txt+="for ";
  222. txt+=_parser_expr(cf_node->arguments[0]);
  223. txt+=" in ";
  224. txt+=_parser_expr(cf_node->arguments[1]);
  225. txt+=":";
  226. _print_indent(p_indent,txt);
  227. ERR_FAIL_COND(!cf_node->body);
  228. _parser_show_block(cf_node->body,p_indent+1);
  229. } break;
  230. case GDParser::ControlFlowNode::CF_WHILE: {
  231. ERR_FAIL_COND(cf_node->arguments.size()!=1);
  232. String txt;
  233. txt+="while ";
  234. txt+=_parser_expr(cf_node->arguments[0]);
  235. txt+=":";
  236. _print_indent(p_indent,txt);
  237. ERR_FAIL_COND(!cf_node->body);
  238. _parser_show_block(cf_node->body,p_indent+1);
  239. } break;
  240. case GDParser::ControlFlowNode::CF_SWITCH: {
  241. } break;
  242. case GDParser::ControlFlowNode::CF_CONTINUE: {
  243. _print_indent(p_indent,"continue");
  244. } break;
  245. case GDParser::ControlFlowNode::CF_BREAK: {
  246. _print_indent(p_indent,"break");
  247. } break;
  248. case GDParser::ControlFlowNode::CF_RETURN: {
  249. if (cf_node->arguments.size())
  250. _print_indent(p_indent,"return "+_parser_expr(cf_node->arguments[0]));
  251. else
  252. _print_indent(p_indent,"return ");
  253. } break;
  254. }
  255. } break;
  256. case GDParser::Node::TYPE_LOCAL_VAR: {
  257. const GDParser::LocalVarNode *lv_node = static_cast<const GDParser::LocalVarNode *>(statement);
  258. _print_indent(p_indent,"var "+String(lv_node->name));
  259. } break;
  260. default: {
  261. //expression i guess
  262. _print_indent(p_indent,_parser_expr(statement));
  263. }
  264. }
  265. }
  266. }
  267. static void _parser_show_function(const GDParser::FunctionNode *p_func,int p_indent,GDParser::BlockNode *p_initializer=NULL) {
  268. String txt;
  269. if (p_func->_static)
  270. txt="static ";
  271. txt+="func ";
  272. if (p_func->name=="") // initializer
  273. txt+="[built-in-initializer]";
  274. else
  275. txt+=String(p_func->name);
  276. txt+="(";
  277. for(int i=0;i<p_func->arguments.size();i++) {
  278. if (i!=0)
  279. txt+=", ";
  280. txt+="var "+String(p_func->arguments[i]);
  281. if (i>=(p_func->arguments.size()-p_func->default_values.size())) {
  282. int defarg = i - (p_func->arguments.size() - p_func->default_values.size());
  283. txt+="=";
  284. txt+=_parser_expr(p_func->default_values[defarg]);
  285. }
  286. }
  287. txt+=")";
  288. //todo constructor check!
  289. txt+=":";
  290. _print_indent(p_indent,txt);
  291. if (p_initializer)
  292. _parser_show_block(p_initializer,p_indent+1);
  293. _parser_show_block(p_func->body,p_indent+1);
  294. }
  295. static void _parser_show_class(const GDParser::ClassNode *p_class,int p_indent,const Vector<String>& p_code) {
  296. if (p_indent==0 && (String(p_class->extends_file)!="" || p_class->extends_class.size())) {
  297. _print_indent(p_indent,_parser_extends(p_class));
  298. print_line("\n");
  299. }
  300. for(int i=0;i<p_class->subclasses.size();i++) {
  301. const GDParser::ClassNode *subclass=p_class->subclasses[i];
  302. String line="class "+subclass->name;
  303. if (String(subclass->extends_file)!="" || subclass->extends_class.size())
  304. line+=" "+_parser_extends(subclass);
  305. line+=":";
  306. _print_indent(p_indent,line);
  307. _parser_show_class(subclass,p_indent+1,p_code);
  308. print_line("\n");
  309. }
  310. for(int i=0;i<p_class->constant_expressions.size();i++) {
  311. const GDParser::ClassNode::Constant &constant=p_class->constant_expressions[i];
  312. _print_indent(p_indent,"const "+String(constant.identifier)+"="+_parser_expr(constant.expression));
  313. }
  314. for(int i=0;i<p_class->variables.size();i++) {
  315. const GDParser::ClassNode::Member &m=p_class->variables[i];
  316. _print_indent(p_indent,"var "+String(m.identifier));
  317. }
  318. print_line("\n");
  319. for(int i=0;i<p_class->static_functions.size();i++) {
  320. _parser_show_function(p_class->static_functions[i],p_indent);
  321. print_line("\n");
  322. }
  323. for(int i=0;i<p_class->functions.size();i++) {
  324. if (String(p_class->functions[i]->name)=="_init") {
  325. _parser_show_function(p_class->functions[i],p_indent,p_class->initializer);
  326. } else
  327. _parser_show_function(p_class->functions[i],p_indent);
  328. print_line("\n");
  329. }
  330. //_parser_show_function(p_class->initializer,p_indent);
  331. print_line("\n");
  332. }
  333. static String _disassemble_addr(const Ref<GDScript>& p_script,const GDFunction& func, int p_addr) {
  334. int addr=p_addr&GDFunction::ADDR_MASK;
  335. switch(p_addr>>GDFunction::ADDR_BITS) {
  336. case GDFunction::ADDR_TYPE_SELF: {
  337. return "self";
  338. } break;
  339. case GDFunction::ADDR_TYPE_CLASS: {
  340. return "class";
  341. } break;
  342. case GDFunction::ADDR_TYPE_MEMBER: {
  343. return "member("+p_script->debug_get_member_by_index(addr)+")";
  344. } break;
  345. case GDFunction::ADDR_TYPE_CLASS_CONSTANT: {
  346. return "class_const("+func.get_global_name(addr)+")";
  347. } break;
  348. case GDFunction::ADDR_TYPE_LOCAL_CONSTANT: {
  349. Variant v=func.get_constant(addr);
  350. String txt;
  351. if (v.get_type()==Variant::STRING || v.get_type()==Variant::NODE_PATH)
  352. txt="\""+String(v)+"\"";
  353. else
  354. txt=v;
  355. return "const("+txt+")";
  356. } break;
  357. case GDFunction::ADDR_TYPE_STACK: {
  358. return "stack("+itos(addr)+")";
  359. } break;
  360. case GDFunction::ADDR_TYPE_STACK_VARIABLE: {
  361. return "var_stack("+itos(addr)+")";
  362. } break;
  363. case GDFunction::ADDR_TYPE_GLOBAL: {
  364. return "global("+func.get_global_name(addr)+")";
  365. } break;
  366. case GDFunction::ADDR_TYPE_NIL: {
  367. return "nil";
  368. } break;
  369. }
  370. return "<err>";
  371. }
  372. static void _disassemble_class(const Ref<GDScript>& p_class,const Vector<String>& p_code) {
  373. const Map<StringName,GDFunction*>& mf = p_class->debug_get_member_functions();
  374. for(const Map<StringName,GDFunction*>::Element *E=mf.front();E;E=E->next()) {
  375. const GDFunction &func=*E->get();
  376. const int *code = func.get_code();
  377. int codelen=func.get_code_size();
  378. String defargs;
  379. if (func.get_default_argument_count()) {
  380. defargs="defarg at: ";
  381. for(int i=0;i<func.get_default_argument_count();i++) {
  382. if (i>0)
  383. defargs+=",";
  384. defargs+=itos(func.get_default_argument_addr(i));
  385. }
  386. defargs+=" ";
  387. }
  388. print_line("== function "+String(func.get_name())+"() :: stack size: "+itos(func.get_max_stack_size())+" "+defargs+"==");
  389. #define DADDR(m_ip) (_disassemble_addr(p_class,func,code[ip+m_ip]))
  390. for(int ip=0;ip<codelen;) {
  391. int incr=0;
  392. String txt=itos(ip)+" ";
  393. switch(code[ip]) {
  394. case GDFunction::OPCODE_OPERATOR: {
  395. int op = code[ip+1];
  396. txt+="op ";
  397. String opname = Variant::get_operator_name(Variant::Operator(op));
  398. txt+=DADDR(4);
  399. txt+=" = ";
  400. txt+=DADDR(2);
  401. txt+=" "+opname+" ";
  402. txt+=DADDR(3);
  403. incr+=5;
  404. } break;
  405. case GDFunction::OPCODE_SET: {
  406. txt+="set ";
  407. txt+=DADDR(1);
  408. txt+="[";
  409. txt+=DADDR(2);
  410. txt+="]=";
  411. txt+=DADDR(3);
  412. incr+=4;
  413. } break;
  414. case GDFunction::OPCODE_GET: {
  415. txt+=" get ";
  416. txt+=DADDR(3);
  417. txt+="=";
  418. txt+=DADDR(1);
  419. txt+="[";
  420. txt+=DADDR(2);
  421. txt+="]";
  422. incr+=4;
  423. } break;
  424. case GDFunction::OPCODE_SET_NAMED: {
  425. txt+=" set_named ";
  426. txt+=DADDR(1);
  427. txt+="[\"";
  428. txt+=func.get_global_name(code[ip+2]);
  429. txt+="\"]=";
  430. txt+=DADDR(3);
  431. incr+=4;
  432. } break;
  433. case GDFunction::OPCODE_GET_NAMED: {
  434. txt+=" get_named ";
  435. txt+=DADDR(3);
  436. txt+="=";
  437. txt+=DADDR(1);
  438. txt+="[\"";
  439. txt+=func.get_global_name(code[ip+2]);
  440. txt+="\"]";
  441. incr+=4;
  442. } break;
  443. case GDFunction::OPCODE_SET_MEMBER: {
  444. txt+=" set_member ";
  445. txt+="[\"";
  446. txt+=func.get_global_name(code[ip+1]);
  447. txt+="\"]=";
  448. txt+=DADDR(2);
  449. incr+=3;
  450. } break;
  451. case GDFunction::OPCODE_GET_MEMBER: {
  452. txt+=" get_member ";
  453. txt+=DADDR(2);
  454. txt+="=";
  455. txt+="[\"";
  456. txt+=func.get_global_name(code[ip+1]);
  457. txt+="\"]";
  458. incr+=3;
  459. } break;
  460. case GDFunction::OPCODE_ASSIGN: {
  461. txt+=" assign ";
  462. txt+=DADDR(1);
  463. txt+="=";
  464. txt+=DADDR(2);
  465. incr+=3;
  466. } break;
  467. case GDFunction::OPCODE_ASSIGN_TRUE: {
  468. txt+=" assign ";
  469. txt+=DADDR(1);
  470. txt+="= true";
  471. incr+=2;
  472. } break;
  473. case GDFunction::OPCODE_ASSIGN_FALSE: {
  474. txt+=" assign ";
  475. txt+=DADDR(1);
  476. txt+="= false";
  477. incr+=2;
  478. } break;
  479. case GDFunction::OPCODE_CONSTRUCT: {
  480. Variant::Type t=Variant::Type(code[ip+1]);
  481. int argc=code[ip+2];
  482. txt+=" construct ";
  483. txt+=DADDR(3+argc);
  484. txt+=" = ";
  485. txt+=Variant::get_type_name(t)+"(";
  486. for(int i=0;i<argc;i++) {
  487. if (i>0)
  488. txt+=", ";
  489. txt+=DADDR(i+3);
  490. }
  491. txt+=")";
  492. incr=4+argc;
  493. } break;
  494. case GDFunction::OPCODE_CONSTRUCT_ARRAY: {
  495. int argc=code[ip+1];
  496. txt+=" make_array ";
  497. txt+=DADDR(2+argc);
  498. txt+=" = [ ";
  499. for(int i=0;i<argc;i++) {
  500. if (i>0)
  501. txt+=", ";
  502. txt+=DADDR(2+i);
  503. }
  504. txt+="]";
  505. incr+=3+argc;
  506. } break;
  507. case GDFunction::OPCODE_CONSTRUCT_DICTIONARY: {
  508. int argc=code[ip+1];
  509. txt+=" make_dict ";
  510. txt+=DADDR(2+argc*2);
  511. txt+=" = { ";
  512. for(int i=0;i<argc;i++) {
  513. if (i>0)
  514. txt+=", ";
  515. txt+=DADDR(2+i*2+0);
  516. txt+=":";
  517. txt+=DADDR(2+i*2+1);
  518. }
  519. txt+="}";
  520. incr+=3+argc*2;
  521. } break;
  522. case GDFunction::OPCODE_CALL:
  523. case GDFunction::OPCODE_CALL_RETURN: {
  524. bool ret=code[ip]==GDFunction::OPCODE_CALL_RETURN;
  525. if (ret)
  526. txt+=" call-ret ";
  527. else
  528. txt+=" call ";
  529. int argc=code[ip+1];
  530. if (ret) {
  531. txt+=DADDR(4+argc)+"=";
  532. }
  533. txt+=DADDR(2)+".";
  534. txt+=String(func.get_global_name(code[ip+3]));
  535. txt+="(";
  536. for(int i=0;i<argc;i++) {
  537. if (i>0)
  538. txt+=", ";
  539. txt+=DADDR(4+i);
  540. }
  541. txt+=")";
  542. incr=5+argc;
  543. } break;
  544. case GDFunction::OPCODE_CALL_BUILT_IN: {
  545. txt+=" call-built-in ";
  546. int argc=code[ip+2];
  547. txt+=DADDR(3+argc)+"=";
  548. txt+=GDFunctions::get_func_name(GDFunctions::Function(code[ip+1]));
  549. txt+="(";
  550. for(int i=0;i<argc;i++) {
  551. if (i>0)
  552. txt+=", ";
  553. txt+=DADDR(3+i);
  554. }
  555. txt+=")";
  556. incr=4+argc;
  557. } break;
  558. case GDFunction::OPCODE_CALL_SELF_BASE: {
  559. txt+=" call-self-base ";
  560. int argc=code[ip+2];
  561. txt+=DADDR(3+argc)+"=";
  562. txt+=func.get_global_name(code[ip+1]);
  563. txt+="(";
  564. for(int i=0;i<argc;i++) {
  565. if (i>0)
  566. txt+=", ";
  567. txt+=DADDR(3+i);
  568. }
  569. txt+=")";
  570. incr=4+argc;
  571. } break;
  572. case GDFunction::OPCODE_YIELD: {
  573. txt+=" yield ";
  574. incr=1;
  575. } break;
  576. case GDFunction::OPCODE_YIELD_SIGNAL: {
  577. txt+=" yield_signal ";
  578. txt+=DADDR(1);
  579. txt+=",";
  580. txt+=DADDR(2);
  581. incr=3;
  582. } break;
  583. case GDFunction::OPCODE_YIELD_RESUME: {
  584. txt+=" yield resume: ";
  585. txt+=DADDR(1);
  586. incr=2;
  587. } break;
  588. case GDFunction::OPCODE_JUMP: {
  589. txt+=" jump ";
  590. txt+=itos(code[ip+1]);
  591. incr=2;
  592. } break;
  593. case GDFunction::OPCODE_JUMP_IF: {
  594. txt+=" jump-if ";
  595. txt+=DADDR(1);
  596. txt+=" to ";
  597. txt+=itos(code[ip+2]);
  598. incr=3;
  599. } break;
  600. case GDFunction::OPCODE_JUMP_IF_NOT: {
  601. txt+=" jump-if-not ";
  602. txt+=DADDR(1);
  603. txt+=" to ";
  604. txt+=itos(code[ip+2]);
  605. incr=3;
  606. } break;
  607. case GDFunction::OPCODE_JUMP_TO_DEF_ARGUMENT: {
  608. txt+=" jump-to-default-argument ";
  609. incr=1;
  610. } break;
  611. case GDFunction::OPCODE_RETURN: {
  612. txt+=" return ";
  613. txt+=DADDR(1);
  614. incr=2;
  615. } break;
  616. case GDFunction::OPCODE_ITERATE_BEGIN: {
  617. txt+=" for-init "+DADDR(4)+" in "+DADDR(2)+" counter "+DADDR(1)+" end "+itos(code[ip+3]);
  618. incr+=5;
  619. } break;
  620. case GDFunction::OPCODE_ITERATE: {
  621. txt+=" for-loop "+DADDR(4)+" in "+DADDR(2)+" counter "+DADDR(1)+" end "+itos(code[ip+3]);
  622. incr+=5;
  623. } break;
  624. case GDFunction::OPCODE_LINE: {
  625. int line = code[ip+1]-1;
  626. if (line>=0 && line <p_code.size())
  627. txt="\n"+itos(line+1)+": "+p_code[line]+"\n";
  628. else
  629. txt="";
  630. incr+=2;
  631. } break;
  632. case GDFunction::OPCODE_END: {
  633. txt+=" end";
  634. incr+=1;
  635. } break;
  636. case GDFunction::OPCODE_ASSERT: {
  637. txt+=" assert ";
  638. txt+=DADDR(1);
  639. incr+=2;
  640. } break;
  641. }
  642. if (incr==0) {
  643. ERR_EXPLAIN("unhandled opcode: "+itos(code[ip]));
  644. ERR_BREAK(incr==0);
  645. }
  646. ip+=incr;
  647. if (txt!="")
  648. print_line(txt);
  649. }
  650. }
  651. }
  652. MainLoop* test(TestType p_test) {
  653. List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
  654. if (cmdlargs.empty()) {
  655. //try editor!
  656. return NULL;
  657. }
  658. String test = cmdlargs.back()->get();
  659. FileAccess *fa = FileAccess::open(test,FileAccess::READ);
  660. if (!fa) {
  661. ERR_EXPLAIN("Could not open file: "+test);
  662. ERR_FAIL_V(NULL);
  663. }
  664. Vector<uint8_t> buf;
  665. int flen = fa->get_len();
  666. buf.resize(fa->get_len()+1);
  667. fa->get_buffer(&buf[0],flen);
  668. buf[flen]=0;
  669. String code;
  670. code.parse_utf8((const char*)&buf[0]);
  671. Vector<String> lines;
  672. int last=0;
  673. for(int i=0;i<=code.length();i++) {
  674. if (code[i]=='\n' || code[i]==0) {
  675. lines.push_back(code.substr(last,i-last));
  676. last=i+1;
  677. }
  678. }
  679. if (p_test==TEST_TOKENIZER) {
  680. GDTokenizerText tk;
  681. tk.set_code(code);
  682. int line=-1;
  683. while(tk.get_token()!=GDTokenizer::TK_EOF) {
  684. String text;
  685. if (tk.get_token()==GDTokenizer::TK_IDENTIFIER)
  686. text="'"+tk.get_token_identifier()+"' (identifier)";
  687. else if (tk.get_token()==GDTokenizer::TK_CONSTANT) {
  688. Variant c= tk.get_token_constant();
  689. if (c.get_type()==Variant::STRING)
  690. text="\""+String(c)+"\"";
  691. else
  692. text=c;
  693. text=text+" ("+Variant::get_type_name(c.get_type())+" constant)";
  694. } else if (tk.get_token()==GDTokenizer::TK_ERROR)
  695. text="ERROR: "+tk.get_token_error();
  696. else if (tk.get_token()==GDTokenizer::TK_NEWLINE)
  697. text="newline ("+itos(tk.get_token_line())+") + indent: "+itos(tk.get_token_line_indent());
  698. else if (tk.get_token()==GDTokenizer::TK_BUILT_IN_FUNC)
  699. text="'"+String(GDFunctions::get_func_name(tk.get_token_built_in_func()))+"' (built-in function)";
  700. else
  701. text=tk.get_token_name(tk.get_token());
  702. if (tk.get_token_line()!=line) {
  703. int from=line+1;
  704. line = tk.get_token_line();;
  705. for(int i=from;i<=line;i++) {
  706. int l=i-1;
  707. if (l>=0 && l<lines.size()) {
  708. print_line("\n"+itos(i)+": "+lines[l]+"\n");
  709. }
  710. }
  711. }
  712. print_line("\t("+itos(tk.get_token_column())+"): "+text);
  713. tk.advance();
  714. }
  715. }
  716. if (p_test==TEST_PARSER) {
  717. GDParser parser;
  718. Error err = parser.parse(code);
  719. if (err) {
  720. print_line("Parse Error:\n"+itos(parser.get_error_line())+":"+itos(parser.get_error_column())+":"+parser.get_error());
  721. memdelete(fa);
  722. return NULL;
  723. }
  724. const GDParser::Node* root = parser.get_parse_tree();
  725. ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,NULL);
  726. const GDParser::ClassNode *cnode=static_cast<const GDParser::ClassNode*>(root);
  727. _parser_show_class(cnode,0,lines);
  728. }
  729. if (p_test==TEST_COMPILER) {
  730. GDParser parser;
  731. Error err = parser.parse(code);
  732. if (err) {
  733. print_line("Parse Error:\n"+itos(parser.get_error_line())+":"+itos(parser.get_error_column())+":"+parser.get_error());
  734. memdelete(fa);
  735. return NULL;
  736. }
  737. GDScript *script = memnew( GDScript );
  738. GDCompiler gdc;
  739. err = gdc.compile(&parser,script);
  740. if (err) {
  741. print_line("Compile Error:\n"+itos(gdc.get_error_line())+":"+itos(gdc.get_error_column())+":"+gdc.get_error());
  742. memdelete(script);
  743. return NULL;
  744. }
  745. Ref<GDScript> gds =Ref<GDScript>( script );
  746. Ref<GDScript> current=gds;
  747. while(current.is_valid()) {
  748. print_line("** CLASS **");
  749. _disassemble_class(current,lines);
  750. current=current->get_base();
  751. }
  752. } else if (p_test==TEST_BYTECODE) {
  753. Vector<uint8_t> buf = GDTokenizerBuffer::parse_code_string(code);
  754. String dst = test.get_basename()+".gdc";
  755. FileAccess *fw = FileAccess::open(dst,FileAccess::WRITE);
  756. fw->store_buffer(buf.ptr(),buf.size());
  757. memdelete(fw);
  758. }
  759. #if 0
  760. Parser parser;
  761. Error err = parser.parse(code);
  762. if (err) {
  763. print_line("error:"+itos(parser.get_error_line())+":"+itos(parser.get_error_column())+":"+parser.get_error());
  764. } else {
  765. print_line("Parse O-K!");
  766. }
  767. #endif
  768. memdelete(fa);
  769. return NULL;
  770. }
  771. }
  772. #else
  773. namespace TestGDScript {
  774. MainLoop* test(TestType p_test) {
  775. return NULL;
  776. }
  777. }
  778. #endif