mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
caching modules: almost there
This commit is contained in:
parent
dbd72ee828
commit
a9a73d9315
@ -106,14 +106,13 @@ fn (v mut V) cc() {
|
|||||||
a << f
|
a << f
|
||||||
}
|
}
|
||||||
|
|
||||||
mut libs := ''// builtin.o os.o http.o etc
|
libs := ''// builtin.o os.o http.o etc
|
||||||
if v.pref.build_mode == .build_module {
|
if v.pref.build_mode == .build_module {
|
||||||
a << '-c'
|
a << '-c'
|
||||||
}
|
}
|
||||||
else if v.pref.build_mode == .embed_vlib {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
else if v.pref.build_mode == .default_mode {
|
else if v.pref.build_mode == .default_mode {
|
||||||
|
/*
|
||||||
|
// TODO
|
||||||
libs = '$v_modules_path/vlib/builtin.o'
|
libs = '$v_modules_path/vlib/builtin.o'
|
||||||
if !os.file_exists(libs) {
|
if !os.file_exists(libs) {
|
||||||
println('object file `$libs` not found')
|
println('object file `$libs` not found')
|
||||||
@ -125,6 +124,7 @@ fn (v mut V) cc() {
|
|||||||
}
|
}
|
||||||
libs += ' "$v_modules_path/vlib/${imp}.o"'
|
libs += ' "$v_modules_path/vlib/${imp}.o"'
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
if v.pref.sanitize {
|
if v.pref.sanitize {
|
||||||
a << '-fsanitize=leak'
|
a << '-fsanitize=leak'
|
||||||
@ -248,8 +248,8 @@ fn (v mut V) cc() {
|
|||||||
println('linux cross compilation done. resulting binary: "$v.out_name"')
|
println('linux cross compilation done. resulting binary: "$v.out_name"')
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if !v.pref.is_debug && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' {
|
if !v.pref.is_debug && v.out_name_c != 'v.c' {
|
||||||
os.rm(v.out_name_c)
|
//os.rm(v.out_name_c)
|
||||||
}
|
}
|
||||||
if v.pref.compress {
|
if v.pref.compress {
|
||||||
$if windows {
|
$if windows {
|
||||||
|
@ -161,6 +161,9 @@ fn (g mut CGen) set_placeholder(pos int, val string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut CGen) insert_before(val string) {
|
fn (g mut CGen) insert_before(val string) {
|
||||||
|
if g.nogen {
|
||||||
|
return
|
||||||
|
}
|
||||||
prev := g.lines[g.lines.len - 1]
|
prev := g.lines[g.lines.len - 1]
|
||||||
g.lines[g.lines.len - 1] = '$prev \n $val \n'
|
g.lines[g.lines.len - 1] = '$prev \n $val \n'
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ fn (s mut Scanner) get_scanner_pos_of_token(t &Token) ScannerPos {
|
|||||||
sptoken.pos += tcol
|
sptoken.pos += tcol
|
||||||
}
|
}
|
||||||
s.ignore_line() s.eat_single_newline()
|
s.ignore_line() s.eat_single_newline()
|
||||||
sline := s.text.substr( prevlinepos, s.pos ).trim_right('\r\n')
|
sline := s.text.substr( prevlinepos, s.pos )//.trim_right('\r\n')
|
||||||
s.file_lines << sline
|
s.file_lines << sline
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
|
@ -144,9 +144,8 @@ fn (p mut Parser) comp_time() {
|
|||||||
// #include, #flag, #v
|
// #include, #flag, #v
|
||||||
fn (p mut Parser) chash() {
|
fn (p mut Parser) chash() {
|
||||||
hash := p.lit.trim_space()
|
hash := p.lit.trim_space()
|
||||||
// println('chsh() file=$p.file is_sig=${p.is_sig()} hash="$hash"')
|
// println('chsh() file=$p.file hash="$hash"')
|
||||||
p.next()
|
p.next()
|
||||||
is_sig := p.is_sig()
|
|
||||||
if hash.starts_with('flag ') {
|
if hash.starts_with('flag ') {
|
||||||
mut flag := hash.right(5)
|
mut flag := hash.right(5)
|
||||||
// expand `@VROOT` `@VMOD` to absolute path
|
// expand `@VROOT` `@VMOD` to absolute path
|
||||||
@ -157,7 +156,7 @@ fn (p mut Parser) chash() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if hash.starts_with('include') {
|
if hash.starts_with('include') {
|
||||||
if p.first_pass() && !is_sig {
|
if p.first_pass() && !p.is_vh {
|
||||||
if p.file_pcguard.len != 0 {
|
if p.file_pcguard.len != 0 {
|
||||||
//println('p: $p.file_platform $p.file_pcguard')
|
//println('p: $p.file_platform $p.file_pcguard')
|
||||||
p.cgen.includes << '$p.file_pcguard\n#$hash\n#endif'
|
p.cgen.includes << '$p.file_pcguard\n#$hash\n#endif'
|
||||||
|
@ -134,12 +134,6 @@ fn (p mut Parser) clear_vars() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// vlib header file?
|
|
||||||
fn (p mut Parser) is_sig() bool {
|
|
||||||
return (p.pref.build_mode == .default_mode || p.pref.build_mode == .build_module) &&
|
|
||||||
(p.file_path.contains(v_modules_path))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function signatures are added to the top of the .c file in the first run.
|
// Function signatures are added to the top of the .c file in the first run.
|
||||||
fn (p mut Parser) fn_decl() {
|
fn (p mut Parser) fn_decl() {
|
||||||
p.clear_vars() // clear local vars every time a new fn is started
|
p.clear_vars() // clear local vars every time a new fn is started
|
||||||
@ -231,10 +225,9 @@ fn (p mut Parser) fn_decl() {
|
|||||||
// C function header def? (fn C.NSMakeRect(int,int,int,int))
|
// C function header def? (fn C.NSMakeRect(int,int,int,int))
|
||||||
is_c := f.name == 'C' && p.tok == .dot
|
is_c := f.name == 'C' && p.tok == .dot
|
||||||
// Just fn signature? only builtin.v + default build mode
|
// Just fn signature? only builtin.v + default build mode
|
||||||
// is_sig := p.builtin_mod && p.pref.build_mode == default_mode
|
if p.pref.build_mode == .build_module {
|
||||||
// is_sig := p.pref.build_mode == default_mode && (p.builtin_mod || p.file.contains(LANG_TMP))
|
println('\n\nfn_decl() name=$f.name receiver_typ=$receiver_typ nogen=$p.cgen.nogen')
|
||||||
is_sig := p.is_sig()
|
}
|
||||||
// println('\n\nfn_decl() name=$f.name receiver_typ=$receiver_typ')
|
|
||||||
if is_c {
|
if is_c {
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
f.name = p.check_name()
|
f.name = p.check_name()
|
||||||
@ -312,13 +305,15 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
p.cgen.typedefs << 'typedef struct $typ $typ;'
|
p.cgen.typedefs << 'typedef struct $typ $typ;'
|
||||||
}
|
}
|
||||||
// Translated C code can have empty functions (just definitions)
|
// Translated C code and .vh can have empty functions (just definitions)
|
||||||
is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr
|
is_fn_header := !is_c && !p.is_vh &&
|
||||||
|
(p.pref.translated || p.pref.is_test || p.is_vh) &&
|
||||||
|
p.tok != .lcbr
|
||||||
if is_fn_header {
|
if is_fn_header {
|
||||||
f.is_decl = true
|
f.is_decl = true
|
||||||
}
|
}
|
||||||
// { required only in normal function declarations
|
// { required only in normal function declarations
|
||||||
if !is_c && !is_sig && !is_fn_header {
|
if !is_c && !p.is_vh && !is_fn_header {
|
||||||
p.fgen(' ')
|
p.fgen(' ')
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
}
|
}
|
||||||
@ -350,7 +345,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
mut fn_name_cgen := p.table.fn_gen_name(f)
|
mut fn_name_cgen := p.table.fn_gen_name(f)
|
||||||
// Start generation of the function body
|
// Start generation of the function body
|
||||||
skip_main_in_test := false
|
skip_main_in_test := false
|
||||||
if !is_c && !is_live && !is_sig && !is_fn_header && !skip_main_in_test {
|
if !is_c && !is_live && !p.is_vh && !is_fn_header && !skip_main_in_test {
|
||||||
if p.pref.obfuscate {
|
if p.pref.obfuscate {
|
||||||
p.genln('; // $f.name')
|
p.genln('; // $f.name')
|
||||||
}
|
}
|
||||||
@ -403,10 +398,10 @@ fn (p mut Parser) fn_decl() {
|
|||||||
// println('register_fn typ=$typ isg=$is_generic')
|
// println('register_fn typ=$typ isg=$is_generic')
|
||||||
p.table.register_fn(f)
|
p.table.register_fn(f)
|
||||||
}
|
}
|
||||||
if is_sig || p.first_pass() || is_live || is_fn_header || skip_main_in_test {
|
if p.is_vh || p.first_pass() || is_live || is_fn_header || skip_main_in_test {
|
||||||
// First pass? Skip the body for now
|
// First pass? Skip the body for now
|
||||||
// Look for generic calls.
|
// Look for generic calls.
|
||||||
if !is_sig && !is_fn_header {
|
if !p.is_vh && !is_fn_header {
|
||||||
p.skip_fn_body()
|
p.skip_fn_body()
|
||||||
}
|
}
|
||||||
// Live code reloading? Load all fns from .so
|
// Live code reloading? Load all fns from .so
|
||||||
@ -422,19 +417,8 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
// Add function definition to the top
|
// Add function definition to the top
|
||||||
if !is_c && p.first_pass() {
|
if !is_c && p.first_pass() {
|
||||||
// TODO hack to make Volt compile without -embed_vlib
|
p.cgen.fns << fn_decl + ';'
|
||||||
if f.name == 'darwin__nsstring' && p.pref.build_mode == .default_mode {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
p.cgen.fns << fn_decl + ';'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Generate .vh header files when building a module
|
|
||||||
/*
|
|
||||||
if p.pref.build_mode == .build_module {
|
|
||||||
p.vh_genln(f.v_definition())
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if p.attr == 'live' && p.pref.is_so {
|
if p.attr == 'live' && p.pref.is_so {
|
||||||
@ -448,8 +432,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// println('is_c=$is_c name=$f.name')
|
// println('is_c=$is_c name=$f.name')
|
||||||
if is_c || is_sig || is_fn_header {
|
if is_c || p.is_vh || is_fn_header {
|
||||||
// println('IS SIG .key_returnING tok=${p.strtok()}')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Profiling mode? Start counting at the beginning of the function (save current time).
|
// Profiling mode? Start counting at the beginning of the function (save current time).
|
||||||
@ -465,7 +448,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
p.cgen.nogen = true
|
p.cgen.nogen = true
|
||||||
}
|
}
|
||||||
p.statements_no_rcbr()
|
p.statements_no_rcbr()
|
||||||
p.cgen.nogen = false
|
//p.cgen.nogen = false
|
||||||
// Print counting result after all statements in main
|
// Print counting result after all statements in main
|
||||||
if p.pref.is_prof && f.name == 'main' {
|
if p.pref.is_prof && f.name == 'main' {
|
||||||
p.genln(p.print_prof_counters())
|
p.genln(p.print_prof_counters())
|
||||||
|
@ -169,7 +169,8 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexCfg) {
|
|||||||
if cfg.is_map {
|
if cfg.is_map {
|
||||||
p.gen('$tmp')
|
p.gen('$tmp')
|
||||||
def := type_default(typ)
|
def := type_default(typ)
|
||||||
p.cgen.insert_before('$typ $tmp = $def; bool $tmp_ok = map_get($index_expr, & $tmp);')
|
p.cgen.insert_before('$typ $tmp = $def; ' +
|
||||||
|
'bool $tmp_ok = map_get(/*$p.file_name : $p.scanner.line_nr*/$index_expr, & $tmp);')
|
||||||
}
|
}
|
||||||
else if cfg.is_arr {
|
else if cfg.is_arr {
|
||||||
if p.pref.translated && !p.builtin_mod {
|
if p.pref.translated && !p.builtin_mod {
|
||||||
|
104
compiler/main.v
104
compiler/main.v
@ -18,9 +18,6 @@ enum BuildMode {
|
|||||||
// `v program.v'
|
// `v program.v'
|
||||||
// Build user code only, and add pre-compiled vlib (`cc program.o builtin.o os.o...`)
|
// Build user code only, and add pre-compiled vlib (`cc program.o builtin.o os.o...`)
|
||||||
default_mode
|
default_mode
|
||||||
// `v -embed_vlib program.v`
|
|
||||||
// vlib + user code in one file (slower compilation, but easier when working on vlib and cross-compiling)
|
|
||||||
embed_vlib
|
|
||||||
// `v -lib ~/v/os`
|
// `v -lib ~/v/os`
|
||||||
// build any module (generate os.o + os.vh)
|
// build any module (generate os.o + os.vh)
|
||||||
build_module
|
build_module
|
||||||
@ -290,36 +287,25 @@ fn (v mut V) compile() {
|
|||||||
cgen.genln('#define V_COMMIT_HASH "' + vhash() + '"')
|
cgen.genln('#define V_COMMIT_HASH "' + vhash() + '"')
|
||||||
cgen.genln('#endif')
|
cgen.genln('#endif')
|
||||||
}
|
}
|
||||||
|
q := cgen.nogen // TODO hack
|
||||||
|
cgen.nogen = false
|
||||||
$if js {
|
$if js {
|
||||||
cgen.genln(js_headers)
|
cgen.genln(js_headers)
|
||||||
} $else {
|
} $else {
|
||||||
cgen.genln(CommonCHeaders)
|
cgen.genln(CommonCHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.generate_hotcode_reloading_declarations()
|
v.generate_hotcode_reloading_declarations()
|
||||||
|
|
||||||
imports_json := 'json' in v.table.imports
|
|
||||||
// TODO remove global UI hack
|
|
||||||
if v.os == .mac && ((v.pref.build_mode == .embed_vlib && 'ui' in
|
|
||||||
v.table.imports) || (v.pref.build_mode == .build_module &&
|
|
||||||
v.dir.contains('/ui'))) {
|
|
||||||
cgen.genln('id defaultFont = 0; // main.v')
|
|
||||||
}
|
|
||||||
// We need the cjson header for all the json decoding that will be done in
|
// We need the cjson header for all the json decoding that will be done in
|
||||||
// default mode
|
// default mode
|
||||||
|
imports_json := 'json' in v.table.imports
|
||||||
if v.pref.build_mode == .default_mode {
|
if v.pref.build_mode == .default_mode {
|
||||||
if imports_json {
|
if imports_json {
|
||||||
cgen.genln('#include "cJSON.h"')
|
cgen.genln('#include "cJSON.h"')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v.pref.build_mode == .embed_vlib || v.pref.build_mode == .default_mode {
|
if v.pref.build_mode == .default_mode {
|
||||||
//if v.pref.build_mode in [.embed_vlib, .default_mode] {
|
|
||||||
// If we declare these for all modes, then when running `v a.v` we'll get
|
// If we declare these for all modes, then when running `v a.v` we'll get
|
||||||
// `/usr/bin/ld: multiple definition of 'total_m'`
|
// `/usr/bin/ld: multiple definition of 'total_m'`
|
||||||
// TODO
|
|
||||||
//cgen.genln('i64 total_m = 0; // For counting total RAM allocated')
|
|
||||||
//if v.pref.is_test {
|
|
||||||
$if !js {
|
$if !js {
|
||||||
cgen.genln('int g_test_oks = 0;')
|
cgen.genln('int g_test_oks = 0;')
|
||||||
cgen.genln('int g_test_fails = 0;')
|
cgen.genln('int g_test_fails = 0;')
|
||||||
@ -335,11 +321,14 @@ fn (v mut V) compile() {
|
|||||||
}
|
}
|
||||||
//cgen.genln('/*================================== FNS =================================*/')
|
//cgen.genln('/*================================== FNS =================================*/')
|
||||||
cgen.genln('this line will be replaced with definitions')
|
cgen.genln('this line will be replaced with definitions')
|
||||||
defs_pos := cgen.lines.len - 1
|
mut defs_pos := cgen.lines.len - 1
|
||||||
|
if defs_pos == -1 {
|
||||||
|
defs_pos = 0
|
||||||
|
}
|
||||||
|
cgen.nogen = q
|
||||||
for file in v.files {
|
for file in v.files {
|
||||||
v.parse(file, .main)
|
v.parse(file, .main)
|
||||||
//if p.pref.autofree { p.scanner.text.free() free(p.scanner) }
|
//if p.pref.autofree { p.scanner.text.free() free(p.scanner) }
|
||||||
// p.g.gen_x64()
|
|
||||||
// Format all files (don't format automatically generated vlib headers)
|
// Format all files (don't format automatically generated vlib headers)
|
||||||
if !v.pref.nofmt && !file.contains('/vlib/') {
|
if !v.pref.nofmt && !file.contains('/vlib/') {
|
||||||
// new vfmt is not ready yet
|
// new vfmt is not ready yet
|
||||||
@ -356,25 +345,25 @@ fn (v mut V) compile() {
|
|||||||
vgen_parser.parse(.main)
|
vgen_parser.parse(.main)
|
||||||
// v.parsers.add(vgen_parser)
|
// v.parsers.add(vgen_parser)
|
||||||
v.log('Done parsing.')
|
v.log('Done parsing.')
|
||||||
// Write everything
|
// All definitions
|
||||||
mut d := strings.new_builder(10000)// Avoid unnecessary allocations
|
mut def := strings.new_builder(10000)// Avoid unnecessary allocations
|
||||||
$if !js {
|
$if !js {
|
||||||
d.writeln(cgen.includes.join_lines())
|
def.writeln(cgen.includes.join_lines())
|
||||||
d.writeln(cgen.typedefs.join_lines())
|
def.writeln(cgen.typedefs.join_lines())
|
||||||
d.writeln(v.type_definitions())
|
def.writeln(v.type_definitions())
|
||||||
d.writeln('\nstring _STR(const char*, ...);\n')
|
def.writeln('\nstring _STR(const char*, ...);\n')
|
||||||
d.writeln('\nstring _STR_TMP(const char*, ...);\n')
|
def.writeln('\nstring _STR_TMP(const char*, ...);\n')
|
||||||
d.writeln(cgen.fns.join_lines()) // fn definitions
|
def.writeln(cgen.fns.join_lines()) // fn definitions
|
||||||
} $else {
|
} $else {
|
||||||
d.writeln(v.type_definitions())
|
def.writeln(v.type_definitions())
|
||||||
}
|
}
|
||||||
d.writeln(cgen.consts.join_lines())
|
def.writeln(cgen.consts.join_lines())
|
||||||
d.writeln(cgen.thread_args.join_lines())
|
def.writeln(cgen.thread_args.join_lines())
|
||||||
if v.pref.is_prof {
|
if v.pref.is_prof {
|
||||||
d.writeln('; // Prof counters:')
|
def.writeln('; // Prof counters:')
|
||||||
d.writeln(v.prof_counters())
|
def.writeln(v.prof_counters())
|
||||||
}
|
}
|
||||||
cgen.lines[defs_pos] = d.str()
|
cgen.lines[defs_pos] = def.str()
|
||||||
v.generate_main()
|
v.generate_main()
|
||||||
v.generate_hot_reload_code()
|
v.generate_hot_reload_code()
|
||||||
if v.pref.is_verbose {
|
if v.pref.is_verbose {
|
||||||
@ -394,8 +383,7 @@ fn (v mut V) generate_main() {
|
|||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
||||||
$if js { return }
|
$if js { return }
|
||||||
|
|
||||||
// if v.build_mode in [.default, .embed_vlib] {
|
if v.pref.build_mode == .default_mode {
|
||||||
if v.pref.build_mode == .default_mode || v.pref.build_mode == .embed_vlib {
|
|
||||||
mut consts_init_body := cgen.consts_init.join_lines()
|
mut consts_init_body := cgen.consts_init.join_lines()
|
||||||
// vlib can't have `init_consts()`
|
// vlib can't have `init_consts()`
|
||||||
cgen.genln('void init_consts() {
|
cgen.genln('void init_consts() {
|
||||||
@ -591,8 +579,14 @@ fn (v &V) v_files_from_dir(dir string) []string {
|
|||||||
|
|
||||||
// Parses imports, adds necessary libs, and then user files
|
// Parses imports, adds necessary libs, and then user files
|
||||||
fn (v mut V) add_v_files_to_compile() {
|
fn (v mut V) add_v_files_to_compile() {
|
||||||
|
mut builtin_files := v.get_builtin_files()
|
||||||
|
// Builtin cache exists? Use it.
|
||||||
|
builtin_vh := '$v_modules_path/builtin.vh'
|
||||||
|
if v.pref.is_debug && os.file_exists(builtin_vh) {
|
||||||
|
builtin_files = [builtin_vh]
|
||||||
|
}
|
||||||
// Parse builtin imports
|
// Parse builtin imports
|
||||||
for file in v.get_builtin_files() {
|
for file in builtin_files {
|
||||||
// add builtins first
|
// add builtins first
|
||||||
v.files << file
|
v.files << file
|
||||||
mut p := v.new_parser_from_file(file)
|
mut p := v.new_parser_from_file(file)
|
||||||
@ -613,19 +607,25 @@ fn (v mut V) add_v_files_to_compile() {
|
|||||||
v.log('imports:')
|
v.log('imports:')
|
||||||
println(v.table.imports)
|
println(v.table.imports)
|
||||||
}
|
}
|
||||||
// resolve deps & add imports in correct order
|
// resolve deps and add imports in correct order
|
||||||
for mod in v.resolve_deps().imports() {
|
imported_mods := v.resolve_deps().imports()
|
||||||
// if mod == v.mod { continue } // Building this module? Skip. TODO it's a hack.
|
for mod in imported_mods {
|
||||||
if mod == 'builtin' { continue } // builtin already added
|
if mod == 'builtin' || mod == 'main' {
|
||||||
if mod == 'main' { continue } // main files will get added last
|
// builtin already added
|
||||||
|
// main files will get added last
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// use cached built module if exists
|
// use cached built module if exists
|
||||||
// vh_path := '$v_modules_path/${mod}.vh'
|
if v.pref.build_mode != .build_module {
|
||||||
// if os.file_exists(vh_path) {
|
vh_path := '$v_modules_path/${mod}.vh'
|
||||||
// println('using cached module `$mod`: $vh_path')
|
//println(vh_path)
|
||||||
// v.files << vh_path
|
if v.pref.is_debug && os.file_exists(vh_path) {
|
||||||
// continue
|
println('using cached module `$mod`: $vh_path')
|
||||||
// }
|
v.files << vh_path
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
// standard module
|
// standard module
|
||||||
mod_path := v.find_module_path(mod) or { verror(err) break }
|
mod_path := v.find_module_path(mod) or { verror(err) break }
|
||||||
vfiles := v.v_files_from_dir(mod_path)
|
vfiles := v.v_files_from_dir(mod_path)
|
||||||
@ -640,8 +640,9 @@ fn (v mut V) add_v_files_to_compile() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get builtin files
|
|
||||||
fn (v &V) get_builtin_files() []string {
|
fn (v &V) get_builtin_files() []string {
|
||||||
|
// .vh cache exists? Use it
|
||||||
|
|
||||||
$if js {
|
$if js {
|
||||||
return v.v_files_from_dir('$v.vroot${os.PathSeparator}vlib${os.PathSeparator}builtin${os.PathSeparator}js')
|
return v.v_files_from_dir('$v.vroot${os.PathSeparator}vlib${os.PathSeparator}builtin${os.PathSeparator}js')
|
||||||
}
|
}
|
||||||
@ -812,11 +813,6 @@ fn new_v(args[]string) &V {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
// TODO embed_vlib is temporarily the default mode. It's much slower.
|
|
||||||
else if !('-embed_vlib' in args) {
|
|
||||||
build_mode = .embed_vlib
|
|
||||||
}
|
|
||||||
//
|
|
||||||
is_test := dir.ends_with('_test.v')
|
is_test := dir.ends_with('_test.v')
|
||||||
is_script := dir.ends_with('.v')
|
is_script := dir.ends_with('.v')
|
||||||
if is_script && !os.file_exists(dir) {
|
if is_script && !os.file_exists(dir) {
|
||||||
|
@ -9,9 +9,10 @@ import (
|
|||||||
os
|
os
|
||||||
)
|
)
|
||||||
|
|
||||||
/* .vh generation logic.
|
/*
|
||||||
.vh files contains only function signatures, consts, and types.
|
.vh generation logic.
|
||||||
They are used together with pre-compiled modules.
|
.vh files contains only function signatures, consts, and types.
|
||||||
|
They are used together with pre-compiled modules.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// "fn foo(a int) string"
|
// "fn foo(a int) string"
|
||||||
@ -27,7 +28,7 @@ fn (f &Fn) v_definition() string {
|
|||||||
}
|
}
|
||||||
if f.is_method {
|
if f.is_method {
|
||||||
recv := f.args[0]
|
recv := f.args[0]
|
||||||
typ := v_type_str(recv.typ)
|
typ := v_type_str(recv.typ).replace('*', '')
|
||||||
mut mu := if recv.is_mut { 'mut' } else { '' }
|
mut mu := if recv.is_mut { 'mut' } else { '' }
|
||||||
if recv.ref {
|
if recv.ref {
|
||||||
mu = '&'
|
mu = '&'
|
||||||
@ -40,6 +41,9 @@ fn (f &Fn) v_definition() string {
|
|||||||
sb.write('$f.name(')
|
sb.write('$f.name(')
|
||||||
}
|
}
|
||||||
for i, arg in f.args {
|
for i, arg in f.args {
|
||||||
|
if i == 0 && f.is_method { // skip the receiver
|
||||||
|
continue
|
||||||
|
}
|
||||||
typ := v_type_str(arg.typ)
|
typ := v_type_str(arg.typ)
|
||||||
if arg.name == '' {
|
if arg.name == '' {
|
||||||
sb.write(typ)
|
sb.write(typ)
|
||||||
@ -62,11 +66,12 @@ fn (f &Fn) v_definition() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn v_type_str(typ_ string) string {
|
fn v_type_str(typ_ string) string {
|
||||||
typ := if typ_.ends_with('*') {
|
mut typ := if typ_.ends_with('*') {
|
||||||
'*' + typ_.left(typ_.len - 1)
|
'*' + typ_.left(typ_.len - 1)
|
||||||
} else {
|
} else {
|
||||||
typ_
|
typ_
|
||||||
}
|
}
|
||||||
|
typ = typ.replace('Option_', '?')
|
||||||
//println('"$typ"')
|
//println('"$typ"')
|
||||||
if typ == '*void' {
|
if typ == '*void' {
|
||||||
return 'voidptr'
|
return 'voidptr'
|
||||||
@ -80,11 +85,11 @@ fn v_type_str(typ_ string) string {
|
|||||||
if typ.contains('__') {
|
if typ.contains('__') {
|
||||||
return typ.all_after('__')
|
return typ.all_after('__')
|
||||||
}
|
}
|
||||||
return typ.replace('Option_', '?')
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (v &V) generate_vh() {
|
fn (v &V) generate_vh() {
|
||||||
println('Generating a V header file for module `$v.mod`')
|
println('\n\n\n\nGenerating a V header file for module `$v.mod`')
|
||||||
dir := '$v_modules_path${os.PathSeparator}$v.mod'
|
dir := '$v_modules_path${os.PathSeparator}$v.mod'
|
||||||
path := dir + '.vh'
|
path := dir + '.vh'
|
||||||
if !os.dir_exists(dir) {
|
if !os.dir_exists(dir) {
|
||||||
@ -95,6 +100,7 @@ fn (v &V) generate_vh() {
|
|||||||
file := os.create(path) or { panic(err) }
|
file := os.create(path) or { panic(err) }
|
||||||
// Consts
|
// Consts
|
||||||
file.writeln('// $v.mod module header \n')
|
file.writeln('// $v.mod module header \n')
|
||||||
|
file.writeln('module $v.mod')
|
||||||
file.writeln('// Consts')
|
file.writeln('// Consts')
|
||||||
if v.table.consts.len > 0 {
|
if v.table.consts.len > 0 {
|
||||||
file.writeln('const (')
|
file.writeln('const (')
|
||||||
@ -126,16 +132,20 @@ fn (v &V) generate_vh() {
|
|||||||
file.writeln('\n')
|
file.writeln('\n')
|
||||||
}
|
}
|
||||||
// Types
|
// Types
|
||||||
file.writeln('// Types')
|
file.writeln('// Types2')
|
||||||
for _, typ in v.table.typesmap {
|
for _, typ in v.table.typesmap {
|
||||||
if typ.mod != v.mod {
|
//println(typ.name)
|
||||||
|
if typ.mod != v.mod && typ.mod != ''{ // int, string etc mod == ''
|
||||||
|
//println('skipping type "$typ.name"')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
mut name := typ.name
|
||||||
if typ.name.contains('__') {
|
if typ.name.contains('__') {
|
||||||
continue
|
name = typ.name.all_after('__')
|
||||||
}
|
}
|
||||||
if typ.cat == .struct_ {
|
if typ.cat in [TypeCategory.struct_, .c_struct] {
|
||||||
file.writeln('struct $typ.name {')
|
c := if typ.is_c { 'C.' } else { '' }
|
||||||
|
file.writeln('struct ${c}$name {')
|
||||||
// Private fields
|
// Private fields
|
||||||
for field in typ.fields {
|
for field in typ.fields {
|
||||||
if field.access_mod == .public {
|
if field.access_mod == .public {
|
||||||
@ -144,13 +154,18 @@ fn (v &V) generate_vh() {
|
|||||||
field_type := v_type_str(field.typ)
|
field_type := v_type_str(field.typ)
|
||||||
file.writeln('\t$field.name $field_type')
|
file.writeln('\t$field.name $field_type')
|
||||||
}
|
}
|
||||||
file.writeln('pub:')
|
//file.writeln('pub:')
|
||||||
|
mut public_str := ''
|
||||||
for field in typ.fields {
|
for field in typ.fields {
|
||||||
if field.access_mod == .private {
|
if field.access_mod == .private {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
field_type := v_type_str(field.typ)
|
field_type := v_type_str(field.typ)
|
||||||
file.writeln('\t$field.name $field_type')
|
public_str += '\t$field.name $field_type\n'
|
||||||
|
//file.writeln('\t$field.name $field_type')
|
||||||
|
}
|
||||||
|
if public_str != '' {
|
||||||
|
file.writeln('pub:' + public_str)
|
||||||
}
|
}
|
||||||
file.writeln('}\n')
|
file.writeln('}\n')
|
||||||
}
|
}
|
||||||
@ -161,8 +176,10 @@ fn (v &V) generate_vh() {
|
|||||||
mut fns := []Fn
|
mut fns := []Fn
|
||||||
// TODO fns := v.table.fns.filter(.mod == v.mod)
|
// TODO fns := v.table.fns.filter(.mod == v.mod)
|
||||||
for _, f in v.table.fns {
|
for _, f in v.table.fns {
|
||||||
if f.mod == v.mod {
|
if f.mod == v.mod || f.mod == ''{
|
||||||
fns << f
|
fns << f
|
||||||
|
} else {
|
||||||
|
println('skipping fn $f.name mod=$f.mod')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, f in fns {
|
for _, f in fns {
|
||||||
@ -181,7 +198,8 @@ fn (v &V) generate_vh() {
|
|||||||
// Methods
|
// Methods
|
||||||
file.writeln('\n// Methods //////////////////')
|
file.writeln('\n// Methods //////////////////')
|
||||||
for _, typ in v.table.typesmap {
|
for _, typ in v.table.typesmap {
|
||||||
if typ.mod != v.mod {
|
if typ.mod != v.mod { //&& typ.mod != '' {
|
||||||
|
println('skipping method typ $typ.name mod=$typ.mod')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for method in typ.methods {
|
for method in typ.methods {
|
||||||
|
@ -253,9 +253,6 @@ pub fn (v mut V) cc_msvc() {
|
|||||||
mut alibs := []string // builtin.o os.o http.o etc
|
mut alibs := []string // builtin.o os.o http.o etc
|
||||||
if v.pref.build_mode == .build_module {
|
if v.pref.build_mode == .build_module {
|
||||||
}
|
}
|
||||||
else if v.pref.build_mode == .embed_vlib {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
else if v.pref.build_mode == .default_mode {
|
else if v.pref.build_mode == .default_mode {
|
||||||
b := os.realpath( '$v_modules_path/vlib/builtin.obj' )
|
b := os.realpath( '$v_modules_path/vlib/builtin.obj' )
|
||||||
alibs << '"$b"'
|
alibs << '"$b"'
|
||||||
|
@ -51,7 +51,6 @@ mut:
|
|||||||
tmp_cnt int
|
tmp_cnt int
|
||||||
is_script bool
|
is_script bool
|
||||||
builtin_mod bool
|
builtin_mod bool
|
||||||
vh_lines []string
|
|
||||||
inside_if_expr bool
|
inside_if_expr bool
|
||||||
inside_unwrapping_match_statement bool
|
inside_unwrapping_match_statement bool
|
||||||
inside_return_expr bool
|
inside_return_expr bool
|
||||||
@ -73,7 +72,7 @@ mut:
|
|||||||
v_script bool // "V bash", import all os functions into global space
|
v_script bool // "V bash", import all os functions into global space
|
||||||
var_decl_name string // To allow declaring the variable so that it can be used in the struct initialization
|
var_decl_name string // To allow declaring the variable so that it can be used in the struct initialization
|
||||||
is_alloc bool // Whether current expression resulted in an allocation
|
is_alloc bool // Whether current expression resulted in an allocation
|
||||||
is_const_literal bool // `1`, `2.0` etc, so that `u64 == 0` works
|
is_const_literal bool // `1`, `2.0` etc, so that `u64_var == 0` works
|
||||||
cur_gen_type string // "App" to replace "T" in current generic function
|
cur_gen_type string // "App" to replace "T" in current generic function
|
||||||
is_vweb bool
|
is_vweb bool
|
||||||
is_sql bool
|
is_sql bool
|
||||||
@ -81,6 +80,7 @@ mut:
|
|||||||
sql_i int // $1 $2 $3
|
sql_i int // $1 $2 $3
|
||||||
sql_params []string // ("select * from users where id = $1", ***"100"***)
|
sql_params []string // ("select * from users where id = $1", ***"100"***)
|
||||||
sql_types []string // int, string and so on; see sql_params
|
sql_types []string // int, string and so on; see sql_params
|
||||||
|
is_vh bool // parsing .vh file (for example `const (a int)` is allowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -100,7 +100,6 @@ fn (v mut V) new_parser_from_string(text string, id string) Parser {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// new parser from file.
|
|
||||||
fn (v mut V) new_parser_from_file(path string) Parser {
|
fn (v mut V) new_parser_from_file(path string) Parser {
|
||||||
//println('new_parser("$path")')
|
//println('new_parser("$path")')
|
||||||
mut path_pcguard := ''
|
mut path_pcguard := ''
|
||||||
@ -119,7 +118,8 @@ fn (v mut V) new_parser_from_file(path string) Parser {
|
|||||||
file_name: path.all_after(os.PathSeparator),
|
file_name: path.all_after(os.PathSeparator),
|
||||||
file_platform: path_platform,
|
file_platform: path_platform,
|
||||||
file_pcguard: path_pcguard,
|
file_pcguard: path_pcguard,
|
||||||
is_script: (v.pref.is_script && os.realpath(path) == os.realpath(path))
|
is_script: (v.pref.is_script && os.realpath(path) == os.realpath(path)),
|
||||||
|
is_vh: path.ends_with('.vh')
|
||||||
}
|
}
|
||||||
if p.pref.building_v {
|
if p.pref.building_v {
|
||||||
p.scanner.should_print_relative_paths_on_error = false
|
p.scanner.should_print_relative_paths_on_error = false
|
||||||
@ -249,6 +249,14 @@ fn (p mut Parser) parse(pass Pass) {
|
|||||||
p.fspace()
|
p.fspace()
|
||||||
p.mod = p.check_name()
|
p.mod = p.check_name()
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
p.cgen.nogen = false
|
||||||
|
if p.pref.build_mode == .build_module && p.mod != p.v.mod {
|
||||||
|
//println('skipping $p.mod (v.mod = $p.v.mod)')
|
||||||
|
p.cgen.nogen = true
|
||||||
|
//defer { p.cgen.nogen = false }
|
||||||
|
}
|
||||||
p.fgenln('\n')
|
p.fgenln('\n')
|
||||||
p.builtin_mod = p.mod == 'builtin'
|
p.builtin_mod = p.mod == 'builtin'
|
||||||
p.can_chash = p.mod=='ui' || p.mod == 'darwin'// TODO tmp remove
|
p.can_chash = p.mod=='ui' || p.mod == 'darwin'// TODO tmp remove
|
||||||
@ -343,16 +351,15 @@ fn (p mut Parser) parse(pass Pass) {
|
|||||||
mut g := p.table.cgen_name_type_pair(name, typ)
|
mut g := p.table.cgen_name_type_pair(name, typ)
|
||||||
if p.tok == .assign {
|
if p.tok == .assign {
|
||||||
p.next()
|
p.next()
|
||||||
// p.gen(' = ')
|
|
||||||
g += ' = '
|
g += ' = '
|
||||||
p.cgen.start_tmp()
|
_, expr := p.tmp_expr()
|
||||||
p.bool_expression()
|
g += expr
|
||||||
// g += '<<< ' + p.cgen.end_tmp() + '>>>'
|
|
||||||
g += p.cgen.end_tmp()
|
|
||||||
}
|
}
|
||||||
// p.genln('; // global')
|
// p.genln('; // global')
|
||||||
g += '; // global'
|
g += '; // global'
|
||||||
p.cgen.consts << g
|
if !p.cgen.nogen {
|
||||||
|
p.cgen.consts << g
|
||||||
|
}
|
||||||
case TokenKind.eof:
|
case TokenKind.eof:
|
||||||
//p.log('end of parse()')
|
//p.log('end of parse()')
|
||||||
// TODO: check why this was added? everything seems to work
|
// TODO: check why this was added? everything seems to work
|
||||||
@ -484,27 +491,36 @@ fn (p mut Parser) const_decl() {
|
|||||||
p.fgenln('')
|
p.fgenln('')
|
||||||
p.fmt_inc()
|
p.fmt_inc()
|
||||||
for p.tok == .name {
|
for p.tok == .name {
|
||||||
if p.lit == '_' && p.peek() == .assign {
|
if p.lit == '_' && p.peek() == .assign && !p.cgen.nogen {
|
||||||
p.gen_blank_identifier_assign()
|
p.gen_blank_identifier_assign()
|
||||||
|
//if !p.cgen.nogen {
|
||||||
p.cgen.consts_init << p.cgen.cur_line.trim_space()
|
p.cgen.consts_init << p.cgen.cur_line.trim_space()
|
||||||
p.cgen.resetln('')
|
p.cgen.resetln('')
|
||||||
|
//}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// `Age = 20`
|
mut name := p.check_name() // `Age = 20`
|
||||||
mut name := p.check_name()
|
|
||||||
//if ! (name[0] >= `A` && name[0] <= `Z`) {
|
//if ! (name[0] >= `A` && name[0] <= `Z`) {
|
||||||
//p.error('const name must be capitalized')
|
//p.error('const name must be capitalized')
|
||||||
//}
|
//}
|
||||||
name = p.prepend_mod(name)
|
name = p.prepend_mod(name)
|
||||||
p.check_space(.assign)
|
mut typ := ''
|
||||||
typ := p.expression()
|
if p.is_vh {
|
||||||
|
// .vh files don't have const values, just types: `const (a int)`
|
||||||
|
typ = p.get_type()
|
||||||
|
p.table.register_const(name, typ, p.mod)
|
||||||
|
continue // Don't generate C code when building a .vh file
|
||||||
|
} else {
|
||||||
|
p.check_space(.assign)
|
||||||
|
typ = p.expression()
|
||||||
|
}
|
||||||
if p.first_pass() && p.table.known_const(name) {
|
if p.first_pass() && p.table.known_const(name) {
|
||||||
p.error('redefinition of `$name`')
|
p.error('redefinition of `$name`')
|
||||||
}
|
}
|
||||||
if p.first_pass() {
|
if p.first_pass() {
|
||||||
p.table.register_const(name, typ, p.mod)
|
p.table.register_const(name, typ, p.mod)
|
||||||
}
|
}
|
||||||
if p.pass == .main {
|
if p.pass == .main && !p.cgen.nogen {
|
||||||
// TODO hack
|
// TODO hack
|
||||||
// cur_line has const's value right now. if it's just a number, then optimize generation:
|
// cur_line has const's value right now. if it's just a number, then optimize generation:
|
||||||
// output a #define so that we don't pollute the binary with unnecessary global vars
|
// output a #define so that we don't pollute the binary with unnecessary global vars
|
||||||
@ -1219,11 +1235,6 @@ fn (p mut Parser) gen(s string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate V header from V source
|
// Generate V header from V source
|
||||||
fn (p mut Parser) vh_genln(s string) {
|
|
||||||
//println('vh $s')
|
|
||||||
p.vh_lines << s
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (p mut Parser) statement(add_semi bool) string {
|
fn (p mut Parser) statement(add_semi bool) string {
|
||||||
if p.returns && !p.is_vweb {
|
if p.returns && !p.is_vweb {
|
||||||
p.error('unreachable code')
|
p.error('unreachable code')
|
||||||
@ -2806,7 +2817,7 @@ fn (p mut Parser) string_expr() {
|
|||||||
p.gen('"$f"')
|
p.gen('"$f"')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.gen('tos2((byte*)"$f")')
|
p.gen('tos3("$f")')
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
return
|
return
|
||||||
|
@ -70,8 +70,4 @@ Options/commands:
|
|||||||
/*
|
/*
|
||||||
- To disable automatic formatting:
|
- To disable automatic formatting:
|
||||||
v -nofmt file.v
|
v -nofmt file.v
|
||||||
|
|
||||||
- To build a program with an embedded vlib (use this if you do not have prebuilt vlib libraries or if you
|
|
||||||
are working on vlib)
|
|
||||||
v -embed_vlib file.v
|
|
||||||
*/
|
*/
|
||||||
|
32
vlib/os2/os2_mac.v
Normal file
32
vlib/os2/os2_mac.v
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
module os2
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
struct File {
|
||||||
|
fd int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C.open(byteptr, int, int) int
|
||||||
|
fn C.write(voidptr, byteptr, int) int
|
||||||
|
|
||||||
|
pub fn create(path string) ?File {
|
||||||
|
fd := C.creat(path.str, 0644)//511)
|
||||||
|
if fd == -1 {
|
||||||
|
return error('failed to create "$path":')
|
||||||
|
//os.print_c_errno()
|
||||||
|
}
|
||||||
|
return File{fd}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (f File) writeln(s string) {
|
||||||
|
ss := s + '\n'
|
||||||
|
ret := C.write(f.fd, ss.str, s.len + 1)
|
||||||
|
if ret == -1 {
|
||||||
|
C.perror('failed to write')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (f File) close() {
|
||||||
|
C.close(f.fd)
|
||||||
|
}
|
||||||
|
|
9
vlib/os2/os2_test.v
Normal file
9
vlib/os2/os2_test.v
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import os2
|
||||||
|
|
||||||
|
fn test_open() {
|
||||||
|
$if mac {
|
||||||
|
f := os2.create('os2.test')
|
||||||
|
f.writeln('hello world!')
|
||||||
|
f.close()
|
||||||
|
}
|
||||||
|
}
|
@ -45,7 +45,8 @@ pub fn dice_coefficient(s1, s2 string) f32 {
|
|||||||
mut first_bigrams := map[string]int
|
mut first_bigrams := map[string]int
|
||||||
for i := 0; i < a.len-1; i++ {
|
for i := 0; i < a.len-1; i++ {
|
||||||
bigram := a.substr(i, i+2)
|
bigram := a.substr(i, i+2)
|
||||||
first_bigrams[bigram] = if bigram in first_bigrams { first_bigrams[bigram]+1 } else { 1 }
|
q := if bigram in first_bigrams { first_bigrams[bigram]+1 } else { 1 }
|
||||||
|
first_bigrams[bigram] = q
|
||||||
}
|
}
|
||||||
mut intersection_size := 0
|
mut intersection_size := 0
|
||||||
for i := 0; i < b.len-1; i++ {
|
for i := 0; i < b.len-1; i++ {
|
||||||
|
@ -29,6 +29,8 @@ fn C.localtime(int) &C.tm
|
|||||||
fn remove_me_when_c_bug_is_fixed() { // TODO
|
fn remove_me_when_c_bug_is_fixed() { // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct C.time_t {}
|
||||||
|
|
||||||
struct C.tm {
|
struct C.tm {
|
||||||
tm_year int
|
tm_year int
|
||||||
tm_mon int
|
tm_mon int
|
||||||
|
Loading…
Reference in New Issue
Block a user