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 >
Text File  |  1995-02-13  |  18KB  |  420 lines

  1. -- Copyright (C) International Computer Science Institute, 1994.  COPYRIGHT  --
  2. -- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
  3. -- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in    --
  4. -- the file "Doc/License" of the Sather distribution.  The license is also   --
  5. -- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA.  --
  6. --------> Please email comments to "sather-bugs@icsi.berkeley.edu". <----------
  7.  
  8. -- sig.sa: Routine and iter type signatures in the Sather compiler.
  9. -------------------------------------------------------------------
  10. -- SIG: The type signature of a routine or iter.   
  11. -- SIG_TBL: Table of routine and iter signatures retrievable by name.
  12. -------------------------------------------------------------------
  13. class SIG < $IS_EQ{SIG} is
  14.    -- The type signature of a routine or iter.
  15.  
  16.    attr tp:$TP;            -- The type to which the signature belongs.
  17.    attr name:IDENT;        -- The name of the routine or iter.
  18.    attr args:ARRAY{$TP};    -- Arg types, void if none.
  19.    attr hot:ARRAY{BOOL};    -- True for "!" iter args, void if none.
  20.    attr ret:$TP;        -- Return type, void if none. 
  21.    attr is_builtin:BOOL;    -- True if this is the signature of a
  22.       -- builtin routine.
  23.    attr string:STR;        -- Cached string representation
  24.  
  25.    prog:PROG is
  26.       -- The program this signature belongs to.
  27.       return tp.prog end;
  28.  
  29.    create:SAME is 
  30.       return new; end;
  31.  
  32.    do_is_builtin is
  33.       -- Assuming everything else is correct, fill in `is_builtin'.
  34.       is_builtin:=prog.back_end.is_built_in_routine(self) end;
  35.    
  36.    num_args:INT is
  37.       -- The number of arguments in this signature.
  38.       return args.size end;
  39.    
  40.    has_ret:BOOL is        
  41.       -- True if there is a return value.
  42.       return ~void(ret) end;
  43.  
  44.    is_iter:BOOL is
  45.       -- True if self is an iter.
  46.       return name.is_iter end;
  47.  
  48.    is_attr_writer_sig:BOOL is
  49.       -- True if self could be a writer signature for an object attribute. 
  50.       -- For ref it has a single argument and no return value, for val
  51.       -- it has a single arg and a return value.
  52.       if tp.kind=TP_KIND::val_tp then
  53.      return args.size=1 and tp=ret
  54. --    else return args.size=1 and void(ret) end end;                            -- NLP
  55.       end; return args.size=1 and void(ret); end;                               -- NLP
  56.  
  57.    is_shared_writer_sig:BOOL is
  58.       -- True if self could be a writer signature for a shared attribute. 
  59.       -- It has a single argument and no return value.
  60.       return args.size=1 and void(ret) end;
  61.    
  62.    is_reader_sig:BOOL is
  63.       -- True if self has a return value but no arguments.
  64.       return void(args) and ~void(ret) end;
  65.    
  66.    is_invariant:BOOL is
  67.       -- True if self is the signature "invariant:BOOL".
  68.       return void(args) and ~void(ret) and prog.tp_builtin.bool=ret and  
  69.          name=prog.ident_builtin.invariant_ident end;      
  70.    
  71.    str:STR is
  72.       -- The string representation of self. Uses no whitespace,
  73.       -- eg. "FOO::foo!(A!,B{C}):D". 
  74.       -- If self is void, returns "void".
  75.       if void(self) then return "void" end;
  76.       if ~void(self.string) then return self.string; end;
  77.       s::=#FSTR + tp.str + "::" + name.str;
  78.       if ~void(args) then
  79.      s:=s + '(';
  80.      loop s:=s+",".separate!(args.elt!.str);
  81.         if ~void(hot) and hot.elt! then s:=s+'!' end end;
  82.      s:=s + ')' end;
  83.       if ~void(ret) then s:=s + ':' + ret.str end;
  84.       self.string:=s.str;
  85.       return s.str end;
  86.       
  87.    conforms_to(s:SAME):BOOL 
  88.       -- True if self conforms to `s' so as to satisfy the inheritance 
  89.       -- rule. This means they: 
  90.       -- 1) Have the same name, 
  91.       -- 2) Have the same the number of args, 
  92.       -- 3) Each argument type of self is a supertype of the 
  93.       --    corresponding argument in `s', 
  94.       -- 4) If iters, then the same args are declared `hot', 
  95.       -- 5) Both have or do not have a return value, 
  96.       -- 6) If they do, then self's return value is a subtype of `s's. 
  97.       -- Ignores `tp'.
  98.       pre ~void(self) and ~void(s) is
  99.       if name/=s.name or args.size/=s.args.size or
  100.      hot.size/=s.hot.size or has_ret/=s.has_ret then return false end;
  101.       loop if hot.elt!/=s.hot.elt! then return false end end;
  102.       loop if ~s.args.elt!.is_subtype(args.elt!) then
  103.      return false end end;
  104.       if has_ret and ~ret.is_subtype(s.ret) then return false end;
  105.       return true end;
  106.  
  107.    conflicts_with(s:SAME):BOOL 
  108.       -- True if self conflicts with `s'. This is a symmetric 
  109.       -- relationship. It means that they:
  110.       -- 1) Have the same name, 
  111.       -- 2) Have the same the number of args, 
  112.       -- 3) There is no argument that they declare as having different
  113.       --    types and neither type declaration is abstract, bound.
  114.       -- 4) Both have or do not have a return value. 
  115.       -- Ignores `tp'.
  116.       pre ~void(self) and ~void(s) is
  117.       if name/=s.name or args.size/=s.args.size or 
  118.      has_ret/=s.has_ret then return false end;
  119.       loop t::=args.elt!; st::=s.args.elt!;
  120.      if t/=st and ~t.is_abstract and ~t.is_bound and 
  121.         ~st.is_abstract and ~st.is_bound then 
  122.         return false end end; 
  123.       return true end;      
  124.  
  125.    is_eq_but_tp(s:SAME):BOOL is
  126.       -- True if self is equal to `s' except for the `tp' field. 
  127.       -- This is a symmetric relationship. 
  128.       -- It means that they:
  129.       -- 1) Have the same name, 
  130.       -- 2) Have the same the number of args, 
  131.       -- 3) Each argument type of `s' *is equal* to the corresponding 
  132.       --    argument in self, 
  133.       -- 4) If iters, then the same args are declared `hot', 
  134.       -- 5) Both have or do not have a return value. 
  135.       -- 6) The return types must be equal, if present.
  136.       if void(self) then return void(s)
  137.       elsif void(s) then return false end;
  138.       if SYS::ob_eq(self,s) then return true end; -- Do easy check first!
  139.       if name/=s.name or args.size/=s.args.size or 
  140.      hot.size/=s.hot.size or has_ret/=s.has_ret then 
  141.      return false end;
  142.       loop if args.elt!/=s.args.elt! then return false end end;
  143.       loop if hot.elt!/=s.hot.elt! then return false end end;
  144.       if has_ret and ret/=s.ret then return false end;
  145.       return true end;      
  146.       
  147.    is_eq(s:SAME):BOOL is
  148.       -- True if self is equal to `s'. This is a symmetric relationship. 
  149.       -- It means that they:
  150.       -- 1) Have the same name, 
  151.       -- 2) Have the same the number of args, 
  152.       -- 3) Each argument type of `s' *is equal* to the corresponding 
  153.       --    argument in self, 
  154.       -- 4) If iters, then the same args are declared `hot', 
  155.       -- 5) Both have or do not have a return value. 
  156.       -- 6) The return types must be equal, if present.
  157.       -- 7) Has an equal `tp'.
  158.       if void(self) then return void(s)
  159.       elsif void(s) then return false end;
  160.       if SYS::ob_eq(self,s) then return true end; -- Do easy check first!
  161.       if tp/=s.tp or name/=s.name or args.size/=s.args.size or 
  162.      hot.size/=s.hot.size or has_ret/=s.has_ret then 
  163.      return false end;
  164.       loop if args.elt!/=s.args.elt! then return false end end;
  165.       loop if hot.elt!/=s.hot.elt! then return false end end;
  166.       if has_ret and ret/=s.ret then return false end;
  167.       return true end;      
  168.       
  169.    is_writer_for(s:SAME):BOOL 
  170.       -- True if self is the writer signature corresponding to the 
  171.       -- reader signature `s'. This means that:
  172.       -- 1) self and `s' have the same name.
  173.       -- 2) self has 1 arg, `s' has none.
  174.       -- 3) For value types self has a return value of type self,
  175.       --    otherwise it has no return value, `s' has 1 .
  176.       -- 4) The type of self's arg is equal to `s's return type.
  177.       pre ~void(self) and ~void(s) is            
  178.       if name/=s.name or ~void(s.args) or void(s.ret) or
  179.      args.size/=1 or args[0]/=s.ret then
  180.      return false end;
  181.       if tp.kind=TP_KIND::val_tp then
  182.      if s.ret/=s.tp then return false end
  183.       elsif ~void(s.ret) then return false end;
  184.       return true end;
  185.    
  186.    rout_sig(tr:TR_ROUT_DEF, nm:IDENT, con:TP_CONTEXT):SAME 
  187.       -- The signature of the routine or iter in the type `con.same' 
  188.       -- defined by `tr' with the name `nm' and types resolved according 
  189.       -- to `con'. 
  190.       pre ~void(tr) and ~void(nm) and ~void(con) is
  191.       r::=new; r.tp:=con.same; r.name:=nm; na::=tr.args_dec.size;
  192.       if na/=0 then r.args:=#(na);
  193.      ad::=tr.args_dec;
  194.      loop until!(void(ad));
  195.         r.args.set!(con.tp_of(ad.tp)); ad:=ad.next end end;
  196.       dohot:BOOL;
  197.       tae::=tr.args_dec;
  198.       loop until!(void(tae));
  199.      if tae.is_hot then dohot:=true end; tae:=tae.next end;
  200.       if dohot then r.hot:=#(na);
  201.      ad::=tr.args_dec;
  202.      loop until!(void(ad));
  203.         r.hot.set!(ad.is_hot); ad:=ad.next end end;     
  204.       r.ret:=con.tp_of(tr.ret_dec);
  205.       r.do_is_builtin; return r end;         
  206.       
  207.    const_reader_sig(tr:TR_CONST_DEF, nm:IDENT, con:TP_CONTEXT):SAME 
  208.       -- The signature of the reader routine in the type `con.same' for 
  209.       -- the constant defined by `tr' with the name specified by `nm' and
  210.       -- types resolved according to `con'. 
  211.       pre ~void(tr) and ~void(nm) and ~void(con) is   
  212.       r::=new; r.tp:=con.same; r.name:=nm; 
  213.       if ~void(tr.tp) then    -- Explicit type specified.
  214.      r.ret:=con.tp_of(tr.tp);
  215.       else            -- No explicit type, so INT. 
  216.      r.ret:=con.prog.tp_builtin.int end;
  217.       r.do_is_builtin; return r end;            
  218.    
  219.    shared_reader_sig(tr:TR_SHARED_DEF, nm:IDENT, con:TP_CONTEXT):SAME
  220.       -- The signature of the reader routine in the type `con.same' for 
  221.       -- the shared defined by `tr' with the name specified by `nm' and
  222.       -- types resolved according to `con'. 
  223.       pre ~void(tr) and ~void(nm) and ~void(con) is         
  224.       r::=new; r.tp:=con.same; r.name:=nm; 
  225.       r.ret:=con.tp_of(tr.tp); r.do_is_builtin; return r end;         
  226.  
  227.    shared_writer_sig(tr:TR_SHARED_DEF, nm:IDENT, con:TP_CONTEXT):SAME 
  228.       -- The signature of the writer routine in the type `con.same' for 
  229.       -- the shared defined by `tr' with the name specified by `nm' and 
  230.       -- types resolved according to `con'. 
  231.       pre ~void(tr) and ~void(nm) and ~void(con) is               
  232.       r::=new; r.tp:=con.same; r.name:=nm;
  233.       r.args:=ARRAY{$TP}::create(1); r.args[0]:=con.tp_of(tr.tp);
  234.       r.do_is_builtin; return r end;
  235.    
  236.    attr_reader_sig(tr:TR_ATTR_DEF, nm:IDENT, con:TP_CONTEXT):SAME 
  237.       -- The signature of the reader routine in the type `con.same' for 
  238.       -- the object attribute defined by `tr' with the name specified 
  239.       -- by `nm' and types resolved according to `con'. 
  240.       pre ~void(tr) and ~void(nm) and ~void(con) is                     
  241.       r::=new; r.tp:=con.same; r.name:=nm; 
  242.       r.ret:=con.tp_of(tr.tp); r.do_is_builtin; return r end;
  243.  
  244.    attr_writer_sig(tr:TR_ATTR_DEF, nm:IDENT, con:TP_CONTEXT):SAME 
  245.       -- The signature of the writer routine in the type `con.same' for 
  246.       -- the object attribute defined by `tr' with the name specified 
  247.       -- by `nm' and types resolved according to `con'. 
  248.       pre ~void(tr) and ~void(nm) and ~void(con) is                        
  249.       r::=new; r.tp:=con.same; r.name:=nm; 
  250.       r.args:=ARRAY{$TP}::create(1); r.args[0]:=con.tp_of(tr.tp);
  251.       if r.tp.kind=TP_KIND::val_tp then r.ret:=r.tp end;
  252.       r.do_is_builtin; return r end;
  253.  
  254.    bound_routine_call(tp:TP_ROUT):SAME 
  255.       -- The signature of the "call" routine for the bound routine
  256.       -- type `tp'.
  257.       pre ~void(tp) is
  258.       r::=new; r.tp:=tp; r.name:=tp.prog.ident_for("call");
  259.       r.args:=tp.args; r.ret:=tp.ret; 
  260.       r.do_is_builtin; return r end;
  261.  
  262.    bound_iter_call(tp:TP_ITER):SAME
  263.       -- The signature of the "call!" routine for the bound iter
  264.       -- type `tp'.
  265.       pre ~void(tp) is      
  266.       r::=new; r.tp:=tp; r.name:=tp.prog.ident_for("call!");
  267.       r.args:=tp.args; r.hot:=tp.hot; r.ret:=tp.ret; 
  268.       r.do_is_builtin; return r end;
  269.  
  270.    with_new_type(t:$TP):SAME 
  271.       -- A new signature, the same as self, but with the new type `t'.
  272.       pre ~void(self) and ~void(t) is
  273.       r::=new; r.tp:=t; r.name:=name; r.args:=args; 
  274.       r.hot:=hot; r.ret:=ret; r.do_is_builtin; return r end;
  275.  
  276.    is_base_type(tp:$TP):BOOL is
  277.       -- True if `tp' is BOOL, CHAR, INT, FLT, FLTD, FLTX, FLTDX, or
  278.       -- EXT_OB.
  279.       case tp
  280.       when prog.tp_builtin.bool then return true 
  281.       when prog.tp_builtin.char then return true 
  282.       when prog.tp_builtin.int then return true 
  283.       when prog.tp_builtin.flt then return true 
  284.       when prog.tp_builtin.fltd then return true 
  285.       when prog.tp_builtin.fltx then return true 
  286.       when prog.tp_builtin.fltdx then return true 
  287.       when prog.tp_builtin.ext_ob then return true 
  288. --    else return false end end;                                                -- NLP
  289.       else; end; return false; end;                                             -- NLP
  290.    
  291.    is_base_aref_type(tp:$TP):BOOL is
  292.       -- True if `tp' has an include path to AREF{CHAR}, AREF{INT}, 
  293.       -- AREF{FLT}, AREF{FLTD}, AREF{FLTX}, AREF{FLTDX}, or AREF{EXT_OB}.
  294.       typecase tp when TP_CLASS then 
  295.      im:IMPL:=prog.impl_tbl.impl_of(tp);
  296.      if void(im) then return false end;
  297.      ar:TP_CLASS:=im.arr; if void(ar) then return false end;       
  298.      if ar.name/=prog.ident_builtin.AREF_ident then return false end;
  299.      if void(ar.params) then
  300.         #OUT + "Compiler error, SIG::is_base_aref_type params=void.";
  301.         return false end;
  302.      if ar.params.size/=1 then
  303.         #OUT + "Compiler error, SIG::is_base_aref_type params.size/=1."; 
  304.         return false end;
  305.      case ar.params[0]
  306.      when prog.tp_builtin.char then return true 
  307.      when prog.tp_builtin.int then return true 
  308.      when prog.tp_builtin.flt then return true 
  309.      when prog.tp_builtin.fltd then return true
  310.      when prog.tp_builtin.fltx then return true
  311.      when prog.tp_builtin.fltdx then return true
  312.      when prog.tp_builtin.ext_ob then return true
  313.      else return false end
  314. --    else return false end end;                                                -- NLP
  315.       else; end; return false; end;                                             -- NLP
  316.     
  317.    is_legal_ext_abs:BOOL 
  318.       -- True if this signature is legal for an abstract routine
  319.       -- in an external class.
  320.       pre ~void(self) is
  321.       if name.is_iter then
  322.      prog.err("The iter signature " + str + 
  323.      " isn't allowed in an external class."); 
  324.      return false end;
  325.       loop a::=args.elt!;
  326.      if is_base_type(a) then 
  327.      elsif is_base_aref_type(a) then
  328.      else
  329.         prog.err("The signature " + str +
  330.         " is not legal for a routine without body in an external "
  331.         "class. The argument type " + a.str +
  332.         " is not of the right type."); return false end end;
  333.       if ~void(ret) and ~is_base_type(ret) then 
  334.         prog.err("The signature " + str +
  335.         " is not legal for a routine without body in an external "
  336.         "class. The return type " + ret.str + 
  337.         " is not of the right type."); return false end;
  338.       return true end;
  339.    
  340.    is_legal_ext_bod:BOOL
  341.       -- True if this signature is legal for a routine with a body
  342.       -- in an external class. 
  343.       pre ~void(self) is
  344.       if name.is_iter then
  345.      prog.err("The iter signature " + str + 
  346.      " isn't allowed in an external class."); 
  347.      return false end;
  348.       loop a::=args.elt!;
  349.      if is_base_type(a) then
  350.      else 
  351.         prog.err("The signature " + str +
  352.         " is not legal for a routine with body in an external "
  353.         "class. The argument type " + a.str +
  354.         " is not of the right type."); return false end end;
  355.       if ~void(ret) and ~is_base_type(ret) then 
  356.         prog.err("The signature " + str +
  357.         " is not legal for a routine with body in an external "
  358.         "class. The return type " + ret.str + 
  359.         " is not of the right type."); return false end;
  360.       return true end;
  361.    
  362. end; -- class SIG
  363.  
  364. -------------------------------------------------------------------
  365. class SIG_TBL is
  366.    -- Table of routine and iter signatures retrievable by name.
  367.    -- 
  368.    -- `get_query!(i:IDENT):SIG' yields each sig with the name `i'.
  369.    -- `test(SIG):BOOL' tests for the given sig.
  370.    -- `insert(SIG):SAME' inserts a sig.
  371.    -- `delete(SIG):SAME' deletes a sig.
  372.    -- `elt!:ELT' yields each sig.   
  373.    include FQSET{IDENT,SIG};   
  374.    
  375.    query_test(name:IDENT, s:SIG):BOOL is
  376.       -- True if `s' is a signature with the name `name'.
  377.       if void(s) then return false end;
  378.       return s.name=name end;
  379.    
  380.    query_hash(i:IDENT):INT is
  381.       -- A hash value computed from the name `i'.
  382.       return i.hash end;
  383.  
  384.    elt_hash(s:SIG):INT is
  385.       -- A hash value computed from the name of an element.
  386.       return s.name.hash end;
  387.  
  388.    private old_sig_eq_to(s:SIG):SIG 
  389.       -- Returns an element of self equal to `s' if one exists,
  390.       -- otherwise returns void.
  391.       pre ~void(s) is
  392.       loop r::=get_query!(s.name); if r=s then return r end end;
  393.       return void end;
  394.    
  395.     sig_eq_to(s:SIG):SIG
  396.       -- Returns an element of self equal to `s' if one exists,
  397.       -- otherwise returns void.  New implementation by MBK.  Much faster.
  398.       pre ~void(s) is
  399.     r ::= get(s);
  400. --    r2 ::= old_sig_eq_to(s);
  401.     
  402. --    if ~(r=r2) then
  403. --        #ERR + " sig_eq_to and old_sig_eq_to differ:"
  404. --        + r.str + " vs " + r2.str + '\n';
  405. --    end;
  406.     return r;
  407.     end;
  408.     
  409.    sig_conflicting_with(s:SIG):SIG 
  410.       -- Returns an element of self that conflicts with `s' if one 
  411.       -- exists, otherwise returns void.
  412.       pre ~void(s) is
  413.       loop r::=get_query!(s.name);
  414.      if r.conflicts_with(s) then return r end end;
  415.       return void end;
  416.       
  417. end; -- class SIG_TBL
  418.  
  419. -------------------------------------------------------------------
  420.