// Copiado do analisador semântico // TODO: refatorar... int jvmcodegen::compute_type(const ast::node_ptr &expr) { switch (expr->type) { case ast::call_node: { auto curr_scope = m_stack.top(); auto sym = curr_scope->get(ast::to_call(expr)->name); if (!sym.is_valid()) return -1; return sym.type & ~types::function; } case ast::variable_node: { auto curr_scope = m_stack.top(); auto sym = curr_scope->get(ast::to_variable(expr)->name); if (!sym.is_valid()) return -1; return sym.type; } case ast::integer_node: return types::integer; case ast::string_node: return types::string; case ast::type_node: return ast::to_type(expr)->type_id; case ast::op_logical_node: { auto op = ast::to_op_logical(expr); int lhs_type = compute_type(op->left); int rhs_type = compute_type(op->right); if (lhs_type == types::integer && rhs_type == types::integer) return types::integer; return -1; } case ast::op_arithm_node: { auto op = ast::to_op_arithm(expr); int lhs_type = compute_type(op->left); int rhs_type = compute_type(op->right); if (lhs_type == types::integer && rhs_type == types::integer) return types::integer; return -1; } default: return -1; } }
bool ClassContainer::read_type(UmlTypeSpec & typespec, Class ** cl) { QCString s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } compute_type(s, typespec, cl); return TRUE; }
void jvmcodegen::gen_write_stmt(const ast::node_ptr &node) { auto write = ast::to_write_stmt(node); m_out << fmt::sprintf("getstatic java/lang/System/out Ljava/io/PrintStream;\n"); int type = compute_type(write->expr); gen_node(write->expr); if (type == types::string) { m_out << fmt::sprintf("invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V\n"); } else if (type == types::integer) { m_out << fmt::sprintf("invokevirtual java/io/PrintStream/print(I)V\n"); } }
void jvmcodegen::gen_return_stmt(const ast::node_ptr &node) { auto ret = ast::to_return_stmt(node); gen_node(ret->expr); int type = compute_type(ret->expr); if (type == types::integer) { m_out << fmt::sprintf("ireturn\n"); } else if (type == types::voidt) { m_out << fmt::sprintf("return\n"); } else if (type == types::string) { m_out << fmt::sprintf("areturn\n"); } }
// Of what type is this field? ciType* type() { return (_type == NULL) ? compute_type() : _type; }
/* Parse the FORMAT string and populate the specification array stored at the address ARGSPECS_ADDR. The caller has provided enough space to store up to MAX_ARGSPECS in that buffer. The function may however ignore the provided buffer and malloc a larger one. On success the addrrss of that larger buffer will be stored at ARGSPECS_ADDR. The actual number of specifications will be returned at R_ARGSPECS_COUNT. */ static int parse_format (const char *format, argspec_t *argspecs_addr, size_t max_argspecs, size_t *r_argspecs_count) { const char *s; argspec_t argspecs = *argspecs_addr; argspec_t arg; size_t argcount = 0; if (!format) goto leave_einval; for (; *format; format++) { unsigned int flags; int width, precision; lenmod_t lenmod; conspec_t conspec; int arg_pos, width_pos, precision_pos; if (*format != '%') continue; s = ++format; if (!*s) goto leave_einval; if (*s == '%') continue; /* Just a quoted percent. */ /* First check whether there is a positional argument. */ arg_pos = 0; /* No positional argument given. */ if (*s >= '1' && *s <= '9') { const char *save_s = s; arg_pos = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) arg_pos = 10*arg_pos + (*s - '0'); if (arg_pos < 0) goto leave_einval; /* Overflow during conversion. */ if (*s == '$') s++; else { arg_pos = 0; s = save_s; } } /* Parse the flags. */ flags = 0; for ( ; *s; s++) { switch (*s) { case '\'': flags |= FLAG_GROUPING; break; case '-': flags |= FLAG_LEFT_JUST; break; case '+': flags |= FLAG_PLUS_SIGN; break; case ' ': flags |= FLAG_SPACE_PLUS; break; case '#': flags |= FLAG_ALT_CONV; break; case '0': flags |= FLAG_ZERO_PAD; break; default: goto flags_parsed; } } flags_parsed: /* Parse the field width. */ width_pos = 0; if (*s == '*') { width = STAR_FIELD_VALUE; s++; /* If we have a positional argument, another one might also be used to give the position of the star's value. */ if (arg_pos && *s >= '1' && *s <= '9') { width_pos = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) width_pos = 10*width_pos + (*s - '0'); if (width_pos < 1) goto leave_einval; /* Overflow during conversion. */ if (*s != '$') goto leave_einval; /* Not followed by $. */ s++; } } else if ( *s >= '0' && *s <= '9') { width = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) { if (!width && *s == '0') goto leave_einval; /* Leading zeroes are not allowed. Fixme: check what other implementations do. */ width = 10*width + (*s - '0'); } if (width < 0) goto leave_einval; /* Overflow during conversion. */ } else width = NO_FIELD_VALUE; /* Parse the precision. */ precision_pos = 0; precision = NO_FIELD_VALUE; if (*s == '.') { int ignore_value = (s[1] == '-'); s++; if (*s == '*') { precision = STAR_FIELD_VALUE; s++; /* If we have a positional argument, another one might also be used to give the position of the star's value. */ if (arg_pos && *s >= '1' && *s <= '9') { precision_pos = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) precision_pos = 10*precision_pos + (*s - '0'); if (precision_pos < 1) goto leave_einval; /* Overflow during conversion. */ if (*s != '$') goto leave_einval; /* Not followed by $. */ s++; } } else if ( *s >= '0' && *s <= '9') { precision = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) { if (!precision && *s == '0') goto leave_einval; /* Leading zeroes are not allowed. Fixme: check what other implementations do. */ precision = 10*precision + (*s - '0'); } if (precision < 0) goto leave_einval; /* Overflow during conversion. */ } else precision = 0; if (ignore_value) precision = NO_FIELD_VALUE; } /* Parse the length modifiers. */ switch (*s) { case 'h': if (s[1] == 'h') { lenmod = LENMOD_CHAR; s++; } else lenmod = LENMOD_SHORT; s++; break; case 'l': if (s[1] == 'l') { lenmod = LENMOD_LONGLONG; s++; } else lenmod = LENMOD_LONG; s++; break; case 'j': lenmod = LENMOD_INTMAX; s++; break; case 'z': lenmod = LENMOD_SIZET; s++; break; case 't': lenmod = LENMOD_PTRDIFF; s++; break; case 'L': lenmod = LENMOD_LONGDBL; s++; break; default: lenmod = LENMOD_NONE; break; } /* Parse the conversion specifier. */ switch (*s) { case 'd': case 'i': conspec = CONSPEC_DECIMAL; break; case 'o': conspec = CONSPEC_OCTAL; break; case 'u': conspec = CONSPEC_UNSIGNED; break; case 'x': conspec = CONSPEC_HEX; break; case 'X': conspec = CONSPEC_HEX_UP; break; case 'f': conspec = CONSPEC_FLOAT; break; case 'F': conspec = CONSPEC_FLOAT_UP; break; case 'e': conspec = CONSPEC_EXP; break; case 'E': conspec = CONSPEC_EXP_UP; break; case 'g': conspec = CONSPEC_F_OR_G; break; case 'G': conspec = CONSPEC_F_OR_G_UP; break; case 'a': conspec = CONSPEC_HEX_EXP; break; case 'A': conspec = CONSPEC_HEX_EXP_UP; break; case 'c': conspec = CONSPEC_CHAR; break; case 's': conspec = CONSPEC_STRING; break; case 'p': conspec = CONSPEC_POINTER; break; case 'n': conspec = CONSPEC_BYTES_SO_FAR; break; case 'C': conspec = CONSPEC_CHAR; lenmod = LENMOD_LONG; break; case 'S': conspec = CONSPEC_STRING; lenmod = LENMOD_LONG; break; case 'm': conspec = CONSPEC_STRERROR; arg_pos = -1; break; default: conspec = CONSPEC_UNKNOWN; } /* Save the args. */ if (argcount >= max_argspecs) { /* We either need to allocate a new array instead of the caller provided one or realloc the array. Instead of using realloc we allocate a new one and release the original one then. */ size_t n, newmax; argspec_t newarg; newmax = max_argspecs + ARGSPECS_BUMP_VALUE; if (newmax <= max_argspecs) goto leave_einval; /* Too many arguments. */ newarg = calloc (newmax, sizeof *newarg); if (!newarg) goto leave; for (n=0; n < argcount; n++) newarg[n] = argspecs[n]; if (argspecs != *argspecs_addr) free (argspecs); argspecs = newarg; max_argspecs = newmax; } arg = argspecs + argcount; arg->length = s - format + 2; arg->flags = flags; arg->width = width; arg->precision = precision; arg->lenmod = lenmod; arg->conspec = conspec; arg->arg_pos = arg_pos; arg->width_pos = width_pos; arg->precision_pos = precision_pos; compute_type (arg); argcount++; format = s; } *argspecs_addr = argspecs; *r_argspecs_count = argcount; return 0; /* Success. */ leave_einval: errno = EINVAL; leave: if (argspecs != *argspecs_addr) free (argspecs); *argspecs_addr = NULL; return -1; }
bool ClassContainer::read_type(UmlTypeSpec & typespec, Class ** cl, const QValueList<FormalParameterList> & tmplts, QValueList<UmlTypeSpec> * actuals, QCString & str_actuals, QCString s, UmlClass ** first_actual_class, QCString & def, QCString & genericname) { str_actuals = 0; if (actuals != 0) actuals->clear(); if (s.isEmpty() && (s = Lex::read_word()).isEmpty()) { Lex::premature_eof(); return FALSE; } QCString path; // type without <..> QCString type; // real type form bool internal_template = FALSE; // true if type is ...<...>... int pfixdef_length = 0; // generic form including first class int first_actual_class_length = 0; // first class's name length genericname = s; for (;;) { internal_template = (path != type); path += s; type += s; s = Lex::read_word(); if (s != "<") break; type += s; str_actuals = s; // read <...> do { Lex::mark(); int level = 0; QCString firstword; // first element in current actual int pfixlen = 0; // type length including firstword for (;;) { s = Lex::read_word(TRUE); if (s == ",") { if (level == 0) break; } else if (s == ">") { if (level-- == 0) break; } else if (s == "]") level -= 1; else if ((s == "<") || (s == "[")) level += 1; else if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } else if (firstword.isEmpty()) { firstword = s; pfixlen = type.length() + Lex::region().length(); } } QCString e = Lex::region(); type += e; str_actuals += e; if (actuals != 0) { UmlTypeSpec t; e.resize(e.length()); // remove , or > e = e.stripWhiteSpace(); if (! e.isEmpty()) compute_type(e, t, tmplts); if (actuals != 0) actuals->append(t); } else if ((first_actual_class != 0) && (*first_actual_class == 0) && !firstword.isEmpty()) { UmlTypeSpec t; compute_type(firstword, t, tmplts); if (t.type != 0) { *first_actual_class = t.type; first_actual_class_length = firstword.length(); pfixdef_length = pfixlen - first_actual_class_length; } } } while (s == ","); s = Lex::read_word(); if (s.isEmpty() || (*s != '.')) break; str_actuals = 0; if (actuals != 0) actuals->clear(); } if (! s.isEmpty()) Lex::unread_word(s); compute_type(path, typespec, tmplts, cl); if (typespec.type != 0) { if (internal_template) // typespec.type stay unchanged typespec.explicit_type = type; } else if ((first_actual_class != 0) && (*first_actual_class != 0)) { def = type.left(pfixdef_length) + "${type}" + type.mid(pfixdef_length+first_actual_class_length); } else // path may be not good typespec.explicit_type = type; return TRUE; }