blob: 69b3e27ad75866cbadd708720348c1f29b19d77a [file] [log] [blame]
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package Type
import Globals "globals"
import Object "object"
export const /* form */ (
// internal types
UNDEF = iota; VOID; BAD; NIL;
// basic types
BOOL; UINT; INT; FLOAT; STRING; INTEGER;
// 'any' type
ANY;
// composite types
ALIAS; ARRAY; STRUCT; INTERFACE; MAP; CHANNEL; FUNCTION; POINTER; REFERENCE;
)
export const /* flag */ (
SEND = 1 << iota; // chan>
RECV; // chan< or method
)
// The 'Type' declaration should be here as well, but 6g cannot handle
// this due to cross-package circular references. For now it's all in
// globals.go.
export func FormStr(form int) string {
switch form {
case UNDEF: return "UNDEF";
case VOID: return "VOID";
case BAD: return "BAD";
case NIL: return "NIL";
case BOOL: return "BOOL";
case UINT: return "UINT";
case INT: return "INT";
case FLOAT: return "FLOAT";
case STRING: return "STRING";
case ANY: return "ANY";
case ALIAS: return "ALIAS";
case ARRAY: return "ARRAY";
case STRUCT: return "STRUCT";
case INTERFACE: return "INTERFACE";
case MAP: return "MAP";
case CHANNEL: return "CHANNEL";
case FUNCTION: return "FUNCTION";
case POINTER: return "POINTER";
case REFERENCE: return "REFERENCE";
}
return "<unknown Type form>";
}
export func Equal(x, y *Globals.Type) bool;
func Equal0(x, y *Globals.Type) bool {
if x == y {
return true; // identical types are equal
}
if x.form == BAD || y.form == BAD {
return true; // bad types are always equal (avoid excess error messages)
}
// TODO where to check for *T == nil ?
if x.form != y.form {
return false; // types of different forms are not equal
}
switch x.form {
case UNDEF, BAD:
break;
case NIL, BOOL, STRING, ANY:
return true;
case UINT, INT, FLOAT:
return x.size == y.size;
case ARRAY:
return
x.len_ == y.len_ &&
Equal(x.elt, y.elt);
case MAP:
return
Equal(x.aux, y.aux) &&
Equal(x.elt, y.elt);
case CHANNEL:
return
x.flags == y.flags &&
Equal(x.elt, y.elt);
case FUNCTION:
{ xp := x.scope.entries;
yp := x.scope.entries;
if x.flags != y.flags && // function or method
x.len_ != y.len_ && // number of parameters
xp.len_ != yp.len_ // recv + parameters + results
{
return false;
}
for p, q := xp.first, yp.first; p != nil; p, q = p.next, q.next {
xf := p.obj;
yf := q.obj;
if xf.kind != Object.VAR || yf.kind != Object.VAR {
panic "parameters must be vars";
}
if !Equal(xf.typ, yf.typ) {
return false;
}
}
}
return true;
case STRUCT:
/*
{ ObjList* xl = &x.scope.list;
ObjList* yl = &y.scope.list;
if xl.len() != yl.len() {
return false; // scopes of different sizes are not equal
}
for int i = xl.len(); i-- > 0; {
Object* xf = (*xl)[i];
Object* yf = (*yl)[i];
ASSERT(xf.kind == Object.VAR && yf.kind == Object.VAR);
if xf.name != yf.name) || ! EqualTypes(xf.type(), yf.type() {
return false;
}
}
}
return true;
*/
// Scopes must be identical for them to be equal.
// If we reach here, they weren't.
return false;
case INTERFACE:
panic "UNIMPLEMENTED";
return false;
case POINTER, REFERENCE:
return Equal(x.elt, y.elt);
}
panic "UNREACHABLE";
return false;
}
export func Equal(x, y *Globals.Type) bool {
res := Equal0(x, y);
// TODO should do the check below only in debug mode
if Equal0(y, x) != res {
panic "type equality must be symmetric";
}
return res;
}
export func Assigneable(from, to *Globals.Type) bool {
if Equal(from, to) {
return true;
}
panic "UNIMPLEMENTED";
return false;
}