# Anonymous-structs.pkg
# implements package equality for unions, structs, enums, at the level of ParseTree
# Compiled by:
#
src/lib/c-kit/src/ast/ast.sublibstipulate
package f8b = eight_byte_float; # eight_byte_float is from
src/lib/std/eight-byte-float.pkgherein
package ty_eq {
stipulate
include package parse_tree;
herein
fun eq_list eq (x ! xl, y ! yl)
=>
eq (x, y) and eq_list eq (xl, yl);
eq_list eq (NIL, NIL)
=>
TRUE;
eq_list _ _
=>
FALSE;
end;
fun eq_pair (eq1, eq2) ((x1, x2), (y1, y2))
=
eq1 (x1, y1) and eq2 (x2, y2);
fun eq_string (x: String, y)
=
x == y;
fun eq_declarator (EMPTY_DECR, EMPTY_DECR) => TRUE;
eq_declarator (ELLIPSES_DECR, ELLIPSES_DECR) => TRUE;
eq_declarator (VAR_DECR s1, VAR_DECR s2) => s1 == s2;
eq_declarator (ARRAY_DECR (d1, e1), ARRAY_DECR (d2, e2))
=>
eq_declarator (d1, d2) and eq_expr (e1, e2);
eq_declarator (POINTER_DECR d1, POINTER_DECR d2)
=>
eq_declarator (d1, d2);
eq_declarator (QUAL_DECR (q1, d1), QUAL_DECR (q2, d2))
=>
q1 == q2 and eq_declarator (d1, d2);
eq_declarator (FUNC_DECR arg1, FUNC_DECR arg2)
=>
eq_pair (eq_declarator, eq_list (eq_pair (eq_decltype, eq_declarator)))
(arg1, arg2);
eq_declarator _ => FALSE; # fix this
end
also
fun eq_decltype (x: Decltype, y) = # not an equality type. Why?
raise exception DIE "eqDecltype not implemented"
also
fun eq_ctype (x: Ctype, y)
=
raise exception DIE "eqCtype not implemented"
# (x = y) not an equality type? Why?
also
fun eq_exp_op (x: Operator, y)
=
raise exception DIE "eqExpOp not implemented"
# (x = y) not an equality type? Why?
also
fun eq_expr (EMPTY_EXPR, EMPTY_EXPR) => TRUE;
eq_expr (INT_CONST i, INT_CONST j) => (i==j);
eq_expr (REAL_CONST i, REAL_CONST j)
=>
case (f8b::compare (i, j))
#
EQUAL => TRUE;
_ => FALSE;
esac;
eq_expr (STRING i, STRING j) => (i==j);
eq_expr (ID i, ID j) => (i == j);
eq_expr (UNOP (exp_op, expr), UNOP (exp_op', expr'))
=>
eq_exp_op (exp_op, exp_op') and eq_expr (expr, expr');
eq_expr (BINOP (exp_op, expr1, expr2), BINOP (exp_op', expr1', expr2'))
=>
eq_exp_op (exp_op, exp_op') and eq_expr (expr1, expr1') and eq_expr (expr2, expr2');
eq_expr (QUESTION_COLON (expr1, expr2, expr3),
QUESTION_COLON (expr1', expr2', expr3')
)
=>
eq_expr (expr1, expr1') and eq_expr (expr2, expr2')
and
eq_expr (expr3, expr3');
eq_expr (CALL (expr1, exprl), CALL (expr1', exprl'))
=>
eq_expr (expr1, expr1') and (eq_list eq_expr (exprl, exprl'));
eq_expr (CAST (ctype, expr), CAST (ctype', expr')) => eq_expr (expr, expr');
eq_expr (INIT_LIST exprl, INIT_LIST exprl') => eq_list eq_expr (exprl, exprl');
eq_expr (EXPR_EXT _, EXPR_EXT _) => FALSE;
eq_expr(_, _) => FALSE;
end;
# Dpo: some small changes to get eqType type correct but is the equality correct?
#
fun eq_type ( { qualifiers => [], specifiers => [ENUM { tag_opt=>s_opt, enumerators=>sel, ... } ] }
,{ qualifiers => [], specifiers => [ENUM { tag_opt=>s_opt', enumerators=>sel', ... } ] } )
=>
s_opt == s_opt' and eq_list (eq_pair (eq_string, eq_expr)) (sel, sel');
eq_type ( { qualifiers => [], specifiers => [STRUCT { is_struct=>b, tag_opt => s_opt, members => cdell } ] },
{ qualifiers => [], specifiers => [STRUCT { is_struct=>b', tag_opt => s_opt', members => cdell' } ] } )
=>
(b == b') and s_opt == s_opt' and
eq_list
(eq_pair (eq_ctype, eq_list (eq_pair (eq_declarator, eq_expr))))
(cdell, cdell');
eq_type(_, _)
=>
FALSE;
end;
end; # stipulate
}; # package ty_eq
end;
package anonymous_structs {
# ------------------------------------------------------------
# Resolving Anonymous Structs (for inter-file analysis)
# The problem: need to resolve structurally equiv anonymous structs in
# different files to same tid.
# ------------------------------------------------------------
anonymous_structs_enums_list = REF (NIL: List( (parse_tree::Ctype, tid::Uid) ));
fun reset_anonymous_structs_enums_list ()
=
anonymous_structs_enums_list := NIL;
fun find_anon_struct_enum type
=
finder *anonymous_structs_enums_list
where
fun finder ((type', tid) ! l)
=>
if (ty_eq::eq_type (type, type'))
(THE tid);
/* debugging code:
print ("recovered anon struct with tid " + (Tid::to_string tid)
+ "\n");
(case type of
ParseTree::Enum _ => print "Enum\n"
| ParseTree::Struct(_, _, (_, (dec, e) ! _) ! _) =>
(case dec of
ParseTree::Name name => print("Struct " + name + ".. \n")
| _ => print("Struct ? .. \n"))
| _ => print "Something else ..\n"); */
else
finder l;
fi;
finder NIL => NULL;
end;
end;
fun add_anon_tid (type, tid)
=
{ l = (type, tid) ! *anonymous_structs_enums_list;
anonymous_structs_enums_list := l;
};
}; # package anonymous_structs