Variables.java 21 KB

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