/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package API; import ast.AbstractSyntaxTree; import ast.Node; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * @author Eugenio */ public class Functions { public static Pattern TYPEANDMETHOD = Pattern.compile("\\((?\\w+(\\.\\w+)+)\\)\\.(?\\w+)"); /*Key: Nome da funcao, Val: Tipo da funcao */ protected static HashMap funcoes; /*Key: Nome da funcao, Val: Tipo da funcao */ protected static HashMap> params; /*Key: Nome da funcao, Val: Numero de parametros */ protected static HashMap numparms; /*Key: Nome da funcao, Val: Tipo de retorno */ protected static HashMap> retorno; /*Key: Nome da funcao, Val: escopo */ protected static HashMap escopo; /*Key: Nome da funcao, Val: Node function */ protected static HashMap funcs; public static String FREE = "__FREE__"; public static String NEW = "__NEW__"; protected static Node callTree; protected static Node currentCall; protected static HashMap called; public static void _init() { System.out.println("Inicializando API.Funcao"); funcoes = new HashMap<>(); params = new HashMap<>(); numparms = new HashMap<>(); retorno = new HashMap<>(); escopo = new HashMap<>(); funcs = new HashMap<>(); called = new HashMap<>(); } public static void List() { StringBuilder sb = new StringBuilder(); for (String name : funcs.keySet()) { sb.append("\t" + name + "\n"); } System.out.println("Funcoes:\n" + sb.toString()); } public static void Add(String id, Node func) throws Exception { if (funcs.containsKey(id)) { throw new Exception( String.format("Função ou metodo '%s' definido previamente na linha %s", id, funcs.get(id).Get("line", "") )); } func.Set("public", Base.IsPublic(func.Get("name")) ? "true" : "false"); // System.out.println("Add FUNC:" + id); funcs.put(id, func); // System.out.println("Funcs:" + funcs.keySet()); } public static boolean Defined(String id) throws Exception { if (!funcs.containsKey(id)) { throw new Exception(String.format("A função '%s' não foi definida. Disponiveis '%s'", id, funcs.keySet())); } return funcs.containsKey(id); } public static Node Get(String id) throws Exception { Node n; if (!Defined(id)) { // Se for metodo de uma struct busca por tipos n = DeepGet(id); } else { n = funcs.get(id); } // if (n == null) { // throw new Exception(String.format("Função ou Metodo '%s' não definido", id)); // } return n; } public static Node DeepGet(String id) throws Exception { Matcher matcher = TYPEANDMETHOD.matcher(id); String type = null, method = null; while (matcher.find()) { type = matcher.group("type"); method = matcher.group("method"); break; } Node T = Types.Get(type); // System.out.println("DeepGet:" + type + ":" + method + ":" + T); if (T != null) { Node def; String packageName; for (Node e : T.findAll("type", "class", 1)) { type = e.Get("type"); packageName = type.split("\\.")[0]; // id = packageName + ".method.(" + type + ")." + method; id = "method.(" + type + ")." + method; // System.out.println("Deep:" + id); def = Get(id); if (def != null) { return def; } } } return null; } // Metodos antigos public static boolean setCurrentCall(String function) { Node n = new Node(function); boolean _continue = true; if (!called.containsKey(function)) { called.put(function, 0); } else { called.put(function, called.get(function) + 1); _continue = false; } if (currentCall != null) { currentCall.addFilho(n); } currentCall = n; return _continue; } public static void returnCallLevel() { if (currentCall.parent != null) { String longid = currentCall.getText(); if (currentCall.closest(longid, "value") != null) { currentCall.Set("recursive", "t"); } currentCall.Set("multi_calls", called.get(longid)); currentCall = currentCall.parent; } } public static void printCallTree() { if (callTree != null) { System.out.println(callTree.stringfy()); } } public static Node getCallTree() { return callTree; } public static void genCallTree(AbstractSyntaxTree ast) throws Exception { Node main = ast.getMain(); String id = main.getText(); setCurrentCall(id); Node parent; callTree = new Node(id); currentCall = callTree; for (Node call : main.find("stmts").findAll("call", "class")) { System.out.println("GenCallTree:" + call.getText()); parent = call.parent; // genCallTree(findDefinition(parent), parent.Get("longid")); } returnCallLevel(); } // // protected static void genCallTree(Node n, String longid) throws Exception { // // if (n == null) { // throw new Exception("Not found definition to " + longid + " !"); // } // // Node parent; // // if (setCurrentCall(longid)) { // for (Node call : n.find("stmts").findAll(".call", "class")) { // parent = call.parent; // genCallTree(findDefinition(parent), parent.Get("longid")); // } // } // // returnCallLevel(); // // } // protected static Node findDefinition(Node call) { // String longid = call.Get("longid"); // // switch (call.Get("class")) { // case "function::call": // System.out.println("longid:" + longid); // return Functions.function(longid); // default: // return Methods.function(longid); // } // } /** * Adiciona uma nova função a linguagem * * @param nome da funcao * @param tipoRetorno tipo do retorno da funcao * @param paramsList liSta de parametroS com tipo * @param escopo eScopo em que função foi declarada * @param func */ public static void add(String nome, HashMap tipoRetorno, HashMap paramsList, String escopo, Node func) { funcoes.put(nome, 1); retorno.put(nome, tipoRetorno); funcs.put(nome, func); params(nome, paramsList); escopo(nome, escopo); } /** * RegiStra uma definicao de uma função O nome deve Ser doS SeguinteS * formatoS
* -- funcname correSponde ao id da funcao
* * {funcname}() // CorreSponde a funcoeS definidaS no pacote local
* {package}.{funcname}() // CorreSponde a funcoeS importadaS de outroS * pacoteS
* {package}.{method}.{type}.{funcname}() //Corresponde a metodos de um tipo * * @param nome * @param func */ public static void add(String nome, Node func) { funcs.put(nome, func); // escopo(nome, escopo); } // /** // * Adiciona uma nova função a linguagem // * // * @param nome da funcao // * @param tipoRetorno tipo do retorno da funcao // * @param escopo escopo em que função foi declarada // * @throws Exception // */ // public static void add(String nome, String tipoRetorno, String escopo) { // HashMap paramsList = new HashMap<>(); // add(nome, tipoRetorno, paramsList, escopo); // numParams(nome, -1); // } public static boolean existe(String nome) { return funcoes.containsKey(nome); } public static HashMap retorno(String nome) { return (existe(nome)) ? retorno.get(nome) : null; } protected static int numParams(String nome, int num) { if (existe(nome)) { numparms.put(nome, num); return num; } return -1; } public static int numParams(String nome) { return (existe(nome)) ? params.get(nome).size() : -1; } public static HashMap params(String nome) { return existe(nome) ? params.get(nome) : null; } public static void params(String nome, HashMap paramsList) { if (existe(nome)) { params.put(nome, paramsList); numParams(nome, paramsList.size()); } } public static void escopo(String nome, String escpo) { if (existe(nome)) { escopo.put(nome, escpo); } } public static String escopo(String nome) { return existe(nome) ? escopo.get(nome) : ""; } public static String toString(String nome) { existe(nome); String params = ""; for (Map.Entry entry : Functions.params.get(nome).entrySet()) { String varNome = entry.getKey(); String tipo = entry.getValue(); params += tipo + "," + varNome + ";"; } return "Nome[" + funcoes.get(nome) + "]numParametros[" + numParams(nome) + "]params[" + params + "]return[" + retorno(nome) + "]"; } public static Node function(String nome) { // System.out.println("Functions:" + funcs.keySet()); return (existe(nome)) ? funcs.get(nome) : null; } // public static String retornoPonteiro(String nome) { // return (existe(nome)) // ? (funcs.Get(nome).eq("ponteiro", "true") ? "true" : "false") // : "false"; // } // public static Node GetDef(String text) { // throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. // } }