Variables.java 21 KB

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