From 8b74c711c66514543c128e26f25a3917001f2f89 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 23 Oct 2019 08:18:44 +0300 Subject: [PATCH] vh generation: consts + cleanup --- vlib/compiler/cgen.v | 26 +++++--- vlib/compiler/main.v | 3 +- vlib/compiler/module_header.v | 122 +++++----------------------------- vlib/compiler/parser.v | 21 +++++- vlib/compiler/scanner.v | 18 +++-- 5 files changed, 69 insertions(+), 121 deletions(-) diff --git a/vlib/compiler/cgen.v b/vlib/compiler/cgen.v index 07d44b9012..1dfc8d52db 100644 --- a/vlib/compiler/cgen.v +++ b/vlib/compiler/cgen.v @@ -289,16 +289,24 @@ fn os_name_to_ifdef(name string) string { } fn platform_postfix_to_ifdefguard(name string) string { - switch name { - case '.v': return '' // no guard needed - case '_win.v': return '#ifdef _WIN32' - case '_nix.v': return '#ifndef _WIN32' - case '_lin.v': return '#ifdef __linux__' - case '_mac.v': return '#ifdef __APPLE__' - case '_solaris.v': return '#ifdef __sun' + s := match name { + '.v' { '' }// no guard needed + '_win.v', '_windows.v' { '#ifdef _WIN32' } + '_nix.v' { '#ifndef _WIN32' } + '_lin.v', '_linux.v' { '#ifdef __linux__' } + '_mac.v', '_darwin.v' { '#ifdef __APPLE__' } + '_solaris.v' { '#ifdef __sun' } + else { + + //verror('bad platform_postfix "$name"') + // TODO + '' + } } - verror('bad platform_postfix "$name"') - return '' + if s == '' { + verror('bad platform_postfix "$name"') + } + return s } // C struct definitions, ordered diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index ab8327fb23..81df5444e8 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -111,6 +111,7 @@ pub mut: // to increase compilation time. // This is on by default, since a vast majority of users do not // work on the builtin module itself. + //generating_vh bool } // Should be called by main at the end of the compilation process, to cleanup @@ -833,7 +834,7 @@ pub fn new_v(args[]string) &V { out_name = dir.left(dir.len - 2) // Building V? Use v2, since we can't overwrite a running // executable on Windows + the precompiled V is more - // optimized. + // optimized. if out_name == 'v' && os.dir_exists('vlib/compiler') { println('Saving the resulting V executable in `./v2`') println('Use `v -o v v.v` if you want to replace current '+ diff --git a/vlib/compiler/module_header.v b/vlib/compiler/module_header.v index e592579298..00d4a53627 100644 --- a/vlib/compiler/module_header.v +++ b/vlib/compiler/module_header.v @@ -15,108 +15,6 @@ import ( They are used together with pre-compiled modules. */ -// "fn foo(a int) string" -fn (f &Fn) v_definition() string { - //t :=time.ticks() - mut sb := strings.new_builder(100) - if f.is_public { - sb.write('pub ') - } - sb.write('fn ') - if f.is_c { - sb.write('C.') - } - if f.is_method { - recv := f.args[0] - typ := v_type_str(recv.typ).replace('*', '') - mut mu := if recv.is_mut { 'mut' } else { '' } - if recv.ref { - mu = '&' - } - sb.write('($recv.name $mu $typ) ') - } - if f.name.contains('__') { - sb.write(f.name.all_after('__') + '(') - } else { - sb.write('$f.name(') - } - for i, arg in f.args { - if i == 0 && f.is_method { // skip the receiver - continue - } - typ := v_type_str(arg.typ).replace('*', '&') - if arg.name == '' { - sb.write(typ) - } else { - sb.write('$arg.name $typ') - } - if i != f.args.len - 1 { - sb.write(', ') - } - } - sb.write(')') - if f.typ != 'void' { - typ := v_type_str(f.typ).replace('*', '&') - sb.write(' ') - sb.write(typ) - sb.writeln(' ') - } - //println('ms: ${time.ticks() - t}') - return sb.str() -} - -fn v_type_str(typ_ string) string { - mut typ := if typ_.ends_with('*') { - '*' + typ_.left(typ_.len - 1) - } else { - typ_ - } - typ = typ.replace('Option_', '?') - // fn parent/alias? - if typ.starts_with('fn ') { - mut types := []string - fi_lpar := typ.index_byte(`(`) - li_rpar := typ.last_index_byte(`)`) - ret_type := typ.right(li_rpar+1) - for t in typ.substr(fi_lpar+1, li_rpar).split(',') { - types << v_type_str(t) - } - return 'fn (' + types.join(', ') + ')$ret_type' - } - typ = typ.replace('Option_', '?') - // multiple return - if typ.contains('_V_MulRet') { - words := typ.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_') - typ = '(' - for i in 0 .. words.len { - typ += v_type_str(words[i]) - if i != words.len - 1 { - typ += ',' - } - } - typ += ')' - return typ - } - //println('"$typ"') - if typ == '*void' { - return 'voidptr' - } - if typ == '*byte' { - return 'byteptr' - } - if typ.starts_with('array_') { - return '[]' + typ.right(6) - } - if typ.contains('__') { - opt := typ.starts_with('?') - typ = typ.all_after('__') - if opt { - typ = '?' + typ - } - } - return typ -} - // `mod` == "vlib/os" fn generate_vh(mod string) { println('\n\n\n\nGenerating a V header file for module `$mod`') @@ -145,6 +43,8 @@ fn generate_vh(mod string) { //v.pref.generating_vh = true for file in filtered { mut p := v.new_parser_from_file(file) + p.scanner.is_vh = true + println('kek $file') p.parse(.decl) for i, tok in p.tokens { if !p.tok.is_decl() { @@ -187,10 +87,23 @@ fn generate_fn(file os.File, tokens []Token, i int) { } fn generate_const(file os.File, tokens []Token, i int) { - //mut out := strings.new_builder(100) - + mut out := strings.new_builder(100) + mut tok := tokens[i] + for i < tokens.len && tok.tok != .rpar { + out.write(tok.str()) + out.write(' ') + if tokens[i+2].tok == .assign { + out.write('\n\t') + + } + i++ + tok = tokens[i] + } + out.writeln('\n)') + file.writeln(out.str()) } +/* fn (v &V) generate_vh_old() { println('\n\n\n\nGenerating a V header file for module `$v.mod`') mod_path := v.mod.replace('.', os.path_separator) @@ -333,4 +246,5 @@ fn (v &V) generate_vh_old() { } */ } +*/ diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index 0b5a117db8..323f219836 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -20,7 +20,7 @@ struct Token { struct Parser { file_path_id string // unique id. if parsing file will be path eg, "/home/user/hello.v" file_name string // "hello.v" - file_platform string // ".v", "_win.v", "_nix.v", "_mac.v", "_lin.v" ... + file_platform string // ".v", "_windows.v", "_nix.v", "_darwin.v", "_linux.v" ... // When p.file_pcguard != '', it contains a // C ifdef guard clause that must be put before // the #include directives in the parsed .v file @@ -106,8 +106,21 @@ fn (v mut V) new_parser_from_file(path string) Parser { //println('new_parser("$path")') mut path_pcguard := '' mut path_platform := '.v' - for path_ending in ['_lin.v', '_mac.v', '_win.v', '_nix.v'] { + for path_ending in ['_lin.v', '_mac.v', '_win.v', '_nix.v', '_linux.v', + '_darwin.v', '_windows.v'] { if path.ends_with(path_ending) { + if path_ending == '_mac.v' { + p := path_ending.replace('_mac.v', '_darwin.v') + println('warning: use "$p" file name instead of "$path"') + } + if path_ending == '_lin.v' { + p := path_ending.replace('_lin.v', '_linux.v') + println('warning: use "$p" file name instead of "$path"') + } + if path_ending == '_win.v' { + p := path_ending.replace('_win.v', '_windows.v') + println('warning: use "$p" file name instead of "$path"') + } path_platform = path_ending path_pcguard = platform_postfix_to_ifdefguard( path_ending ) break @@ -124,6 +137,10 @@ fn (v mut V) new_parser_from_file(path string) Parser { if p.pref.building_v { p.scanner.should_print_relative_paths_on_error = true } + //if p.pref.generating_vh { + // Keep newlines + //p.scanner.is_vh = true + //} p.scan_tokens() //p.scanner.debug_tokens() return p diff --git a/vlib/compiler/scanner.v b/vlib/compiler/scanner.v index 39d3bc92a0..b5e57de91b 100644 --- a/vlib/compiler/scanner.v +++ b/vlib/compiler/scanner.v @@ -41,6 +41,7 @@ mut: quote byte // which quote is used to denote current string: ' or " line_ends []int // the positions of source lines ends (i.e. \n signs) nlines int // total number of lines in the source file that were scanned + is_vh bool // Keep newlines } // new scanner from file. @@ -221,7 +222,12 @@ fn (s mut Scanner) ident_number() string { } fn (s mut Scanner) skip_whitespace() { + //if s.is_vh { println('vh') return } for s.pos < s.text.len && s.text[s.pos].is_white() { + if is_nl(s.text[s.pos]) && s.is_vh { + return + + } // Count \r\n as one line if is_nl(s.text[s.pos]) && !s.expect('\r\n', s.pos-1) { s.inc_line_number() @@ -231,10 +237,10 @@ fn (s mut Scanner) skip_whitespace() { } fn (s mut Scanner) scan() ScanRes { - if s.line_comment != '' { - //s.fgenln('// LOL "$s.line_comment"') + //if s.line_comment != '' { + //s.fgenln('// LC "$s.line_comment"') //s.line_comment = '' - } + //} if s.started { s.pos++ } @@ -242,13 +248,12 @@ fn (s mut Scanner) scan() ScanRes { if s.pos >= s.text.len { return scan_res(.eof, '') } - // skip whitespace if !s.inside_string { s.skip_whitespace() } // End of $var, start next string if s.inter_end { - if s.text[s.pos] == s.quote { //single_quote { + if s.text[s.pos] == s.quote { s.inter_end = false return scan_res(.str, '') } @@ -419,6 +424,7 @@ fn (s mut Scanner) scan() ScanRes { s.error('@ must be used before keywords (e.g. `@type string`)') } return scan_res(.name, name) + /* case `\r`: if nextc == `\n` { s.pos++ @@ -428,6 +434,7 @@ fn (s mut Scanner) scan() ScanRes { case `\n`: s.last_nl_pos = s.pos return scan_res(.nl, '') + */ case `.`: if nextc == `.` { s.pos++ @@ -783,6 +790,7 @@ fn is_name_char(c byte) bool { return c.is_letter() || c == `_` } +[inline] fn is_nl(c byte) bool { return c == `\r` || c == `\n` }