Variables.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. /*
  2. * To change this license header, choose License Headers in Project Properties.
  3. * To change this template file, choose Tools | Templates
  4. * and open the template in the editor.
  5. */
  6. package API;
  7. import ast.Node;
  8. import common.Instruction;
  9. import java.util.ArrayList;
  10. import java.util.Arrays;
  11. import java.util.HashMap;
  12. import java.util.List;
  13. import java.util.Map;
  14. import java.util.regex.Matcher;
  15. import java.util.regex.Pattern;
  16. /**
  17. *
  18. * @author Eugenio
  19. */
  20. public class Variables {
  21. public static Integer indexCount = 0;
  22. public static HashMap<String, Node> vars;
  23. public static HashMap<String, Instruction> scopes;
  24. public static String UNDEFINED = "undefined";
  25. public static String currentKey;
  26. public static Pattern BASEVEXPR = Pattern.compile("(\\w+(\\.@\\w+)*\\.\\w+)");
  27. public static String CLEARBASEVAR = "(\\w+)(\\.@\\w+)*(\\.)";
  28. public static String SCOPE_LEVE = "(\\.@\\w+)((\\.\\w)*)";
  29. public static String VARNAME = "(\\.\\w*)+";
  30. public static void _init() {
  31. vars = new HashMap<>();
  32. scopes = new HashMap<>();
  33. }
  34. public static void Add(String id, Node var) throws Exception {
  35. // System.out.println("AddVar:" + id + "\n" + var);
  36. if (vars.containsKey(id)) {
  37. String[] parts = id.split("\\.");
  38. throw new Exception("'" + parts[parts.length - 1] + "' previamente declarado em na linha " + vars.get(id).Get("line", ""));
  39. // throw new Exception("'" + id + "' previamente declarado em na linha " + vars.Get(id).Get("line", ""));
  40. }
  41. var.Set("public", Base.IsPublic(var.Get("name")) ? "true" : "false");
  42. // System.out.println("Add var:" + var.Get("name"));
  43. vars.put(id, var);
  44. }
  45. public static boolean Defined(String id) {
  46. return Defined(id, true);
  47. }
  48. public static boolean Defined(String id, boolean clear) {
  49. if (clear) {
  50. id = BaseVar(id);
  51. }
  52. // System.out.println("Defined:"+id+":"+vars.containsKey(id));
  53. return vars.containsKey(id);
  54. }
  55. public static String BaseVar(String id) {
  56. Matcher match = BASEVEXPR.matcher(id);
  57. while (match.find()) {
  58. return match.group(1);
  59. }
  60. return id;
  61. }
  62. public static String TypeOf(String varname) throws Exception {
  63. // System.out.println("Type of " + varname);
  64. Node var = Get(varname);
  65. Node tmp, t;
  66. String type = "undefined";
  67. // System.out.println("Type:" + varname + " var: " + var);
  68. if (var != null) {
  69. // System.out.println("TypeOf:\n" + varname + "\n" + var + "\n" + var.contem("scope", "."));
  70. String path;
  71. if (var.contem("scope", ".")) {
  72. path = varname.replace(var.Get("fullname"), "");
  73. } else {
  74. ArrayList<String> parts = new ArrayList<>();
  75. for (String s : var.Get("fullname").split("\\.")) {
  76. parts.add(s);
  77. }
  78. parts.add(1, "(\\.@\\w+)+\\.");
  79. // System.out.println("PARTS:" + Utils.Join(parts, ""));
  80. path = varname.replaceFirst(Utils.Join(parts, ""), "");
  81. }
  82. // System.out.println("path:" + var.Get("fullname") + "---" + path);
  83. // Sem path
  84. if (path.length() > 0) {
  85. ArrayList<String> parts = new ArrayList<>(Arrays.asList(path.split("\\.")));
  86. parts.remove(0); // Remove a primaira parte que é uma string vazia
  87. String typed = var.Get("type"), attr;
  88. t = Types.Get(typed);
  89. while (parts.size() > 0) {
  90. if (Types.Primitive(typed)) {
  91. return typed;
  92. }
  93. if (t == null) {
  94. throw new Exception(String.format("Tipo '%s' não definido", typed));
  95. }
  96. attr = parts.remove(0);
  97. tmp = t.find(attr);
  98. if (tmp == null) {
  99. throw new Exception(String.format("Tipo '%s' não possui o atributo '%s'", typed, attr));
  100. }
  101. typed = tmp.find("type").Get("type");
  102. t = Types.Get(typed);
  103. }
  104. // System.out.println("Type:" + t + type);
  105. type = t.Get("type");
  106. } else {
  107. type = var.Get("type");
  108. }
  109. }
  110. // System.out.println("Type of:" + varname + ":" + type);
  111. return type;
  112. }
  113. public static Node Get(String id) {
  114. // System.out.println("Get VAR:" + id);
  115. String x = id;
  116. id = BaseVar(id);
  117. // System.out.println("Get:" + id + "=" + x);
  118. if (Defined(id, false)) {
  119. // System.out.println("##################### Var defined:" + id);
  120. return vars.get(id);
  121. }
  122. List<String> items = Arrays.asList(id.split("\\."));
  123. // Minima representacao de uma variavel sendo o pacote e o id
  124. if (items.size() <= 2) {
  125. return null;
  126. }
  127. List<String> parts = items.subList(0, items.size() - 2);
  128. parts = new ArrayList<>(parts);
  129. parts.add(items.get(items.size() - 1));
  130. // System.out.println("Get ID:" + Utils.Join(parts, "."));
  131. return Get(Utils.Join(parts, "."));
  132. }
  133. /**
  134. * Metodos antigos
  135. */
  136. /**
  137. * Adiciona uma variavel em um eScopo
  138. *
  139. * @param name
  140. * @param type
  141. * @param scope
  142. * @param array
  143. */
  144. public static void add(String name, String type, String scope, Node n) {
  145. String key = name + ":" + scope;
  146. vars.put(key, n);
  147. if (!scopes.containsKey(scope)) {
  148. scopes.put(scope, new Instruction());
  149. }
  150. scopes.get(scope).Set(name, type);
  151. }
  152. public static String type(String id, String scope) {
  153. if (exist(id, scope)) {
  154. return vars.get(currentKey).Get("type");
  155. }
  156. return UNDEFINED;
  157. }
  158. /**
  159. * Retorna true Se uma variavel é aceSSivel de um determinado eScopo.
  160. *
  161. * @param name
  162. * @param scope
  163. * @return
  164. */
  165. public static boolean accessible(String name, String scope) {
  166. return type(name, scope) != UNDEFINED;
  167. }
  168. /**
  169. * Verifica Se uma variavel foi declarada em um determinado eScopo
  170. *
  171. * @param name
  172. * @param scope
  173. * @return
  174. */
  175. public static boolean exist(String name, String scope) {
  176. String key = name + ":" + scope;
  177. if (vars.containsKey(key)) {
  178. currentKey = key;
  179. return true;
  180. }
  181. String[] path = scope.split(",", 2);
  182. if (path.length == 2) {
  183. return exist(name, path[1]);
  184. }
  185. key = name + ":" + path[0];
  186. if (vars.containsKey(key)) {
  187. currentKey = key;
  188. return true;
  189. }
  190. return false;
  191. }
  192. /**
  193. * Verifica Se uma variavel foi declarada por meio do no da AST
  194. *
  195. * @param nome
  196. * @param escopo
  197. * @return
  198. */
  199. public static boolean exist(Node var) {
  200. return exist(var.getText(), var.Get("scope"));
  201. }
  202. public static Node get(Node n) {
  203. return exist(n) ? vars.get(currentKey) : null;
  204. }
  205. public static Node get(String name, String scope) {
  206. return exist(name, scope) ? vars.get(currentKey) : null;
  207. }
  208. public static String printScope(String scope) {
  209. if (!scopes.containsKey(scope)) {
  210. return "Scope " + scope + " não definido!";
  211. }
  212. return "Scope{" + scope + "}\n" + scopes.get(scope);
  213. }
  214. /**
  215. *
  216. * DAQUI PRA CIMA O RESTO APAGA
  217. *
  218. *
  219. */
  220. /**
  221. * Verifica Se uma dada variavel é um array
  222. *
  223. * @param varname
  224. * @return
  225. */
  226. public static boolean isArray(String varname) {
  227. return (varname.lastIndexOf("[") >= 0);
  228. }
  229. public static String clearName(String nome) {
  230. return nome.split("\\[")[0].replace("&", "");
  231. }
  232. // /**
  233. // * Retorna uma variavel em um dado escopo do programa
  234. // *
  235. // * @param nome nome da variavel
  236. // * @param escopo escopo da variavel (onde foi declarada)
  237. // * @return Node | null
  238. // * @throws Exception
  239. // */
  240. // public static Node var(String nome, String escopo) {
  241. // existe(nome, escopo);
  242. // return varsNodes.Get(index.Get(baseName(nome) + ":" + escopo));
  243. //
  244. // }
  245. //
  246. // /**
  247. // * Adiciona uma variavel em um dado escopo do programa
  248. // *
  249. // * @param nome nome da variavel
  250. // * @param escopo escopo da variavel (onde foi declarada)
  251. // * @param var no com todos os dados da variavel
  252. // * @throws Exception
  253. // */
  254. // public static void var(String nome, String escopo, Node var) {
  255. // existe(nome, escopo);
  256. // varsNodes.put(index.Get(baseName(nome) + ":" + escopo), var);
  257. // }
  258. //
  259. // public static String tipo(Node variavel) {
  260. // return tipo(variavel.Get("value"), variavel.Get("escopo"));
  261. // }
  262. // public static String tipo(String nome, String escopo) {
  263. // nome = baseName(nome);
  264. // try {
  265. // existe(nome, escopo);
  266. // return types.Get(index.Get(nome + ":" + escopo));
  267. // } catch (Exception e) {
  268. // return _tipo(nome, escopo);
  269. // }
  270. // }
  271. // protected static String _tipo(String nome, String escopo) {
  272. // nome = baseName(nome);
  273. // try {
  274. // String[] escopos = escopo.split(",", 2);
  275. // if (escopos.length == 2) {
  276. // return tipo(nome, escopos[1]);
  277. // }
  278. // existe(nome, escopos[0]);
  279. // return types.Get(index.Get(nome + ":" + escopos[0]));
  280. // } catch (Exception e) {
  281. // return null;
  282. // }
  283. // }
  284. // /**
  285. // * Retorna uma variavel do escopo, caso não a encontre vai buscar no escopo
  286. // * pai. Se chegar ao no root e não encontrar a variavel, será retornado o
  287. // * valor null.
  288. // *
  289. // * @param nome
  290. // * @param escopo
  291. // * @return
  292. // */
  293. // public static Node find(Node variavel) {
  294. // if (variavel == null) {
  295. // return null;
  296. // }
  297. // return find(variavel.getText(), variavel.Get("escopo"));
  298. // }
  299. //
  300. // /**
  301. // * Retorna uma variavel do escopo, caso não a encontre vai buscar no escopo
  302. // * pai. Se chegar ao no root e não encontrar a variavel, será retornado o
  303. // * valor null.
  304. // *
  305. // * @param nome
  306. // * @param escopo
  307. // * @return
  308. // */
  309. // public static Node find(String nome, String escopo) {
  310. // nome = baseName(nome);
  311. // return existe(nome, escopo)
  312. // ? varsNodes.Get(index.Get(nome + ":" + escopo))
  313. // : _find(nome, escopo);
  314. // }
  315. // /**
  316. // * Auxiliar do metodo find
  317. // *
  318. // * @param nome
  319. // * @param escopo
  320. // * @return
  321. // */
  322. // protected static Node _find(String nome, String escopo) {
  323. // nome = baseName(nome);
  324. // String[] escopos = escopo.split(",", 2);
  325. // if (escopos.length == 2) {
  326. // return find(nome, escopos[1]);
  327. // }
  328. // return existe(nome, escopos[0])
  329. // ? varsNodes.Get(index.Get(nome + ":" + escopos[0]))
  330. // : null;
  331. // }
  332. // /**
  333. // * Retorna o escopo onde a variavel foi declarada.
  334. // *
  335. // * @param nome
  336. // * @param escopo
  337. // * @return
  338. // */
  339. // public static String declaracao(String nome, String escopo) {
  340. // nome = baseName(nome);
  341. // try {
  342. // existe(nome, escopo);
  343. // return escopo;
  344. // } catch (Exception e) {
  345. // return _declaracao(nome, escopo);
  346. // }
  347. // }
  348. //
  349. // /**
  350. // * Auxiliar do metodo declaracao.
  351. // *
  352. // * @param nome
  353. // * @param escopo
  354. // * @return
  355. // */
  356. // protected static String _declaracao(String nome, String escopo) {
  357. // nome = baseName(nome);
  358. // try {
  359. // String[] escopos = escopo.split(",", 2);
  360. // if (escopos.length == 2) {
  361. // return declaracao(nome, escopos[1]);
  362. // }
  363. // existe(nome, escopos[0]);
  364. // return escopos[0];
  365. // } catch (Exception e) {
  366. // return null;
  367. // }
  368. // }
  369. // public static void var(int cod, Node var) {
  370. // varsNodes.put(cod, var);
  371. // }
  372. public static String baseName(String text) {
  373. return clearName(text).split("\\.")[0];
  374. }
  375. public static void print() {
  376. String str = "Variaveis\n";
  377. for (Map.Entry<String, Node> entry : vars.entrySet()) {
  378. String varKey = entry.getKey();
  379. Node value = entry.getValue();
  380. str += "\n" + value;
  381. }
  382. System.out.println(str);
  383. }
  384. // /**
  385. // * Testa ocorrencia de uma variavel, verifica se a mesma existe e se o tipo
  386. // * corresponde com o esperado.
  387. // *
  388. // * @param current
  389. // * @param tipoEsperado
  390. // */
  391. // public static boolean teste(Node current, String tipoEsperado) {
  392. // /*Verifica se existe declaracao da variavel*/
  393. // String varpath = current.getText();
  394. // existe(varpath, current.Get("escopo"));
  395. //
  396. //// if (Types.structAcesso(varpath)) {
  397. //// Types.validarAtribuicao(current);
  398. //// }
  399. // Node var = find(varpath, current.Get("escopo"));
  400. // if (!var.Get("tipo").equals(tipoEsperado)) {
  401. // return false;
  402. // }
  403. // return true;
  404. //
  405. // }
  406. // static String getFullName(Node param) {
  407. // System.out.println("\n\nFULL:" + param);
  408. // String indices = "";
  409. // Node indicesNodes = param.encontre("indices");
  410. // if (null != indicesNodes) {
  411. // for (Node ind : indicesNodes.filhos()) {
  412. // indices += "[" + ind.getText() + "]";
  413. // }
  414. // }
  415. // return param.getText() + indices;
  416. // }
  417. // protected static void verificarIndices(ArrayList<Node> acessoIndices) {
  418. // for (Node indice : acessoIndices) {
  419. // if (!indice.IsNumber("value")) {
  420. // AnalizadorSemantico.testExist(indice);
  421. // }
  422. // }
  423. // }
  424. // public static void acessoMatrixIsValid(Node var) throws Exception {
  425. // String tipoParent = var.parent.Get("tipo");
  426. // String atributo = ivannosysUtils.clearName(var.getText());
  427. // int limit, acesso, i = 0;
  428. //
  429. // Node indices = var.encontre("indices");
  430. //
  431. // /*Caso não seja acessado nenhum indice da matrix return*/
  432. // if (null == indices) {
  433. // return;
  434. // }
  435. //
  436. // ArrayList<Node> acessoIndices = indices.filhos();
  437. //
  438. // verificarIndices(acessoIndices);
  439. //
  440. // /*Se for declaração apenas verifica se indices são corretos*/
  441. // if (var.igual("class", "dec::var")) {
  442. // return;
  443. // }
  444. // /*Se for acesso de uma variavel e possuir indices verificar se os mesmos estao dentro dos limites*/
  445. // ArrayList<String> decIndices;
  446. // boolean isAtributo = var.igual("class", "atributo");
  447. // decIndices = isAtributo
  448. // ? Types.getIndices(var) : Variables.getIndices(var);
  449. // limit = decIndices.size();
  450. // acesso = acessoIndices.size();
  451. //
  452. //// if (acesso < limit) {
  453. //// throw new Exception(Api.getFormatedPosition(var) + " Matriz acesso invalido. "
  454. //// + "Quantidade de indices inferior ao da matriz");
  455. //// } else
  456. //// System.out.println("VAR:" + var.getText() + ",limit:" + limit + ", acesso:" + acesso);
  457. // if (acesso > limit) {
  458. // throw new Exception(Api.getFormatedPosition(var) + " Matriz acesso invalido. "
  459. // + "Quantidade {" + acesso + "} de indices superior ao da matriz {" + limit + "} ");
  460. // }
  461. // if (decIndices.size() != 0) {
  462. // return;
  463. // }
  464. //
  465. // for (Node indice : acessoIndices) {
  466. // if (indice.IsNumber("value")) {
  467. // limit = Integer.parseInt(decIndices.Get(i));
  468. // acesso = indice.GetInt("value");
  469. // if (acesso >= limit || acesso < 0) {
  470. // throw new Exception("Acesso indevido a um array, limite {"
  471. // + (limit - 1) + "} enquanto a tentativa foi {"
  472. // + acesso + "} na posição {" + i + "}");
  473. //
  474. // }
  475. // }
  476. // i++;
  477. // }
  478. //
  479. // Node attr = var.encontreByClass("atributo");
  480. // if (null == attr) {
  481. // return;
  482. // }
  483. // if (!temAtributo(tipoParent, atributo)) {
  484. // throw new Exception(" Acessando atributo [" + atributo + "] não definido no tipo[" + tipoParent + "]");
  485. // }
  486. //
  487. // acessoMatrixIsValid(attr);
  488. //
  489. // }
  490. //
  491. // public static ArrayList<String> getIndices(Node var) {
  492. // Node declaracao = find(var);
  493. // ArrayList<String> indices = new ArrayList<>();
  494. // for (Node n : declaracao.encontre("indices").filhos()) {
  495. // indices.add(n.getText());
  496. // }
  497. // return indices;
  498. // }
  499. //
  500. // public static boolean isMagica(String nome) {
  501. // return nome.matches("__.*__(\\[.*\\])*");
  502. // }
  503. // /**
  504. // * Verfica se todos os indices do acesso são numericos
  505. // *
  506. // * @param var
  507. // * @return
  508. // */
  509. // public static boolean todosIndicesNumericos(Node var) {
  510. // Node indices = var.encontre("indices");
  511. // if (null != indices) {
  512. // for (Node n : indices.filhos()) {
  513. // if (!n.IsNumber("value")) {
  514. // return false;
  515. // }
  516. // }
  517. // }
  518. // Node atributo = var.encontreByClass("atributo");
  519. // return (null != atributo) ? todosIndicesNumericos(atributo) : true;
  520. // }
  521. //
  522. // public static int tamanhoVetor(Node n) throws Exception {
  523. // Node indices = n.encontre("indices");
  524. // int size = 1;
  525. // if (null != indices) {
  526. // for (Node indice : indices.filhos()) {
  527. // size *= indice.GetInt("value");
  528. // }
  529. // }
  530. // return size;
  531. // }
  532. public static void List() {
  533. StringBuilder s = new StringBuilder();
  534. Node v;
  535. String index, constant, Public;
  536. for (String var : vars.keySet()) {
  537. index = "";
  538. constant = "";
  539. v = vars.get(var);
  540. if (v.eq("constant", "true")) {
  541. constant = "constant";
  542. }
  543. Public = v.eq("public", "true") ? "public" : "private";
  544. for (Node i : v.childrens()) {
  545. index += "[" + i.getText() + "]";
  546. }
  547. s.append("\t" + var + ": " + index + v.Get("type") + " [" + Public + " " + constant + "]\n");
  548. }
  549. System.out.println("Vars:\n" + s.toString());
  550. }
  551. public static String Type(String id) {
  552. Node var = Get(id);
  553. if (var == null) {
  554. return "undefined";
  555. }
  556. return var.Get("type");
  557. }
  558. public static int Shift(String id) throws Exception {
  559. Node var = Get(id);
  560. if (var == null) {
  561. return 0;
  562. }
  563. // System.out.println("Var Shift:" + id);
  564. String[] varparts = var.getText().split("\\.");
  565. String varname = varparts[varparts.length - 1];
  566. String[] idparts = id.split(varname + "\\.?");
  567. if (idparts.length == 2) {
  568. ArrayList<String> path = new ArrayList<>(Arrays.asList(idparts[1].split("\\.")));
  569. // System.out.println("shift:" + var.Get("type") + "-" + path);
  570. return Types.Shift(var.Get("type"), path);
  571. }
  572. // Não é acesso a um atributo
  573. return 0;
  574. }
  575. }
  576. // Node attrib = getAtributo(tipoParent, atributo);
  577. // if (attrib.igual("matrix", "false")) {
  578. // throw new Exception("Atributo [" + atributo + "] não é matrix");
  579. // return;
  580. // }
  581. //
  582. // int i = 0, limit, limitCall, acesso;
  583. // ArrayList<Node> tipoIndices = new ArrayList<>();
  584. //
  585. // String atributo = ivannosysUtils.clearName(var.getText());
  586. // boolean eDeclaracao = var.igual("class", "dec::var");
  587. // if (!eDeclaracao) {
  588. //
  589. // if (!temAtributo(tipoParent, atributo)) {
  590. // throw new Exception(" Acessando atributo [" + atributo + "] não definido no tipo[" + tipoParent + "]");
  591. // }
  592. //
  593. // Node attrib = getAtributo(tipoParent, atributo);
  594. //
  595. // if (attrib.igual("matrix", "false")) {
  596. // if (!acessoIndices.isEmpty()) {
  597. // throw new Exception("Atributo [" + atributo + "] não é matrix");
  598. // }
  599. // return;
  600. // }
  601. // tipoIndices = attrib.encontre("indices").getChildrens();
  602. // }
  603. //
  604. // for (Node indice : acessoIndices) {
  605. // if (!indice.eNumerico("value")) {
  606. // AnalizadorSemantico.testExist(indice);
  607. // continue;
  608. // } else if (!eDeclaracao) {
  609. // limit = tipoIndices.Get(i).GetInt("value");
  610. // acesso = indice.GetInt("value");
  611. // if (acesso >= limit || acesso < 0) {
  612. // throw new Exception("Acesso indevido a um array, limite {"
  613. // + (limit - 1) + "} enquanto a tentativa foi {"
  614. // + acesso + "} na posição {" + i + "}");
  615. //
  616. // }
  617. // }
  618. // i++;
  619. // }