From 155e1fa96175212be8ad8ab9ae102a9580b95ccb Mon Sep 17 00:00:00 2001 From: marco Date: Wed, 3 Jul 2019 21:53:25 +0200 Subject: [PATCH] FIX #202 allow interface method with empty (void) return type -> only look for type declaration if no new line has been while skipping whitespace --- compiler/parser.v | 32 ++++++++++++++++++++------------ compiler/scanner.v | 17 ++++++++++++++++- compiler/tests/interface_test.v | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 compiler/tests/interface_test.v diff --git a/compiler/parser.v b/compiler/parser.v index c1e887f990..748da98218 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -393,6 +393,25 @@ fn (p mut Parser) type_decl() { p.table.register_type_with_parent(name, parent) } +fn (p mut Parser) interface_method(field_name, receiver string) &Fn { + mut method := &Fn { + name: field_name + is_interface: true + is_method: true + receiver_typ: receiver + } + p.log('is interface. field=$field_name run=$p.run') + p.fn_args(mut method) + if p.scanner.has_gone_over_line_end() { + method.typ = 'void' + } else { + method.typ = p.get_type()// method return type + p.fspace() + p.fgenln('') + } + return method +} + // also unions and interfaces fn (p mut Parser) struct_decl() { // Attribute before type? @@ -525,18 +544,7 @@ fn (p mut Parser) struct_decl() { // We are in an interface? // `run() string` => run is a method, not a struct field if is_interface { - mut interface_method := &Fn { - name: field_name - is_interface: true - is_method: true - receiver_typ: name - } - println('is interface. field=$field_name run=$p.run') - p.fn_args(mut interface_method) - p.fspace() - interface_method.typ = p.get_type()// method return type - typ.add_method(interface_method) - p.fgenln('') + typ.add_method(p.interface_method(field_name, name)) continue } // `pub` access mod diff --git a/compiler/scanner.v b/compiler/scanner.v index 0e2e183438..46172d17b8 100644 --- a/compiler/scanner.v +++ b/compiler/scanner.v @@ -120,6 +120,20 @@ fn (s mut Scanner) ident_number() string { return number } +fn (s Scanner) has_gone_over_line_end() bool { + mut i := s.pos-1 + for i >= 0 && !is_white(s.text[i]) { + i-- + } + for i >= 0 && is_white(s.text[i]) { + if is_nl(s.text[i]) { + return true + } + i-- + } + return false +} + fn (s mut Scanner) skip_whitespace() { for s.pos < s.text.len && is_white(s.text[s.pos]) { if is_nl(s.text[s.pos]) { @@ -148,7 +162,8 @@ fn (s mut Scanner) cao_change(operator string) { s.text = s.text.substr(0, s.pos - operator.len) + ' = ' + s.get_var_name(s.pos - operator.len) + ' ' + operator + ' ' + s.text.substr(s.pos + 1, s.text.len) } -fn (s mut Scanner) scan() ScanRes { +fn (s mut Scanner) scan() +ScanRes { // if s.file_path == 'd.v' { // println('\nscan()') // } diff --git a/compiler/tests/interface_test.v b/compiler/tests/interface_test.v new file mode 100644 index 0000000000..822d5c1dcf --- /dev/null +++ b/compiler/tests/interface_test.v @@ -0,0 +1,32 @@ + +struct Dog { +} + +fn (d Dog) speak() { + println('dog.speak()') +} + +fn (d Dog) name() string { + return 'old gray' +} + +interface Speaker { + name() string + speak() +} + +interface Speak2er { + speak() + name() string +} + +fn perform_speak(s Speaker) bool { + s.speak() + return true +} + +fn test_perform_speak() { + d := Dog{} + assert perform_speak(d) +} +