Upload
moriyoshi-koizumi
View
236
Download
2
Embed Size (px)
Citation preview
All I know about rsc.io/c2goMoriyoshi KoizumiOpen Collector, Inc.
Hey
I can be found amongst CONTRIBUTORS :)
rsc.io/c2go
C to Go translation tool behind the Go's self-hosting effort.
Written by rsc.
Apparently not intended to be a generic translation tool.
$ go get rsc.io/c2go
こんにちは、世界void print(char *fmt, ...);
void main(){ print("Hello, %s.\n", "world");}
⬇️ bin/c2go -dst $GOPATH hello.c
package main
func main() { fmt.Printf("Hello, %s.\n", "world")}
(generated under $GOPATH/src/main)
Quicksort1
Quicksort1
Involves pointer arithmetics, compound types, and function pointers.
Quicksort1 (code)
int print(const char *fmt, ...);
typedef struct Data { int v;} Data;
void swap(Data *a, Data *b){ Data v = *a; *a = *b; *b = v;}
int cmp(Data *a, Data *b){ if (a->v < b->v) return -1; else if (a->v > b->v) return 1; else return 0;}...
Quicksort1 (code)
...void _qsort(Data *d, int l, int (*cmp)(Data *a, Data *b)){ int pivot, le, i, j; Data pv; if (l == 0) return; le = l - 1; pivot = l / 2; pv = d[pivot]; swap(&d[pivot], &d[le]); i = 0; for (j = 0; j < le; j++) { if (cmp(&d[j], &pv) < 0) { swap(&d[i], &d[j]); i++; } } swap(&d[i], &d[le]); _qsort(d, i, cmp); if (l > i) _qsort(&d[i + 1], l - (i + 1), cmp);}...
Quicksort1 (code)
...void main() { int i; Data values[] = { { 1 }, { 9 }, { 5 }, { 2 }, { 4 }, { 3 }, { 8 }, { 6 }, { 7 } }; _qsort(values, 9, cmp); for (i = 0; i < 9; i++) print("%d\n", values[i].v);}
Quicksort1
Compile:
$ cc -o qsort1 qsort1.c $GO_1_4_ROOT/pkg/obj/darwin_amd64/lib9.a
Run:
$ ./qsort1123456789
Quicksort1
Translate:
$ c2go -dst $GOPATH qsort1.c
No worry about the message; this is a warning.
main/qsort1.go: cannot find copyright notice in C file qsort1.c
Generated code:
package main
type Data struct { v int}
func swap(a *Data, b *Data) { var v Data = *a *a = *b *b = v}...
Quicksort1
...func _qsort(d *Data, l int, cmp func(*Data, *Data) int) { var pivot int var le int var i int var j int var pv Data if l == 0 { return } le = l - 1 pivot = l / 2 pv = d[pivot] swap(&d[pivot], &d[le])...
Looks like it went well so far, but Aw, Snap! #
src/main/qsort1.go:24: invalid operation: d[pivot] (type *Data does not support indexing)src/main/qsort1.go:25: invalid operation: d[pivot] (type *Data does not support indexing)src/main/qsort1.go:25: invalid operation: d[le] (type *Data does not support indexing)...
Quicksort2
Quicksort2
int print(const char *fmt, ...);
typedef struct Data { int v;} Data;
typedef struct DataSlice { Data *p; int len; int cap;} DataSlice;
Quicksort2
...void swap(Data *a, Data *b){ Data v = *a; *a = *b; *b = v;}
int cmp(Data *a, Data *b){ if (a->v < b->v) return -1; else if (a->v > b->v) return 1; else return 0;}...
Quicksort2
...void _qsort(DataSlice *ds, int (*cmp)(Data *a, Data *b)){ int pivot, le, i, j; Data pv; if (ds->len == 0) return; le = ds->len - 1; pivot = ds->len / 2; pv = ds->p[pivot]; swap(&ds->p[pivot], &ds->p[le]); i = 0; for (j = 0; j < le; j++) { if (cmp(&ds->p[j], &pv) < 0) { swap(&ds->p[i], &ds->p[j]); i++; } } swap(&ds->p[i], &ds->p[le]);...
Quicksort2
... { DataSlice ns = { ds->p, i, ds->cap }; _qsort(&ns, cmp); } if (ds->len > i) { DataSlice ns = { &ds->p[i + 1], ds->len - (i + 1), ds->cap - (i + 1) }; _qsort(&ns, cmp); }}
void main() { int i; Data values[] = { { 1 }, { 9 }, { 5 }, { 2 }, { 4 }, { 3 }, { 8 }, { 6 }, { 7 } }; DataSlice s = { values, 9, 9 }; _qsort(&s, cmp); for (i = 0; i < 9; i++) print("%d\n", values[i].v);}
Quicksort2
my.cfg:
slice DataSlice.p DataSlice.len DataSlice.cap
diff {- var ns = DataSlice{ds.p, i, cap(ds.p)}+ var ns = DataSlice{ds.p[0:i]}}
diff {- var ns = DataSlice{&ds.p[i+1], len(ds.p) - (i + 1), cap(ds.p) - (i + 1)}+ var ns = DataSlice{ds.p[i+1:]}}
diff {- var s = DataSlice{values, 9, 9}+ var s = DataSlice{values}}
Quicksort2
Translate:
c2go -c my.cfg -dst $GOPATH qsort2.c
Forget all the unfamiliar messages; these are warnings:
qsort2.c:39: too many fields in braced initializer of DataSliceqsort2.c:43: too many fields in braced initializer of DataSliceqsort2.c:61: too many fields in braced initializer of DataSlicemain/qsort2.go: cannot find copyright notice in C file qsort2.c
Quicksort2
Generated Code:
...func _qsort(ds *DataSlice, cmp func(*Data, *Data) int) { var pivot int var le int var i int var j int var pv Data if len(ds.p) == 0 { return } le = len(ds.p) - 1 pivot = len(ds.p) / 2 pv = ds.p[pivot] swap(&ds.p[pivot], &ds.p[le]) i = 0 for j = 0; j < le; j++ { if cmp(&ds.p[j], &pv) < 0 {...
Looks pretty promising!
Quicksort2
$ go run $GOPATH/src/main/qsort2.go# command-line-argumentssrc/main/qsort2.go:66: undefined: fmt in fmt.Printf
Seems we had to add import "fmt" manually $
package main
import "fmt" // here
type Data struct { v int}
func swap(a *Data, b *Data) {...
Quicksort2
Let's give it a second try:
$ go run $GOPATH/src/main/qsort2.go123456789
WOW %
Quicksort2
The configuration file gives more control over the generated code.
Its directives are not totally demystified yet.
Quicksort3
Quicksort3
This is CHEATING
void qsort(void *d, int l, int s, int(*cmp)(void *, void *));
int print(char *fmt, ...);
typedef struct Data { int v;} Data;
int cmp(void *a, void *b){ Data *_a, *_b; _a = a; _b = b; if (_a->v < _b->v) return -1; else if (_a->v > _b->v) return 1; else return 0;}...
Quicksort3
...void main() { int i; Data values[] = { { 1 }, { 9 }, { 5 }, { 2 }, { 4 }, { 3 }, { 8 }, { 6 }, { 7 } }; qsort(values, 9, sizeof(values[0]), cmp); for (i = 0; i < 9; i++) print("%d\n", values[i].v);}
Quicksort3
Translate:
$ c2go -dst $GOPATH qsort3.c
Generated code:
package main
type Data struct { v int}
type cmp []Data
func (x cmp) Len() int { return len(x)}
func (x cmp) Swap(i, j int) { x[i], x[j] = x[j], x[i]}...
Quicksort3
...func (x cmp) Less(i, j int) bool { var _a *Data var _b *Data _a = &x[i] _b = &x[j] if _a.v < _b.v { return true } else if _a.v > _b.v { return 1 < 0 } else { return false }}
func main() { var i int var values = []Data{Data{1}, Data{9}, Data{5}, Data{2}, Data{4}, Data{3}, Data{8}, Data{6}, Data{7}} sort.Sort(cmp(values[:9])) for i = 0; i < 9; i++ { fmt.Printf("%d\n", values[i].v) }}
Quicksort3
This is a MAGIC.
Some "standard" C functions are treated specially so that they get translated into the Go'scounterparts.
print() ➡️ fmt.Printf()
qsort() ➡️ sort.Sort()
memset() / memmove()
strcpy() / strcat / strlen() / strcmp()
malloc() / strdup() / free()
abort() '
DISCLAIMER: this is just informational; not a complete list.
Quicksort3
If you want to get the MAGIC happening right, You need to make sure...
The prototype:
void qsort(void *d, int l, int s, int(*cmp)(void *, void *));
The third argument cmp() function:
void cmp(void *a, void *b){ type_in_question *a_, *b_; a_ = a; b_ = b;}
not
void cmp(void *a, void *b){ type_in_question *a_ = a, *b_ = b;}
Quicksort3
Call to qsort():
qsort(list, nitems, sizeof(list[0]), cmp);
not
qsort(list, nitems, sizeof(type_in_question), cmp);
Want to go further?
See src/rsc.io/c2go/typecheck.go.
More magics can be added!
Thank you
2015/6/21 1:15:00 (2015/6/21%201:15:00)
Tags: golang, c2go (#ZgotmplZ)
Moriyoshi KoizumiOpen Collector, [email protected] (mailto:[email protected])
http://mozo.jp/ (http://mozo.jp/)
@moriyoshit (http://twitter.com/moriyoshit)