2019-10-04 14:48:09 +02:00
|
|
|
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
2019-10-13 15:37:43 +02:00
|
|
|
module compiler
|
2019-10-04 14:48:09 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
strings
|
|
|
|
os
|
2019-11-09 21:49:15 +01:00
|
|
|
filepath
|
2019-10-04 14:48:09 +02:00
|
|
|
)
|
|
|
|
|
2019-10-07 00:31:01 +02:00
|
|
|
/*
|
|
|
|
.vh generation logic.
|
2019-10-10 01:59:33 +02:00
|
|
|
.vh files contain only function signatures, consts, and types.
|
2019-10-07 00:31:01 +02:00
|
|
|
They are used together with pre-compiled modules.
|
2019-10-04 14:48:09 +02:00
|
|
|
*/
|
|
|
|
|
2019-11-01 14:10:28 +01:00
|
|
|
struct VhGen {
|
|
|
|
mut:
|
|
|
|
i int // token index
|
|
|
|
consts strings.Builder
|
|
|
|
fns strings.Builder
|
|
|
|
types strings.Builder
|
|
|
|
tokens []Token
|
2019-12-06 13:24:53 +01:00
|
|
|
|
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
|
2019-10-21 13:21:30 +02:00
|
|
|
// `mod` == "vlib/os"
|
|
|
|
fn generate_vh(mod string) {
|
2019-11-09 21:49:15 +01:00
|
|
|
println('\n\n\n\nGenerating a V header file for module `$mod`')
|
2019-11-21 02:34:08 +01:00
|
|
|
vexe := vexe_path()
|
2019-11-09 21:49:15 +01:00
|
|
|
full_mod_path := filepath.join(os.dir(vexe), mod)
|
|
|
|
dir := if mod.starts_with('vlib') { '$compiler.v_modules_path${os.path_separator}$mod' } else { mod }
|
2019-10-21 13:21:30 +02:00
|
|
|
path := dir + '.vh'
|
|
|
|
pdir := dir.all_before_last(os.path_separator)
|
2019-12-04 21:03:12 +01:00
|
|
|
if !os.is_dir(pdir) {
|
2019-10-21 13:21:30 +02:00
|
|
|
os.mkdir_all(pdir)
|
2019-11-23 17:55:18 +01:00
|
|
|
// os.mkdir(os.realpath(dir)) or { panic(err) }
|
2019-10-21 13:21:30 +02:00
|
|
|
}
|
2019-12-01 10:50:13 +01:00
|
|
|
mut out := os.create(path) or { panic(err) }
|
2019-11-09 21:49:15 +01:00
|
|
|
mod_path := mod.replace("\\", "/")
|
|
|
|
out.writeln('// $mod_path module header\n')
|
|
|
|
mod_def := if mod_path.contains('/') { mod_path.all_after('/') } else { mod_path } // "os"
|
2019-10-23 14:55:14 +02:00
|
|
|
out.writeln('module $mod_def\n')
|
2019-10-21 13:21:30 +02:00
|
|
|
// Consts
|
|
|
|
println(full_mod_path)
|
2019-12-06 13:24:53 +01:00
|
|
|
vfiles := os.walk_ext(full_mod_path, '.v')
|
2019-10-23 12:03:14 +02:00
|
|
|
//mut vfiles := os.ls(full_mod_path) or {
|
|
|
|
//exit(1)
|
2019-12-06 13:24:53 +01:00
|
|
|
//}
|
2019-10-23 12:03:14 +02:00
|
|
|
filtered := vfiles.filter(it.ends_with('.v') && !it.ends_with('test.v') &&
|
|
|
|
!it.ends_with('_windows.v') && !it.ends_with('_win.v') &&
|
2019-10-30 13:04:25 +01:00
|
|
|
!it.ends_with('_lin.v') &&
|
2019-11-09 21:49:15 +01:00
|
|
|
!it.contains('${os.path_separator}examples') &&
|
2019-11-01 14:10:28 +01:00
|
|
|
!it.contains('_js.v') &&
|
2019-11-18 01:51:14 +01:00
|
|
|
!it.contains('_bare.v') &&
|
2019-11-09 21:49:15 +01:00
|
|
|
!it.contains('${os.path_separator}js')) // TODO merge once filter allows it
|
2019-11-18 01:51:14 +01:00
|
|
|
//println('f:')
|
|
|
|
//println(filtered)
|
2019-10-21 13:21:30 +02:00
|
|
|
mut v := new_v(['foo.v'])
|
|
|
|
//v.pref.generating_vh = true
|
2019-11-01 14:10:28 +01:00
|
|
|
mut g := VhGen{
|
|
|
|
consts : strings.new_builder(1000)
|
|
|
|
fns : strings.new_builder(1000)
|
|
|
|
types : strings.new_builder(1000)
|
|
|
|
}
|
2019-10-21 13:21:30 +02:00
|
|
|
for file in filtered {
|
|
|
|
mut p := v.new_parser_from_file(file)
|
2019-10-23 07:18:44 +02:00
|
|
|
p.scanner.is_vh = true
|
2019-10-21 13:21:30 +02:00
|
|
|
p.parse(.decl)
|
2019-11-01 14:10:28 +01:00
|
|
|
g.tokens = p.tokens
|
|
|
|
g.i = 0
|
|
|
|
for ; g.i < p.tokens.len; g.i++ {
|
|
|
|
if !p.tokens[g.i].tok.is_decl() {
|
2019-10-21 13:21:30 +02:00
|
|
|
continue
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
match g.tokens[g.i].tok {
|
|
|
|
.key_fn { g.generate_fn() }
|
|
|
|
.key_const { g.generate_const() }
|
|
|
|
.key_struct { g.generate_type() }
|
|
|
|
.key_type { g.generate_alias() }
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
result :=
|
|
|
|
g.types.str() +
|
|
|
|
g.consts.str() +
|
|
|
|
g.fns.str().replace('\n\n\n', '\n').replace('\n\n', '\n')
|
2019-12-06 13:24:53 +01:00
|
|
|
|
2019-10-23 11:54:35 +02:00
|
|
|
out.writeln(result.replace('[ ] ', '[]').replace('? ', '?'))
|
2019-10-23 11:35:51 +02:00
|
|
|
out.close()
|
2019-10-21 13:21:30 +02:00
|
|
|
}
|
|
|
|
|
2019-11-01 14:10:28 +01:00
|
|
|
fn (g mut VhGen) generate_fn() {
|
|
|
|
if g.i >= g.tokens.len - 2 {
|
|
|
|
return
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
mut next := g.tokens[g.i+1]
|
|
|
|
if g.i > 0 && g.tokens[g.i-1].tok != .key_pub {
|
2019-10-21 13:21:30 +02:00
|
|
|
// Skip private fns
|
2019-11-01 14:10:28 +01:00
|
|
|
//return ''
|
2019-10-21 13:21:30 +02:00
|
|
|
}
|
2019-12-06 13:24:53 +01:00
|
|
|
|
2019-10-21 13:21:30 +02:00
|
|
|
if next.tok == .name && next.lit == 'C' {
|
2019-11-18 01:51:14 +01:00
|
|
|
//println('skipping C')
|
2019-11-01 14:10:28 +01:00
|
|
|
return
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-10-21 13:21:30 +02:00
|
|
|
//out.write('pub ')
|
2019-11-01 14:10:28 +01:00
|
|
|
mut tok := g.tokens[g.i]
|
|
|
|
for g.i < g.tokens.len - 1 && tok.tok != .lcbr {
|
|
|
|
next = g.tokens[g.i+1]
|
2019-12-06 13:24:53 +01:00
|
|
|
|
2019-11-01 14:10:28 +01:00
|
|
|
g.fns.write(tok.str())
|
2019-10-21 13:21:30 +02:00
|
|
|
if tok.tok != .lpar && !(next.tok in [.comma, .rpar]) {
|
|
|
|
// No space after (), [], etc
|
2019-11-01 14:10:28 +01:00
|
|
|
g.fns.write(' ')
|
2019-10-21 13:21:30 +02:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.i++
|
|
|
|
tok = g.tokens[g.i]
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.fns.writeln('')
|
|
|
|
//g.i--
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-10-21 13:21:30 +02:00
|
|
|
|
2019-11-01 14:10:28 +01:00
|
|
|
fn (g mut VhGen) generate_alias() {
|
|
|
|
mut tok := g.tokens[g.i]
|
|
|
|
for g.i < g.tokens.len-1 {
|
|
|
|
g.types.write(tok.str())
|
|
|
|
g.types.write(' ')
|
|
|
|
if tok.line_nr != g.tokens[g.i+1].line_nr {
|
2019-10-31 11:08:01 +01:00
|
|
|
break
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.i++
|
|
|
|
tok = g.tokens[g.i]
|
2019-10-31 11:08:01 +01:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.types.writeln('\n')
|
|
|
|
//g.i--
|
2019-10-31 11:08:01 +01:00
|
|
|
}
|
|
|
|
|
2019-11-01 14:10:28 +01:00
|
|
|
fn (g mut VhGen) generate_const() {
|
|
|
|
mut tok := g.tokens[g.i]
|
|
|
|
for g.i < g.tokens.len && tok.tok != .rpar {
|
|
|
|
g.consts.write(tok.str())
|
|
|
|
g.consts.write(' ')
|
|
|
|
if g.tokens[g.i+2].tok == .assign {
|
|
|
|
g.consts.write('\n\t')
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.i++
|
|
|
|
tok = g.tokens[g.i]
|
2019-10-23 07:18:44 +02:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.consts.writeln('\n)')
|
|
|
|
//g.i--
|
2019-10-21 13:21:30 +02:00
|
|
|
}
|
|
|
|
|
2019-11-01 14:10:28 +01:00
|
|
|
fn (g mut VhGen) generate_type() {
|
|
|
|
//old := g.i
|
|
|
|
mut tok := g.tokens[g.i]
|
|
|
|
for g.i < g.tokens.len && tok.tok != .rcbr {
|
|
|
|
g.types.write(tok.str())
|
|
|
|
g.types.write(' ')
|
|
|
|
if g.tokens[g.i+1].line_nr != g.tokens[g.i].line_nr {
|
|
|
|
g.types.write('\n\t')
|
2019-12-06 13:24:53 +01:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.i++
|
|
|
|
tok = g.tokens[g.i]
|
2019-10-23 12:03:14 +02:00
|
|
|
}
|
2019-11-01 14:10:28 +01:00
|
|
|
g.types.writeln('\n}')
|
|
|
|
//g.i = old
|
|
|
|
//g.i--
|
2019-10-23 12:03:14 +02:00
|
|
|
}
|