From 3b94a2b77ab57fa242739889b585360a86b02124 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 9 Dec 2020 17:01:12 +0200 Subject: [PATCH] cgen: fix interface _name_table generation; closes issue #73 --- vlib/v/gen/cgen.v | 3 -- vlib/v/tests/interface_edge_cases/i1_test.v | 31 +++++++++++++++++ vlib/v/tests/interface_edge_cases/i2_test.v | 34 ++++++++++++++++++ vlib/v/tests/interface_edge_cases/i3_test.v | 33 ++++++++++++++++++ vlib/v/tests/interface_edge_cases/i4_test.v | 31 +++++++++++++++++ vlib/v/tests/interface_edge_cases/i5_test.v | 31 +++++++++++++++++ vlib/v/tests/interface_edge_cases/i6_test.v | 31 +++++++++++++++++ vlib/v/tests/interface_edge_cases/i7_test.v | 38 +++++++++++++++++++++ vlib/v/tests/interface_edge_cases/i8_test.v | 31 +++++++++++++++++ 9 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 vlib/v/tests/interface_edge_cases/i1_test.v create mode 100644 vlib/v/tests/interface_edge_cases/i2_test.v create mode 100644 vlib/v/tests/interface_edge_cases/i3_test.v create mode 100644 vlib/v/tests/interface_edge_cases/i4_test.v create mode 100644 vlib/v/tests/interface_edge_cases/i5_test.v create mode 100644 vlib/v/tests/interface_edge_cases/i6_test.v create mode 100644 vlib/v/tests/interface_edge_cases/i7_test.v create mode 100644 vlib/v/tests/interface_edge_cases/i8_test.v diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 5c8e5b3656..f2931bb3ba 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -5598,9 +5598,6 @@ fn (mut g Gen) interface_table() string { continue } inter_info := ityp.info as table.Interface - if inter_info.types.len == 0 { - continue - } // interface_name is for example Speaker interface_name := c_name(ityp.name) // generate a struct that references interface methods diff --git a/vlib/v/tests/interface_edge_cases/i1_test.v b/vlib/v/tests/interface_edge_cases/i1_test.v new file mode 100644 index 0000000000..750b981684 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i1_test.v @@ -0,0 +1,31 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +struct Point { + x i8 + y i8 +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +fn to_string(d Drawer) { + println(d.draw()) +} + +interface Drawer { + draw() string +} + +fn test_to_string_can_be_called() { + p := Point{ + x: 2 + y: 3 + } + to_string(p) + assert true +} diff --git a/vlib/v/tests/interface_edge_cases/i2_test.v b/vlib/v/tests/interface_edge_cases/i2_test.v new file mode 100644 index 0000000000..7c8d97acaa --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i2_test.v @@ -0,0 +1,34 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +struct Point { + x i8 + y i8 + z i8 +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +fn to_string(d Drawer) string { + x := d.draw() + println(x) + return x +} + +interface Drawer { + draw() string +} + +fn test_to_string_can_be_called() { + p := Point{ + x: 2 + y: 3 + } + res := to_string(p) + assert res == 'Point(2,3)' +} diff --git a/vlib/v/tests/interface_edge_cases/i3_test.v b/vlib/v/tests/interface_edge_cases/i3_test.v new file mode 100644 index 0000000000..557bc37d2a --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i3_test.v @@ -0,0 +1,33 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +struct Point { + x int + y int + z int +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +fn to_string(d Drawer) string { + return d.draw() +} + +interface Drawer { + draw() string +} + +fn test_calling_to_string() { + p := Point{ + x: 2 + y: 3 + } + res := to_string(p) + println(res) + assert res == 'Point(2,3)' +} diff --git a/vlib/v/tests/interface_edge_cases/i4_test.v b/vlib/v/tests/interface_edge_cases/i4_test.v new file mode 100644 index 0000000000..c4ee13ff6b --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i4_test.v @@ -0,0 +1,31 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +struct Point { + x int + y int +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +fn to_string(d Drawer) string { + return d.draw() +} + +interface Drawer { + draw() string +} + +fn test_p_draw_can_be_called() { + p := Point{ + x: 2 + y: 3 + } + res := p.draw() + assert res == 'Point(2,3)' +} diff --git a/vlib/v/tests/interface_edge_cases/i5_test.v b/vlib/v/tests/interface_edge_cases/i5_test.v new file mode 100644 index 0000000000..765da988f8 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i5_test.v @@ -0,0 +1,31 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +struct Point { + x int + y int +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +interface Drawer { + draw() string +} + +fn to_string(d Drawer) string { + return d.draw() +} + +fn test_p_draw_can_be_called() { + p := Point{ + x: 2 + y: 3 + } + res := p.draw() + assert res == 'Point(2,3)' +} diff --git a/vlib/v/tests/interface_edge_cases/i6_test.v b/vlib/v/tests/interface_edge_cases/i6_test.v new file mode 100644 index 0000000000..0ec9b8e1c8 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i6_test.v @@ -0,0 +1,31 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +struct Point { + x int + y int +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +fn to_string(d Drawable) string { + return d.draw() +} + +interface Drawable { + draw() string +} + +fn test_p_draw_can_be_called() { + p := Point{ + x: 2 + y: 3 + } + res := p.draw() + assert res == 'Point(2,3)' +} diff --git a/vlib/v/tests/interface_edge_cases/i7_test.v b/vlib/v/tests/interface_edge_cases/i7_test.v new file mode 100644 index 0000000000..1b70481c0b --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i7_test.v @@ -0,0 +1,38 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +interface Drawable { + draw() string +} + +struct Point { + x int + y int +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +// Note: this helper function forced the compiler to generate an +// interface dispatch table. Now, it should not be needed anymore, +// but it is better to test it too, to prevent future interface regressions. +fn (x Point) tointerface() Drawable { + return x +} + +fn to_string(d Drawable) string { + return d.draw() +} + +fn test_p_draw_can_be_called() { + p := Point{ + x: 2 + y: 3 + } + res := p.draw() + assert res == 'Point(2,3)' +} diff --git a/vlib/v/tests/interface_edge_cases/i8_test.v b/vlib/v/tests/interface_edge_cases/i8_test.v new file mode 100644 index 0000000000..d7f6b41701 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/i8_test.v @@ -0,0 +1,31 @@ +// The series of i?_test.v files, do test different edge cases for +// interface table generation. The differences may seem very minor +// (placement of the interface declaration, whether or not there are +// helper methods, etc), but PLEASE do NOT be tempted to merge them in +// a single _test.v file. Debugging interface code generation issues +// is *much easier* when the _test.v files are very short and focused. +interface Drawable { + draw() string +} + +struct Point { + x int + y int +} + +fn (p Point) draw() string { + return 'Point($p.x,$p.y)' +} + +fn to_string(d Drawable) string { + return d.draw() +} + +fn test_p_draw_can_be_called() { + p := Point{ + x: 2 + y: 3 + } + res := p.draw() + assert res == 'Point(2,3)' +}