home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
sa104os2.zip
/
SATHR104.ZIP
/
SATHER
/
COMPILER
/
SIG.SA
< prev
next >
Wrap
Text File
|
1995-02-13
|
18KB
|
420 lines
-- Copyright (C) International Computer Science Institute, 1994. COPYRIGHT --
-- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
-- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in --
-- the file "Doc/License" of the Sather distribution. The license is also --
-- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA. --
--------> Please email comments to "sather-bugs@icsi.berkeley.edu". <----------
-- sig.sa: Routine and iter type signatures in the Sather compiler.
-------------------------------------------------------------------
-- SIG: The type signature of a routine or iter.
-- SIG_TBL: Table of routine and iter signatures retrievable by name.
-------------------------------------------------------------------
class SIG < $IS_EQ{SIG} is
-- The type signature of a routine or iter.
attr tp:$TP; -- The type to which the signature belongs.
attr name:IDENT; -- The name of the routine or iter.
attr args:ARRAY{$TP}; -- Arg types, void if none.
attr hot:ARRAY{BOOL}; -- True for "!" iter args, void if none.
attr ret:$TP; -- Return type, void if none.
attr is_builtin:BOOL; -- True if this is the signature of a
-- builtin routine.
attr string:STR; -- Cached string representation
prog:PROG is
-- The program this signature belongs to.
return tp.prog end;
create:SAME is
return new; end;
do_is_builtin is
-- Assuming everything else is correct, fill in `is_builtin'.
is_builtin:=prog.back_end.is_built_in_routine(self) end;
num_args:INT is
-- The number of arguments in this signature.
return args.size end;
has_ret:BOOL is
-- True if there is a return value.
return ~void(ret) end;
is_iter:BOOL is
-- True if self is an iter.
return name.is_iter end;
is_attr_writer_sig:BOOL is
-- True if self could be a writer signature for an object attribute.
-- For ref it has a single argument and no return value, for val
-- it has a single arg and a return value.
if tp.kind=TP_KIND::val_tp then
return args.size=1 and tp=ret
-- else return args.size=1 and void(ret) end end; -- NLP
end; return args.size=1 and void(ret); end; -- NLP
is_shared_writer_sig:BOOL is
-- True if self could be a writer signature for a shared attribute.
-- It has a single argument and no return value.
return args.size=1 and void(ret) end;
is_reader_sig:BOOL is
-- True if self has a return value but no arguments.
return void(args) and ~void(ret) end;
is_invariant:BOOL is
-- True if self is the signature "invariant:BOOL".
return void(args) and ~void(ret) and prog.tp_builtin.bool=ret and
name=prog.ident_builtin.invariant_ident end;
str:STR is
-- The string representation of self. Uses no whitespace,
-- eg. "FOO::foo!(A!,B{C}):D".
-- If self is void, returns "void".
if void(self) then return "void" end;
if ~void(self.string) then return self.string; end;
s::=#FSTR + tp.str + "::" + name.str;
if ~void(args) then
s:=s + '(';
loop s:=s+",".separate!(args.elt!.str);
if ~void(hot) and hot.elt! then s:=s+'!' end end;
s:=s + ')' end;
if ~void(ret) then s:=s + ':' + ret.str end;
self.string:=s.str;
return s.str end;
conforms_to(s:SAME):BOOL
-- True if self conforms to `s' so as to satisfy the inheritance
-- rule. This means they:
-- 1) Have the same name,
-- 2) Have the same the number of args,
-- 3) Each argument type of self is a supertype of the
-- corresponding argument in `s',
-- 4) If iters, then the same args are declared `hot',
-- 5) Both have or do not have a return value,
-- 6) If they do, then self's return value is a subtype of `s's.
-- Ignores `tp'.
pre ~void(self) and ~void(s) is
if name/=s.name or args.size/=s.args.size or
hot.size/=s.hot.size or has_ret/=s.has_ret then return false end;
loop if hot.elt!/=s.hot.elt! then return false end end;
loop if ~s.args.elt!.is_subtype(args.elt!) then
return false end end;
if has_ret and ~ret.is_subtype(s.ret) then return false end;
return true end;
conflicts_with(s:SAME):BOOL
-- True if self conflicts with `s'. This is a symmetric
-- relationship. It means that they:
-- 1) Have the same name,
-- 2) Have the same the number of args,
-- 3) There is no argument that they declare as having different
-- types and neither type declaration is abstract, bound.
-- 4) Both have or do not have a return value.
-- Ignores `tp'.
pre ~void(self) and ~void(s) is
if name/=s.name or args.size/=s.args.size or
has_ret/=s.has_ret then return false end;
loop t::=args.elt!; st::=s.args.elt!;
if t/=st and ~t.is_abstract and ~t.is_bound and
~st.is_abstract and ~st.is_bound then
return false end end;
return true end;
is_eq_but_tp(s:SAME):BOOL is
-- True if self is equal to `s' except for the `tp' field.
-- This is a symmetric relationship.
-- It means that they:
-- 1) Have the same name,
-- 2) Have the same the number of args,
-- 3) Each argument type of `s' *is equal* to the corresponding
-- argument in self,
-- 4) If iters, then the same args are declared `hot',
-- 5) Both have or do not have a return value.
-- 6) The return types must be equal, if present.
if void(self) then return void(s)
elsif void(s) then return false end;
if SYS::ob_eq(self,s) then return true end; -- Do easy check first!
if name/=s.name or args.size/=s.args.size or
hot.size/=s.hot.size or has_ret/=s.has_ret then
return false end;
loop if args.elt!/=s.args.elt! then return false end end;
loop if hot.elt!/=s.hot.elt! then return false end end;
if has_ret and ret/=s.ret then return false end;
return true end;
is_eq(s:SAME):BOOL is
-- True if self is equal to `s'. This is a symmetric relationship.
-- It means that they:
-- 1) Have the same name,
-- 2) Have the same the number of args,
-- 3) Each argument type of `s' *is equal* to the corresponding
-- argument in self,
-- 4) If iters, then the same args are declared `hot',
-- 5) Both have or do not have a return value.
-- 6) The return types must be equal, if present.
-- 7) Has an equal `tp'.
if void(self) then return void(s)
elsif void(s) then return false end;
if SYS::ob_eq(self,s) then return true end; -- Do easy check first!
if tp/=s.tp or name/=s.name or args.size/=s.args.size or
hot.size/=s.hot.size or has_ret/=s.has_ret then
return false end;
loop if args.elt!/=s.args.elt! then return false end end;
loop if hot.elt!/=s.hot.elt! then return false end end;
if has_ret and ret/=s.ret then return false end;
return true end;
is_writer_for(s:SAME):BOOL
-- True if self is the writer signature corresponding to the
-- reader signature `s'. This means that:
-- 1) self and `s' have the same name.
-- 2) self has 1 arg, `s' has none.
-- 3) For value types self has a return value of type self,
-- otherwise it has no return value, `s' has 1 .
-- 4) The type of self's arg is equal to `s's return type.
pre ~void(self) and ~void(s) is
if name/=s.name or ~void(s.args) or void(s.ret) or
args.size/=1 or args[0]/=s.ret then
return false end;
if tp.kind=TP_KIND::val_tp then
if s.ret/=s.tp then return false end
elsif ~void(s.ret) then return false end;
return true end;
rout_sig(tr:TR_ROUT_DEF, nm:IDENT, con:TP_CONTEXT):SAME
-- The signature of the routine or iter in the type `con.same'
-- defined by `tr' with the name `nm' and types resolved according
-- to `con'.
pre ~void(tr) and ~void(nm) and ~void(con) is
r::=new; r.tp:=con.same; r.name:=nm; na::=tr.args_dec.size;
if na/=0 then r.args:=#(na);
ad::=tr.args_dec;
loop until!(void(ad));
r.args.set!(con.tp_of(ad.tp)); ad:=ad.next end end;
dohot:BOOL;
tae::=tr.args_dec;
loop until!(void(tae));
if tae.is_hot then dohot:=true end; tae:=tae.next end;
if dohot then r.hot:=#(na);
ad::=tr.args_dec;
loop until!(void(ad));
r.hot.set!(ad.is_hot); ad:=ad.next end end;
r.ret:=con.tp_of(tr.ret_dec);
r.do_is_builtin; return r end;
const_reader_sig(tr:TR_CONST_DEF, nm:IDENT, con:TP_CONTEXT):SAME
-- The signature of the reader routine in the type `con.same' for
-- the constant defined by `tr' with the name specified by `nm' and
-- types resolved according to `con'.
pre ~void(tr) and ~void(nm) and ~void(con) is
r::=new; r.tp:=con.same; r.name:=nm;
if ~void(tr.tp) then -- Explicit type specified.
r.ret:=con.tp_of(tr.tp);
else -- No explicit type, so INT.
r.ret:=con.prog.tp_builtin.int end;
r.do_is_builtin; return r end;
shared_reader_sig(tr:TR_SHARED_DEF, nm:IDENT, con:TP_CONTEXT):SAME
-- The signature of the reader routine in the type `con.same' for
-- the shared defined by `tr' with the name specified by `nm' and
-- types resolved according to `con'.
pre ~void(tr) and ~void(nm) and ~void(con) is
r::=new; r.tp:=con.same; r.name:=nm;
r.ret:=con.tp_of(tr.tp); r.do_is_builtin; return r end;
shared_writer_sig(tr:TR_SHARED_DEF, nm:IDENT, con:TP_CONTEXT):SAME
-- The signature of the writer routine in the type `con.same' for
-- the shared defined by `tr' with the name specified by `nm' and
-- types resolved according to `con'.
pre ~void(tr) and ~void(nm) and ~void(con) is
r::=new; r.tp:=con.same; r.name:=nm;
r.args:=ARRAY{$TP}::create(1); r.args[0]:=con.tp_of(tr.tp);
r.do_is_builtin; return r end;
attr_reader_sig(tr:TR_ATTR_DEF, nm:IDENT, con:TP_CONTEXT):SAME
-- The signature of the reader routine in the type `con.same' for
-- the object attribute defined by `tr' with the name specified
-- by `nm' and types resolved according to `con'.
pre ~void(tr) and ~void(nm) and ~void(con) is
r::=new; r.tp:=con.same; r.name:=nm;
r.ret:=con.tp_of(tr.tp); r.do_is_builtin; return r end;
attr_writer_sig(tr:TR_ATTR_DEF, nm:IDENT, con:TP_CONTEXT):SAME
-- The signature of the writer routine in the type `con.same' for
-- the object attribute defined by `tr' with the name specified
-- by `nm' and types resolved according to `con'.
pre ~void(tr) and ~void(nm) and ~void(con) is
r::=new; r.tp:=con.same; r.name:=nm;
r.args:=ARRAY{$TP}::create(1); r.args[0]:=con.tp_of(tr.tp);
if r.tp.kind=TP_KIND::val_tp then r.ret:=r.tp end;
r.do_is_builtin; return r end;
bound_routine_call(tp:TP_ROUT):SAME
-- The signature of the "call" routine for the bound routine
-- type `tp'.
pre ~void(tp) is
r::=new; r.tp:=tp; r.name:=tp.prog.ident_for("call");
r.args:=tp.args; r.ret:=tp.ret;
r.do_is_builtin; return r end;
bound_iter_call(tp:TP_ITER):SAME
-- The signature of the "call!" routine for the bound iter
-- type `tp'.
pre ~void(tp) is
r::=new; r.tp:=tp; r.name:=tp.prog.ident_for("call!");
r.args:=tp.args; r.hot:=tp.hot; r.ret:=tp.ret;
r.do_is_builtin; return r end;
with_new_type(t:$TP):SAME
-- A new signature, the same as self, but with the new type `t'.
pre ~void(self) and ~void(t) is
r::=new; r.tp:=t; r.name:=name; r.args:=args;
r.hot:=hot; r.ret:=ret; r.do_is_builtin; return r end;
is_base_type(tp:$TP):BOOL is
-- True if `tp' is BOOL, CHAR, INT, FLT, FLTD, FLTX, FLTDX, or
-- EXT_OB.
case tp
when prog.tp_builtin.bool then return true
when prog.tp_builtin.char then return true
when prog.tp_builtin.int then return true
when prog.tp_builtin.flt then return true
when prog.tp_builtin.fltd then return true
when prog.tp_builtin.fltx then return true
when prog.tp_builtin.fltdx then return true
when prog.tp_builtin.ext_ob then return true
-- else return false end end; -- NLP
else; end; return false; end; -- NLP
is_base_aref_type(tp:$TP):BOOL is
-- True if `tp' has an include path to AREF{CHAR}, AREF{INT},
-- AREF{FLT}, AREF{FLTD}, AREF{FLTX}, AREF{FLTDX}, or AREF{EXT_OB}.
typecase tp when TP_CLASS then
im:IMPL:=prog.impl_tbl.impl_of(tp);
if void(im) then return false end;
ar:TP_CLASS:=im.arr; if void(ar) then return false end;
if ar.name/=prog.ident_builtin.AREF_ident then return false end;
if void(ar.params) then
#OUT + "Compiler error, SIG::is_base_aref_type params=void.";
return false end;
if ar.params.size/=1 then
#OUT + "Compiler error, SIG::is_base_aref_type params.size/=1.";
return false end;
case ar.params[0]
when prog.tp_builtin.char then return true
when prog.tp_builtin.int then return true
when prog.tp_builtin.flt then return true
when prog.tp_builtin.fltd then return true
when prog.tp_builtin.fltx then return true
when prog.tp_builtin.fltdx then return true
when prog.tp_builtin.ext_ob then return true
else return false end
-- else return false end end; -- NLP
else; end; return false; end; -- NLP
is_legal_ext_abs:BOOL
-- True if this signature is legal for an abstract routine
-- in an external class.
pre ~void(self) is
if name.is_iter then
prog.err("The iter signature " + str +
" isn't allowed in an external class.");
return false end;
loop a::=args.elt!;
if is_base_type(a) then
elsif is_base_aref_type(a) then
else
prog.err("The signature " + str +
" is not legal for a routine without body in an external "
"class. The argument type " + a.str +
" is not of the right type."); return false end end;
if ~void(ret) and ~is_base_type(ret) then
prog.err("The signature " + str +
" is not legal for a routine without body in an external "
"class. The return type " + ret.str +
" is not of the right type."); return false end;
return true end;
is_legal_ext_bod:BOOL
-- True if this signature is legal for a routine with a body
-- in an external class.
pre ~void(self) is
if name.is_iter then
prog.err("The iter signature " + str +
" isn't allowed in an external class.");
return false end;
loop a::=args.elt!;
if is_base_type(a) then
else
prog.err("The signature " + str +
" is not legal for a routine with body in an external "
"class. The argument type " + a.str +
" is not of the right type."); return false end end;
if ~void(ret) and ~is_base_type(ret) then
prog.err("The signature " + str +
" is not legal for a routine with body in an external "
"class. The return type " + ret.str +
" is not of the right type."); return false end;
return true end;
end; -- class SIG
-------------------------------------------------------------------
class SIG_TBL is
-- Table of routine and iter signatures retrievable by name.
--
-- `get_query!(i:IDENT):SIG' yields each sig with the name `i'.
-- `test(SIG):BOOL' tests for the given sig.
-- `insert(SIG):SAME' inserts a sig.
-- `delete(SIG):SAME' deletes a sig.
-- `elt!:ELT' yields each sig.
include FQSET{IDENT,SIG};
query_test(name:IDENT, s:SIG):BOOL is
-- True if `s' is a signature with the name `name'.
if void(s) then return false end;
return s.name=name end;
query_hash(i:IDENT):INT is
-- A hash value computed from the name `i'.
return i.hash end;
elt_hash(s:SIG):INT is
-- A hash value computed from the name of an element.
return s.name.hash end;
private old_sig_eq_to(s:SIG):SIG
-- Returns an element of self equal to `s' if one exists,
-- otherwise returns void.
pre ~void(s) is
loop r::=get_query!(s.name); if r=s then return r end end;
return void end;
sig_eq_to(s:SIG):SIG
-- Returns an element of self equal to `s' if one exists,
-- otherwise returns void. New implementation by MBK. Much faster.
pre ~void(s) is
r ::= get(s);
-- r2 ::= old_sig_eq_to(s);
-- if ~(r=r2) then
-- #ERR + " sig_eq_to and old_sig_eq_to differ:"
-- + r.str + " vs " + r2.str + '\n';
-- end;
return r;
end;
sig_conflicting_with(s:SIG):SIG
-- Returns an element of self that conflicts with `s' if one
-- exists, otherwise returns void.
pre ~void(s) is
loop r::=get_query!(s.name);
if r.conflicts_with(s) then return r end end;
return void end;
end; -- class SIG_TBL
-------------------------------------------------------------------