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
39101613
Commit
39101613
authored
Feb 25, 2010
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gc: implement []int(string) and []byte(string)
R=ken2 CC=golang-dev
https://golang.org/cl/224060
parent
b86c0b0c
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
175 additions
and
14 deletions
+175
-14
builtin.c.boot
src/cmd/gc/builtin.c.boot
+2
-0
go.h
src/cmd/gc/go.h
+3
-2
runtime.go
src/cmd/gc/runtime.go
+2
-0
typecheck.c
src/cmd/gc/typecheck.c
+58
-2
walk.c
src/cmd/gc/walk.c
+22
-10
string.cgo
src/pkg/runtime/string.cgo
+31
-0
convlit.go
test/convlit.go
+27
-0
string_lit.go
test/string_lit.go
+30
-0
No files found.
src/cmd/gc/builtin.c.boot
View file @
39101613
...
...
@@ -26,6 +26,8 @@ char *runtimeimport =
"func \"\".intstring (? int64) string\n"
"func \"\".slicebytetostring (? []uint8) string\n"
"func \"\".sliceinttostring (? []int) string\n"
"func \"\".stringtoslicebyte (? string) []uint8\n"
"func \"\".stringtosliceint (? string) []int\n"
"func \"\".stringiter (? string, ? int) int\n"
"func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n"
"func \"\".slicecopy (to any, fr any, wid uint32) int\n"
...
...
src/cmd/gc/go.h
View file @
39101613
...
...
@@ -351,6 +351,7 @@ enum
OAPPENDSTR
,
OARRAY
,
OARRAYBYTESTR
,
OARRAYRUNESTR
,
OSTRARRAYBYTE
,
OSTRARRAYRUNE
,
OAS
,
OAS2
,
OAS2MAPW
,
OAS2FUNC
,
OAS2RECV
,
OAS2MAPR
,
OAS2DOTTYPE
,
OASOP
,
OBAD
,
OCALL
,
OCALLFUNC
,
OCALLMETH
,
OCALLINTER
,
...
...
@@ -411,7 +412,7 @@ enum
OTINTER
,
OTFUNC
,
OTARRAY
,
// misc
ODDD
,
...
...
@@ -458,7 +459,7 @@ enum
TIDEAL
,
// 32
TNIL
,
TBLANK
,
// pseudo-type for frame layout
TFUNCARGS
,
TCHANARGS
,
...
...
src/cmd/gc/runtime.go
View file @
39101613
...
...
@@ -38,6 +38,8 @@ func indexstring(string, int) byte
func
intstring
(
int64
)
string
func
slicebytetostring
([]
byte
)
string
func
sliceinttostring
([]
int
)
string
func
stringtoslicebyte
(
string
)
[]
byte
func
stringtosliceint
(
string
)
[]
int
func
stringiter
(
string
,
int
)
int
func
stringiter2
(
string
,
int
)
(
retk
int
,
retv
int
)
func
slicecopy
(
to
any
,
fr
any
,
wid
uint32
)
int
...
...
src/cmd/gc/typecheck.c
View file @
39101613
...
...
@@ -32,6 +32,7 @@ static void checklvalue(Node*, char*);
static
void
checkassign
(
Node
*
);
static
void
checkassignlist
(
NodeList
*
);
static
void
toslice
(
Node
**
);
static
void
stringtoarraylit
(
Node
**
);
void
typechecklist
(
NodeList
*
l
,
int
top
)
...
...
@@ -835,6 +836,13 @@ reswitch:
n
=
typecheckconv
(
n
,
n
->
left
,
n
->
type
,
1
,
"conversion"
);
if
(
n
->
type
==
T
)
goto
error
;
switch
(
n
->
op
)
{
case
OSTRARRAYBYTE
:
case
OSTRARRAYRUNE
:
if
(
n
->
left
->
op
==
OLITERAL
)
stringtoarraylit
(
&
n
);
break
;
}
goto
ret
;
case
OMAKE
:
...
...
@@ -1406,6 +1414,18 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et, char *desc)
}
}
// from string
if
(
istype
(
nt
,
TSTRING
)
&&
isslice
(
t
)
&&
t
->
sym
==
S
)
{
switch
(
t
->
type
->
etype
)
{
case
TUINT8
:
*
op
=
OSTRARRAYBYTE
;
return
1
;
case
TINT
:
*
op
=
OSTRARRAYRUNE
;
return
1
;
}
}
// convert to unsafe pointer
if
(
isptrto
(
t
,
TANY
)
&&
(
isptr
[
nt
->
etype
]
||
nt
->
etype
==
TUINTPTR
))
...
...
@@ -1534,7 +1554,7 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc)
// TODO(rsc): drop first if in DDD cleanup
if
(
t
->
etype
!=
TINTER
)
if
(
checkconv
(
nl
->
n
->
type
,
t
->
type
,
0
,
&
xx
,
&
yy
,
desc
)
<
0
)
yyerror
(
"cannot use %+N as type %T in %s"
,
nl
->
n
,
t
->
type
,
desc
);
yyerror
(
"cannot use %+N as type %T in %s"
,
nl
->
n
,
t
->
type
,
desc
);
}
goto
out
;
}
...
...
@@ -1587,7 +1607,7 @@ exportassignok(Type *t, char *desc)
// it only happens for fields in a ... struct.
if
(
s
!=
nil
&&
!
exportname
(
s
->
name
)
&&
s
->
pkg
!=
localpkg
)
{
char
*
prefix
;
prefix
=
""
;
if
(
desc
!=
nil
)
prefix
=
" in "
;
...
...
@@ -2164,3 +2184,39 @@ typecheckfunc(Node *n)
if
(
rcvr
!=
nil
&&
n
->
shortname
!=
N
&&
!
isblank
(
n
->
shortname
))
addmethod
(
n
->
shortname
->
sym
,
t
,
1
);
}
static
void
stringtoarraylit
(
Node
**
np
)
{
int32
i
;
NodeList
*
l
;
Strlit
*
s
;
char
*
p
,
*
ep
;
Rune
r
;
Node
*
nn
,
*
n
;
n
=
*
np
;
if
(
n
->
left
->
op
!=
OLITERAL
||
n
->
left
->
val
.
ctype
!=
CTSTR
)
fatal
(
"stringtoarraylit %N"
,
n
);
s
=
n
->
left
->
val
.
u
.
sval
;
l
=
nil
;
p
=
s
->
s
;
ep
=
s
->
s
+
s
->
len
;
i
=
0
;
if
(
n
->
type
->
type
->
etype
==
TUINT8
)
{
// raw []byte
while
(
p
<
ep
)
l
=
list
(
l
,
nod
(
OKEY
,
nodintconst
(
i
++
),
nodintconst
((
uchar
)
*
p
++
)));
}
else
{
// utf-8 []int
while
(
p
<
ep
)
{
p
+=
chartorune
(
&
r
,
p
);
l
=
list
(
l
,
nod
(
OKEY
,
nodintconst
(
i
++
),
nodintconst
(
r
)));
}
}
nn
=
nod
(
OCOMPLIT
,
N
,
typenod
(
n
->
type
));
nn
->
list
=
l
;
typecheck
(
&
nn
,
Erv
);
*
np
=
nn
;
}
src/cmd/gc/walk.c
View file @
39101613
...
...
@@ -8,6 +8,7 @@ static Node* walkprint(Node*, NodeList**, int);
static
Node
*
conv
(
Node
*
,
Type
*
);
static
Node
*
mapfn
(
char
*
,
Type
*
);
static
Node
*
makenewvar
(
Type
*
,
NodeList
**
,
Node
**
);
enum
{
Inone
,
...
...
@@ -122,7 +123,7 @@ static void
domethod
(
Node
*
n
)
{
Node
*
nt
;
nt
=
n
->
type
->
nname
;
typecheck
(
&
nt
,
Etype
);
if
(
nt
->
type
==
T
)
{
...
...
@@ -142,7 +143,7 @@ walkdeftype(Node *n)
int
maplineno
,
embedlineno
,
lno
;
Type
*
t
;
NodeList
*
l
;
nwalkdeftype
++
;
lno
=
lineno
;
setlineno
(
n
);
...
...
@@ -183,7 +184,7 @@ walkdeftype(Node *n)
ret:
lineno
=
lno
;
// if there are no type definitions going on, it's safe to
// try to resolve the method types for the interfaces
// we just read.
...
...
@@ -868,7 +869,7 @@ walkexpr(Node **np, NodeList **init)
case
OINDEX
:
walkexpr
(
&
n
->
left
,
init
);
walkexpr
(
&
n
->
right
,
init
);
// if range of type cannot exceed static array bound,
// disable bounds check
if
(
!
isslice
(
n
->
left
->
type
))
...
...
@@ -1092,10 +1093,20 @@ walkexpr(Node **np, NodeList **init)
goto
ret
;
case
OARRAYRUNESTR
:
// sliceinttostring([]
byte
) string;
// sliceinttostring([]
int
) string;
n
=
mkcall
(
"sliceinttostring"
,
n
->
type
,
init
,
n
->
left
);
goto
ret
;
case
OSTRARRAYBYTE
:
// stringtoslicebyte(string) []byte;
n
=
mkcall
(
"stringtoslicebyte"
,
n
->
type
,
init
,
n
->
left
);
goto
ret
;
case
OSTRARRAYRUNE
:
// stringtosliceint(string) []int
n
=
mkcall
(
"stringtosliceint"
,
n
->
type
,
init
,
n
->
left
);
goto
ret
;
case
OCMPIFACE
:
// ifaceeq(i1 any-1, i2 any-2) (ret bool);
if
(
!
eqtype
(
n
->
left
->
type
,
n
->
right
->
type
))
...
...
@@ -1117,6 +1128,7 @@ walkexpr(Node **np, NodeList **init)
case
OARRAYLIT
:
case
OMAPLIT
:
case
OSTRUCTLIT
:
arraylit:
nvar
=
nod
(
OXXX
,
N
,
N
);
tempname
(
nvar
,
n
->
type
);
anylit
(
n
,
nvar
,
init
);
...
...
@@ -1448,18 +1460,18 @@ mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init)
{
Node
*
a
,
*
n
;
Type
*
tslice
;
tslice
=
typ
(
TARRAY
);
tslice
->
type
=
l
->
type
->
type
;
tslice
->
bound
=
-
1
;
n
=
nod
(
OCOMPLIT
,
N
,
typenod
(
tslice
));
n
->
list
=
lr0
;
typecheck
(
&
n
,
Erv
);
if
(
n
->
type
==
T
)
fatal
(
"mkdotargslice: typecheck failed"
);
walkexpr
(
&
n
,
init
);
a
=
nod
(
OAS
,
nodarg
(
l
,
fp
),
n
);
nn
=
list
(
nn
,
convas
(
a
,
init
));
return
nn
;
...
...
@@ -1758,7 +1770,7 @@ walkprint(Node *nn, NodeList **init, int defer)
n
=
nod
(
OCONV
,
n
,
N
);
n
->
type
=
t
;
}
if
(
defer
)
{
intypes
=
list
(
intypes
,
nod
(
ODCLFIELD
,
N
,
typenod
(
t
)));
args
=
list
(
args
,
n
);
...
...
@@ -1788,7 +1800,7 @@ walkprint(Node *nn, NodeList **init, int defer)
calls
=
list
(
calls
,
mkcall
(
"printnl"
,
T
,
nil
));
typechecklist
(
calls
,
Etop
);
walkexprlist
(
calls
,
init
);
if
(
op
==
OPANIC
||
op
==
OPANICN
)
r
=
mkcall
(
"panicl"
,
T
,
nil
);
else
...
...
src/pkg/runtime/string.cgo
View file @
39101613
...
...
@@ -4,6 +4,7 @@
package
runtime
#
include
"runtime.h"
#
include
"malloc.h"
String
emptystring
;
...
...
@@ -210,6 +211,12 @@ func slicebytetostring(b Slice) (s String) {
mcpy
(
s
.
str
,
b
.
array
,
s
.
len
);
}
func
stringtoslicebyte
(
s
String
)
(
b
Slice
)
{
b
.
array
=
mallocgc
(
s
.
len
,
RefNoPointers
,
1
,
1
);
b
.
len
=
s
.
len
;
b
.
cap
=
s
.
len
;
mcpy
(
b
.
array
,
s
.
str
,
s
.
len
);
}
func
sliceinttostring
(
b
Slice
)
(
s
String
)
{
int32
siz1
,
siz2
,
i
;
...
...
@@ -233,6 +240,30 @@ func sliceinttostring(b Slice) (s String) {
s
.
len
=
siz2
;
}
func
stringtosliceint
(
s
String
)
(
b
Slice
)
{
int32
n
;
int32
dum
,
*
r
;
uint8
*
p
,
*
ep
;
//
two
passes
.
//
unlike
sliceinttostring
,
no
race
because
strings
are
immutable
.
p
=
s
.
str
;
ep
=
s
.
str
+
s
.
len
;
n
=
0
;
while
(
p
<
ep
)
{
p
+=
charntorune
(&
dum
,
p
,
ep
-
p
);
n
++;
}
b
.
array
=
mallocgc
(
n
*
sizeof
(
r
[
0
]),
RefNoPointers
,
1
,
1
);
b
.
len
=
n
;
b
.
cap
=
n
;
p
=
s
.
str
;
r
=
(
int32
*)
b
.
array
;
while
(
p
<
ep
)
p
+=
charntorune
(
r
++,
p
,
ep
-
p
);
}
enum
{
Runeself
=
0x80
,
...
...
test/convlit.go
View file @
39101613
...
...
@@ -35,3 +35,30 @@ var good2 int = 1.0;
var
good3
int
=
1e9
;
var
good4
float
=
1e20
;
// explicit conversion of string is okay
var
_
=
[]
int
(
"abc"
)
var
_
=
[]
byte
(
"abc"
)
// implicit is not
var
_
[]
int
=
"abc"
// ERROR "cannot use|incompatible|invalid"
var
_
[]
byte
=
"abc"
// ERROR "cannot use|incompatible|invalid"
// named string is okay
type
Tstring
string
var
ss
Tstring
=
"abc"
var
_
=
[]
int
(
ss
)
var
_
=
[]
byte
(
ss
)
// implicit is still not
var
_
[]
int
=
ss
// ERROR "cannot use|incompatible|invalid"
var
_
[]
byte
=
ss
// ERROR "cannot use|incompatible|invalid"
// named slice is not
type
Tint
[]
int
type
Tbyte
[]
byte
var
_
=
Tint
(
"abc"
)
// ERROR "convert|incompatible|invalid"
var
_
=
Tbyte
(
"abc"
)
// ERROR "convert|incompatible|invalid"
// implicit is still not
var
_
Tint
=
"abc"
// ERROR "cannot use|incompatible|invalid"
var
_
Tbyte
=
"abc"
// ERROR "cannot use|incompatible|invalid"
test/string_lit.go
View file @
39101613
...
...
@@ -34,6 +34,19 @@ func assert(a, b, c string) {
}
}
const
(
gx1
=
"aä本☺"
gx2
=
"aä
\xFF\xFF
本☺"
gx2fix
=
"aä
\uFFFD\uFFFD
本☺"
)
var
(
gr1
=
[]
int
(
gx1
)
gr2
=
[]
int
(
gx2
)
gb1
=
[]
byte
(
gx1
)
gb2
=
[]
byte
(
gx2
)
)
func
main
()
{
ecode
=
0
;
s
:=
...
...
@@ -86,5 +99,22 @@ func main() {
r
=
0x10ffff
+
1
;
s
=
string
(
r
);
assert
(
s
,
"
\xef\xbf\xbd
"
,
"too-large rune"
);
assert
(
string
(
gr1
),
gx1
,
"global ->[]int"
)
assert
(
string
(
gr2
),
gx2fix
,
"global invalid ->[]int"
)
assert
(
string
(
gb1
),
gx1
,
"->[]byte"
)
assert
(
string
(
gb2
),
gx2
,
"global invalid ->[]byte"
)
var
(
r1
=
[]
int
(
gx1
)
r2
=
[]
int
(
gx2
)
b1
=
[]
byte
(
gx1
)
b2
=
[]
byte
(
gx2
)
)
assert
(
string
(
r1
),
gx1
,
"->[]int"
)
assert
(
string
(
r2
),
gx2fix
,
"invalid ->[]int"
)
assert
(
string
(
b1
),
gx1
,
"->[]byte"
)
assert
(
string
(
b2
),
gx2
,
"invalid ->[]byte"
)
os
.
Exit
(
ecode
);
}
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