33
All I know about rsc.io/c2go Moriyoshi Koizumi Open Collector, Inc.

All I know about rsc.io/c2go

Embed Size (px)

Citation preview

Page 1: All I know about rsc.io/c2go

All I know about rsc.io/c2goMoriyoshi KoizumiOpen Collector, Inc.

Page 2: All I know about rsc.io/c2go

Hey

I can be found amongst CONTRIBUTORS :)

Page 3: All I know about rsc.io/c2go

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

Page 4: All I know about 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)

Page 5: All I know about rsc.io/c2go

Quicksort1

Page 6: All I know about rsc.io/c2go

Quicksort1

Involves pointer arithmetics, compound types, and function pointers.

Page 7: All I know about rsc.io/c2go

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;}...

Page 8: All I know about rsc.io/c2go

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);}...

Page 9: All I know about rsc.io/c2go

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);}

Page 10: All I know about rsc.io/c2go

Quicksort1

Compile:

$ cc -o qsort1 qsort1.c $GO_1_4_ROOT/pkg/obj/darwin_amd64/lib9.a

Run:

$ ./qsort1123456789

Page 11: All I know about rsc.io/c2go

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}...

Page 12: All I know about rsc.io/c2go

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)...

Page 13: All I know about rsc.io/c2go

Quicksort2

Page 14: All I know about rsc.io/c2go

Quicksort2

int print(const char *fmt, ...);

typedef struct Data { int v;} Data;

typedef struct DataSlice { Data *p; int len; int cap;} DataSlice;

Page 15: All I know about rsc.io/c2go

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;}...

Page 16: All I know about rsc.io/c2go

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]);...

Page 17: All I know about rsc.io/c2go

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);}

Page 18: All I know about rsc.io/c2go

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}}

Page 19: All I know about rsc.io/c2go

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

Page 20: All I know about rsc.io/c2go

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!

Page 21: All I know about rsc.io/c2go

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) {...

Page 22: All I know about rsc.io/c2go

Quicksort2

Let's give it a second try:

$ go run $GOPATH/src/main/qsort2.go123456789

WOW %

Page 23: All I know about rsc.io/c2go

Quicksort2

The configuration file gives more control over the generated code.

Its directives are not totally demystified yet.

Page 24: All I know about rsc.io/c2go

Quicksort3

Page 25: All I know about rsc.io/c2go

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;}...

Page 26: All I know about rsc.io/c2go

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);}

Page 27: All I know about rsc.io/c2go

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]}...

Page 28: All I know about rsc.io/c2go

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) }}

Page 29: All I know about rsc.io/c2go

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.

Page 30: All I know about rsc.io/c2go

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;}

Page 31: All I know about rsc.io/c2go

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!

Page 32: All I know about rsc.io/c2go

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)

Page 33: All I know about rsc.io/c2go