Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

All I know about rsc.io/c2go

887 views

Published on

Published in: Engineering
  • Be the first to comment

All I know about rsc.io/c2go

  1. 1. All I know about rsc.io/c2go Moriyoshi Koizumi Open Collector, Inc.
  2. 2. Hey I can be found amongst CONTRIBUTORS :)
  3. 3. 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
  4. 4. こんにちは、世界 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)
  5. 5. Quicksort1
  6. 6. Quicksort1 Involves pointer arithmetics, compound types, and function pointers.
  7. 7. 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; } ...
  8. 8. 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); } ...
  9. 9. 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("%dn", values[i].v); }
  10. 10. Quicksort1 Compile: $ cc -o qsort1 qsort1.c $GO_1_4_ROOT/pkg/obj/darwin_amd64/lib9.a Run: $ ./qsort1 1 2 3 4 5 6 7 8 9
  11. 11. 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 } ...
  12. 12. 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) ...
  13. 13. Quicksort2
  14. 14. Quicksort2 int print(const char *fmt, ...); typedef struct Data { int v; } Data; typedef struct DataSlice { Data *p; int len; int cap; } DataSlice;
  15. 15. 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; } ...
  16. 16. 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]); ...
  17. 17. 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("%dn", values[i].v); }
  18. 18. 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} }
  19. 19. 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 DataSlice qsort2.c:43: too many fields in braced initializer of DataSlice qsort2.c:61: too many fields in braced initializer of DataSlice main/qsort2.go: cannot find copyright notice in C file qsort2.c
  20. 20. 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!
  21. 21. Quicksort2 $ go run $GOPATH/src/main/qsort2.go # command-line-arguments src/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) { ...
  22. 22. Quicksort2 Let's give it a second try: $ go run $GOPATH/src/main/qsort2.go 1 2 3 4 5 6 7 8 9 WOW %
  23. 23. Quicksort2 The configuration file gives more control over the generated code. Its directives are not totally demystified yet.
  24. 24. Quicksort3
  25. 25. 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; } ...
  26. 26. 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("%dn", values[i].v); }
  27. 27. 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] } ...
  28. 28. 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("%dn", values[i].v) } }
  29. 29. Quicksort3 This is a MAGIC. Some "standard" C functions are treated specially so that they get translated into the Go's counterparts. 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.
  30. 30. 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; }
  31. 31. 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!
  32. 32. Thank you 2015/6/21 1:15:00(2015/6/21%201:15:00) Tags: golang, c2go(#ZgotmplZ) Moriyoshi Koizumi Open Collector, Inc. mozo@mozo.jp(mailto:mozo@mozo.jp) http://mozo.jp/(http://mozo.jp/) @moriyoshit(http://twitter.com/moriyoshit)

×