Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
2119294a
Commit
2119294a
authored
Sep 14, 2008
by
Ken Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
methods on any type
-- but only *struct tested R=r OCL=15326 CL=15326
parent
b9cee1b6
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
169 additions
and
177 deletions
+169
-177
gsubr.c
src/cmd/6g/gsubr.c
+3
-3
obj.c
src/cmd/6g/obj.c
+10
-2
dcl.c
src/cmd/gc/dcl.c
+55
-45
export.c
src/cmd/gc/export.c
+20
-1
go.h
src/cmd/gc/go.h
+9
-5
go.y
src/cmd/gc/go.y
+7
-2
walk.c
src/cmd/gc/walk.c
+60
-116
print.c
src/runtime/print.c
+4
-3
runtime.c
src/runtime/runtime.c
+1
-0
No files found.
src/cmd/6g/gsubr.c
View file @
2119294a
...
...
@@ -306,15 +306,15 @@ loop:
switch
(
t
->
etype
)
{
default:
fatal
(
"signame: unknown type %T"
,
t
);
e
=
"sigs"
;
break
;
case
TPTR32
:
case
TPTR64
:
t
=
t
->
type
;
goto
loop
;
case
TSTRUCT
:
e
=
"sigs"
;
break
;
case
TINTER
:
e
=
"sigi"
;
break
;
...
...
src/cmd/6g/obj.c
View file @
2119294a
...
...
@@ -566,7 +566,12 @@ dumpsignatures(void)
a
=
nil
;
o
=
0
;
for
(
f
=
t
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
f
=
t
->
type
;
if
(
et
!=
TINTER
)
f
=
t
->
method
;
for
(;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
type
->
etype
!=
TFUNC
)
continue
;
...
...
@@ -589,8 +594,11 @@ dumpsignatures(void)
a
->
name
=
sp
+
1
;
a
->
hash
=
PRIME8
*
stringhash
(
a
->
name
)
+
PRIME9
*
typehash
(
f
->
type
,
0
);
a
->
sym
=
f
->
sym
;
a
->
offset
=
o
;
snprint
(
namebuf
,
sizeof
(
namebuf
),
"%s_%s"
,
at
.
sym
->
name
+
5
,
f
->
sym
->
name
);
a
->
sym
=
lookup
(
namebuf
);
o
++
;
}
...
...
src/cmd/gc/dcl.c
View file @
2119294a
...
...
@@ -219,6 +219,10 @@ methodname(Node *n, Type *t)
{
Sym
*
s
;
if
(
t
==
T
)
goto
bad
;
// method receiver must be typename or *typename
s
=
S
;
if
(
t
->
sym
!=
S
)
s
=
t
->
sym
;
...
...
@@ -226,12 +230,9 @@ methodname(Node *n, Type *t)
t
=
t
->
type
;
if
(
t
->
sym
!=
S
)
s
=
t
->
sym
;
// if(t->etype != TSTRUCT)
// goto bad;
if
(
s
==
S
)
goto
bad
;
snprint
(
namebuf
,
sizeof
(
namebuf
),
"%s_%s"
,
s
->
name
,
n
->
sym
->
name
);
return
newname
(
lookup
(
namebuf
));
...
...
@@ -242,71 +243,85 @@ bad:
/*
* add a method, declared as a function,
*
into the structur
e
*
n is fieldname, pa is base type, t is function typ
e
*/
void
addmethod
(
Node
*
n
,
Type
*
pa
,
Type
*
t
)
addmethod
(
Node
*
n
,
Type
*
t
,
int
local
)
{
Type
*
f
,
*
d
,
*
p
;
Sym
*
s
;
Type
*
f
,
*
d
,
*
pa
;
Sym
*
st
,
*
sf
;
int
ptr
;
// get field sym
if
(
n
==
N
)
goto
bad
;
if
(
n
->
op
!=
ONAME
)
goto
bad
;
s
=
n
->
sym
;
if
(
s
==
S
)
s
f
=
n
->
sym
;
if
(
s
f
==
S
)
goto
bad
;
// get parent type sym
pa
=
*
getthis
(
t
);
// ptr to this structure
if
(
pa
==
T
)
goto
bad
;
if
(
!
isptr
[
pa
->
etype
])
goto
bad
;
p
=
pa
->
type
;
if
(
p
==
T
)
goto
bad
;
if
(
p
->
etype
!=
TSTRUCT
)
pa
=
pa
->
type
;
// ptr to this field
if
(
pa
==
T
)
goto
bad
;
if
(
p
->
sym
==
S
)
pa
=
pa
->
type
;
// ptr to this type
if
(
pa
==
T
)
goto
bad
;
if
(
p
->
type
==
T
)
{
n
=
nod
(
ODCLFIELD
,
newname
(
s
),
N
);
n
->
type
=
t
;
// optionally rip off ptr to type
ptr
=
0
;
if
(
isptr
[
pa
->
etype
])
{
if
(
pa
->
sym
==
S
||
pa
->
sym
->
name
[
0
]
==
'_'
)
{
ptr
=
1
;
pa
=
pa
->
type
;
if
(
pa
==
T
)
goto
bad
;
}
}
if
(
pa
->
etype
==
TINTER
)
yyerror
(
"no methods on interfaces"
);
stotype
(
n
,
&
p
->
type
);
// and finally the receiver sym
st
=
pa
->
sym
;
if
(
st
==
S
)
goto
bad
;
if
(
local
&&
!
st
->
local
)
{
yyerror
(
"method receiver type must be locally defined: %S"
,
st
);
return
;
}
n
=
nod
(
ODCLFIELD
,
newname
(
sf
),
N
);
n
->
type
=
t
;
if
(
pa
->
method
==
T
)
pa
->
methptr
=
ptr
;
if
(
pa
->
methptr
!=
ptr
)
yyerror
(
"combination of direct and ptr receivers of: %S"
,
st
);
d
=
T
;
// last found
for
(
f
=
p
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
for
(
f
=
p
a
->
method
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
etype
!=
TFIELD
)
fatal
(
"addmethod: not TFIELD: %N"
,
f
);
if
(
strcmp
(
s
->
name
,
f
->
sym
->
name
)
!=
0
)
{
if
(
strcmp
(
s
f
->
name
,
f
->
sym
->
name
)
!=
0
)
{
d
=
f
;
continue
;
}
// if a field matches a non-this function
// then delete it and let it be redeclared
if
(
methcmp
(
t
,
f
->
type
))
{
if
(
d
==
T
)
{
p
->
type
=
f
->
down
;
continue
;
}
d
->
down
=
f
->
down
;
continue
;
}
if
(
!
eqtype
(
t
,
f
->
type
,
0
))
yyerror
(
"field redeclared as method: %S"
,
s
);
return
;
yyerror
(
"method redeclared: %S of type %S"
,
sf
,
st
);
}
n
=
nod
(
ODCLFIELD
,
newname
(
s
),
N
);
n
->
type
=
t
;
if
(
d
==
T
)
stotype
(
n
,
&
p
->
type
);
stotype
(
n
,
&
p
a
->
method
);
else
stotype
(
n
,
&
d
->
down
);
if
(
dflag
())
print
(
"method %S of type %s%S
\n
"
,
sf
,
(
ptr
?
"*"
:
""
),
st
);
return
;
bad:
...
...
@@ -393,11 +408,6 @@ funchdr(Node *n)
markdcl
();
funcargs
(
n
->
type
);
if
(
n
->
type
->
thistuple
>
0
)
{
Type
*
t
;
t
=
*
getthis
(
n
->
type
);
addmethod
(
n
->
nname
,
t
->
type
->
type
,
n
->
type
);
}
}
void
...
...
src/cmd/gc/export.c
View file @
2119294a
...
...
@@ -233,6 +233,13 @@ dumpexporttype(Sym *s)
Bprint
(
bout
,
"%lS %d %lS
\n
"
,
s
,
t
->
chan
,
t
->
type
->
sym
);
break
;
}
for
(
f
=
t
->
method
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
etype
!=
TFIELD
)
fatal
(
"dumpexporttype: method not field: %lT"
,
f
);
reexport
(
f
->
type
);
Bprint
(
bout
,
"
\t
func %S %lS
\n
"
,
f
->
sym
,
f
->
type
->
sym
);
}
}
void
...
...
@@ -548,7 +555,6 @@ doimport3(Node *ss, Node *n)
t
->
thistuple
=
importcount
(
t
->
type
);
t
->
outtuple
=
importcount
(
t
->
type
->
down
);
t
->
intuple
=
importcount
(
t
->
type
->
down
->
down
);
dowidth
(
t
);
importfuncnam
(
t
);
...
...
@@ -648,3 +654,16 @@ doimport8(Node *ss, Val *v, Node *st)
importaddtyp
(
ss
,
t
);
}
/*
* LFUNC importsym sym
* method type
*/
void
doimport9
(
Sym
*
sf
,
Node
*
ss
)
{
Sym
*
sfun
;
sfun
=
getimportsym
(
ss
);
addmethod
(
newname
(
sf
),
sfun
->
otype
,
0
);
}
src/cmd/gc/go.h
View file @
2119294a
...
...
@@ -115,6 +115,7 @@ struct Type
uchar
chan
;
uchar
recur
;
// to detect loops
uchar
trecur
;
// to detect loops
uchar
methptr
;
// all methods are pointers to this type
// TFUNCT
uchar
thistuple
;
...
...
@@ -122,9 +123,14 @@ struct Type
uchar
intuple
;
uchar
outnamed
;
Type
*
method
;
Sym
*
sym
;
int32
vargen
;
// unique name for OTYPE/ONAME
Node
*
nname
;
vlong
argwid
;
// most nodes
Type
*
type
;
vlong
width
;
// offset in TFIELD, width in all others
...
...
@@ -135,10 +141,6 @@ struct Type
// TPTR
Type
*
nforw
;
// TFUNCT
Node
*
nname
;
vlong
argwid
;
// TARRAY
int32
bound
;
// negative is dynamic array
};
...
...
@@ -609,6 +611,7 @@ void dodcltype(Type*, Type*);
void
dodclconst
(
Node
*
,
Node
*
);
void
defaultlit
(
Node
*
);
int
listcount
(
Node
*
);
void
addmethod
(
Node
*
,
Type
*
,
int
);
Node
*
methodname
(
Node
*
,
Type
*
);
Type
*
functype
(
Node
*
,
Node
*
,
Node
*
);
char
*
thistypenam
(
Node
*
);
...
...
@@ -658,6 +661,7 @@ void doimport5(Node*, Val*);
void
doimport6
(
Node
*
,
Node
*
);
void
doimport7
(
Node
*
,
Node
*
);
void
doimport8
(
Node
*
,
Val
*
,
Node
*
);
void
doimport9
(
Sym
*
,
Node
*
);
/*
* walk.c
...
...
@@ -671,7 +675,7 @@ Type* walkswitch(Node*, Type*(*)(Node*, Type*));
int
casebody
(
Node
*
);
void
walkselect
(
Node
*
);
int
whatis
(
Node
*
);
void
walkdot
(
Node
*
,
int
);
void
walkdot
(
Node
*
);
Node
*
ascompatee
(
int
,
Node
**
,
Node
**
);
Node
*
ascompatet
(
int
,
Node
**
,
Type
**
,
int
);
Node
*
ascompatte
(
int
,
Type
**
,
Node
**
,
int
);
...
...
src/cmd/gc/go.y
View file @
2119294a
...
...
@@ -1057,12 +1057,12 @@ fndcl:
|
'('
oarg_type_list
')'
new_name
'('
oarg_type_list
')'
fnres
{
b0stack
=
dclstack
;
//
mark
base
for
fn
literals
if
($
2
==
N
||
$
2
->
op
==
OLIST
)
yyerror
(
"syntax error in method receiver"
);
$$
=
nod
(
ODCLFUNC
,
N
,
N
);
$$->
nname
=
methodname
($
4
,
$
2
->
type
);
$$->
type
=
functype
($
2
,
$
6
,
$
8
);
funchdr
($$);
addmethod
($
4
,
$$->
type
,
1
);
}
fntype
:
...
...
@@ -1573,6 +1573,11 @@ hidden_import:
//
type
interface
doimport8
($
2
,
&$
3
,
$
4
);
}
|
LFUNC
sym1
hidden_importsym
{
//
method
doimport9
($
2
,
$
3
);
}
isym
:
sym1
'.'
sym2
...
...
src/cmd/gc/walk.c
View file @
2119294a
...
...
@@ -17,10 +17,6 @@ int
walkret
(
Node
*
n
)
{
// until gri gets rid
// of the bugs on this
return
0
;
loop:
if
(
n
!=
N
)
switch
(
n
->
op
)
{
...
...
@@ -866,7 +862,7 @@ loop:
case
ODOTINTER
:
if
(
top
==
Etop
)
goto
nottop
;
walkdot
(
n
,
top
);
walkdot
(
n
);
goto
ret
;
case
OADDR
:
...
...
@@ -1323,17 +1319,15 @@ walkselect(Node *sel)
* normal binary operations.
*/
Type
*
lookdot
(
Node
*
n
,
Type
*
t
,
int
d
)
lookdot
(
Node
*
n
,
Type
*
f
)
{
Type
*
f
,
*
r
,
*
c
;
Type
*
r
,
*
c
;
Sym
*
s
;
r
=
T
;
s
=
n
->
sym
;
if
(
d
>
0
)
goto
deep
;
for
(
f
=
t
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
for
(;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
sym
==
S
)
continue
;
if
(
f
->
sym
!=
s
)
...
...
@@ -1345,38 +1339,18 @@ lookdot(Node *n, Type *t, int d)
r
=
f
;
}
return
r
;
deep:
/* deeper look after shallow failed */
for
(
f
=
t
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
// only look at unnamed sub-structures
// BOTCH no such thing -- all are assigned temp names
if
(
f
->
sym
!=
S
)
continue
;
c
=
f
->
type
;
if
(
c
->
etype
!=
TSTRUCT
)
continue
;
c
=
lookdot
(
n
,
c
,
d
-
1
);
if
(
c
==
T
)
continue
;
if
(
r
!=
T
)
{
yyerror
(
"ambiguous unnamed DOT reference %s"
,
s
->
name
);
break
;
}
r
=
c
;
}
return
r
;
}
void
walkdot
(
Node
*
n
,
int
top
)
walkdot
(
Node
*
n
)
{
Node
*
mn
;
Type
*
t
,
*
f
;
int
i
;
if
(
n
->
left
==
N
||
n
->
right
==
N
)
return
;
if
(
n
->
op
==
ODOTINTER
||
n
->
op
==
ODOTMETH
)
return
;
// already done
walktype
(
n
->
left
,
Erv
);
if
(
n
->
right
->
op
!=
ONAME
)
{
...
...
@@ -1395,50 +1369,29 @@ walkdot(Node *n, int top)
n
->
op
=
ODOTPTR
;
}
if
(
n
->
right
->
op
!=
ONAME
)
fatal
(
"walkdot: not name %O"
,
n
->
right
->
op
);
switch
(
t
->
etype
)
{
default:
badtype
(
ODOT
,
t
,
T
);
return
;
case
TSTRUCT
:
case
TINTER
:
for
(
i
=
0
;
i
<
5
;
i
++
)
{
f
=
lookdot
(
n
->
right
,
t
,
i
);
if
(
f
!=
T
)
break
;
}
// look up the field as TYPE_name
// for a mothod. botch this should
// be done better.
if
(
f
==
T
&&
t
->
etype
==
TSTRUCT
)
{
mn
=
methodname
(
n
->
right
,
t
);
for
(
i
=
0
;
i
<
5
;
i
++
)
{
f
=
lookdot
(
mn
,
t
,
i
);
if
(
f
!=
T
)
break
;
}
}
if
(
f
==
T
)
{
yyerror
(
"undefined DOT reference %N"
,
n
->
right
);
break
;
}
n
->
xoffset
=
f
->
width
;
n
->
right
=
f
->
nname
;
// substitute real name
n
->
type
=
f
->
type
;
if
(
n
->
type
->
etype
==
TFUNC
)
{
n
->
op
=
ODOTMETH
;
if
(
t
->
etype
==
TINTER
)
{
// as a structure field
if
(
t
->
etype
==
TSTRUCT
||
t
->
etype
==
TINTER
)
{
f
=
lookdot
(
n
->
right
,
t
->
type
);
if
(
f
!=
T
)
{
n
->
xoffset
=
f
->
width
;
n
->
right
=
f
->
nname
;
// substitute real name
n
->
type
=
f
->
type
;
if
(
t
->
etype
==
TINTER
)
n
->
op
=
ODOTINTER
;
}
return
;
}
break
;
}
f
=
lookdot
(
n
->
right
,
t
->
method
);
if
(
f
==
T
)
{
yyerror
(
"undefined DOT reference %N"
,
n
->
right
);
return
;
}
n
->
xoffset
=
f
->
width
;
n
->
right
=
methodname
(
n
->
right
,
t
);
n
->
type
=
f
->
type
;
n
->
op
=
ODOTMETH
;
}
Node
*
...
...
@@ -1841,25 +1794,21 @@ fixmap(Type *tm)
Type
*
t
;
t
=
tm
->
type
;
if
(
t
==
T
)
{
fatal
(
"fixmap: t nil"
);
return
T
;
}
if
(
t
->
etype
!=
TMAP
)
{
fatal
(
"fixmap: %lT not map"
,
tm
);
return
T
;
}
if
(
t
->
down
==
T
||
t
->
type
==
T
)
{
fatal
(
"fixmap: map key/value types are nil"
);
return
T
;
}
if
(
t
==
T
)
goto
bad
;
if
(
t
->
etype
!=
TMAP
)
goto
bad
;
if
(
t
->
down
==
T
||
t
->
type
==
T
)
goto
bad
;
dowidth
(
t
->
down
);
dowidth
(
t
->
type
);
return
t
;
bad:
yyerror
(
"not a map: %lT"
,
tm
);
return
T
;
}
Type
*
...
...
@@ -1867,25 +1816,23 @@ fixchan(Type *tm)
{
Type
*
t
;
if
(
tm
==
T
)
goto
bad
;
t
=
tm
->
type
;
if
(
t
==
T
)
{
fatal
(
"fixchan: t nil"
);
return
T
;
}
if
(
t
->
etype
!=
TCHAN
)
{
fatal
(
"fixchan: %lT not chan"
,
tm
);
return
T
;
}
if
(
t
->
type
==
T
)
{
fatal
(
"fixchan: chan element type is nil"
);
return
T
;
}
if
(
t
==
T
)
goto
bad
;
if
(
t
->
etype
!=
TCHAN
)
goto
bad
;
if
(
t
->
type
==
T
)
goto
bad
;
dowidth
(
t
->
type
);
return
t
;
bad:
yyerror
(
"not a channel: %lT"
,
tm
);
return
T
;
}
static
int
...
...
@@ -2288,24 +2235,21 @@ fixarray(Type *tm)
Type
*
t
;
t
=
tm
->
type
;
if
(
t
==
T
)
{
fatal
(
"fixarray: t nil"
);
return
T
;
}
if
(
t
->
etype
!=
TARRAY
)
{
fatal
(
"fixarray: %lT not array"
,
tm
);
return
T
;
}
if
(
t
->
type
==
T
)
{
fatal
(
"fixarray: array element type is nil"
);
return
T
;
}
if
(
t
==
T
)
goto
bad
;
if
(
t
->
etype
!=
TARRAY
)
goto
bad
;
if
(
t
->
type
==
T
)
goto
bad
;
dowidth
(
t
->
type
);
return
t
;
bad:
yyerror
(
"not an array: %lT"
,
tm
);
return
T
;
}
Node
*
...
...
src/runtime/print.c
View file @
2119294a
...
...
@@ -96,12 +96,13 @@ sys·printfloat(float64 v)
buf
[
1
]
=
buf
[
2
];
buf
[
2
]
=
'.'
;
buf
[
n
+
2
]
=
'+'
;
buf
[
n
+
2
]
=
'e'
;
buf
[
n
+
3
]
=
'+'
;
if
(
e
<
0
)
{
e
=
-
e
;
buf
[
n
+
2
]
=
'-'
;
buf
[
n
+
3
]
=
'-'
;
}
buf
[
n
+
3
]
=
'e'
;
buf
[
n
+
4
]
=
(
e
/
10
)
+
'0'
;
buf
[
n
+
5
]
=
(
e
%
10
)
+
'0'
;
sys
·
write
(
1
,
buf
,
n
+
6
);
...
...
src/runtime/runtime.c
View file @
2119294a
...
...
@@ -201,6 +201,7 @@ loop2:
hash
[
h
]
=
m
;
return
nil
;
}
if
(
ihash
!=
ss
[
ns
].
hash
||
strcmp
(
sname
,
iname
)
!=
0
)
{
ns
++
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment