home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
sa104os2.zip
/
SATHR104.ZIP
/
SATHER
/
COMPILER
/
CALL.SA
< prev
next >
Wrap
Text File
|
1995-02-13
|
10KB
|
263 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". <----------
-- call5.sa: Representation of routine and iter calls.
-------------------------------------------------------------------
-- $CALL_TP: Supertype of argument types in a call.
-- CALL_TP_VOID: The type of a "void" expression.
-- CALL_TP_CREATE: The type of an untyped creation expression.
-- CALL_TP_ARRAY: The type of an array creation expression.
-- CALL_TP_UNDERSCORE: The type of a bound underscore argument.
-- CALL_SIG: The type signature of a routine or iter call.
-------------------------------------------------------------------
type $CALL_TP is
-- Supertype of the possible types of an argument in a call.
-- This is either an actual type under $TP or CALL_TP_VOID for a
-- "void" argument, CALL_TP_CREATE for a creation expression without
-- a type, CALL_TP_ARRAY for an array creation expression,
-- or CALL_TP_UNDERSCORE for an underscore argument in a bound
-- routine or iter.
str:STR; -- The string representation of self.
is_subtype(t:$TP):BOOL; -- True if self might be a legal
-- argument type for an argument whose declared type is `t'.
end; -- type $CALL_TP
-------------------------------------------------------------------
class CALL_TP_VOID < $CALL_TP is
-- The type of the argument "void".
shared cache:SAME;
create:SAME is
-- The representative object.
if void(cache) then cache:=new end; return cache end;
str:STR is
-- The string: "void".
return "void-expression" end;
is_subtype(t:$TP):BOOL
-- True.
pre ~void(t) is
return true end;
end; -- class CALL_TP_VOID
-------------------------------------------------------------------
class CALL_TP_CREATE < $CALL_TP is
-- The type of an untyped creation expression.
shared cache:SAME;
create:SAME is
-- The representative object.
if void(cache) then cache:=new end;
return cache end;
str:STR is
-- The string: "create".
return "create-expression" end;
is_subtype(t:$TP):BOOL
-- True if `t' is a reference or value type.
pre ~void(t) is
case t.kind
when TP_KIND::val_tp then return true
when TP_KIND::ref_tp then return true
when TP_KIND::abs_tp then return false
when TP_KIND::ext_tp then return false
when TP_KIND::rout_tp then return false
-- when TP_KIND::iter_tp then return false end end; -- NLP
when TP_KIND::iter_tp then return false end; return false; end; -- NLP
end; -- class CALL_TP_CREATE
-------------------------------------------------------------------
class CALL_TP_ARRAY < $CALL_TP is
-- The type of an array creation expression.
shared cache:SAME;
create:SAME is
-- The representative object.
if void(cache) then cache:=new end;
return cache end;
str:STR is
-- The string: "array".
return "array-expression" end;
is_subtype(t:$TP):BOOL is
-- True if `t' is ARRAY{T} for some T.
typecase t
when TP_CLASS then
return t.name=t.prog.ident_for("ARRAY")
-- else return false end end; -- NLP
else; end; return false; end; -- NLP
end; -- class CALL_TP_ARRAY
-------------------------------------------------------------------
class CALL_TP_UNDERSCORE < $CALL_TP is
-- The type of an underscore argument in a bound routine or iter
-- call and doesn't have a type specified.
attr tp:$TP; -- The type if one is specified.
create:SAME is
-- A new object.
return new end;
str:STR is
-- The string: "underscore" followed by ":TYPE" if a type is
-- present.
if void(tp) then return "underscore-expression" else
-- return "underscore-expression:" + tp.str end end; -- NLP
end; return "underscore-expression:" + tp.str; end; -- NLP
is_subtype(t:$TP):BOOL
-- True if self may represent `t'.
pre ~void(t) is
if void(tp) then return true else
-- return tp.is_subtype(t) end end; -- NLP
end; return tp.is_subtype(t); end; -- NLP
end; -- class CALL_TP_UNDERSCORE
-------------------------------------------------------------------
class CALL_SIG is
-- The type signature of a routine or iter *call*. There are special
-- type objects for arguments which are void, untyped creation
-- expressions, array creation expressions, integer literals, or
-- floating point literals.
attr tp:$TP; -- The type on which the call is made.
attr name:IDENT; -- The name of the call.
attr args:ARRAY{$CALL_TP}; -- The argument types, if any.
attr has_ret:BOOL; -- True if the return value is used.
attr unknown_ret:BOOL; -- True if this is a bound routine
-- or iter call signature and we don't know whether there
-- is a return value or not.
prog:PROG is
-- The program in which this call appears.
return tp.prog end;
create:SAME is
-- An uninitialized call sig.
return new end;
str:STR is
-- The string representation of self. Uses no whitespace. Use
-- an underbar "_" for the return type if there is one, and
-- the special strings "void", "create", "array", and
-- "underscore" for call arguments whose type is inferred:
-- "FOO::foo!(A,void,C,array):_".
-- If self is void, returns "void".
if void(self) then return "void" end;
s::=#FSTR + tp.str + "::" + name.str;
if ~void(args) then
s:=s + '(';
loop s:=s + ",".separate!(args.elt!.str) end;
s:=s + ')' end;
if unknown_ret then s:=s + ":?"
elsif has_ret then s:=s + ":_" end;
return s.str end;
conforms_to(s:SIG):BOOL is
-- True if a call with signature self could be made on the routine
-- or iter described by `s'. They must:
-- 1) have the same name,
-- 2) have the same number of arguments,
-- 3) each call argument must conform to the corresponding
-- declared argument,
-- 4) both must have or not have a return value.
-- 5) Appear in the same type.
if void(self) or void(s) then return false end;
if tp/=s.tp then return false end;
if name/=s.name then return false end;
if ~unknown_ret then
if has_ret then if void(s.ret) then return false end
elsif ~void(s.ret) then return false end end;
if args.size/=s.args.size then return false end;
loop ca::=args.elt!; sa::=s.args.elt!;
if ~ca.is_subtype(sa) then return false end end;
return true end;
lookup(in_class:BOOL):SIG is
-- Lookup self and return the corresponding signature if there
-- is one. Print an error message if it is ambiguous or absent and
-- return void. Callers should set the err_loc. If `in_class'
-- is true, then consider both public and private routines,
-- otherwise just public ones.
st::=tp; -- The type the call is made on.
typecase st
when TP_CLASS then
if in_class then
return prog.impl_tbl.impl_of(tp).sig_for_internal_call(self);
else return prog.ifc_tbl.ifc_of(tp).sig_for_call(self) end;
when TP_ROUT then
if name/=prog.ident_builtin.call_ident then
prog.err("Only `call' may be applied to a bound routine.");
return void end;
if ~unknown_ret then
if has_ret and void(st.ret) then
prog.err("The bound routine " + st.str +
" has no return value, but one is needed.");
return void
elsif ~has_ret and ~void(st.ret) then
prog.err("The bound routine " + st.str +
" has a return value, but it isn't used.");
return void end end;
if st.args.size/=args.size then
prog.err("The call " + str +
" has the wrong number of args for " + st.str + ".");
return void end;
loop at::=args.elt!; brat::=st.args.elt!;
if ~at.is_subtype(brat) then
prog.err("The argument type " + at.str + " in the call " +
str + " doesn't conform to " + brat.str +
" in the bound routine " + st.str + ".");
return void end end;
return SIG::bound_routine_call(st)
when TP_ITER then
if name/=prog.ident_builtin.call_bang_ident then
prog.err("Only `call!' may be applied to a bound iter.");
return void end;
if ~unknown_ret then
if has_ret and void(st.ret) then
prog.err("The bound iter " + st.str +
" has no return value, but one is needed."); return void
elsif ~has_ret and ~void(st.ret) then
prog.err("The bound iter " + st.str +
" has a return value, but it isn't used.");
return void end end;
if st.args.size/=args.size then
prog.err("The call " + str +
" has the wrong number of args for " + st.str +".");
return void end;
loop at::=args.elt!; brat::=st.args.elt!;
if ~at.is_subtype(brat) then
prog.err("The argument type " + at.str + " in the call " +
str + " doesn't conform to " + brat.str +
" in the bound routine " + st.str + ".");
return void end end;
-- return SIG::bound_iter_call(st) end end; -- NLP
return SIG::bound_iter_call(st) end; return void; end; -- NLP
end; -- class CALL_SIG
-------------------------------------------------------------------