Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions analyze/aps-bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ struct env_item {
};
typedef struct env_item *SCOPE;

static Declaration module_TYPE;
static Declaration module_PHYLUM;
Declaration module_TYPE;
Declaration module_PHYLUM;

static TypeEnvironment current_type_env = 0;

Expand Down
3 changes: 3 additions & 0 deletions analyze/aps-bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ extern int decl_namespaces(Declaration d);
extern int bind_debug;
#define PRAGMA_ACTIVATION 1

extern Declaration module_TYPE;
extern Declaration module_PHYLUM;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two global static variables were originally defined for canonical stuff. So I thought let's reuse them.

#endif
3 changes: 0 additions & 3 deletions analyze/aps-type.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,6 @@ static void* validate_canonicals(void* ignore, void*node) {
return node;
}

static Declaration module_TYPE;
static Declaration module_PHYLUM;

static void* set_root_phylum(void *ignore, void *node)
{
switch (ABSTRACT_APS_tnode_phylum(node))
Expand Down
6 changes: 2 additions & 4 deletions analyze/canonical-signature.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ static CanonicalSignatureSet from_declaration(Declaration decl);
static CanonicalSignatureSet substitute_canonical_signature_set_actuals(CanonicalType* source, CanonicalSignatureSet sig_set);
static int canonical_signature_compare(CanonicalSignature *sig1, CanonicalSignature *sig2);

static Declaration module_TYPE;
static Declaration module_PHYLUM;
static bool initialized = false;

/**
Expand Down Expand Up @@ -352,9 +350,9 @@ static int canonical_signature_compare(CanonicalSignature *sig1, CanonicalSignat
return sig1->is_var - sig2->is_var;
}

if (tnode_line_number(sig1->source_class) != tnode_line_number(sig2->source_class))
if (sig1->source_class != sig2->source_class)
{
return tnode_line_number(sig1->source_class) - tnode_line_number(sig2->source_class);
return (sig1->source_class > sig2->source_class) ? 1 : -1;
}

if (sig1->num_actuals != sig2->num_actuals)
Expand Down
25 changes: 16 additions & 9 deletions analyze/canonical-type.c
Original file line number Diff line number Diff line change
Expand Up @@ -1006,9 +1006,12 @@ CanonicalType *canonical_type_join(CanonicalType *ctype_outer, CanonicalType *ct
* Comparator for two canonical types
* @param ctype1 first canonical type
* @param ctype2 second canonical type
* @param ctype1_mdecl_result Result decl from the source (inherited) module, or NULL
* @param ctype2_mdecl_result Result decl from the target (implementing) module, or NULL
* @return integer value representing the comparison
*/
int canonical_type_compare(CanonicalType *ctype1, CanonicalType *ctype2)
int canonical_type_compare2(CanonicalType *ctype1, CanonicalType *ctype2,
Declaration ctype1_mdecl_result, Declaration ctype2_mdecl_result)
{
if (ctype1->key != ctype2->key)
{
Expand All @@ -1022,19 +1025,23 @@ int canonical_type_compare(CanonicalType *ctype1, CanonicalType *ctype2)
struct Canonical_use_type *canonical_use_type1 = (struct Canonical_use_type *)ctype1;
struct Canonical_use_type *canonical_use_type2 = (struct Canonical_use_type *)ctype2;

return tnode_line_number(canonical_use_type1->decl) - tnode_line_number(canonical_use_type2->decl);
Declaration d1 = (ctype1_mdecl_result != NULL && canonical_use_type1->decl == ctype1_mdecl_result) ? ctype2_mdecl_result : canonical_use_type1->decl;
Declaration d2 = canonical_use_type2->decl;
return (d1 > d2) ? 1 : (d1 < d2) ? -1 : 0;
}
case KEY_CANONICAL_QUAL:
{
struct Canonical_qual_type *canonical_qual_type1 = (struct Canonical_qual_type *)ctype1;
struct Canonical_qual_type *canonical_qual_type2 = (struct Canonical_qual_type *)ctype2;

if (tnode_line_number(canonical_qual_type1->decl) != tnode_line_number(canonical_qual_type2->decl))
Declaration d1 = (ctype1_mdecl_result != NULL && canonical_qual_type1->decl == ctype1_mdecl_result) ? ctype2_mdecl_result : canonical_qual_type1->decl;
Declaration d2 = canonical_qual_type2->decl;
if (d1 != d2)
{
return tnode_line_number(canonical_qual_type1->decl) - tnode_line_number(canonical_qual_type2->decl);
return (d1 > d2) ? 1 : -1;
}

return canonical_type_compare(canonical_qual_type1->source, canonical_qual_type2->source);
return canonical_type_compare2(canonical_qual_type1->source, canonical_qual_type2->source, ctype1_mdecl_result, ctype2_mdecl_result);
}
case KEY_CANONICAL_FUNC:
{
Expand All @@ -1043,10 +1050,10 @@ int canonical_type_compare(CanonicalType *ctype1, CanonicalType *ctype2)

if (canonical_function_type1->num_formals != canonical_function_type2->num_formals)
{
return canonical_function_type1->num_formals - canonical_function_type2->num_formals > 0 ? 1 : -1;
return (canonical_function_type1->num_formals > canonical_function_type2->num_formals) ? 1 : -1;
}

int return_type_comp = canonical_type_compare(canonical_function_type1->return_type, canonical_function_type2->return_type);
int return_type_comp = canonical_type_compare2(canonical_function_type1->return_type, canonical_function_type2->return_type, ctype1_mdecl_result, ctype2_mdecl_result);
if (return_type_comp != 0)
{
return return_type_comp;
Expand All @@ -1055,7 +1062,7 @@ int canonical_type_compare(CanonicalType *ctype1, CanonicalType *ctype2)
int i;
for (i = 0; i < canonical_function_type1->num_formals; i++)
{
int formal_type_comp = canonical_type_compare(canonical_function_type1->param_types[i], canonical_function_type2->param_types[i]);
int formal_type_comp = canonical_type_compare2(canonical_function_type1->param_types[i], canonical_function_type2->param_types[i], ctype1_mdecl_result, ctype2_mdecl_result);
if (formal_type_comp != 0)
{
return formal_type_comp;
Expand All @@ -1065,7 +1072,7 @@ int canonical_type_compare(CanonicalType *ctype1, CanonicalType *ctype2)
return 0;
}
default:
fatal_error("canonical_type_compare failed");
fatal_error("canonical_type_compare2 failed");
return 0;
}
}
22 changes: 19 additions & 3 deletions analyze/canonical-type.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,29 @@ CanonicalType *canonical_type_join(CanonicalType *ctype_outer, CanonicalType *ct
*/
CanonicalType *new_canonical_type_use(Declaration decl);

/**
* Compares two canonical types with Result-decl substitution.
* The inherited module's Result maps to the implementing module's Result.
* @param ctype1 Canonical type to compare
* @param ctype2 Canonical type to compare against
* @param ctype1_mdecl_result Result decl of ctype1's enclosing module
* @param ctype2_mdecl_result Result decl of ctype2's enclosing module
* @return Integer value representing comparison of two canonical types
*/
int canonical_type_compare2(CanonicalType *ctype1, CanonicalType *ctype2,
Declaration ctype1_mdecl_result,
Declaration ctype2_mdecl_result);

/**
* Compares two canonical types
* @param ctype1 Canonical type A
* @param ctype2 Canonical type B
* @param ctype1 Canonical type to compare
* @param ctype2 Canonical type to compare against
* @return Integer value representing comparison of two canonical types
*/
int canonical_type_compare(CanonicalType *ctype1, CanonicalType *ctype2);
static inline int canonical_type_compare(CanonicalType *ctype1, CanonicalType *ctype2)
{
return canonical_type_compare2(ctype1, ctype2, NULL, NULL);
}

/**
* Given a canonical type, it returns a Declaration
Expand Down
119 changes: 114 additions & 5 deletions aps2scala/dump-scala.cc
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ void dump_formal(Declaration formal, ostream&os)
if (KEYseq_formal == Declaration_KEY(formal)) os << "*";
}

void dump_function_prototype(string name, Type ft, bool dump_anchor_actual, ostream& oss)
void dump_function_prototype(string name, Type ft, bool dump_anchor_actual, bool override_needed, ostream& oss)
{
oss << indent() << "val v_" << name << " = f_" << name << " _;\n";
oss << indent() << "def f_" << name << "(";
oss << indent() << (override_needed ? "override " : "") << "val v_" << name << " = f_" << name << " _;\n";
oss << indent() << (override_needed ? "override " : "") << "def f_" << name << "(";

bool started = false;
Declarations formals = function_type_formals(ft);
Expand Down Expand Up @@ -1392,7 +1392,7 @@ static void dump_scala_pattern_function(

if (!body) {
// the constructor function:
dump_function_prototype(name,ft,dump_anchor_actual,oss);
dump_function_prototype(name,ft,dump_anchor_actual,false /* override_needed */,oss);
oss << " = c_" << name << args;
if (is_syntax) oss << ".register";
oss << ";\n";
Expand Down Expand Up @@ -1451,6 +1451,78 @@ void dump_scala_Declaration_header(Declaration decl, ostream& oss)
}
}

// Recursive helper function to check given a surrounding declaration (module_decl, class_decl or type_decl)
// if it contains a function declaration that matches the given name and return type
// if true then override would be needed otherwise not needed
static void type_has_service_function(Declaration decl, Symbol fdecl_name, vector<Declaration>& found_decls) {
switch (Declaration_KEY(decl)) {
case KEYsome_type_decl: {
Type type = some_type_decl_type(decl);
switch (Type_KEY(type))
{
case KEYno_type: {
bool is_phylum = Declaration_KEY(decl) == KEYphylum_decl;
return type_has_service_function(is_phylum ? module_PHYLUM : module_TYPE, fdecl_name, found_decls);
}
case KEYtype_use:
return type_has_service_function(canonical_type_decl(canonical_type(type)), fdecl_name, found_decls);
case KEYtype_inst:
return type_has_service_function(USE_DECL(module_use_use(type_inst_module(type))), fdecl_name, found_decls);
default:
break;
}
}
case KEYsome_class_decl: {
Block body = some_class_decl_contents(decl);
Declaration item;
for (item = first_Declaration(block_body(body)); item != NULL; item = DECL_NEXT(item)) {
switch (Declaration_KEY(item)) {
case KEYsome_function_decl:
if (def_name(some_function_decl_def(item)) == fdecl_name) {
found_decls.push_back(item);
}

break;
default:
break;
}
}

if (decl == module_PHYLUM || decl == module_TYPE) {
return;
} else {
type_has_service_function(some_class_decl_result_type(decl), fdecl_name, found_decls);
}
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite. This should check the rtype, or you might miss something. Let me see if I can create a counter-example, before you change anything. If my guess is right (and it might not be), then the example will miss an override.

default:
break;
}
}

Declaration get_enclosing_some_class_decl(Declaration source) {
void* node = (void*)source;
while (node != NULL) {
switch (ABSTRACT_APS_tnode_phylum(node)) {
case KEYDeclaration: {
Declaration decl = (Declaration) node;
switch (Declaration_KEY(decl)) {
case KEYsome_class_decl:
return decl;
default:
break;
}
break;
}
default:
break;
}

node = tnode_parent(node);
}

return NULL;
}

void dump_scala_Declaration(Declaration decl,ostream& oss)
{
const char *name = 0;
Expand Down Expand Up @@ -1922,7 +1994,44 @@ void dump_scala_Declaration(Declaration decl,ostream& oss)
Type fty = function_decl_type(decl);
Declaration rdecl = first_Declaration(function_type_return_values(fty));
Block b = function_decl_body(decl);
dump_function_prototype(name,fty,false /* dump_anchor_actual */,oss);
Declaration mdecl = get_enclosing_some_class_decl(decl);
bool override_needed = false;
if (mdecl != NULL) {
vector<Declaration> found_fdecls;
type_has_service_function(some_class_decl_result_type(mdecl), def_name(declaration_def(decl)), found_fdecls);

auto cftype2 = (struct Canonical_function_type *)canonical_type(fty);
// Result declaration of the current (implementing) module
Declaration current_result = some_class_decl_result_type(mdecl);
for (auto& found_fdecl : found_fdecls) {
auto cftype1 = (struct Canonical_function_type *)canonical_type(some_function_decl_type(found_fdecl));
// Result declaration of the inherited (source) module
Declaration found_mdecl = get_enclosing_some_class_decl(found_fdecl);
Declaration ctype1_mdecl_result = found_mdecl ? some_class_decl_result_type(found_mdecl) : NULL;
if (cftype1->num_formals == cftype2->num_formals) {
bool formals_type_match = true;
for (int i = 0; i < cftype1->num_formals; ++i) {
if (canonical_type_compare2(cftype1->param_types[i], cftype2->param_types[i],
ctype1_mdecl_result, current_result) != 0) {
formals_type_match = false;
}
}

if (formals_type_match) {
if (canonical_type_compare2(cftype1->return_type, cftype2->return_type,
ctype1_mdecl_result, current_result) == 0) {
override_needed = true;
break;
} else {
aps_error(decl, "Function %s has same name as inherited function but different return type; overriding not possible since return types are incompatible", decl_name(decl));
return;
}
}
}
}
}

dump_function_prototype(name, fty, false /* dump_anchor_actual */, override_needed, oss);

// three kinds of definitions:
// 1. the whole thing: a non-empty body:
Expand Down